Dokcer 容器基础篇(二)
接收上面的基础篇一写的
Docker 镜像
什么是镜像
镜像 Image 是一种轻量级, 可执行的独立软件包, 用来打包软件运行环境和基于运行环境开发的软件. 它包含运行某个软件所需的所有内容, 包括代码, 运行时, 库, 环境变量和配置文件
联合文件系统 UnionFS
Union 文件系统 (UnionFS) 是一种分层, 轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下 (unite several directories into a single virtual filesystem)
Union 文件系统是 Docker 镜像的基础. 镜像可以通过分层来进行继承,基于基础镜像 (没有父镜像), 可以制作各种具体的应用镜像
特性:
一次同时加载多个文件, 但从外面看起来, 只能看到一个文件系统, 联合加载会把各层文件系统叠加, 这样最后的文件系统会包含所有底层的文件和目录
Docker 中使用的 AUFS(AnotherUnionFS)就是一种 Union FS。 AUFS 支持为每一个成员目录(类似 Git 的分支)设定只读(readonly)、读写(readwrite)和写出(whiteout-able)权限, 同时 AUFS 里有一个类似分层的概念, 对只读权限的分支可以逻辑上进行增量地修改(不影响只读部分的)。
Docker 目前支持的 Union 文件系统种类包括 AUFS, btrfs, vfs 和 DeviceMapper。
Docker 镜像加载原理
Docker 镜像实际上是由一层一层的文件系统组成, 这种层级的文件系统 UnionFS.
bootfs (boot file system) 主要包含 bootloader 和 kernel
bootloader 主要是引导加载 kernel, Linux 刚启动时回家再 bootfs 文件系统, 在 Docker 镜像的最底层是 bootfs, 包含 boot 加载器和内核
当 boot 加载完成之后, 整个内核就都在内存之中, 此时内存的使用权已经由 bootfs 转交给内核, 系统会卸载 bootfs
rootfs (root file system), 在 bootfs 智商, 包含的就是经典 Linux 系统中的 /dev, /proc, /bin 等标准目录和文件
镜像分层
以 docker pull
为例, 下载过程可以看到 docker 镜像好像是一层一层在下载
以 tomcat 为例, docker pull 下来的镜像文件有 400 MB, 为何文件如此之大?
答: “镜像分层”, kernel -> centOS -> jdk8 -> tomcat, 虽然我们只是用到了最后的 tomcat, 但是所有之前的都下载了
为什么 Docker 镜像是分层结构?
共享资源
比如: 多个镜像都从相同的 base 镜像构建而来, 那么宿主机只需要在磁盘上保存一份 base 镜像. 同时内存中也只需加载一份 base 镜像, 就可以为所有容器服务了. 而且镜像的每一层都可以被共享
镜像有什么特点?
特点:
Docker 镜像都是只读的
当容器启动时, 一个新的可写层被加载安东镜像的顶部
这一层通常被称作”容器层”, “容器层”之下被叫做”镜像层”
Docker 镜像操作补充
$ docker commit
提交容器副本使之成为一个新的镜像
$ docker commit -m="message" -a="author" <container_id> target_name:[tag_name]
Docker 容器数据卷
什么是 Docker 容器数据卷
将运用与运行的环境打包成容器运行, 运行可以伴随着容器, 但是我们希望数据持久化
容器之间可以会有数据共享的需要 (容器间继承 + 共享数据)
Docker 容器产生的数据, 如果不 docker commit
那么容器删除后, 数据也就丢失了
类似于 Redis 里的 RDB 和 AOF
特点:
- 数据卷可在容器之间共享或者重用数据
- 卷中的更改可以直接生效
- 数据卷中的更改不会包含在镜像的更新中
- 数据卷的生命周期一直持续到没有容器使用它为止
数据卷
数据卷是一个可供一个或多个容器使用的特殊目录, 它绕过 UFS, 可以提供很多有用的特性:
- 数据卷可以在容器之间共享和重用
- 对数据卷的修改会立马生效
- 对数据卷的更新,不会影响镜像
- 卷会一直存在,直到没有容器使用
数据卷的使用,类似于 Linux 下对目录或文件进行 mount
创建一个数据卷
1. 直接命令添加
添加数据卷命令
在用 docker run 命令的时候, 使用 -v (volume 缩写) 标记来创建一个数据卷并挂载到容器里. 在一次 run 中多次使用可以挂载多个数据卷
docker run -it -v /宿主机绝对路径:/容器内目录 <image_name>
# eg: (目录没有会自动创建)
docker run -it -v /mydataVolume:/containerDataVolume centos
查看数据卷是否挂载成功
docker inspect centos
在 Volumes key 中会看到挂载的文件夹, 在 HostConfig
中的 Binds 看到二者相互绑定, 那么成功.
容器和宿主机之间数据共享
在容器中修改文件内容, 宿主机中可以发现文件内容发生改变. “可读可写”
注意:如果是centos7上安装的docker,其默认容器中的containerDataVolume是不能进行写操作的。是因为CentOS7中的安全模块SELinux把权限禁掉了。
解决办法:
- 在运行容器的时候,给容器加特权,及加上 --privileged=true 参数。使用该参数,容器内的root拥有真正的root权限.否则,容器内的root只是外部的一个普通用户权限
docker run -it --privileged=true -v /mydataVolume:/containerDataVolume centos
- 临时关闭SELinux:
setenforce 0
- 添加SELinux规则,改变要挂载的目录的安全性文本。参考这个
容器停止退出后, 宿主机修改后数据是否同步?
同步
文件操作权限
$ docker run -it -v /宿主机绝对路径:/容器内目录:权限 <image_name>
# eg:
docker run -it --privileged=true -v /mydataVolume:/containerDataVolume:ro centos
ro - Read Only, 只读
在 container 中 执行 touch container.txt 会返回错误信息
2. 使用 Dockerfile 添加
Dockerfile 会在下一章讲解
- 在宿主机目录下创建
mydocker
目录,并进入到该目录下 - 在改目录下创建Dockerfile文件,
touch Dockerfile
- 编写Dockerfile文件
FROM centos
VOLUME ["/dataVolumeContainer1","/dataVolumerContainer2"]
CMD echo ">>> finish, success...."
CMD /bin/bash
说明:
出于可移植性和分享的考虑,用-v 主机目录:容器目录这种方法不能直接在Dockerfile中实现
由于宿主机目录是依赖于特定宿主机的,并不能保证在所有的宿主机上都存在这样的特定目录。
- build后生成镜像
# 生成名称为mycentos/centos 的镜像
docker build -f /mydocker/Dockerfile -t mycentos/centos .
-
查看镜像
docker imgaes
-
运行镜像
docker run -it mycentos/centos /bin/bash
我们发现容器中已经存在了我们创建的两个数据卷
- 查看主机对应默认地址
docker inspect mycentos/centos
可以查看到对应的绑定目录
数据卷容器
命名的容器挂载数据卷, 其他的容器通过挂载这个 (父容器) 实现数据共享, 挂载数据卷的容器被称为数据卷容器
容器间数据的传递共享
容器间传递共享(--volumes-from)
1. 先启动一个父容器dco1
docker run -it -d --name dc01 mycentos/centos
在容器中的dataVolumeContainer1/目录下创建一个dc_add.txt文件
echo 'this is parent container dc01' >> dc01_add.txt
2. 分别创建dc02,dc03,继承自dc01
先创建dc02
docker run -it -d --volumes-from dc01 --name dc02 mycentos/centos
进入到dc02容器中dataVolumeContainer1/目录查看,是否存在dc01_add.txt文件??
答案:是
然后在这个目录下再创建dc02_add.txt
echo 'this is dc02 container' >> dc02_add.txt
再创建dc03
docker run -it -d --volumes-from dc01 --name dc03 mycentos/centos
发现目录下dc01_add.txt和dc02_add.txt文件都存在
在该目录下创建dc_03.txt
echo 'this is dc03 container' > dc03_add.txt
3. 回到dc01,可以看到dc01也有了dc02_add.txt和dc03_add.txt文件
4. 删除父容器dc01,dc02修改后dc03可否访问??
可以
5. 删除dc02后dc03可否访问??
可以
结论:
容器之间配置信息的传递,数据卷的生周期一直持续到没有容器使用它为止。
Dockerfile解析
利用数据卷容器来备份, 恢复, 迁移数据卷
摘选自: Docker - 从入门到实践 Gitbook
可以利用数据卷对其中的数据进行进行备份, 恢复和迁移.