乔克视界 乔克视界
首页
  • 运维
  • 开发
  • 监控
  • 安全
  • 随笔
  • Docker
  • Golang
  • Python
  • AIOps
  • DevOps
  • 心情杂货
  • 读书笔记
  • 面试
  • 实用技巧
  • 博客搭建
友链
关于
收藏
  • 分类
  • 标签
  • 归档

乔克

云原生爱好者
首页
  • 运维
  • 开发
  • 监控
  • 安全
  • 随笔
  • Docker
  • Golang
  • Python
  • AIOps
  • DevOps
  • 心情杂货
  • 读书笔记
  • 面试
  • 实用技巧
  • 博客搭建
友链
关于
收藏
  • 分类
  • 标签
  • 归档
  • Docker

    • Docker简介
    • Docker的架构
    • Docker的安装
    • Docker基础用法
    • Docker镜像和容器的基本操作
    • Docker的网络模式
    • Docker存储卷
    • Dockerfile 介绍
      • 一、简介
      • 二、工作逻辑
      • 三、指令介绍
        • 3.1 FROM
        • 3.2 MAINTANIER
        • 3.3 LABEL
        • 3.4 COPY
        • 3.5 ADD
        • 3.6 WORKDIR
        • 3.7 VOLUME
        • 3.8 EXPOSE
        • 3.9 ENV
        • 3.10 RUN
        • 3.11 CMD
        • 3.12 ENTRYPOINT
        • 3.13 USER
        • 3.14 HEALTHCHECK
        • 3.15 SHELL
        • 3.16 ARG
        • 3.17 ONBUILD
    • 多阶段构建
    • 镜像加速
    • Docker的NS和CGroups
    • Docker用法整理
    • Docker和Containerd的区别
    • 镜像安全
  • Golang

  • AIOps

  • Python

  • DevOps

  • 专栏
  • Docker
乔克
2025-07-19
目录

Dockerfile 介绍

# 一、简介

Dockerfile 是一个文本文件,里面包含一条条指令,每一条指令就是一层镜像。

一般情况下,Dockerfile 分为 4 个部分:

  • 基础镜像
  • 维护者信息
  • 镜像操作指令
  • 容器启动时执行命令

例如:

FROM docker.io/centos
LABEL "auth"="joker" \
      "mail"="unclejoker520@163.com"
ENV TIME_ZOME Asia/Shanghai
RUN yum install -y gcc gcc-c++ make openssl-devel prce-devel
ADD nginx-1.14.2.tar.gz /opt/
RUN cd /opt/nginx-1.14.2 && \
    ./configure --prefix=/usr/local/nginx && \
    make -j 4 && \
    make install

RUN rm -rf /opt/nginx* && \
    yum clean all && \
    echo "${TIME_ZOME}" > /etc/timezone && \
    ln -sf /usr/share/zoneinfo/${TIME_ZOME} /etc/localtime

COPY nginx.conf /usr/local/nginx/conf/
WORKDIR /usr/local/nginx/
EXPOSE 80
CMD ["./sbin/nginx","-g","daemon off;"]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

其中 FROM 指令必须是开篇第一个非注释行,是必须存在的一个指令,后面所有的操作都是基于这个镜像的。后面的指令就是一些操作指令,指令的详情在后面介绍。最后是 CMD 指定,这个指令表示在容器运行是需要执行的命令。

# 二、工作逻辑

1、在一个自定义的目录下有 Dockerfile 文件;

  • 命名首字母必须是大写;
  • 引用的文件必须在当前的目录及其一下目录;
  • 如果有些文件不需要被打包,可以将这些文件当前目录下隐藏文件(.dockeringore)中;

2、在当前目录下执行 docker build 来进行打包成镜像,Dockerfile 中的命令必须是 docker 支持的命令;

3、基于刚才打包的镜像启动容器;

通过 Dockerfile 制作成镜像并启动容器的过程如下:

8ee0e9f9938a12754dd3f77aa39028df_MD5

其中上面提到的 CMD 指令还有后面介绍的 ENTRYPOINT 指令都是在 docker run 的时候执行,其他指令在 docker build 的时候执行。

# 三、指令介绍

# 3.1 FROM

重要且必须是开篇第一个非注释行,用于为映像文件构建过程指定基础镜像,后续的指令运行是在此基础上运行。在实践中,基础镜像可以是任何可用镜像文件,默认情况下,docker build 会在 docker 主机上查找指定的镜像文件,在其不存在时,则会从 docker HUB 上拉取镜像,如果找不到镜像,则会报错。

语法如下:

FROM <repository>[:<tag>] 或 FROM <repository>@<digest>
 - <repository>:指定作为base image的名称
 - <tag>:base image的标签,为可省略项,省略时默认为latest
1
2
3

# 3.2 MAINTANIER

用于指定 Dockerfile 制作者本人的信息,目前已经废弃了。

语法如下:

MAINTANIER <AUTHOR'S detail>
1

# 3.3 LABEL

指定 Dockerfile 的标签信息,我们可以将 MAINTANIER 的作者信息写在 LABEL 标签里。

语法如下:

LABEL <key>=<value>
1

# 3.4 COPY

从 docker 主机复制文件到镜像中。

语法如下:

 COPY <SRC>...<DEST> 或者
 COPY ["<SRC>",..."<DEST>"]
1
2

其中:

  • RC :源文件或目录;
  • DEST:目标路径,建议用绝对路径;

注意:

  • 路径中有空白文件,通常使用第二种;
  • SRC 目录,其内部文件和子目录会被递归复制,但是,但是 SRC 不会被复制;
  • 复制多个 SRC,则 DEST 必须是一个,切必须以/结尾;
  • 如果 DEST 不存在,则会自动创建;

# 3.5 ADD

ADD 命令和 COPY 命令有相似之处,都是像镜像中添加内容。

语法如下:

ADD <src>...<dest> 或者
ADD ["<src>",...,"<dest>"]
1
2

操作准则如下:

  • 如果 SRC 为 URL,且 DEST 不以/结尾,则 SRC 指定的文件将被下载并直接创建为 DEST;如果 DEST 以/结尾,则文件名 URL 指定的文件将被直接下载并保存为<dest>/<filename>;
  • 如果 SRC 是一个本地系统上的压缩格式的 tar 文件,它将直接展开为一个目录,其行为类似于“tar -x”命令;然而,通过 URL 获取到的 tar 文件将不会自动展开;
  • 如果 SRC 有多个,或其间接或直接使用的通配符,则 DEST 必须是一个以/结尾的目录路径;如果 dest 不以/结尾,则其被视作一个普通文件,SRC 的内容将被直接写入到 dest;

# 3.6 WORKDIR

指定工作目录,每一次只影响当前目录到后的目录。

语法如下:

WORKDIR PATH
1

# 3.7 VOLUME

用于在 image 中创建一个挂载点目录,以挂载 docker 主机上的卷或者其它容器上的卷。

语法如下:

VOLUME <mountpoint> 或者
VOLUME ["<mountpoint>"]
1
2

注意:如果挂载点目录路径下存在文件,docker run 命令会在挂载完成后将此前得所有文件复制到新挂载的卷中。

# 3.8 EXPOSE

用于为容器打开指定要监听的端口以实现与外部通信,在 docker run 的时候,如果没有指定-P 参数,是不会暴露在 docker  主机上的。

语法如下:

EXPOSE <port>[/<portocol>] <port>[/<portocol>]
1

其中:<portocol>用于指定传输层协议,可以是 tcp 或 udp 二者之一,默认是 TCP。

EXPOSE 指令可以一次指定多个端口,例如:

EXPOSE 11222/udp 11222/tcp
1

# 3.9 ENV

用于为镜像定义所需环境变量,并可被 dockerfile 文件中位于其后的其他指定所调用。如果在 docker run 的时候,在 Dockerfile 中指定的变量名如果没有被替换,在容器启动后通过执行 printenv 指令依然可以看到我们在 Dockerfile 中定义的变量。

语法如下:

ENV <key> <value> 或者
ENV <key>=<value>
1
2

其中:

  • 第一种格式中,<key>之后的所有内容均被视作 value,因此,一次只能设置一个变量;
  • 第二种格式可以设置多个变量,每个变量为一个<key>=<value>的键值对,如果<value>中包含空格,可以用\进行转义,也可以用个对<value>加""进行标识;另外,反斜杠也可用于续行;
  • 定义多个变量时,建议使用第二种方式,以便在同一层中完成所有功能;

调用方式为:

$variable_nam 或者
${variable_nam}
1
2

如果要指定默认参数可以用下面格式:

${variable_name:-word}    # 变量为空,就用word,变量有值,就用本身的值
${variable_name:+word}    # 变量有值就现实word,没有值就不显示
1
2

# 3.10 RUN

用于指定 docker build 过程中运行的程序,其可以是任何可执行命令。

语法如下:

RUN <COMMAND> 或者
RUN ["executable","<param1>","<param2>"]
1
2

其中:

  • 第一种格式中,<command>通常是一个 shell 命令,且以“/bin/sh -c”来运行它,这意味着次进程在容器中的 PID 不为 1,不能接受 Unix 信号,因此,当使用 docker stop <container> 命令停止容器时,此进程接受不到 SIGTERM 信号;
  • 第二种语法格式中的参数是一个 JSON 格式的数组,其中<executable>为要运行的命令,后面的<paramN>为传递给命令的选项或参数,然而,这种格式的指定不会以"/bin/sh -c"来发起,因此常见的 shell 操作如变量替换以及通配符(?,*等)将不会被替换,如果要运行的命令依赖于此 shell 特性的话,可以将其替换为下面的格式:
RUN ["/bin/sh","-c","<executable>","<param1>","<param2>"]
1

# 3.11 CMD

类似于 RUN 命令,CMD 指令也可以运行命令或应用程序,不过二者的运行时间点不同:

  • RUN 指令运行于映像文件构建过程,CMD 运行于 docker run 的时候;
  • CMD 指令的首要目的在于启动容器的时候运行程序,切她运行结束后,容器也将终止,不过 CMD 指令可以被 docker run 的命令选项所覆盖;
  • 在 Dockerfile 中可以存多个 CMD 指令,但仅最后一个会生效;

语法如下:

CMD <command> 或者
CMD ["<executable>","<param1>","<param2>"] 或者
CMD ["<param1>","<param2>"]
1
2
3

其中:

  • 前两种语法格式的意义同与 RUN;
  • 第三种则用于 ENTRYPOINT 指令提供默认参数;

# 3.12 ENTRYPOINT

类似 CMD 指令功能,用于容器指定默认运行程序,从而使得容器像是一个单独的可执行程序。

与 CMD 不同的是,由 ENTRYPOINT 启动程序不会被 docker run 命令指定的参数覆盖,而且,这些命令参数会被当做参数传递给 ENTRYPOINT 指定的程序。不过,docker run 命令的 --entrypoint 选项的参数可覆盖 NETRYPOINT 指定的程序。

语法如下:

ENTRYPOINT <command> 或者
ENTRYPOINT ["<executable>","<param1>","<param2>"]
1
2

其中:

  • docker 命令传入的参数会覆盖 CMD 指令的内容且附加到 ENTRYPOINT 命令最后作为其参数使用;
  • dockerfile 文件中也可以存在多个 ENTRYPOINT 指令,但最后一个有效;

# 3.13 USER

用于指定运行 image 时的或运行 dockerfile 中任何 RUN,CMD 或者 ENTRYPOINT 指令指定的程序的用户名或 UID。

语法如下:

USER daemon
1

当服务器不需要管理员权限时,可以使用该命令指定运行用户,并且可以在之前创建所需要的用户,例如:

RUN groupadd -r test && \
    useradd -r -g test test
1
2

如果需要临时获取管理员权限,推荐使用 gosu,而不推荐 sudo。

# 3.14 HEALTHCHECK

健康检查,可以设置定时去检查应用是否正常。

语法如下:

 HEALTHCHECK [OPTIONS] CMD command
   --interval=DURATION    (default=30s)
   --timeout=DURATION (default=30s)
   --start-period=DURATION (default=0s)
   --retries=N (default=3)
1
2
3
4
5

返回值:0 是成功,1 是失败,2 是预留值。

# 3.15 SHELL

指定 SHELL 环境,默认是/bin/sh -c

# 3.16 ARG

ARG 在 build 的时候使用,语法如下:

ARG <name>[=,default value.]
1

比如:

ARG NGINX_TAG="1.14"'
docker build --build-arg NGINX_TAG="1.15"
1
2

# 3.17 ONBUILD

用于在 dockerfile 中定义一个触发器。

dockerfile 用于 build 映像文件,此映像文件亦可作为 base image 被另一个 dockerfile 用作 FRM 指令参数,并以之构建新的映像,在后面的 dockerfile 中的 FROM 指令在 build 过程中被执行时,将会触发创建其 baseimage 的 dockerfile 文件中的 ONBUILD 指令定义的触发器。

语法如下:

ONBUILD <INSTRUCTION>
1

注意:

  • 尽管任何指令都可以注册成触发器指令,但 ONBUILD 不能自我嵌套,其不会触发 FROM 和 MAINTAINER 指令;
  • 使用包含 ONBUILD 指令的 dockerfile 构建镜像应该使用特殊的标签,例如 ruby:2.0-onbuild;
  • 在 ONBUILD 指令中使用 ADD 或 COPY 指令应该格外小心,因为新构建过程中的上下文在缺少指定的源文件时会失败;

作者:乔克

本文链接:https://jokerbai.com

版权声明:本博客所有文章除特别声明外,均采用 署名-非商业性-相同方式共享 4.0 国际 (CC-BY-NC-SA-4.0) 许可协议。转载请注明出处!

#Docker
上次更新: 2025/07/19, 08:23:38
Docker存储卷
多阶段构建

← Docker存储卷 多阶段构建→

最近更新
01
使用 Generic Webhook Trigger 触发 Jenkins 多分支流水线自动化构建
07-19
02
使用Zadig从0到1实现持续交付平台
07-19
03
基于Jira的运维发布平台
07-19
更多文章>
Theme by Vdoing | Copyright © 2019-2025 乔克 | MIT License | 渝ICP备20002153号 |
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式