云计算百科
云计算领域专业知识百科平台

《Docker 镜像构建详解:docker commit、Dockerfile 与 docker build 实战》

Docker 镜像构建详解:docker commit、Dockerfile 与 docker build 实战

  • Docker 镜像构建详解:docker commit、Dockerfile 与 docker build 实战
  • 一、使用 docker commit 构建镜像
      • 1. docker commit 的作用
    • 二、将运行中的 Tomcat 容器制作成镜像
    • 三、查看生成的镜像
    • 四、为镜像添加仓库信息
    • 五、登录 Docker Hub
    • 六、上传镜像到 Docker Hub
  • 七、docker commit 的特点
  • 八、使用 Dockerfile 构建镜像
  • 九、Dockerfile 常用指令
  • 十、Dockerfile 实战:构建一个 Nginx Web 镜像
    • 十一、使用 docker build 构建镜像
  • 十二、Docker 镜像的分层构建机制
  • 十三、查看构建完成的镜像
  • 十四、启动自己构建的 Nginx 容器
  • 十五、Dockerfile 综合案例:CentOS + JDK + Tomcat + Web 应用
  • 十六、编写 Java Web Dockerfile
  • 十七、逐条理解 Dockerfile
      • 1. 指定基础镜像
      • 2. 设置维护者信息
      • 3. 创建目录
      • 4. 复制 JDK
      • 5. 解压 JDK
      • 6. 设置 Java 环境变量
      • 7. 获取 Tomcat
      • 8. 解压 Tomcat
      • 9. 部署 Web 应用
      • 10. 设置容器启动程序
  • 十八、构建 Java Web 镜像
  • 十九、运行 Java Web 容器
  • 二十、docker commit 和 Dockerfile 怎么选?
  • 二十一、几个容易混淆的 Docker 命令
      • docker commit
      • docker build
      • docker run
      • docker tag
      • docker push
  • 二十二、总结

Docker 镜像构建详解:docker commit、Dockerfile 与 docker build 实战

在 Docker 的日常使用中,我们通常会直接使用 Docker Hub 或其他镜像仓库中的现成镜像,例如 CentOS、Nginx、Tomcat、MySQL 等。

但在实际项目中,经常需要把自己的应用程序、运行环境和相关配置一起制作成镜像。这就涉及 Docker 自定义镜像的构建。

常见的构建方式主要有两种:

  • 基于已有容器,通过 docker commit 生成新镜像。
  • 编写 Dockerfile,通过 docker build 自动构建镜像。
  • 其中,docker commit 更适合快速验证和理解镜像生成过程;实际开发、部署和持续集成中,则更推荐使用 Dockerfile。


    一、使用 docker commit 构建镜像

    1. docker commit 的作用

    docker commit 可以把一个容器当前的文件系统状态保存为新的 Docker 镜像。

    基本语法:

    docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]

    常用参数包括:

    -a, –author string 设置作者信息
    -c, –change list 对生成的镜像应用 Dockerfile 指令
    -m, –message string 设置提交说明
    -p, –pause commit 时暂停容器,默认为 true

    它的核心逻辑可以理解为:

    基础镜像

    创建并运行容器

    在容器中安装软件、部署应用、修改文件

    docker commit

    生成新的 Docker 镜像


    二、将运行中的 Tomcat 容器制作成镜像

    假设已经基于 Tomcat 镜像创建了一个容器,并且已经在容器中部署好了 Web 应用。

    首先查看当前正在运行的容器:

    docker ps

    也可以通过自定义的命令别名查看:

    myps

    输出类似:

    CONTAINER ID IMAGE NAMES PORTS
    33a3e34fcf0a tomcat mytomcat 0.0.0.0:8080->8080/tcp

    这里需要重点记住容器 ID:

    33a3e34fcf0a

    接下来将这个容器保存为新的镜像:

    docker commit 33a3e34fcf0a tomcat_with_application

    命令执行成功后,会返回新镜像对应的 SHA256 ID。


    三、查看生成的镜像

    可以使用:

    docker images

    如果配置了别名,也可以使用:

    myimages

    可以看到刚刚生成的镜像:

    REPOSITORY TAG
    tomcat_with_application latest
    docker.io/nginx latest
    docker.io/tomcat latest
    docker.io/mysql 5.7.19

    如果没有显式指定 Tag,Docker 默认使用:

    latest

    因此:

    docker commit 33a3e34fcf0a tomcat_with_application

    实际上相当于生成:

    tomcat_with_application:latest


    四、为镜像添加仓库信息

    如果准备把镜像上传到远程镜像仓库,需要按照目标仓库的命名规则给镜像重新打标签。

    例如:

    docker tag tomcat_with_application:latest username/tomcat_with_application:latest

    再次执行:

    docker images

    就可以看到带有仓库路径的新镜像名称。

    需要注意,docker tag 不会重新复制一份完整的镜像数据,本质上只是给已有镜像增加一个新的引用名称。


    五、登录 Docker Hub

    上传镜像之前需要先登录:

    docker login

    根据终端提示输入 Docker Hub 的用户名和认证信息。

    登录成功后即可进行后续的镜像推送操作。


    六、上传镜像到 Docker Hub

    使用:

    docker push username/tomcat_with_application:latest

    Docker 会逐层上传镜像,例如:

    Preparing
    Pushing
    Pushed
    Layer already exists

    Docker 镜像采用分层存储机制。如果远程仓库已经存在某些相同的镜像层,这些层不需要重复上传,因此可能出现:

    Layer already exists

    这种机制能够减少重复数据传输,提高镜像上传和下载效率。


    七、docker commit 的特点

    docker commit 使用起来非常直接:

    启动容器

    进入容器

    安装软件

    修改配置

    部署应用

    docker commit

    生成镜像

    但是它也存在比较明显的问题。

    容器内部执行了哪些操作,很难仅通过最终镜像完整追溯。例如一个人可能在容器中执行了几十条命令,最后只执行:

    docker commit ...

    其他开发者拿到镜像之后,并不知道这个镜像具体是如何制作出来的。

    因此,docker commit 更适合:

    • 快速保存当前容器状态;
    • 实验和测试;
    • 临时制作镜像;
    • 学习 Docker 镜像和容器之间的关系。

    对于正式项目,更推荐使用 Dockerfile。


    八、使用 Dockerfile 构建镜像

    Dockerfile 本质上是一个文本文件。

    文件中按照一定规则写入 Docker 构建镜像需要执行的指令,例如:

    FROM nginx

    RUN …

    COPY …

    ENV …

    ENTRYPOINT …

    然后通过:

    docker build

    读取 Dockerfile 中的指令,自动完成整个镜像构建过程。

    其基本流程为:

    Dockerfile

    docker build

    逐条执行构建指令

    生成镜像层

    最终 Docker 镜像

    与 docker commit 相比,Dockerfile 最大的优势就是构建过程可以被记录、复现和版本管理。


    九、Dockerfile 常用指令

    常见 Dockerfile 指令如下:

    指令作用
    FROM 指定基础镜像
    MAINTAINER 指定维护者信息,属于旧式写法
    RUN 在镜像构建过程中执行命令
    COPY 将构建上下文中的文件复制到镜像
    ADD 添加文件,并具有额外处理能力
    ENV 设置环境变量
    WORKDIR 设置后续指令的工作目录
    EXPOSE 声明容器提供服务的端口
    VOLUME 声明数据卷
    USER 指定运行命令时使用的用户
    CMD 设置容器默认执行命令
    ENTRYPOINT 设置容器启动时执行的程序

    现在编写新的 Dockerfile 时,一般建议使用 LABEL 维护作者等元数据,而不是继续使用已经过时的 MAINTAINER。


    十、Dockerfile 实战:构建一个 Nginx Web 镜像

    先从一个简单示例开始。

    创建一个名为:

    Dockerfile

    的文件。

    注意:

    Dockerfile

    通常没有扩展名。

    写入:

    FROM nginx

    RUN echo 'This is a Demo HTML' > /usr/share/nginx/html/index.html

    这里做了两件事情。

    首先:

    FROM nginx

    表示以 Nginx 镜像作为基础镜像。

    然后:

    RUN echo 'This is a Demo HTML' > /usr/share/nginx/html/index.html

    在构建镜像过程中修改 Nginx 默认首页。


    十一、使用 docker build 构建镜像

    进入 Dockerfile 所在目录后执行:

    docker build -t mynginx .

    这里有两个非常重要的参数。

    -t mynginx

    用于指定最终生成的镜像名称。

    最后的:

    .

    同样非常重要,它表示当前目录作为构建上下文(Build Context)。

    所以完整命令不要漏掉最后的点:

    docker build -t mynginx .

    构建过程中会看到类似:

    Sending build context to Docker daemon

    Step 1/2 : FROM nginx
    —> …

    Step 2/2 : RUN echo 'This is a Demo HTML' > /usr/share/nginx/html/index.html
    —> Running in …

    Successfully built …
    Successfully tagged mynginx:latest

    Docker 会按照 Dockerfile 中指令的顺序逐条完成构建。


    十二、Docker 镜像的分层构建机制

    Dockerfile 中的很多指令都会产生新的镜像层。

    例如:

    FROM nginx

    RUN apt-get update

    RUN echo "hello" > /usr/share/nginx/html/index.html

    可以简单理解为:

    基础层:nginx

    RUN apt-get update

    新的镜像层

    RUN echo …

    新的镜像层

    最终镜像

    Docker 在构建过程中会利用缓存机制。

    如果某一层以及它之前的构建条件没有变化,那么再次执行:

    docker build

    时,就可能直接复用已有缓存,而不需要重新执行全部操作。

    这也是为什么 Dockerfile 的指令顺序会影响镜像构建效率。


    十三、查看构建完成的镜像

    执行:

    docker images

    可以看到:

    REPOSITORY TAG
    mynginx latest
    nginx latest

    然后就可以使用这个镜像启动容器。


    十四、启动自己构建的 Nginx 容器

    执行:

    docker run -d -p 7788:80 mynginx

    参数含义:

    -d

    表示容器在后台运行。

    -p 7788:80

    表示端口映射:

    宿主机 7788

    容器 80

    Nginx 默认监听容器内部的 80 端口,因此访问:

    http://服务器IP:7788

    即可访问刚刚创建的页面。


    十五、Dockerfile 综合案例:CentOS + JDK + Tomcat + Web 应用

    下面进一步构建一个完整 Java Web 运行环境。

    目标环境:

    CentOS

    安装 JDK

    安装 Tomcat

    部署 WAR

    生成 Docker 镜像

    运行 Java Web 容器

    需要准备:

    Dockerfile
    jdk-8u144-linux-x64.tar.gz
    MyDemoWeb.war

    目录结构类似:

    demo/
    ├── Dockerfile
    ├── jdk-8u144-linux-x64.tar.gz
    └── MyDemoWeb.war


    十六、编写 Java Web Dockerfile

    示例:

    FROM centos

    MAINTAINER zhaoyuqian

    RUN mkdir /root/training
    RUN mkdir /root/tools

    COPY jdk-8u144-linux-x64.tar.gz /root/tools

    RUN tar zxvf /root/tools/jdk-8u144-linux-x64.tar.gz \\
    -C /root/training

    ENV JAVA_HOME /root/training/jdk1.8.0_144
    ENV PATH $JAVA_HOME/bin:$PATH

    ADD https://dlcdn.apache.org/tomcat/tomcat-8/v8.5.73/bin/apache-tomcat-8.5.73.tar.gz /root/tools

    RUN tar zxvf /root/tools/apache-tomcat-8.5.73.tar.gz \\
    -C /root/training

    COPY MyDemoWeb.war \\
    /root/training/apache-tomcat-8.5.73/webapps

    ENTRYPOINT ["/root/training/apache-tomcat-8.5.73/bin/catalina.sh","run"]

    这个 Dockerfile 描述了从基础操作系统一直到 Java Web 应用部署的完整过程。


    十七、逐条理解 Dockerfile

    1. 指定基础镜像

    FROM centos

    表示后续环境建立在 CentOS 基础之上。


    2. 设置维护者信息

    MAINTAINER zhaoyuqian

    用于记录镜像维护者。

    不过现在更推荐:

    LABEL maintainer="your-name"


    3. 创建目录

    RUN mkdir /root/training
    RUN mkdir /root/tools

    其中:

    /root/tools

    用于保存安装包。

    /root/training

    用于安装 JDK、Tomcat 等运行环境。


    4. 复制 JDK

    COPY jdk-8u144-linux-x64.tar.gz /root/tools

    把构建上下文中的 JDK 安装包复制到镜像内部。


    5. 解压 JDK

    RUN tar zxvf /root/tools/jdk-8u144-linux-x64.tar.gz \\
    -C /root/training

    将 JDK 安装到:

    /root/training


    6. 设置 Java 环境变量

    ENV JAVA_HOME /root/training/jdk1.8.0_144
    ENV PATH $JAVA_HOME/bin:$PATH

    这样后续构建步骤以及最终容器都能够直接找到 Java。

    现代 Dockerfile 中也可以写成:

    ENV JAVA_HOME=/root/training/jdk1.8.0_144
    ENV PATH="${JAVA_HOME}/bin:${PATH}"


    7. 获取 Tomcat

    示例中使用:

    ADD https://dlcdn.apache.org/tomcat/tomcat-8/v8.5.73/bin/apache-tomcat-8.5.73.tar.gz /root/tools

    将 Tomcat 安装包放入:

    /root/tools


    8. 解压 Tomcat

    RUN tar zxvf /root/tools/apache-tomcat-8.5.73.tar.gz \\
    -C /root/training

    最终 Tomcat 位于:

    /root/training/apache-tomcat-8.5.73


    9. 部署 Web 应用

    COPY MyDemoWeb.war \\
    /root/training/apache-tomcat-8.5.73/webapps

    将 WAR 包放入 Tomcat:

    webapps

    目录中。

    Tomcat 启动之后即可加载该 Web 应用。


    10. 设置容器启动程序

    ENTRYPOINT ["/root/training/apache-tomcat-8.5.73/bin/catalina.sh","run"]

    这意味着使用该镜像创建容器时,默认启动:

    catalina.sh run

    从而让 Tomcat 以前台方式运行。

    这点对 Docker 容器非常重要:容器需要一个持续运行的前台主进程。


    十八、构建 Java Web 镜像

    准备好:

    Dockerfile
    jdk-8u144-linux-x64.tar.gz
    MyDemoWeb.war

    之后,在当前目录执行:

    docker build -t mywebapp .

    注意最后仍然有:

    .

    构建成功后执行:

    docker images

    可以看到:

    REPOSITORY TAG
    mywebapp latest


    十九、运行 Java Web 容器

    使用刚刚生成的镜像:

    docker run -d -p 8080:8080 mywebapp

    这里的端口关系为:

    宿主机 8080

    Docker 端口映射

    容器 8080

    Tomcat

    MyDemoWeb

    然后通过:

    http://服务器IP:8080/MyDemoWeb/

    访问部署完成的 Java Web 应用。


    二十、docker commit 和 Dockerfile 怎么选?

    两种方式最终都能够生成 Docker 镜像,但思路有明显区别。

    对比项docker commitDockerfile
    构建方式 基于已有容器 基于构建脚本
    操作过程 手工修改容器 自动执行指令
    可读性 较差
    可复现性 较差
    版本管理 不方便 非常方便
    自动化构建 不适合 适合
    CI/CD 不推荐 推荐
    学习理解 直观 更接近实际开发

    可以把两种方式理解为:

    docker commit
    = 先手工把环境配置好,再保存结果

    Dockerfile
    = 先把构建过程写下来,再让 Docker 自动执行

    在实际项目中,优先选择:

    Dockerfile + docker build


    二十一、几个容易混淆的 Docker 命令

    docker commit

    把容器当前状态制作成镜像:

    docker commit 容器ID 镜像名


    docker build

    根据 Dockerfile 构建镜像:

    docker build -t 镜像名 .


    docker run

    根据镜像创建并启动容器:

    docker run -d -p 宿主机端口:容器端口 镜像名


    docker tag

    给已有镜像增加新的名称或标签:

    docker tag 原镜像 新镜像名:标签


    docker push

    把本地镜像上传到镜像仓库:

    docker push 用户名/镜像名:标签

    因此整个流程可以串起来理解:

    ┌─ docker commit ─┐
    运行中的容器 ────┤ ├──→ Docker 镜像
    └─────────────────┘

    Dockerfile ── docker build ───────────→ Docker 镜像

    ├─ docker run → Docker 容器

    └─ docker push → 镜像仓库


    二十二、总结

    Docker 自定义镜像构建需要重点掌握两条路线。

    第一条:

    基础镜像
    → 创建容器
    → 修改容器
    → docker commit
    → 新镜像
    → docker tag
    → docker push

    第二条,也是实际开发中更重要的一条:

    准备应用程序和运行环境
    → 编写 Dockerfile
    → docker build
    → 生成镜像
    → docker run
    → 启动容器
    → 对外提供服务

    其中最需要掌握的是 Dockerfile 中几个核心指令:

    FROM
    RUN
    COPY
    ADD
    ENV
    WORKDIR
    EXPOSE
    CMD
    ENTRYPOINT

    同时要理解三个基本概念之间的关系:

    Dockerfile:描述“镜像应该怎么构建”

    docker build

    Image:构建完成、可重复使用的运行模板

    docker run

    Container:镜像真正运行起来后的实例

    掌握这条链路之后,再学习镜像仓库、容器编排以及 Kubernetes 时,很多概念就会自然衔接起来。


    若有转载,请标明出处:

    赞(0)
    未经允许不得转载:网硕互联帮助中心 » 《Docker 镜像构建详解:docker commit、Dockerfile 与 docker build 实战》
    分享到: 更多 (0)

    评论 抢沙发

    评论前必须登录!