Docker 镜像原理
思考:
- Docker 镜像的本质是什么?
- 是一个分层文件系统
- 为什么 Docker 中的一个 CentOS 镜像只有 200MB,而一个 CentOS 操作系统的 iso 文件却要几个 G?
- CentOS 的 iso 镜像文件包含 bootfs 和 rootfs,而 Docker 的 CentOS 镜像复用了宿主机的 bootfs,只包含 rootfs 和其他镜像层
- 为什么 Docker 中的一个 Tomcat 镜像要 500MB,而一个 Tomcat 安装包却只要 70 MB?
- 由于 Docker 中的镜像是分层的,Tomcat 虽然只有 70 MB,但它需要依赖于父镜像和基础镜像,因此对外暴露的整个 Tomcat 镜像有 500MB
操作系统组成:
- 进程调度子系统
- 进程通信子系统
- 内存管理子系统
- 设备管理子系统
- 文件管理子系统
- 网络通信子系统
- 作业控制子系统
Docker 与操作系统中的文件管理子系统有关;Linux 文件系统由 bootfs 和 rootfs 两部分组成:
- bootfs:包含 bootloader(引导加载程序)和 kernel(内核)
- rootfs:root 文件系统,包括 Linux 系统中的 /dev、/proc、/bin、/etc 等标准目录和文件
- 不同的 Linux 发行版,bootfs 基本一样,但 rootfs 会有不同,如 ubuntu、centos等
Docker 镜像是由特殊的文件系统叠加而成:
- 最底端是 bootfs,一般使用宿主机的 bootfs
- 第二层是 root 文件系统 rootfs,称为基础镜像(base image)
- 再往上可以叠加其他的镜像文件,比如往上叠加一个 jdk 镜像,再往上叠加一个 tomcat 镜像
统一文件系统(Union File System)技术能够将不同的层整合成一个文件系统,为这些层提供了一个统一的视角,这样就隐藏了多层的存在,在用户的角度看来,只存在一个文件系统。
一个镜像可以放在另一个镜像的上面,位于下面的镜像称为父镜像,最底部的镜像称为基础镜像。
只读镜像不能修改,而容器可以;当从一个镜像启动容器时,Docker 会在最顶层加载一个读写文件系统作为容器。
Docker 镜像如何制作:
-
容器转为镜像
shelldocker commit 容器id 镜像名称:版本号 # 将容器转为镜像,镜像名称和版本号都是自定义的 docker save -o 压缩文件名称 镜像名称:版本号 # 将镜像保存成一个压缩文件 docker load -i 压缩文件名称 # 将压缩文件解压成一个镜像 docker commit 381827f60f7c hp_tomcat:1.0 # 若无版本号则默认为 latest docker save -o hp_tomcat.tar hp_tomcat:1.0 # 将 hp_tomcat 镜像压缩成 hp_tomcat.tar 文件 docker rmi 3ab93a1 # 删除 hp_tomcat 镜像(此时没有 hp_tomcat 镜像了) docker load -i hp_tomcat.tar # 将 hp_tomcat.tar 压缩文件解压成镜像(此时又有 hp_tomcat 镜像了)
-
Dockerfile
Dockerfile 概念及作用
Dockerfile 是一个文本文件,包含了一条条的指令,每一条指令构建一层,基于基础镜像,最终构建出一个新的镜像。
对于开发人员而言,Dockerfile 可以为开发团队提供一个完全一致的开发环境。
对于测试人员而言,可以直接拿开发时构建的镜像或通过 Dockerfile 文件构建一个新的镜像进行工作。
对于运维人员而言,在部署时,可以实现应用的无缝移植。
Dockerfile 文件中的指令可以仿照别人的来写,具体可以在 Docker 的官网去查看。
Dockerfile 关键字
关键字 | 作用 | 备注 |
---|---|---|
FROM | 指定父镜像 | 指定 dockerfile 基于哪个镜像来构建 |
MAINTAINER | 作者信息 | 用来标明这个 dockerfile 是谁写的 |
LABEL | 标签 | 用来标明 dockerfile 的标签,可以使用 Label 代替 Maintainer,最终都可以在 docker image 基本信息中查看到 |
RUN | 执行命令 | 执行一段命令,默认在 /bin/bash 中执行;格式为 RUN command 或 RUN ["command", "param1", "param2"] |
CMD | 容器启动命令 | 提供启动容器时候的默认命令,与 ENTRYPOINT 配合使用;格式为 CMD command param1 param2 或 CMD ["command", "param1", "param2"] |
ENTRYPOINT | 入口 | 一般在制作一些执行就关闭的容器中使用 |
COPY | 复制文件 | build 的时候复制文件到 image 中 |
ADD | 添加文件 | build 的时候添加文件到 image 中,不仅仅局限于当前 build 上下文,可以来源于远程服务 |
ENV | 环境变量 | 指定 build 时的环境变量,可以在启动容器的时候,通过 -e 覆盖;格式为 ENV name=value |
ARG | 构建参数 | 只在构建的时候使用的参数,如果有 ENV,那么 ENV 的相同名称的值会始终覆盖 arg 的参数 |
VOLUME | 定义外部可以挂载的数据卷 | 指定 build 的 image 中哪些目录可以在启动的时候挂载到文件系统中,启动容器时使用 -v 绑定;格式为 VOLUME ["目录"] |
EXPOSE | 暴露端口 | 定义容器运行时监听的端口,启动容器时使用 -p 来绑定暴露端口;格式为 EXPOSE 8080 或 EXPOSE 8080/udp |
WORKDIR | 工作目录 | 指定容器内部的工作目录,如果没有创建的话会自动创建;如果使用的是相对路径,那相对路径的开头是上一条 Workdir 路径 |
USER | 指定执行用户 | 指定 build 或启动时的用户 |
HEALTHCHECK | 健康检查 | 指定监测当前容器的健康监测的命令,基本上没用,因为很多时候应用本身有健康监测机制 |
ONBUILD | 触发器 | 当有 ONBUILD 关键字的镜像作为基础镜像时,FROM 指令执行完后,会执行 ONBUILD 命令,但是不影响当前镜像,用处不大 |
SHELL | 指定执行脚本的 shell | 指定执行 RUN CMD ENTRYPOINT 命令时所使用的 shell |