Dockerfile

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 镜像如何制作:

  1. 容器转为镜像

    shell 复制代码
    docker 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 镜像了)
  2. 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
相关推荐
老司机张师傅25 分钟前
【微服务实战之Docker容器】第七章-Dockerfile解析
容器·dockerfile·虚悬镜像·docker学习
微信-since8119231 分钟前
[ruby on rails] 安装docker
后端·docker·ruby on rails
blessing。。39 分钟前
I2C学习
linux·单片机·嵌入式硬件·嵌入式
2202_754421541 小时前
生成MPSOC以及ZYNQ的启动文件BOOT.BIN的小软件
java·linux·开发语言
努力的悟空1 小时前
国土变更调查拓扑错误自动化修复工具的研究
运维·自动化
运维&陈同学2 小时前
【zookeeper03】消息队列与微服务之zookeeper集群部署
linux·微服务·zookeeper·云原生·消息队列·云计算·java-zookeeper
吴半杯2 小时前
gateway漏洞(CVE-2022-22947)
docker·kubernetes·gateway
今天我刷leetcode了吗2 小时前
docker 配置同宿主机共同网段的IP 同时通过通网段的另一个电脑实现远程连接docker
tcp/ip·docker·电脑
周末不下雨3 小时前
win11+ubuntu22.04双系统 | 联想 24 y7000p | ubuntu 22.04 | 把ubuntu系统装到1T的移动固态硬盘上!!!
linux·运维·ubuntu
lwprain3 小时前
常用docker应用部署,wordpress、mysql、tomcat、nginx、redis
mysql·docker·tomcat