base 镜像有两层含义:
不依赖其他镜像,从 scratch 构建。
其他镜像可以之为基础进行扩展。
所以,能称作 base 镜像的通常都是各种 Linux 发行版的 Docker 镜像,比如 Ubuntu, Debian, CentOS 等。
base 镜像提供的是最小安装的 Linux 发行版。
我们大部分镜像都将是基于base镜像构建的。所以,通常使用的是官方发布的base镜像。可以在docker hub里找到。比如centos: https://hub.docker.com/_/centos
点击版本可以看到github里的Dockerfile
FROM scratch ADD centos-7-docker.tar.xz / LABEL org.label-schema.schema-version="1.0" \ org.label-schema.name="CentOS Base Image" \ org.label-schema.vendor="CentOS" \ org.label-schema.license="GPLv2" \ org.label-schema.build-date="20181205" CMD ["/bin/bash"]ADD命令将本地的centos7的tar包添加到镜像,并解压到根目录/下。生成/dev,/proc/,/bin等。
我们可以自己构建docker base镜像,也可以直接使用已有的base镜像。比如centos。我们可以直接从docker hub上拉取。
拉取
docker pull centos查看
# docker images centos REPOSITORY TAG IMAGE ID CREATED SIZE centos latest 1e1148e4cc2c 2 months ago 202MB可以看到最新的centos镜像只有200mb,是不是觉得太小了?这是因为docker镜像在运行的时候直接使用docker宿主机器的kernel。
Linux操作系统由内核空间和用户空间组成。
内核空间是kernel,用户空间是rootfs, 不同Linux发行版的区别主要是rootfs.比如 Ubuntu 14.04 使用 upstart 管理服务,apt 管理软件包;而 CentOS 7 使用 systemd 和 yum。这些都是用户空间上的区别,Linux kernel 差别不大。
所以 Docker 可以同时支持多种 Linux 镜像,模拟出多种操作系统环境。
需要注意的是:
base镜像只是用户空间和发行版一致。kernel使用的是docker宿主机器的kernel。例如 CentOS 7 使用 3.x.x 的 kernel,如果 Docker Host 是 Ubuntu 16.04(比如我们的实验环境),那么在 CentOS 容器中使用的实际是是 Host 4.x.x 的 kernel。
① Host kernel 为 4.4.0-31
② 启动并进入 CentOS 容器
③ 验证容器是 CentOS 7
④ 容器的 kernel 版本与 Host 一致
关于存储结构(About storage drivers)上文里展示了如何下载一个base镜像。我们通常是基于这份base镜像来构建我们自己的镜像。比如,在centos里添加一个nginx负载均衡。首先,得需要了解镜像的结构是什么。
官方文档: https://docs.docker.com/storage/storagedriver/
先来创建一个自己的镜像首先,base镜像是基于docker宿主机器kernel之上的Linux发行版。
现在,我们给这台机器安装一个vim,一个httpd. 基于Dockerfile来创建一个新的镜像。
我们的Dockerfile
FROM centos:7 RUN yum install -y vim RUN yum install -y httpd CMD ["/bin/bash"]含义:
基于centos7的base镜像构建
安装vim
安装httpd
执行bash
在当前目录下新建一个文件Dockerfile, 填充上述内容。然后执行
# docker build -t ryan/httpd:v1.0 . Sending build context to Docker daemon 6.144kB Step 1/4 : FROM centos:7 ---> 1e1148e4cc2c Step 2/4 : RUN yum install -y vim ---> Using cache ---> 74bdbea98f73 Step 3/4 : RUN yum install -y httpd ---> Using cache ---> 17d8c4095dc4 Step 4/4 : CMD /bin/bash ---> Using cache ---> f2b58b1192de Successfully built f2b58b1192de Successfully tagged ryan/httpd:latest-t 指定我们创建的镜像名称,镜像名称可以用组织/id:version的方式标记
最后一个参数是Dockerfile所在的路径., 表示当前目录
然后我们添加一个tag latest
docker tag ryan/httpd:v1.0 ryan/httpd:latest即给镜像ryan/httpd:v1.0标记为ryan/httpd:latest
构建完成之后,查看
# docker images | grep -E '(ryan|centos)' ryan/httpd latest f2b58b1192de About an hour ago 444MB ryan/httpd v1.0 f2b58b1192de About an hour ago 444MB centos 7 1e1148e4cc2c 2 months ago 202MB centos latest 1e1148e4cc2c 2 months ago 202MB可以运行我们创建的镜像:
# docker run -d --privileged=true -it ryan/httpd:v1.0 /usr/sbin/init 48a4a128cd7b6924149cd97670919d4e2af6cb96c73c901af60d05fe4478225a # docker ps | grep ryan 48a4a128cd7b ryan/httpd:v1.0 "/usr/sbin/init" 8 seconds ago Up 8 seconds现在我们的基于原生base centos7的httpd服务器已经启动了。可以通过docker exec -it zealous_kirch /bin/bash来进入容器内部,查看启动httpd。
docker镜像的分层结构我们可以查看镜像的历史,用上一步的镜像id f2b58b1192de
# docker history f2b58b1192de IMAGE CREATED CREATED BY SIZE COMMENT f2b58b1192de About an hour ago /bin/sh -c #(nop) CMD ["/bin/bash"] 0B 17d8c4095dc4 About an hour ago /bin/sh -c yum install -y httpd 110MB 74bdbea98f73 About an hour ago /bin/sh -c yum install -y vim 133MB 1e1148e4cc2c 2 months ago /bin/sh -c #(nop) CMD ["/bin/bash"] 0B <missing> 2 months ago /bin/sh -c #(nop) LABEL org.label-schema.... 0B <missing> 2 months ago /bin/sh -c #(nop) ADD file:6f877549795f479... 202MB启动镜像的时候,一个新的可写层会加载到镜像的顶部。这一层通常称为“容器层”, 之下是“镜像层”。
容器层可以读写,容器所有发生文件变更写都发生在这一层。镜像层read-only,只允许读取。
(上图来自官方文档,和本次实验内容略有不同,但原理一样)