自学内容网 自学内容网

docker 初步理解

1 docker 相关文件

1.1 image 文件

Docker 把应用程序及其依赖,打包在 image 文件里面。只有通过这个文件,才能生成 Docker 容器。image 文件可以看作是容器的模板。Docker 根据 image 文件生成容器的实例。同一个 image 文件,可以生成多个同时运行的容器实例。

image 是二进制文件。实际开发中,一个 image 文件往往通过继承另一个 image 文件,加上一些个性化设置而生成。例如,可以在 Ubuntu 的 image 基础上,往里面加入 Apache 服务器,形成新的 image。

# 列出本机的所有 image 文件
docker image ls

# 删除 image 文件
docker image rm [imageName]

image 文件是通用的,一台机器的 image 文件拷贝到另一台机器,可以直接使用。一般来说,为了节省时间,我们应该尽量使用别人制作好的 image 文件。如果需要定制,可以基于别人的 image 文件进行加工,不必要从零开始制作。

为了方便共享,image 文件制作完成后,可以上传到网上的仓库。Docker 的官方仓库 Docker Hub 是最重要、最常用的 image 仓库。

1.2 镜像实例

从仓库下载 image 文件,国内访问 Docker 的官方仓库很慢,还经常断线,所以要把仓库网址改成国内的镜像站。

  • 打开/etc/default/docker文件(需要sudo权限),在文件的底部加上一行。
DOCKER_OPTS="--registry-mirror=https://registry.docker-cn.com"
  • 重启 Docker 服务
sudo service docker restart

现在就会自动从镜像仓库下载 image 文件.

运行下面的命令,将 image 文件从仓库抓取到本地

docker image pull library/hello-world

说明:

  • docker image pull是抓取 image 文件的命令
  • library/hello-world是 image 文件在仓库里面的位置,其中library是 image 文件所在的组
  • hello-world是 image 文件的名字
    Docker 官方提供的 image 文件,都放在library组里面,所以它的是默认组,可以省略。因此,上面的命令可以写成下面这样:
docker image pull hello-world

运行这个 image 文件:

docker container run hello-world

说明:

  • docker container run命令会从 image 文件,生成一个正在运行的容器实例。docker container run命令具有自动抓取 image 文件的功能。如果发现本地没有指定的 image 文件,就会从仓库自动抓取。因此,前面的docker image pull命令并不是必需的步骤。

如果运行成功,屏幕上会有相应的输出:

Hello from Docker!
This message shows that your installation appears to be working correctly.

输出这段提示以后,hello world就会停止运行,容器自动终止。

有些容器不会自动终止,因为提供的是服务。比如,安装运行 centos 的 image,就可以在命令行体验 centos 系统。对于那些不会自动终止的容器,必须使用docker container kill 命令手动终止:

docker container kill [containID]
1.3 容器文件

image 文件生成的容器实例,本身也是一个文件,称为容器文件。也就是说,一旦容器生成,就会同时存在两个文件: image 文件和容器文件。而且关闭容器并不会删除容器文件,只是容器停止运行而已。

# 列出本机正在运行的容器
docker container ls

# 列出本机所有容器,包括终止运行的容器
docker container ls --all

终止运行的容器文件,依然会占据硬盘空间,可以使用docker container rm命令删除。

docker container rm [containerID]
1.4 Dockerfile 文件

Dockerfile 文件是一个文本文件,用来配置 image。Docker 根据该文件生成二进制的 image 文件。

镜像文件可以通过Dockerfile来一步一步的去进行构建,Dockerfile其实这就是一堆的命令和脚本。

1.4.1 dockerfile 基本语法:
  • 每个保留关键字(指令)都是必须是大写字母
  • 执行从上到下顺序
  • #表示注释
  • 每一个指令都会创建提交一个新的镜像,并提交
1.4.2 DockerFile常用指令
FROM             # 基础镜像,一切从这里开始构建  centos
MAINTAINER        # 镜像是谁写的, 姓名+邮箱
RUN             # 镜像构建的时候需要运行的命令
ADD             # 步骤,tomcat镜像,这个tomcat压缩包!添加内容 添加同目录
WORKDIR         # 镜像的工作目录
VOLUME             # 挂载的目录
EXPOSE             # 暴露端口配置  和 -p 一样
CMD             # 指定这个容器启动的时候要运行的命令,只有最后一个会生效,可被替代。
ENTRYPOINT         # 指定这个容器启动的时候要运行的命令,可以追加命令
ONBUILD         # 当构建一个被继承 DockerFile 这个时候就会运行ONBUILD的指令,触发指令。
COPY             # 类似ADD,将我们文件拷贝到镜像中
ENV             # 构建的时候设置环境变量!

2 Docker镜像加载原理

2.1 UnionFS(联合文件系统)

Union文件系统(UnionFS)是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,类似于Git中的一层一层提交的一个概念,同时可以将不同目录挂载到同一个虚拟文件系统下(unite several directories into a single virtual filesystem)。Union文件系统是Docker镜像的基础。镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。

UnionFS 一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把文件系统叠加起来,这样最终的文件系统包含所有底层的文件和目录。因此在下载镜像的时候,在 Terminal 看到的日志是在下载名称类似 git commit ID 那一个个文件。

2.2 Dcoker镜像加载原理

bootfs(boot file system):主要包含bootloader和kernel。bootloader主要是引导加载kernel,Linux刚启动时会加载bootfs文件系统,在Docker镜像的最底层是bootfs。这一层与我们电脑的Linux/Unix系统是一样的,包含boot加载器和内核。当boot加载完成之后整个内核就都在内存中了,此时内存的使用权已由bootfs转交给内核,此时系统也会卸载bootfs。

rootfs(root file system):在bootfs之上。包含的就是典型Linux 系统中的 /dev,/proc,/bin,/etc 等标准目录和文件。rootfs就是各种不同的操作系统发行版,比如Ubuntu,Centos等等。

前面提到虚拟机的体积比docker占用的资源和存储空间都要大很多,例如安装进虚拟机的CentOS都是好几个G,Docker只有200M。原因是:对于个精简的OS,rootfs可以很小,只需要包合最基本的命令,工具和程序库就可以了,因为底层直接用Host的kernel,自己只需要提供rootfs就可以了。由此可见对于不同的Linux发行版, bootfs基本是一致的, rootfs会有差別,因此不同的发行版可以公用bootfs。

2.3 分层理解

前面提到,docker 的文件系统是分层的,这样做的目的是为了能够提高资源共享,有多个镜像都从相同的Base镜像构建而来,那么宿主机只需在磁盘上保留一份base镜像,同时内存中也只需要加载一份base镜像,这样就可以为所有的容器服务了,而且镜像的每一层都可以被共享。

查看镜像分层的方式可以通过docker image inspect 命令:

docker inspect redis

所有的docker镜像都起始于一个基础镜像层,当进行修改或者增加新的内容时,就会在当前镜像层之上,创建新的镜像层。

在添加额外的镜像层的同时,镜像始终是保持当前所有镜像的组合。例如在一些基础层当中,原本有了一些环境,比如java、tomcat、maven,然后我们需要再去安装一些redis、mysql或者是python等等,那么就只需要在层的概念上,添加上一层需要添加的环境就可以。对于一个新的镜像,如果其他层级不变,都与前面那个镜像相同,可以直接用。如果其他的一些文件发生了一些变化,那只需要操作文件就可以,新增修改这一层的文件。所有的镜像都是一步一步的进行分层的。这种情况下,上层镜像层中的文件覆盖了底层镜像层中的文件。这样就使得文件的更新版本作为一个新的镜像层添加到镜像当中。

Docker通过存储引擎(新版本采用快照机制)的方式来实现镜像层堆栈,并保证多镜像层对外展示为统一的文件系统。Linux 上可用的存储引擎有AUFS、Overlay2,Device Maper、Btrfs 以及 ZFS,每种存储引擎都基于Linux中对应的文件系统或者块设备技术。Docker在Windows上仅支持windowsfiler 一种存储引擎,该引擎基于NTFS文件系统之上实现了分层和CoW。

Docker镜像都是只读的,当容器启动时,一个新的可写层被加载到镜像的顶部。这一层就是通常说的容器层,容器之下的都叫镜像层。

3 容器数据卷

数据卷技术的目的是容器的持久化,实现容器之间数据共享,Docker容器中产生的数据,同步到本地。

3.1 使用数据卷
  • 直接使用命令挂载 -v, -v, --volume list Bind mount a volume
docker run -it -v 主机目录:容器内目录 

# 下面将启动一个 centos 容器,并将 centos 容器的 /home 映射到本地的 /home/centosTest 路径
run -it -v /home/centosTest:/home centos /bin/bash
# 在 本地主机查看centos 容器的 ID :
docker ps
# CONTAINER ID   IMAGE     COMMAND       CREATED         STATUS         PORTS     NAMES
# f8c960030aaa   centos    "/bin/bash"   4 minutes ago   Up 4 minutes             quirky_mendel
# 在本地主机通过 docker inspect 命令查看
docker inspect f8c960030aaa
# 可以看到挂载的地址
"HostConfig": {
            "Binds": [
                "/home/centosTest:/home"
            ],

cd /home
# 新建 test.txt 并在文件中添加 test,保存退出
# 在本地主机查看 /home/centosTest 会发现下面有一个 test.txt 文件,文件内容为 test, 就是刚才在 centos 容器内新建的
# 在本地主机编辑 /home/centosTest/test.txt 这个文件,在文件末尾添加 test also
# 在 centos 容器内查看 /home/test.txt,看到 文件内容为 test 和 test also

# 在本地主机关闭容器
docker kill f8c960030aaa
# 再在本地主机查看 /home/centosTest,看到 文件内容还是为 test 和 test also

上面的实验说明:

  • 通过上面的命令,可以将本地主机的目录挂载在容器内
  • 容器内的数据和本地主机的挂载地址的数据是同步的,并且同步是双向的
  • 在容器关闭之后,本地的数据还在
3.2 具名和匿名挂载
  • -v 容器内地址 匿名挂载
  • -v 卷名:容器内地址 具名挂载
  • -v /宿主机路径:容器路径 指定路径挂载
    其中具名挂载的卷所在位置可以通过下面的命令来查看:
docker volume inspect valume_name
# 或者
docker inspect nginx_hh valume_name

所有的docker容器内的卷,没有指定目录的情况下都是在 /var/lib/docker/volumes/xxx/_data

  • 通过 -v 容器内路径: ro rw 改变读写权限
ro readonly 只读
rw readwrite 可读可写

一旦设置了容器权限,容器对我们挂载出来的内容权限就有限制了。ro 说明这个路径只能通过宿主机来操作,容器内部是无法操作。


原文地址:https://blog.csdn.net/qq_38342510/article/details/143027257

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!