[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"article-detail-ssr-55597605563927564":3},{"id":4,"title":5,"tag":6,"createTime":7,"updateTime":7,"renderedHtml":8,"description":9,"ogImageUrl":10},"55597605563927564","Dockerfile 详解","Docker","2024-01-19","\u003Ch2 id=\"h2-0-dockerfile-\">Dockerfile 文件\u003C\u002Fh2>\n\u003Cp>Dockerfile 是用于构建 Docker 镜像的脚本文件，由一系列指令构成。通过 docker build 命令构建镜像时，Dockerfile 中的指令会由上到下依次执行，每条指令都将会构建出一个镜像。这就是镜像的分层。因此，指令越多，层次就越多，创建的镜像就越多，效率就越低。所以在定义 Dockerfile 时，能在一个指令完成的动作就不要分为两条。\u003C\u002Fp>\n\u003Ch2 id=\"h2-1-dockerfile-\">Dockerfile 指令\u003C\u002Fh2>\n\u003Col>\n\u003Cli>\n\u003Cp>\u003Cstrong>FROM\u003C\u002Fstrong>\u003C\u002Fp>\n\u003Cp>【语法】FROM &lt;image&gt;[:&lt;tag&gt;]\u003C\u002Fp>\n\u003Cp>【解析】用于指定基础镜像，且必须是第一条指令；若省略了 tag，则默认为 latest。\u003C\u002Fp>\n\u003C\u002Fli>\n\u003Cli>\n\u003Cp>\u003Cstrong>MAINTAINER\u003C\u002Fstrong>\u003C\u002Fp>\n\u003Cp>【语法】MAINTAINER &lt;name&gt;\u003C\u002Fp>\n\u003Cp>【解析】MAINTAINER 指令的参数填写的一般是维护者姓名和信箱。不过，该指令官方已不建议使用，而是使用 LABEL 指令代替。\u003C\u002Fp>\n\u003C\u002Fli>\n\u003Cli>\n\u003Cp>\u003Cstrong>LABEL\u003C\u002Fstrong>\u003C\u002Fp>\n\u003Cp>【语法】LABEL &lt;key&gt;=&lt;value&gt; &lt;key&gt;=&lt;value&gt;\u003C\u002Fp>\n\u003Cp>【解析】LABEL 指令中可以以键值对的方式包含任意镜像的元数据信息，用于替代 MAINTAINER 指令。通过 docker inspect 可查看到 LABEL 与 MAINTAINER 的内容。\u003C\u002Fp>\n\u003C\u002Fli>\n\u003Cli>\n\u003Cp>\u003Cstrong>ENV\u003C\u002Fstrong>\u003C\u002Fp>\n\u003Cp>【语法 1】ENV &lt;key&gt; &lt;value&gt;\u003C\u002Fp>\n\u003Cp>【解析】用于指定环境变量，这些环境变量，后续可以被 RUN 指令使用，容器运行起来之后，也可以在容器中获取这些环境变量。\u003C\u002Fp>\n\u003Cp>【语法 2】ENV &lt;key1&gt;=&lt;value1&gt; &lt;key2&gt;=&lt;value2&gt; …\u003C\u002Fp>\n\u003Cp>【解析】可以设置多个变量，每个变量为一对&lt;key&gt;=&lt;value&gt;指定。\u003C\u002Fp>\n\u003C\u002Fli>\n\u003Cli>\n\u003Cp>\u003Cstrong>WORKDIR\u003C\u002Fstrong>\u003C\u002Fp>\n\u003Cp>【语法】WORKDIR path\u003C\u002Fp>\n\u003Cp>【解析】容器打开后默认进入的目录，一般在后续的 RUN、CMD、ENTRYPOINT、ADD 等指令中会引用该目录。可以设置多个 WORKDIR 指令。后续 WORKDIR 指令若用的是相对路径，则会基于之前 WORKDIR 指令指定的路径。在使用 docker run 运行容器时，可以通过-w 参数覆盖构建时所设置的工作目录。\u003C\u002Fp>\n\u003C\u002Fli>\n\u003Cli>\n\u003Cp>\u003Cstrong>RUN\u003C\u002Fstrong>\u003C\u002Fp>\n\u003Cp>【语法 1】RUN &lt;command&gt;\u003C\u002Fp>\n\u003Cp>【解析】这里的&lt;command&gt;就是 shell 命令。docker build 执行过程中，会使用 shell 运行指定的 command。\u003C\u002Fp>\n\u003Cp>【语法 2】RUN [“EXECUTABLE”,“PARAM1”,“PARAM2”, …]\u003C\u002Fp>\n\u003Cp>【解析】在 docker build 执行过程中，会调用第一个参数&quot;EXECUTABLE&quot;指定的应用程序运行，并使用后面第二、三等参数作为应用程序的运行参数。\u003C\u002Fp>\n\u003C\u002Fli>\n\u003Cli>\n\u003Cp>\u003Cstrong>CMD\u003C\u002Fstrong>\u003C\u002Fp>\n\u003Cp>【语法 1】CMD [“EXECUTABLE”,“PARAM1”,“PARAM2”, …]\u003C\u002Fp>\n\u003Cp>【解析】在容器启动后，即在执行完 docker run 后会立即调用执行&quot;EXECUTABLE&quot;指定的可执行文件，并使用后面第二、三等参数作为应用程序的运行参数。\u003C\u002Fp>\n\u003Cp>【语法 2】CMD command param1 param2, …\u003C\u002Fp>\n\u003Cp>【解析】这里的 command 就是 shell 命令。在容器启动后会立即运行指定的 shell 命令。\u003C\u002Fp>\n\u003Cp>【语法 3】CMD [“PARAM1”,“PARAM2”, …]\u003C\u002Fp>\n\u003Cp>【解析】当 CMD 和 ENTRYPOINT 指令一起使用时，CMD 可以提供参数给 ENTRYPOINT。\u003C\u002Fp>\n\u003C\u002Fli>\n\u003Cli>\n\u003Cp>\u003Cstrong>ENTRYPOINT\u003C\u002Fstrong>\u003C\u002Fp>\n\u003Cp>【语法 1】ENTRYPOINT [“EXECUTABLE”,“PARAM1”,“PARAM2”, …]\u003C\u002Fp>\n\u003Cp>【解析】在容器启动过程中，即在执行 docker run 时，会调用执行&quot;EXECUTABLE&quot;指定的应用程序，并使用后面第二、三等参数作为应用程序的运行参数。\u003C\u002Fp>\n\u003Cp>【语法 2】ENTRYPOINT command param1 param2, …\u003C\u002Fp>\n\u003Cp>【解析】这里的 command 就是 shell 命令。在容器启动过程中，即在执行 docker run 时，会运行指定的 shell 命令。\u003C\u002Fp>\n\u003C\u002Fli>\n\u003Cli>\n\u003Cp>\u003Cstrong>EXPOSE\u003C\u002Fstrong>\u003C\u002Fp>\n\u003Cp>【语法】EXPOSE &lt;port&gt; [&lt;port&gt;…]\u003C\u002Fp>\n\u003Cp>【解析】指定容器准备对外暴露的端口号，但该端口号并不会真正的对外暴露。若要真正暴露，则需要在执行 docker run 命令时使用-p(小 p)来指定说要真正暴露出的端口号。\u003C\u002Fp>\n\u003C\u002Fli>\n\u003Cli>\n\u003Cp>\u003Cstrong>ARG\u003C\u002Fstrong>\u003C\u002Fp>\n\u003Cp>【语法】ARG &lt; varname &gt;[=&lt;default value&gt;]\u003C\u002Fp>\n\u003Cp>【解析】定义一个变量，该变量将会使用于镜像构建运行时。若要定义多个变量，则需要定义多个 ARG 指令。\u003C\u002Fp>\n\u003C\u002Fli>\n\u003Cli>\n\u003Cp>\u003Cstrong>ADD\u003C\u002Fstrong>\u003C\u002Fp>\n\u003Cp>【语法 1】ADD &lt;src&gt; &lt;dest&gt;\u003C\u002Fp>\n\u003Cp>【语法 2】ADD [“&lt;src&gt;”, “&lt;dest&gt;”] # 路径中存在空格时使用双引号引起来\u003C\u002Fp>\n\u003Cp>【解析】该指令将复制当前宿主机中指定文件 src 到容器中的指定目录 dest 中。src 可以是宿主机中的绝对路径，也可以时相对路径。但相对路径是相对于 docker build 命令所指定的路径的。src 指定的文件可以是一个压缩文件，压缩文件复制到容器后会自动解压为目录；src 也可以是一个 URL，此时的 ADD 指令相当于 wget 命令；src 最好不要是目录，其会将该目录中所有内容复制到容器的指定目录中。dest 是一个绝对路径，其最后面的路径必须要加上斜杠，否则系统会将最后的目录名称当做是文件名的。\u003C\u002Fp>\n\u003C\u002Fli>\n\u003Cli>\n\u003Cp>\u003Cstrong>COPY\u003C\u002Fstrong>\u003C\u002Fp>\n\u003Cp>【说明】功能与 ADD 指令相同，只不过 src 不能是 URL。若 src 为压缩文件，复制到容器后不会自动解压。\u003C\u002Fp>\n\u003C\u002Fli>\n\u003Cli>\n\u003Cp>\u003Cstrong>ONBUILD\u003C\u002Fstrong>\u003C\u002Fp>\n\u003Cp>【语法】ONBUILD [INSTRUCTION]\u003C\u002Fp>\n\u003Cp>【解析】该指令用于指定当前镜像的子镜像进行构建时要执行的指令。\u003C\u002Fp>\n\u003C\u002Fli>\n\u003Cli>\n\u003Cp>\u003Cstrong>VOLUME\u003C\u002Fstrong>\u003C\u002Fp>\n\u003Cp>【语法】VOLUME [“dir1”, “dir2”, …]\u003C\u002Fp>\n\u003Cp>【解析】在容器创建可以挂载的数据卷。\u003C\u002Fp>\n\u003C\u002Fli>\n\u003C\u002Fol>\n\u003Ch2 id=\"h2-2--hello-world-\">构建自己的 hello-world 镜像\u003C\u002Fh2>\n\u003Ch3 id=\"h3-3-scratch-\">scratch 镜像\u003C\u002Fh3>\n\u003Cp>在构建自己的镜像之前，首先要了解一个特殊的镜像 scratch。\u003C\u002Fp>\n\u003Cp>scratch 镜像是一个空镜像，是所有镜像的 Base Image（相当于面向对象编程中的 Object 类）。scratch 镜像只能在 Dockerfile 中被继承，不能通过 pull 命令拉取，不能 run，也没有 tag。并且它也不会生成镜像中的文件系统层。在 Docker 中，scratch 是一个保留字，用户不能作为自己的镜像名称使用。\u003C\u002Fp>\n\u003Ch3 id=\"h3-4--helloc\">创建和编译 hello.c\u003C\u002Fh3>\n\u003Cp>在宿主机任意目录创建一个名称为 hello.c 的文件。这里在\u002Froot 下 mkdir 一个目录 hello_world，然后将 hello.c 文件创建在这里。文件内容如下：\u003C\u002Fp>\n\u003Cdiv class=\"ssr-code-block\" data-lang=\"c\">\u003Cdiv class=\"ssr-code-head\">\u003Cspan class=\"ssr-code-lang\">c\u003C\u002Fspan>\u003Cdiv class=\"ssr-code-actions\">\u003Cbutton class=\"ssr-code-fullscreen ssr-code-iconbtn\" type=\"button\" aria-label=\"全屏查看代码\" title=\"全屏\">\u003Csvg viewBox=\"0 0 24 24\" width=\"17\" height=\"17\" aria-hidden=\"true\">\u003Cpath fill=\"currentColor\" d=\"M5 5h6v2H7v4H5V5zm14 0v6h-2V7h-4V5h6zM5 19v-6h2v4h4v2H5zm14 0h-6v-2h4v-4h2v6z\"\u002F>\u003C\u002Fsvg>\u003C\u002Fbutton>\u003Cbutton class=\"ssr-code-copy ssr-code-iconbtn\" type=\"button\" aria-label=\"复制代码\" title=\"复制\">\u003Csvg class=\"ssr-code-copy-icon ssr-code-copy-icon--default\" viewBox=\"0 0 24 24\" width=\"15\" height=\"15\" aria-hidden=\"true\">\u003Cpath fill=\"currentColor\" d=\"M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z\"\u002F>\u003C\u002Fsvg>\u003Csvg class=\"ssr-code-copy-icon ssr-code-copy-icon--success\" viewBox=\"0 0 24 24\" width=\"15\" height=\"15\" aria-hidden=\"true\">\u003Cpath fill=\"currentColor\" d=\"M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z\"\u002F>\u003C\u002Fsvg>\u003Csvg class=\"ssr-code-copy-icon ssr-code-copy-icon--error\" viewBox=\"0 0 24 24\" width=\"15\" height=\"15\" aria-hidden=\"true\">\u003Cpath fill=\"currentColor\" d=\"M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z\"\u002F>\u003C\u002Fsvg>\u003C\u002Fbutton>\u003C\u002Fdiv>\u003C\u002Fdiv>\u003Cdiv class=\"ssr-code-body\">\u003Cdiv class=\"ssr-code-pane\">\u003Cdiv class=\"ssr-code-gutter\" aria-hidden=\"true\">\u003Cspan class=\"ssr-code-num\">1\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">2\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">3\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">4\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">5\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">6\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">7\u003C\u002Fspan>\u003C\u002Fdiv>\u003Cpre class=\"ssr-code-pre\">\u003Ccode class=\"hljs language-c\">\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#F97583\">#include\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> \u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">&lt;stdio.h&gt;\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">​\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#F97583\">int\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> \u003C\u002Fspan>\u003Cspan style=\"color:#B392F0\">main\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">()\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#E1E4E8\">{\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#E1E4E8\">    \u003C\u002Fspan>\u003Cspan style=\"color:#B392F0\">printf\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">(\u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">&quot;hello docker world!\u003C\u002Fspan>\u003Cspan style=\"color:#79B8FF\">\\n\u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">&quot;\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">);\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#E1E4E8\">    \u003C\u002Fspan>\u003Cspan style=\"color:#F97583\">return\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> \u003C\u002Fspan>\u003Cspan style=\"color:#79B8FF\">0\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">;\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#E1E4E8\">}\u003C\u002Fspan>\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>\u003C\u002Fdiv>\u003C\u002Fdiv>\u003C\u002Fdiv>\n\u003Cp>使用 gcc 编译 hello.c 文件。\u003C\u002Fp>\n\u003Cp>\u003Cimg class=\"article-img article-img-zoomable\" src=\"https:\u002F\u002Fliubing-1314895948.cos.ap-chengdu.myqcloud.com\u002Fimg\u002F202309091955723.png\" alt=\"image-20230909195522683\" loading=\"lazy\" decoding=\"async\" style=\"width: 100%; height: auto; max-width: 100%; display: block;\" srcset=\"https:\u002F\u002Fliubing-1314895948.cos.ap-chengdu.myqcloud.com\u002Fimg\u002F202309091955723.png?imageMogr2\u002Fthumbnail\u002F400x\u002Fformat\u002Fwebp\u002Fquality\u002F85 400w, https:\u002F\u002Fliubing-1314895948.cos.ap-chengdu.myqcloud.com\u002Fimg\u002F202309091955723.png?imageMogr2\u002Fthumbnail\u002F800x\u002Fformat\u002Fwebp\u002Fquality\u002F85 800w, https:\u002F\u002Fliubing-1314895948.cos.ap-chengdu.myqcloud.com\u002Fimg\u002F202309091955723.png?imageMogr2\u002Fthumbnail\u002F1200x\u002Fformat\u002Fwebp\u002Fquality\u002F85 1200w, https:\u002F\u002Fliubing-1314895948.cos.ap-chengdu.myqcloud.com\u002Fimg\u002F202309091955723.png?imageMogr2\u002Fthumbnail\u002F1920x\u002Fformat\u002Fwebp\u002Fquality\u002F85 1920w\" sizes=\"(max-width: 576px) 100vw, (max-width: 992px) 90vw, 720px\">\u003C\u002Fp>\n\u003Ch3 id=\"h3-5--dockerfile-\">编写 Dockerfile 文件\u003C\u002Fh3>\n\u003Cp>在 hello_world 目录中新建一个 Dockerfile 文件，切记文件名必须是 Dockerfile。内容如下：\u003C\u002Fp>\n\u003Cdiv class=\"ssr-code-block\" data-lang=\"dockerfile\">\u003Cdiv class=\"ssr-code-head\">\u003Cspan class=\"ssr-code-lang\">dockerfile\u003C\u002Fspan>\u003Cdiv class=\"ssr-code-actions\">\u003Cbutton class=\"ssr-code-fullscreen ssr-code-iconbtn\" type=\"button\" aria-label=\"全屏查看代码\" title=\"全屏\">\u003Csvg viewBox=\"0 0 24 24\" width=\"17\" height=\"17\" aria-hidden=\"true\">\u003Cpath fill=\"currentColor\" d=\"M5 5h6v2H7v4H5V5zm14 0v6h-2V7h-4V5h6zM5 19v-6h2v4h4v2H5zm14 0h-6v-2h4v-4h2v6z\"\u002F>\u003C\u002Fsvg>\u003C\u002Fbutton>\u003Cbutton class=\"ssr-code-copy ssr-code-iconbtn\" type=\"button\" aria-label=\"复制代码\" title=\"复制\">\u003Csvg class=\"ssr-code-copy-icon ssr-code-copy-icon--default\" viewBox=\"0 0 24 24\" width=\"15\" height=\"15\" aria-hidden=\"true\">\u003Cpath fill=\"currentColor\" d=\"M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z\"\u002F>\u003C\u002Fsvg>\u003Csvg class=\"ssr-code-copy-icon ssr-code-copy-icon--success\" viewBox=\"0 0 24 24\" width=\"15\" height=\"15\" aria-hidden=\"true\">\u003Cpath fill=\"currentColor\" d=\"M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z\"\u002F>\u003C\u002Fsvg>\u003Csvg class=\"ssr-code-copy-icon ssr-code-copy-icon--error\" viewBox=\"0 0 24 24\" width=\"15\" height=\"15\" aria-hidden=\"true\">\u003Cpath fill=\"currentColor\" d=\"M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z\"\u002F>\u003C\u002Fsvg>\u003C\u002Fbutton>\u003C\u002Fdiv>\u003C\u002Fdiv>\u003Cdiv class=\"ssr-code-body\">\u003Cdiv class=\"ssr-code-pane\">\u003Cdiv class=\"ssr-code-gutter\" aria-hidden=\"true\">\u003Cspan class=\"ssr-code-num\">1\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">2\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">3\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">4\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">5\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">6\u003C\u002Fspan>\u003C\u002Fdiv>\u003Cpre class=\"ssr-code-pre\">\u003Ccode class=\"hljs language-dockerfile\">\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#6A737D\"># 表示基础镜像是scratch，也就是一个空白的镜像。\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#F97583\">FROM\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> scratch\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#6A737D\"># 将当前目录下的hello文件添加到镜像的根目录（\u002F）下。\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#F97583\">ADD\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> hello \u002F\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#6A737D\"># 设置了容器的默认命令，也就是当运行一个基于这个镜像的容器时，如果不指定运行的命令，那么默认会运行\u002Fhello这个命令。\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#F97583\">CMD\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> [\u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">&quot;\u002Fhello&quot;\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">]\u003C\u002Fspan>\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>\u003C\u002Fdiv>\u003C\u002Fdiv>\u003C\u002Fdiv>\n\u003Ch3 id=\"h3-6-\">构建镜像\u003C\u002Fh3>\n\u003Cp>\u003Cimg class=\"article-img article-img-zoomable\" src=\"https:\u002F\u002Fliubing-1314895948.cos.ap-chengdu.myqcloud.com\u002Fimg\u002F202309092007938.png\" alt=\"\" loading=\"lazy\" decoding=\"async\" style=\"width: 100%; height: auto; max-width: 100%; display: block;\" srcset=\"https:\u002F\u002Fliubing-1314895948.cos.ap-chengdu.myqcloud.com\u002Fimg\u002F202309092007938.png?imageMogr2\u002Fthumbnail\u002F400x\u002Fformat\u002Fwebp\u002Fquality\u002F85 400w, https:\u002F\u002Fliubing-1314895948.cos.ap-chengdu.myqcloud.com\u002Fimg\u002F202309092007938.png?imageMogr2\u002Fthumbnail\u002F800x\u002Fformat\u002Fwebp\u002Fquality\u002F85 800w, https:\u002F\u002Fliubing-1314895948.cos.ap-chengdu.myqcloud.com\u002Fimg\u002F202309092007938.png?imageMogr2\u002Fthumbnail\u002F1200x\u002Fformat\u002Fwebp\u002Fquality\u002F85 1200w, https:\u002F\u002Fliubing-1314895948.cos.ap-chengdu.myqcloud.com\u002Fimg\u002F202309092007938.png?imageMogr2\u002Fthumbnail\u002F1920x\u002Fformat\u002Fwebp\u002Fquality\u002F85 1920w\" sizes=\"(max-width: 576px) 100vw, (max-width: 992px) 90vw, 720px\">\u003C\u002Fp>\n\u003Cul>\n\u003Cli>\n\u003Cp>-t 用于指定要生成的镜像的&lt;repository&gt;与&lt;tag&gt;。若省略 tag，则默认为 latest。\u003C\u002Fp>\n\u003C\u002Fli>\n\u003Cli>\n\u003Cp>最后的点(.)是一个\u003Ccode>宿主机的 URL 路径\u003C\u002Fcode>，构建镜像时会\u003Ccode>从该路径中查找 Dockerfile 文件\u003C\u002Fcode>。同时，在 Dockerfile 中 ADD、COPY 指令中有使用的是相对路径，那个相对路径就相对的是这个路径。不过需要注意，即使 ADD、COPY 指令中使用绝对路径来指定源文件，该源文件所在路径也必须要在这个 URL 指定目录或子目录内，否则将无法找到该文件。\u003C\u002Fp>\n\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Ch3 id=\"h3-7-\">运行新镜像\u003C\u002Fh3>\n\u003Cp>\u003Cimg class=\"article-img article-img-zoomable\" src=\"https:\u002F\u002Fliubing-1314895948.cos.ap-chengdu.myqcloud.com\u002Fimg\u002F202309092016226.png\" alt=\"image-20230909201612177\" loading=\"lazy\" decoding=\"async\" style=\"width: 100%; height: auto; max-width: 100%; display: block;\" srcset=\"https:\u002F\u002Fliubing-1314895948.cos.ap-chengdu.myqcloud.com\u002Fimg\u002F202309092016226.png?imageMogr2\u002Fthumbnail\u002F400x\u002Fformat\u002Fwebp\u002Fquality\u002F85 400w, https:\u002F\u002Fliubing-1314895948.cos.ap-chengdu.myqcloud.com\u002Fimg\u002F202309092016226.png?imageMogr2\u002Fthumbnail\u002F800x\u002Fformat\u002Fwebp\u002Fquality\u002F85 800w, https:\u002F\u002Fliubing-1314895948.cos.ap-chengdu.myqcloud.com\u002Fimg\u002F202309092016226.png?imageMogr2\u002Fthumbnail\u002F1200x\u002Fformat\u002Fwebp\u002Fquality\u002F85 1200w, https:\u002F\u002Fliubing-1314895948.cos.ap-chengdu.myqcloud.com\u002Fimg\u002F202309092016226.png?imageMogr2\u002Fthumbnail\u002F1920x\u002Fformat\u002Fwebp\u002Fquality\u002F85 1920w\" sizes=\"(max-width: 576px) 100vw, (max-width: 992px) 90vw, 720px\">\u003C\u002Fp>\n\u003Ch2 id=\"h2-8--centos-\">构建自己的 centos 镜像\u003C\u002Fh2>\n\u003Cdiv class=\"ssr-code-block\" data-lang=\"dockerfile\">\u003Cdiv class=\"ssr-code-head\">\u003Cspan class=\"ssr-code-lang\">dockerfile\u003C\u002Fspan>\u003Cdiv class=\"ssr-code-actions\">\u003Cbutton class=\"ssr-code-fullscreen ssr-code-iconbtn\" type=\"button\" aria-label=\"全屏查看代码\" title=\"全屏\">\u003Csvg viewBox=\"0 0 24 24\" width=\"17\" height=\"17\" aria-hidden=\"true\">\u003Cpath fill=\"currentColor\" d=\"M5 5h6v2H7v4H5V5zm14 0v6h-2V7h-4V5h6zM5 19v-6h2v4h4v2H5zm14 0h-6v-2h4v-4h2v6z\"\u002F>\u003C\u002Fsvg>\u003C\u002Fbutton>\u003Cbutton class=\"ssr-code-copy ssr-code-iconbtn\" type=\"button\" aria-label=\"复制代码\" title=\"复制\">\u003Csvg class=\"ssr-code-copy-icon ssr-code-copy-icon--default\" viewBox=\"0 0 24 24\" width=\"15\" height=\"15\" aria-hidden=\"true\">\u003Cpath fill=\"currentColor\" d=\"M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z\"\u002F>\u003C\u002Fsvg>\u003Csvg class=\"ssr-code-copy-icon ssr-code-copy-icon--success\" viewBox=\"0 0 24 24\" width=\"15\" height=\"15\" aria-hidden=\"true\">\u003Cpath fill=\"currentColor\" d=\"M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z\"\u002F>\u003C\u002Fsvg>\u003Csvg class=\"ssr-code-copy-icon ssr-code-copy-icon--error\" viewBox=\"0 0 24 24\" width=\"15\" height=\"15\" aria-hidden=\"true\">\u003Cpath fill=\"currentColor\" d=\"M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z\"\u002F>\u003C\u002Fsvg>\u003C\u002Fbutton>\u003C\u002Fdiv>\u003C\u002Fdiv>\u003Cdiv class=\"ssr-code-body\">\u003Cdiv class=\"ssr-code-pane\">\u003Cdiv class=\"ssr-code-gutter\" aria-hidden=\"true\">\u003Cspan class=\"ssr-code-num\">1\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">2\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">3\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">4\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">5\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">6\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">7\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">8\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">9\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">10\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">11\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">12\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">13\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">14\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">15\u003C\u002Fspan>\u003C\u002Fdiv>\u003Cpre class=\"ssr-code-pre\">\u003Ccode class=\"hljs language-dockerfile\">\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#6A737D\"># 新建一个Dockerfile文件\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#E1E4E8\">vim Dockerfile\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#E1E4E8\">在文件中写入如下内容\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#F97583\">FROM\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> centos:7\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#F97583\">MAINTAINER\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> bing 1234@qq.com\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#F97583\">LABEL\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> auth=\u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">&quot;bing&quot;\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> version=\u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">&quot;1.0&quot;\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> description=\u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">&quot;This is a Centos image I wrote myself&quot;\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#F97583\">ENV\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> WORKPATH \u002Fusr\u002Flocal\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#F97583\">WORKDIR\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> $WORKPATH\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#F97583\">RUN\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> yum -y install vim net-tools wget\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#F97583\">CMD\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> \u002Fbin\u002Fbash\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">​\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#6A737D\"># 写完之后构建镜像\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#E1E4E8\">docker build -t my-centos:1.0 .\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#6A737D\"># 运行新镜像\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#E1E4E8\">docker run --name my-centos -it my-centos:1.0\u003C\u002Fspan>\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>\u003C\u002Fdiv>\u003C\u002Fdiv>\u003C\u002Fdiv>\n\u003Cp>运行结果如下：\u003C\u002Fp>\n\u003Cp>\u003Cimg class=\"article-img article-img-zoomable\" src=\"https:\u002F\u002Fliubing-1314895948.cos.ap-chengdu.myqcloud.com\u002Fimg\u002F202309121036578.png\" alt=\"image-20230912103614491\" loading=\"lazy\" decoding=\"async\" style=\"width: 100%; height: auto; max-width: 100%; display: block;\" srcset=\"https:\u002F\u002Fliubing-1314895948.cos.ap-chengdu.myqcloud.com\u002Fimg\u002F202309121036578.png?imageMogr2\u002Fthumbnail\u002F400x\u002Fformat\u002Fwebp\u002Fquality\u002F85 400w, https:\u002F\u002Fliubing-1314895948.cos.ap-chengdu.myqcloud.com\u002Fimg\u002F202309121036578.png?imageMogr2\u002Fthumbnail\u002F800x\u002Fformat\u002Fwebp\u002Fquality\u002F85 800w, https:\u002F\u002Fliubing-1314895948.cos.ap-chengdu.myqcloud.com\u002Fimg\u002F202309121036578.png?imageMogr2\u002Fthumbnail\u002F1200x\u002Fformat\u002Fwebp\u002Fquality\u002F85 1200w, https:\u002F\u002Fliubing-1314895948.cos.ap-chengdu.myqcloud.com\u002Fimg\u002F202309121036578.png?imageMogr2\u002Fthumbnail\u002F1920x\u002Fformat\u002Fwebp\u002Fquality\u002F85 1920w\" sizes=\"(max-width: 576px) 100vw, (max-width: 992px) 90vw, 720px\">\u003C\u002Fp>\n\u003Cp>通过这两个例子，大部分的 Dockerfile 指令都使用过了。\u003C\u002Fp>\n\u003Ch2 id=\"h2-9-\">应用的构建和发布\u003C\u002Fh2>\n\u003Cp>下面就用 go 语言写一个简单的 web 服务应用，然后将该应用构建成镜像并运行。\u003C\u002Fp>\n\u003Ch3 id=\"h3-10-\">准备应用\u003C\u002Fh3>\n\u003Cp>创建一个 go 项目，创建一个 main.go 文件，写入如下内容：\u003C\u002Fp>\n\u003Cdiv class=\"ssr-code-block\" data-lang=\"go\">\u003Cdiv class=\"ssr-code-head\">\u003Cspan class=\"ssr-code-lang\">go\u003C\u002Fspan>\u003Cdiv class=\"ssr-code-actions\">\u003Cbutton class=\"ssr-code-fullscreen ssr-code-iconbtn\" type=\"button\" aria-label=\"全屏查看代码\" title=\"全屏\">\u003Csvg viewBox=\"0 0 24 24\" width=\"17\" height=\"17\" aria-hidden=\"true\">\u003Cpath fill=\"currentColor\" d=\"M5 5h6v2H7v4H5V5zm14 0v6h-2V7h-4V5h6zM5 19v-6h2v4h4v2H5zm14 0h-6v-2h4v-4h2v6z\"\u002F>\u003C\u002Fsvg>\u003C\u002Fbutton>\u003Cbutton class=\"ssr-code-copy ssr-code-iconbtn\" type=\"button\" aria-label=\"复制代码\" title=\"复制\">\u003Csvg class=\"ssr-code-copy-icon ssr-code-copy-icon--default\" viewBox=\"0 0 24 24\" width=\"15\" height=\"15\" aria-hidden=\"true\">\u003Cpath fill=\"currentColor\" d=\"M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z\"\u002F>\u003C\u002Fsvg>\u003Csvg class=\"ssr-code-copy-icon ssr-code-copy-icon--success\" viewBox=\"0 0 24 24\" width=\"15\" height=\"15\" aria-hidden=\"true\">\u003Cpath fill=\"currentColor\" d=\"M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z\"\u002F>\u003C\u002Fsvg>\u003Csvg class=\"ssr-code-copy-icon ssr-code-copy-icon--error\" viewBox=\"0 0 24 24\" width=\"15\" height=\"15\" aria-hidden=\"true\">\u003Cpath fill=\"currentColor\" d=\"M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z\"\u002F>\u003C\u002Fsvg>\u003C\u002Fbutton>\u003C\u002Fdiv>\u003C\u002Fdiv>\u003Cdiv class=\"ssr-code-body\">\u003Cdiv class=\"ssr-code-pane\">\u003Cdiv class=\"ssr-code-gutter\" aria-hidden=\"true\">\u003Cspan class=\"ssr-code-num\">1\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">2\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">3\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">4\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">5\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">6\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">7\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">8\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">9\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">10\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">11\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">12\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">13\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">14\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">15\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">16\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">17\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">18\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">19\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">20\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">21\u003C\u002Fspan>\u003C\u002Fdiv>\u003Cpre class=\"ssr-code-pre\">\u003Ccode class=\"hljs language-go\">\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#F97583\">package\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> \u003C\u002Fspan>\u003Cspan style=\"color:#B392F0\">main\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">​\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#F97583\">import\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> (\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#E1E4E8\">    \u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">&quot;\u003C\u002Fspan>\u003Cspan style=\"color:#B392F0\">github.com\u002Fgin-gonic\u002Fgin\u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">&quot;\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#E1E4E8\">    \u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">&quot;\u003C\u002Fspan>\u003Cspan style=\"color:#B392F0\">log\u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">&quot;\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#E1E4E8\">    \u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">&quot;\u003C\u002Fspan>\u003Cspan style=\"color:#B392F0\">net\u002Fhttp\u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">&quot;\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#E1E4E8\">)\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">​\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#F97583\">func\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> \u003C\u002Fspan>\u003Cspan style=\"color:#B392F0\">main\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">() {\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#E1E4E8\">    r \u003C\u002Fspan>\u003Cspan style=\"color:#F97583\">:=\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> gin.\u003C\u002Fspan>\u003Cspan style=\"color:#B392F0\">Default\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">()\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#E1E4E8\">    r.\u003C\u002Fspan>\u003Cspan style=\"color:#B392F0\">GET\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">(\u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">&quot;\u002Fimage_demo&quot;\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">, \u003C\u002Fspan>\u003Cspan style=\"color:#F97583\">func\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">(\u003C\u002Fspan>\u003Cspan style=\"color:#FFAB70\">c\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> \u003C\u002Fspan>\u003Cspan style=\"color:#F97583\">*\u003C\u002Fspan>\u003Cspan style=\"color:#B392F0\">gin\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">.\u003C\u002Fspan>\u003Cspan style=\"color:#B392F0\">Context\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">) {\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#E1E4E8\">        c.\u003C\u002Fspan>\u003Cspan style=\"color:#B392F0\">JSON\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">(http.StatusOK, \u003C\u002Fspan>\u003Cspan style=\"color:#B392F0\">gin\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">.\u003C\u002Fspan>\u003Cspan style=\"color:#B392F0\">H\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">{\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#E1E4E8\">            \u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">&quot;code&quot;\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">:    \u003C\u002Fspan>\u003Cspan style=\"color:#79B8FF\">200\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">,\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#E1E4E8\">            \u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">&quot;message&quot;\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">: \u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">&quot;This is a go web service&quot;\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">,\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#E1E4E8\">        })\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#E1E4E8\">    })\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#E1E4E8\">    err \u003C\u002Fspan>\u003Cspan style=\"color:#F97583\">:=\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> r.\u003C\u002Fspan>\u003Cspan style=\"color:#B392F0\">Run\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">(\u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">&quot;0.0.0.0:8080&quot;\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">)\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#E1E4E8\">    \u003C\u002Fspan>\u003Cspan style=\"color:#F97583\">if\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> err \u003C\u002Fspan>\u003Cspan style=\"color:#F97583\">!=\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> \u003C\u002Fspan>\u003Cspan style=\"color:#79B8FF\">nil\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> {\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#E1E4E8\">        log.\u003C\u002Fspan>\u003Cspan style=\"color:#B392F0\">Panicln\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">(err)\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#E1E4E8\">    }\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#E1E4E8\">}\u003C\u002Fspan>\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>\u003C\u002Fdiv>\u003C\u002Fdiv>\u003C\u002Fdiv>\n\u003Cp>使用 go build main.go 编译 go 代码，这样就得到了一个 main.exe 的可执行文件。\u003C\u002Fp>\n\u003Ch3 id=\"h3-11-\">镜像的构建\u003C\u002Fh3>\n\u003Cp>首先新建一个 web 目录，用于存放任意一个地方新建一个 image_build 的目录，在该目录下编写 Dockerfile 文件，并把刚刚得到的 main 文件移动到该目录下，并记得赋予 main 文件有 x 的权限（chmod +x main）。Dockerfile 文件的内容如下：\u003C\u002Fp>\n\u003Cdiv class=\"ssr-code-block\" data-lang=\"text\">\u003Cdiv class=\"ssr-code-head\">\u003Cspan class=\"ssr-code-lang\">text\u003C\u002Fspan>\u003Cdiv class=\"ssr-code-actions\">\u003Cbutton class=\"ssr-code-fullscreen ssr-code-iconbtn\" type=\"button\" aria-label=\"全屏查看代码\" title=\"全屏\">\u003Csvg viewBox=\"0 0 24 24\" width=\"17\" height=\"17\" aria-hidden=\"true\">\u003Cpath fill=\"currentColor\" d=\"M5 5h6v2H7v4H5V5zm14 0v6h-2V7h-4V5h6zM5 19v-6h2v4h4v2H5zm14 0h-6v-2h4v-4h2v6z\"\u002F>\u003C\u002Fsvg>\u003C\u002Fbutton>\u003Cbutton class=\"ssr-code-copy ssr-code-iconbtn\" type=\"button\" aria-label=\"复制代码\" title=\"复制\">\u003Csvg class=\"ssr-code-copy-icon ssr-code-copy-icon--default\" viewBox=\"0 0 24 24\" width=\"15\" height=\"15\" aria-hidden=\"true\">\u003Cpath fill=\"currentColor\" d=\"M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z\"\u002F>\u003C\u002Fsvg>\u003Csvg class=\"ssr-code-copy-icon ssr-code-copy-icon--success\" viewBox=\"0 0 24 24\" width=\"15\" height=\"15\" aria-hidden=\"true\">\u003Cpath fill=\"currentColor\" d=\"M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z\"\u002F>\u003C\u002Fsvg>\u003Csvg class=\"ssr-code-copy-icon ssr-code-copy-icon--error\" viewBox=\"0 0 24 24\" width=\"15\" height=\"15\" aria-hidden=\"true\">\u003Cpath fill=\"currentColor\" d=\"M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z\"\u002F>\u003C\u002Fsvg>\u003C\u002Fbutton>\u003C\u002Fdiv>\u003C\u002Fdiv>\u003Cdiv class=\"ssr-code-body\">\u003Cdiv class=\"ssr-code-pane\">\u003Cdiv class=\"ssr-code-gutter\" aria-hidden=\"true\">\u003Cspan class=\"ssr-code-num\">1\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">2\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">3\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">4\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">5\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">6\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">7\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">8\u003C\u002Fspan>\u003C\u002Fdiv>\u003Cpre class=\"ssr-code-pre\">\u003Ccode class=\"hljs language-text\">\u003Cspan class=\"ssr-code-line\"># 使用官方的 Golang 镜像作为基础镜像\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">FROM golang:alpine\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">LABEL auth=&quot;bing&quot; version=&quot;1.0&quot; description=&quot;This is a go web service&quot;\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">WORKDIR \u002Fweb\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">COPY .\u002Fmain \u002Fweb\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">ENTRYPOINT [&quot;\u002Fweb\u002Fmain&quot;]\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\"># 准备要暴露端口，也就是应用的默认端口\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">EXPOSE 8080\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>\u003C\u002Fdiv>\u003C\u002Fdiv>\u003C\u002Fdiv>\n\u003Ch3 id=\"h3-12-\">运行应用\u003C\u002Fh3>\n\u003Cp>\u003Cimg class=\"article-img article-img-zoomable\" src=\"https:\u002F\u002Fliubing-1314895948.cos.ap-chengdu.myqcloud.com\u002Fimg\u002F202309121418009.png\" alt=\"\" loading=\"lazy\" decoding=\"async\" style=\"width: 100%; height: auto; max-width: 100%; display: block;\" srcset=\"https:\u002F\u002Fliubing-1314895948.cos.ap-chengdu.myqcloud.com\u002Fimg\u002F202309121418009.png?imageMogr2\u002Fthumbnail\u002F400x\u002Fformat\u002Fwebp\u002Fquality\u002F85 400w, https:\u002F\u002Fliubing-1314895948.cos.ap-chengdu.myqcloud.com\u002Fimg\u002F202309121418009.png?imageMogr2\u002Fthumbnail\u002F800x\u002Fformat\u002Fwebp\u002Fquality\u002F85 800w, https:\u002F\u002Fliubing-1314895948.cos.ap-chengdu.myqcloud.com\u002Fimg\u002F202309121418009.png?imageMogr2\u002Fthumbnail\u002F1200x\u002Fformat\u002Fwebp\u002Fquality\u002F85 1200w, https:\u002F\u002Fliubing-1314895948.cos.ap-chengdu.myqcloud.com\u002Fimg\u002F202309121418009.png?imageMogr2\u002Fthumbnail\u002F1920x\u002Fformat\u002Fwebp\u002Fquality\u002F85 1920w\" sizes=\"(max-width: 576px) 100vw, (max-width: 992px) 90vw, 720px\">\u003C\u002Fp>\n\u003Cp>访问浏览器的结果如下：\u003C\u002Fp>\n\u003Cp>\u003Cimg class=\"article-img article-img-zoomable\" src=\"https:\u002F\u002Fliubing-1314895948.cos.ap-chengdu.myqcloud.com\u002Fimg\u002F202309121419099.png\" alt=\"\" loading=\"lazy\" decoding=\"async\" style=\"width: 100%; height: auto; max-width: 100%; display: block;\" srcset=\"https:\u002F\u002Fliubing-1314895948.cos.ap-chengdu.myqcloud.com\u002Fimg\u002F202309121419099.png?imageMogr2\u002Fthumbnail\u002F400x\u002Fformat\u002Fwebp\u002Fquality\u002F85 400w, https:\u002F\u002Fliubing-1314895948.cos.ap-chengdu.myqcloud.com\u002Fimg\u002F202309121419099.png?imageMogr2\u002Fthumbnail\u002F800x\u002Fformat\u002Fwebp\u002Fquality\u002F85 800w, https:\u002F\u002Fliubing-1314895948.cos.ap-chengdu.myqcloud.com\u002Fimg\u002F202309121419099.png?imageMogr2\u002Fthumbnail\u002F1200x\u002Fformat\u002Fwebp\u002Fquality\u002F85 1200w, https:\u002F\u002Fliubing-1314895948.cos.ap-chengdu.myqcloud.com\u002Fimg\u002F202309121419099.png?imageMogr2\u002Fthumbnail\u002F1920x\u002Fformat\u002Fwebp\u002Fquality\u002F85 1920w\" sizes=\"(max-width: 576px) 100vw, (max-width: 992px) 90vw, 720px\">\u003C\u002Fp>\n\u003Cp>可以看到，虽然 Dockerfile 中准备要对外映射的端口是 8080，但是我实际运行的时候使用了 8888 端口，没有使用 8080 端口。也就是说 EXPOSE 指令指定的端口只是告诉使用者该应用的默认端口是 8080，仅此而已。\u003C\u002Fp>\n\u003Cblockquote>\n\u003Cp>\u003Ccode>需要注意的地方\u003C\u002Fcode>：\u003C\u002Fp>\n\u003Col>\n\u003Cli>\n\u003Cp>如果是 java 程序，可以不用看，因为 java 代码在编译的时候中间有个 JVM，屏蔽了底层的操作系统。\u003C\u002Fp>\n\u003C\u002Fli>\n\u003Cli>\n\u003Cp>如果是 go 程序，并且写代码的环境还是 ｗ indows 操作系统。那么需要注意这里要使用\u003Ccode>交叉编译\u003C\u002Fcode>的方式来编译 main.go 文件。也就是需要在 windows 操作系统下能够编译出可以在 linux 操作系统下跑的可执行文件。只需要修改 GOOS 这个环境变量即可。\u003C\u002Fp>\n\u003Cp>\u003Cimg class=\"article-img article-img-zoomable\" src=\"https:\u002F\u002Fliubing-1314895948.cos.ap-chengdu.myqcloud.com\u002Fimg\u002F202309121440419.png\" alt=\"image-20230912144012355\" loading=\"lazy\" decoding=\"async\" style=\"width: 100%; height: auto; max-width: 100%; display: block;\" srcset=\"https:\u002F\u002Fliubing-1314895948.cos.ap-chengdu.myqcloud.com\u002Fimg\u002F202309121440419.png?imageMogr2\u002Fthumbnail\u002F400x\u002Fformat\u002Fwebp\u002Fquality\u002F85 400w, https:\u002F\u002Fliubing-1314895948.cos.ap-chengdu.myqcloud.com\u002Fimg\u002F202309121440419.png?imageMogr2\u002Fthumbnail\u002F800x\u002Fformat\u002Fwebp\u002Fquality\u002F85 800w, https:\u002F\u002Fliubing-1314895948.cos.ap-chengdu.myqcloud.com\u002Fimg\u002F202309121440419.png?imageMogr2\u002Fthumbnail\u002F1200x\u002Fformat\u002Fwebp\u002Fquality\u002F85 1200w, https:\u002F\u002Fliubing-1314895948.cos.ap-chengdu.myqcloud.com\u002Fimg\u002F202309121440419.png?imageMogr2\u002Fthumbnail\u002F1920x\u002Fformat\u002Fwebp\u002Fquality\u002F85 1920w\" sizes=\"(max-width: 576px) 100vw, (max-width: 992px) 90vw, 720px\">\u003C\u002Fp>\n\u003C\u002Fli>\n\u003C\u002Fol>\n\u003C\u002Fblockquote>\n\u003Ch2 id=\"h2-13-build-cache\">build cache\u003C\u002Fh2>\n\u003Ch3 id=\"h3-14-\">测试环境搭建\u003C\u002Fh3>\n\u003Cp>以下面的 Dockerfile 文件为例，我简单讲一下镜像的构建过程和对 build cache 的理解。\u003C\u002Fp>\n\u003Cdiv class=\"ssr-code-block\" data-lang=\"dockerfile\">\u003Cdiv class=\"ssr-code-head\">\u003Cspan class=\"ssr-code-lang\">dockerfile\u003C\u002Fspan>\u003Cdiv class=\"ssr-code-actions\">\u003Cbutton class=\"ssr-code-fullscreen ssr-code-iconbtn\" type=\"button\" aria-label=\"全屏查看代码\" title=\"全屏\">\u003Csvg viewBox=\"0 0 24 24\" width=\"17\" height=\"17\" aria-hidden=\"true\">\u003Cpath fill=\"currentColor\" d=\"M5 5h6v2H7v4H5V5zm14 0v6h-2V7h-4V5h6zM5 19v-6h2v4h4v2H5zm14 0h-6v-2h4v-4h2v6z\"\u002F>\u003C\u002Fsvg>\u003C\u002Fbutton>\u003Cbutton class=\"ssr-code-copy ssr-code-iconbtn\" type=\"button\" aria-label=\"复制代码\" title=\"复制\">\u003Csvg class=\"ssr-code-copy-icon ssr-code-copy-icon--default\" viewBox=\"0 0 24 24\" width=\"15\" height=\"15\" aria-hidden=\"true\">\u003Cpath fill=\"currentColor\" d=\"M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z\"\u002F>\u003C\u002Fsvg>\u003Csvg class=\"ssr-code-copy-icon ssr-code-copy-icon--success\" viewBox=\"0 0 24 24\" width=\"15\" height=\"15\" aria-hidden=\"true\">\u003Cpath fill=\"currentColor\" d=\"M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z\"\u002F>\u003C\u002Fsvg>\u003Csvg class=\"ssr-code-copy-icon ssr-code-copy-icon--error\" viewBox=\"0 0 24 24\" width=\"15\" height=\"15\" aria-hidden=\"true\">\u003Cpath fill=\"currentColor\" d=\"M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z\"\u002F>\u003C\u002Fsvg>\u003C\u002Fbutton>\u003C\u002Fdiv>\u003C\u002Fdiv>\u003Cdiv class=\"ssr-code-body\">\u003Cdiv class=\"ssr-code-pane\">\u003Cdiv class=\"ssr-code-gutter\" aria-hidden=\"true\">\u003Cspan class=\"ssr-code-num\">1\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">2\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">3\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">4\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">5\u003C\u002Fspan>\u003C\u002Fdiv>\u003Cpre class=\"ssr-code-pre\">\u003Ccode class=\"hljs language-dockerfile\">\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#F97583\">FROM\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> centos:7\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#F97583\">LABEL\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> auth=\u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">&quot;Tom&quot;\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#F97583\">COPY\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> hello.log \u002Fvar\u002Flog\u002F\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#F97583\">RUN\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> yum -y install vim\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#F97583\">CMD\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> \u002Fbin\u002Fbash\u003C\u002Fspan>\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>\u003C\u002Fdiv>\u003C\u002Fdiv>\u003C\u002Fdiv>\n\u003Cp>Dockerfile 文件写完之后，使用 docker build -t test:1.0 构建 test:1.0 镜像。在第一次构建镜像的过程中：\u003C\u002Fp>\n\u003Col>\n\u003Cli>第一条 FROM 指令是 Dockerfile 中唯一不可缺少的指令，它为最终构建出的镜像设定了一个基础镜像。该语句并不会产生新的镜像层，它是使用指定的镜像（centos:7）作为基础镜像层的。由于每一个镜像由两部分组成，一个是该镜像的文件系统；另一个是记录该文件系统元数据的一个 json 文件，简称 json 镜像文件。docker daemon 根据进行镜像 ID 找到 centos:7 镜像，然后提取出对应的 json 文件，以备下一条指令镜像层构建时使用。\u003C\u002Fli>\n\u003Cli>LABEL 指令仅修改上一步中提取出的镜像 json 文件内容，在 json 文件中添加 LABEL auth=“Tom”，无需更新镜像文件系统，但也会生成一个新的镜像层。这是因为新镜像层的 ID 就是把文件系统和 json 文件这两个部分的内容序列化为一个 json 串，docker daemon 对这个 json 串进行哈希运算，得到一个 SHA256 哈希值，这个哈希值就是镜像 ID。由于 json 文件发生了变化，导致 SHA256 哈希值的改变，镜像 ID 也就发生了变化，所以产生了新的镜像层。\u003C\u002Fli>\n\u003Cli>COPY 指令会将宿主机中的指定文件复制到容器中的指定目录，所以会改变该镜像层文件系统大小，并生成新的镜像层文件系统内容。所以 json 文件中的镜像 ID 也就发生了变化，产生了新的镜像层。\u003C\u002Fli>\n\u003Cli>RUN 指令本身并不会改变镜像层文件系统大小，但由于其 RUN 的命令是 yum install，而该命令运行的结果是下载并安装一个工具，所以导致 RUN 命令最终也改变了镜像层文件系统大小，所以也就生成了新的镜像层文件系统内容。所以 json 文件中的镜像 ID 也就发生了变化，产生了新的镜像层。\u003C\u002Fli>\n\u003Cli>对于 CMD 或 ENTRYPOINT 指令，其是不会改变镜像层文件系统大小的，因为其不会在 docker build 过程中执行。所以该条指令没有改变镜像层文件系统大小。但对于 CMD 或 ENTRYPOINT 指令，由于其是将来容器启动后要执行的命令，所以会将该条指令写入到 json 文件中，会引发 json 文件的变化。所以 json 文件中的镜像 ID 也就发生了变化，产生了新的镜像层。\u003C\u002Fli>\n\u003C\u002Fol>\n\u003Ch3 id=\"h3-15--dockerfile-\">修改 Dockerfile 文件\u003C\u002Fh3>\n\u003Cdiv class=\"ssr-code-block\" data-lang=\"dockerfile\">\u003Cdiv class=\"ssr-code-head\">\u003Cspan class=\"ssr-code-lang\">dockerfile\u003C\u002Fspan>\u003Cdiv class=\"ssr-code-actions\">\u003Cbutton class=\"ssr-code-fullscreen ssr-code-iconbtn\" type=\"button\" aria-label=\"全屏查看代码\" title=\"全屏\">\u003Csvg viewBox=\"0 0 24 24\" width=\"17\" height=\"17\" aria-hidden=\"true\">\u003Cpath fill=\"currentColor\" d=\"M5 5h6v2H7v4H5V5zm14 0v6h-2V7h-4V5h6zM5 19v-6h2v4h4v2H5zm14 0h-6v-2h4v-4h2v6z\"\u002F>\u003C\u002Fsvg>\u003C\u002Fbutton>\u003Cbutton class=\"ssr-code-copy ssr-code-iconbtn\" type=\"button\" aria-label=\"复制代码\" title=\"复制\">\u003Csvg class=\"ssr-code-copy-icon ssr-code-copy-icon--default\" viewBox=\"0 0 24 24\" width=\"15\" height=\"15\" aria-hidden=\"true\">\u003Cpath fill=\"currentColor\" d=\"M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z\"\u002F>\u003C\u002Fsvg>\u003Csvg class=\"ssr-code-copy-icon ssr-code-copy-icon--success\" viewBox=\"0 0 24 24\" width=\"15\" height=\"15\" aria-hidden=\"true\">\u003Cpath fill=\"currentColor\" d=\"M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z\"\u002F>\u003C\u002Fsvg>\u003Csvg class=\"ssr-code-copy-icon ssr-code-copy-icon--error\" viewBox=\"0 0 24 24\" width=\"15\" height=\"15\" aria-hidden=\"true\">\u003Cpath fill=\"currentColor\" d=\"M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z\"\u002F>\u003C\u002Fsvg>\u003C\u002Fbutton>\u003C\u002Fdiv>\u003C\u002Fdiv>\u003Cdiv class=\"ssr-code-body\">\u003Cdiv class=\"ssr-code-pane\">\u003Cdiv class=\"ssr-code-gutter\" aria-hidden=\"true\">\u003Cspan class=\"ssr-code-num\">1\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">2\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">3\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">4\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">5\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">6\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">7\u003C\u002Fspan>\u003C\u002Fdiv>\u003Cpre class=\"ssr-code-pre\">\u003Ccode class=\"hljs language-dockerfile\">\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#F97583\">FROM\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> centos:7\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#F97583\">LABEL\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> auth=\u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">&quot;Tom&quot;\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#F97583\">COPY\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> hello.log \u002Fvar\u002Flog\u002F\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#F97583\">RUN\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> yum -y install vim\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#F97583\">CMD\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> \u002Fbin\u002Fbash\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#6A737D\"># 就是在最后添加一条指令\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#F97583\">EXPOSE\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> 9000\u003C\u002Fspan>\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>\u003C\u002Fdiv>\u003C\u002Fdiv>\u003C\u002Fdiv>\n\u003Cp>此时再构建新的镜像 test:2.0，会发现没有下载安装 vim 的过程了，并且发现了很多的 Using cache。说明这是使用了 build cache。然后使用 docker history test:1.0 和 docker history test:2.0 这两条命令查看它们每层的镜像 ID，会发现 test1.0 和 test:2.0 的前五个镜像层的 ID 一模一样，这也说明了 test:2.0 的镜像在构建过程中复用了 test:1.0 的镜像层。\u003C\u002Fp>\n\u003Ch3 id=\"h3-16-build-cache-\">build cache 机制\u003C\u002Fh3>\n\u003Cp>Docker Daemnon 通过 Dockerfile 构建镜像时，当发现即将新构建出的镜像(层)与本地已存在的某镜像(层)重复时，默认会复用已存在镜像(层)而不是重新构建新的镜像(层)，这种机制称为 docker build cache 机制。该机制不仅加快了镜像的构建过程，同时也大量节省了 Docker 宿主机的空间。\u003C\u002Fp>\n\u003Cp>Docker 构建缓存并不是存储在内存中，而是存储在 Docker 的本地存储中。这个本地存储通常位于 Docker 守护进程的数据目录下，例如在 Linux 系统上，这个目录通常是 \u002Fvar\u002Flib\u002Fdocker。所以，无论是关闭 Docker 引擎，还是重启 Docker 宿主机，只要该镜像(层)存在于本地，那么就会复用。\u003C\u002Fp>\n\u003Ch3 id=\"h3-17-build-cache-\">build cache 失效\u003C\u002Fh3>\n\u003Col>\n\u003Cli>\n\u003Cp>Dockerfile 文件发生变化\u003C\u002Fp>\n\u003Cp>当 Dockerfile 文件中某个指令内容发生变化，那么从发生变化的这个指令层开始的所有镜像层 cache 全部失效。即从该指令行开始的镜像层将构建出新的镜像层，而不再使用 build cache，即使后面的指令并未发生变化。因为镜像关系本质上是一种树状关系，只要其上层节点变了，那么该发生变化节点的所有下层节点也就全部变化了。\u003C\u002Fp>\n\u003C\u002Fli>\n\u003Cli>\n\u003Cp>ADD 或 COPY 指令内容变化\u003C\u002Fp>\n\u003Cp>Dockerfile 文件内容没有变化，但 ADD 或 COPY 指令所复制的文件内容发生了变化，同样会使从该指令镜像层开始的后面所有镜像层的 build cache 失效。\u003C\u002Fp>\n\u003C\u002Fli>\n\u003Cli>\n\u003Cp>RUN 指令外部依赖变化\u003C\u002Fp>\n\u003Cp>与 ADD\u002FCOPY 指令相似。Dockerfile 文件内容没有变化，但 RUN 命令的外部依赖发生了变化，例如本例中要安装的 vim 软件源发生了变更(版本变化、下载地址变化等)，那么从发生变化的这个指令层开始的所有镜像层 cache 全部失效。\u003C\u002Fp>\n\u003C\u002Fli>\n\u003Cli>\n\u003Cp>指定不使用 build cache\u003C\u002Fp>\n\u003Cp>有些时候为了确保在镜像构建过程中使用到新的数据，在镜像构建 docker build 时，通过添加 --no-cache 选项指定不使用 build cache。\u003C\u002Fp>\n\u003C\u002Fli>\n\u003C\u002Fol>\n","Dockerfile 文件 Dockerfile 是用于构建 Docker 镜像的脚本文件，由一系列指令构成。通过 docker build 命令构建镜像时，Dockerfile 中的指令会由上到下依次执行，每条指令都将会构建出一个镜像。这就是镜像的分层。因此，指令越多，层次就越多，创建的镜像就越多，效率就越低。所以在","https:\u002F\u002Fliubing-1314895948.cos.ap-chengdu.myqcloud.com\u002Fimg\u002F202309091955723.png"]