跳到主要内容

指令

2023年12月08日
柏拉文
越努力,越幸运

一、FROM


FROM 指定基础镜像,用于后续的指令构建。

语法

FROM [--platform=<platform>] <image> [AS <name>]

// 或者
FROM [--platform=<platform>] <image>[:<tag>] [AS <name>]

1.1 FROM php

1.2 FROM node

1.3 from mysql

1.4 FROM mongo

1.5 FROM nginx

1.6 FROM redis

1.7 FROM httpd

1.8 FROM centos

FROM centoscentos 镜像为基础, 定制镜像。

FROM centos

FROM centos as centos1 // 将 centos 命名为 centos1

1.9 FROM ubuntu

FROM ubuntuubuntu 镜像为基础, 定制镜像

FROM ubuntu

FROM ubuntu as ubuntu1 // 将 ubuntu 命名为 ubuntu1

1.10 FROM scratch

FROM scratch 基于 scratch 镜像来构建镜像。scratch 是一个空的镜像,里面什么都没有。

二、MAINTAINER


MAINTAINER 指定Dockerfile的作者/维护者。(已弃用,推荐使用LABEL指令)

三、LABEL


LABEL 添加镜像的元数据,使用键值对的形式。LABEL 指令用来给镜像添加一些元数据(metadata

2.1 语法

LABEL <key>=<value> <key>=<value> <key>=<value> ...

2.2 用法

我们可以添加镜像的作者

LABEL org.opencontainers.image.authors="runoob"

四、RUN


RUN 主要用于在镜像中执行命令。RUN 是执行命令并创建新的 Image Layer。 每一个 RUN 命令都会创建一个新的镜像层,导致镜像的臃肿。为了减少镜像层数,可以将多个命令合并到一个 RUN 命令中,并使用 Shell 运算符 && 链接。备注: 可以通过 docker history [镜像名称]:[镜像Tab] 查看镜像分层。

4.1 语法

shell 格式

RUN <命令行命令>
# <命令行命令> 等同于,在终端操作的 shell 命令。

exec 格式

RUN ["可执行文件", "参数1", "参数2"]
# 例如:
# RUN ["./test.php", "dev", "offline"] 等价于 RUN ./test.php dev offline

ADD shell 格式: 命令被作为一个字符串传递给 /bin/sh -c

ADD exec 格式: 正确的 exec 形式 ADD 需要使用双引号 " 来包围整个数组及每个数组元素。这是因为 JSON 语法规定了数组和字符串必须用双引号来表示。不可以是 单引号, 否则这会导致 Docker 解析时将其视为 shell 形式。正确的 exec 格式命令被作为一个 JSON 数组传递,不会经过 /bin/sh

4.2 用法

一、在镜像中,通过 NPM 安装依赖, 并且启动服务: 因为每一个 RUN 命令都会创建一个新的镜像层。为了减少镜像层数,可以将多个命令合并到一个 RUN 命令中。Shell 格式中使用 && 链接

FROM node:latest
RUN npm install && npm run start

五、CMD


CMD 设置容器启动后默认执行的命令和参数(可覆盖),同时 CMD 可以为 ENTRYPOINT 提供默认参数。CMD 指令指定的程序可被 docker run 命令行参数中指定要运行的程序所覆盖。类似于 RUN 指令,用于运行程序,但二者运行的时间点不同:

  1. CMDdocker run 时运行。

  2. RUN 是在 docker build

注意:如果 Dockerfile 中如果存在多个 CMD 指令,仅最后一个生效。

5.1 语法

CMD <shell 命令> 
CMD ["<可执行文件或命令>","<param1>","<param2>",...]
CMD ["<param1>","<param2>",...] # 该写法是为 ENTRYPOINT 指令指定的程序提供默认参数

推荐使用第二种格式,执行过程比较明确。第一种格式实际上在运行的过程中也会自动转换成第二种格式运行,并且默认可执行文件是 sh

CMD shell 格式: 命令被作为一个字符串传递给 /bin/sh -c

CMD exec 格式: 正确的 exec 形式 CMD 需要使用双引号 " 来包围整个数组及每个数组元素。这是因为 JSON 语法规定了数组和字符串必须用双引号来表示。不可以是 单引号, 否则这会导致 Docker 解析时将其视为 shell 形式。正确的 exec 格式命令被作为一个 JSON 数组传递,不会经过 /bin/sh

5.2 用法

一、通过 CMD 打印日志

FROM ubuntu
CMD ["echo", "Hello, World!"]

// 1. 构建镜像
docker build -t cmd .
// 2. 运行镜像
docker run cmd
// 3. 输出 Hello, World!

二、通过 CMD [] 来覆盖之前的 CMD 命令

FROM ubuntu:21.04
CMD []

三、docker run -it [镜像]:[镜像Tag] 命令 覆盖 CMD 命令

FROM ubuntu
CMD ["echo", "Hello, World!"]

// 1. 构建镜像
docker build -t cmd .
// 2. 运行镜像
docker run -it cmd echo "Hello World! 覆盖"
// 3. 输出 ello World! 覆盖, 覆盖了 CMD ["echo", "Hello, World!"] 命令

六、ENTRYPOINT


ENTRYPOINT 设置容器启动时运行的命令(不可被覆盖)。类似于 CMD 指令,但其不会被 docker run 的命令行参数指定的指令所覆盖,而且这些命令行参数会被当作参数送给 ENTRYPOINT 指令指定的程序。但是, 如果运行 docker run 时使用了 --entrypoint 选项,将覆盖 ENTRYPOINT 指令指定的程序。

  • 优点: 在执行 docker run 的时候可以指定 ENTRYPOINT 运行所需的参数。

  • 缺点: 如果 Dockerfile 中如果存在多个 ENTRYPOINT 指令,仅最后一个生效。

6.1 语法

ENTRYPOINT ["<executeable>","<param1>","<param2>",...]

6.2 用法

一、通过 ENTRYPOINT 打印日志, 省略参数

FROM ubuntu
ENTRYPOINT ["echo"]

// 1. 构建镜像
docker build -t entrypoint .
// 2. 直接运行镜像
docker run entrypoint
// 3. 输出为空
// 4. 通过 -it 运行镜像
docker run -it entrypoint Hello World
// 5. 输出为 Hello World

二、通过 ENTRYPOINT 打印日志, 通过 CMD 设置 ENTRYPOINT 默认参数: 如果 docker run 中提供了额外参数, 那么会覆盖 CMD 提供的默认参数。

FROM ubuntu
ENTRYPOINT ["echo"]
CMD ["Hello, World!"]

// 1. 构建镜像
docker build -t entrypoint .
// 2. 运行镜像
docker run entrypoint
// 3. 输出为 Hello, World!
// 4. 运行镜像
docker run -it entrypoint Hello World 覆盖
// 5. 输出为 Hello World 覆盖

三、通过 ENTRYPOINT 打印日志, 通过 ENTRYPOINT 设置参数: 如果在 docker run 中额外提供而来参数,那么会往后新增参数。

FROM ubuntu
ENTRYPOINT ["echo", "Hello World!"]

// 1. 构建镜像
docker build -t entrypoint1 .
// 2. 直接运行镜像
docker run entrypoint1
// 3. 输出为 Hello World!
// 4. 通过 -it 运行镜像
docker run -it entrypoint1 Hello World 覆盖
// 5. 输出为 Hello World! Hello World 覆盖

七、EXPOSE


EXPOSEDockerfile 中的一个指令,用于声明容器在运行时会监听的端口。可以用来记录容器应用程序所需的端口。它提供了一种规范化的方式来告诉其他开发者或运维人员该容器需要哪些端口。EXPOSE 并不是强制性的,你可以不在 Dockerfile 中指定它。即使没有 EXPOSE,你仍然可以通过 -p--publish 选项将容器端口映射到主机端口。

7.1 语法

EXPOSE <端口1> [<端口2>...]

八、ENV


ENV 在容器内部设置环境变量。定义了环境变量,那么在后续的指令中,就可以使用这个环境变量。ENV 变量可以在构建过程中使用, 也可以在镜像中使用。

8.1 语法

ENV <key> <value>
ENV <key1>=<value1> <key2>=<value2>...

8.2 用法

一、打印变量日志

FROM node
ENV a=1 b=2
CMD echo ${a} ${b}

九、ADD


ADD 将当前构建上下文(通常是 Dockerfile 所在的目录)中的所有文件和目录复制到容器的目标目录。如果目标目录不存在则会自动创建。ADD 指令和 COPY的使用格类似(同样需求下,官方推荐使用 COPY)。功能也类似,不同之处如下:

  1. ADD 的优点:在执行 <源文件>tar 压缩文件的话,压缩格式为 gzip, bzip2 以及 xz 的情况下,会自动复制并解压到 <目标路径>

  2. ADD 的缺点:在不解压的前提下,无法复制 tar 压缩文件。会令镜像构建缓存失效,从而可能会令镜像构建变得比较缓慢。具体是否使用,可以根据是否需要自动解压来决定。

因此,ADDCOPY 最佳实践为: 所有的文件复制均使用 COPY 指令, 仅在需要自动解压缩的场合使用 ADD

9.1 语法

ADD [本地文件] [镜像文件]

9.2 用法

一、将当前构建上下文(通常是 Dockerfile 所在的目录)中的所有文件和目录复制到容器的当前工作目录: 注意: 这里的目标目录是相对路径,因此它依赖于之前设置的工作目录。如果之前没有设置 WORKDIR,它会复制到容器的根目录(/

ADD . .

二、将当前构建上下文(通常是 Dockerfile 所在的目录)中的所有文件和目录复制到容器的 /dist 目录: 这里的目标目录是绝对路径,因此它不依赖于工作目录,始终会将文件复制到容器的 /dist 目录。

ADD . /dist

三、指定镜像工作目录为 /dist, 将本地当前目录下所有文件复制到镜像工作目录 /dist, 之后的所有指令都会在这个目录下执行

WORKDIR /dist

ADD . /dist // 将当前构建上下文(通常是 Dockerfile 所在的目录)中的所有文件和目录复制到容器的 /dist 目录。这里的目标目录是绝对路径,因此它不依赖于工作目录,始终会将文件复制到容器的 /dist 目录。

ADD . . // 将当前构建上下文(通常是 Dockerfile 所在的目录)中的所有文件和目录复制到容器的当前工作目录,在这里,由于 WORKDIR 设置为 /dist,因此它会将所有文件复制到 /dist 目录下。注意: 这里的目标目录是相对路径,因此它依赖于之前设置的工作目录。如果之前没有设置 WORKDIR,它会复制到容器的根目录(/)。、

// 总结: 在大多数情况下,效果是一样的,因为 WORKDIR 已经设置为了 /dist。但为了代码的清晰度和避免潜在的错误,通常建议使用绝对路径,尤其是在复杂的 Dockerfile 中,使用绝对路径更容易理解和维护。

十、COPY


COPY 将当前构建上下文(通常是 Dockerfile 所在的目录)中的所有文件和目录复制到容器的目标目录。如果目标目录不存在则会自动创建。因此,ADDCOPY 最佳实践为: 所有的文件复制均使用 COPY 指令, 仅在需要自动解压缩的场合使用 ADD

10.1 语法

COPY [--chown=<user>:<group>] <源路径1>...  <目标路径>
COPY [--chown=<user>:<group>] ["<源路径1>",... "<目标路径>"]
  • [--chown=<user>:<group>]: 可选参数,用户改变复制到容器内文件的拥有者和属组。

  • <源路径>: 源文件或者源目录,这里可以是通配符表达式,其通配符规则要满足 Gofilepath.Match 规则

  • <目标路径>: 容器内的指定路径,该路径不用事先建好,路径不存在的话,会自动创建。

10.2 用法

一、将当前构建上下文(通常是 Dockerfile 所在的目录)中的所有文件和目录复制到容器的当前工作目录: 注意: 这里的目标目录是相对路径,因此它依赖于之前设置的工作目录。如果之前没有设置 WORKDIR,它会复制到容器的根目录(/

COPY . .

二、将当前构建上下文(通常是 Dockerfile 所在的目录)中的所有文件和目录复制到容器的 /dist 目录: 这里的目标目录是绝对路径,因此它不依赖于工作目录,始终会将文件复制到容器的 /dist 目录。

COPY . /dist

三、指定镜像工作目录为 /dist, 将本地当前目录下所有文件复制到镜像工作目录 /dist, 之后的所有指令都会在这个目录下执行

WORKDIR /dist

COPY . /dist // 将当前构建上下文(通常是 Dockerfile 所在的目录)中的所有文件和目录复制到容器的 /dist 目录。这里的目标目录是绝对路径,因此它不依赖于工作目录,始终会将文件复制到容器的 /dist 目录。

COPY . . // 将当前构建上下文(通常是 Dockerfile 所在的目录)中的所有文件和目录复制到容器的当前工作目录,在这里,由于 WORKDIR 设置为 /dist,因此它会将所有文件复制到 /dist 目录下。注意: 这里的目标目录是相对路径,因此它依赖于之前设置的工作目录。如果之前没有设置 WORKDIR,它会复制到容器的根目录(/)。、

// 总结: 在大多数情况下,效果是一样的,因为 WORKDIR 已经设置为了 /dist。但为了代码的清晰度和避免潜在的错误,通常建议使用绝对路径,尤其是在复杂的 Dockerfile 中,使用绝对路径更容易理解和维护。

十一、VOLUME


VOLUME 为容器创建挂载点或声明卷。定义匿名数据卷。在启动容器时忘记挂载数据卷,会自动挂载到匿名卷,名字是随机的 Hash 值。

  1. 避免重要的数据,因容器重启而丢失,这是非常致命的。

  2. 避免容器不断变大。

在启动容器 docker run 的时候,我们可以通过 -v 参数修改挂载点。如果我们没有通过 -v 指定挂载点, Docker 会默认生成一个 Hash 目录, 每次启动时值都不一样。

11.1 语法

VOLUME ["<路径1>", "<路径2>"...]
VOLUME <路径>

11.2 用法

一、将Docker 工作目录 WORKDIR 持久化存储

// 1. 编辑 Dockerfile
WORKDIR /app
VOLUME ["/app"]
// 2. 运行 Docker 镜像, 需要通过 -v 来指定本地持久化存储数据的位置
docker run -t --name xx -v 本地指定位置:/app [镜像ID:Tag]

十二、WORKDIR


WORKDIR 设置后续指令的工作目录。指定工作目录。用 WORKDIR 指定的工作目录,会在构建镜像的每一层中都存在。以后各层的当前目录就被改为指定的目录,如该目录不存在,WORKDIR 会帮你建立目录。docker build 构建镜像过程中的,每一个 RUN 命令都是新建的一层。只有通过 WORKDIR 创建的目录才会一直存在。

理解: WORKDIR 的功能类似于 CD, 用于进入到某个目录, 但是比 CD 好的一点是, 如果目录不存在会自动创建。

12.1 语法

WORKDIR <工作目录路径>

12.2 用法

一、指定镜像工作目录为 /dist, 将当前构建上下文(通常是 Dockerfile 所在的目录)中的所有文件和目录复制到容器的当前工作目录 dist, 之后的所有指令都会在这个目录下执行

WORKDIR /dist

COPY . /dist // 将当前构建上下文(通常是 Dockerfile 所在的目录)中的所有文件和目录复制到容器的 /dist 目录。这里的目标目录是绝对路径,因此它不依赖于工作目录,始终会将文件复制到容器的 /dist 目录。

COPY . . // 将当前构建上下文(通常是 Dockerfile 所在的目录)中的所有文件和目录复制到容器的当前工作目录,在这里,由于 WORKDIR 设置为 /dist,因此它会将所有文件复制到 /dist 目录下。注意: 这里的目标目录是相对路径,因此它依赖于之前设置的工作目录。如果之前没有设置 WORKDIR,它会复制到容器的根目录(/)。

十三、USER


USER 指定后续指令的用户上下文。用于指定执行后续命令的用户和用户组,这边只是切换后续命令执行的用户(用户和用户组必须提前已经存在)。

13.1 语法

USER <用户名>[:<用户组>]

13.2 用法

十四、ARG


ARG 定义在构建过程中传递给构建器的变量,可使用 docker build 命令设置。构建参数,与 ENV 作用一致。不过作用域不一样。ARG 设置的环境变量仅对 Dockerfile 内有效,也就是说只有 docker build 的过程中有效,构建好的镜像内不存在此环境变量。构建命令 docker build 中可以用 --build-arg <参数名>=<值> 来覆盖。

14.1 语法

ARG <参数名>[=<默认值>]

14.2 用法

一、打印变量日志

FROM node
ARG a=1 b=2 // ARG 变量在构建过程中传递给构建器,所以设置的变量仅在 docker build 构建过程中有效
RUN echo ${a} ${b} // 所以, RUN 命令中是可以访问到 ARG 变量的

十五、ONBUILD


ONBUILD 当该镜像被用作另一个构建过程的基础时,添加触发器。用于延迟构建命令的执行。简单的说,就是 Dockerfile 里用 ONBUILD 指定的命令,在本次构建镜像的过程中不会执行(假设镜像为 test-build)。当有新的 Dockerfile 使用了之前构建的镜像 FROM test-build ,这时执行新镜像的 Dockerfile 构建时候,会执行 test-buildDockerfile 里的 ONBUILD 指定的命令。

15.1 语法

ONBUILD <其它指令>

十六、STOPSIGNAL


STOPSIGNAL 设置发送给容器以退出的系统调用信号。

十七、HEALTHCHECK


HEALTHCHECK 定义周期性检查容器健康状态的命令。用于指定某个程序或者指令来监控 docker 容器服务的运行状态。

17.1 语法

HEALTHCHECK [选项] CMD <命令>:设置检查容器健康状况的命令
HEALTHCHECK NONE:如果基础镜像有健康检查指令,使用这行可以屏蔽掉其健康检查指令

HEALTHCHECK [选项] CMD <命令> : 这边 CMD 后面跟随的命令使用,可以参考 CMD 的用法。

17.2 用法

1. HEALTHCHECK --interval=30s CMD xxx: 比如 HEALTHCHECK --interval=30s CMD curl -f http://localhost:3000 || exit 1

2. HEALTHCHECK --interval=30s --timeout=3s CMD xxx: 比如 HEALTHCHECK --interval=30s --timeout=3s CMD curl -f http://localhost:3000 || exit 1 每隔 30s 访问服务,如果失败,则退出进程

十八、SHELL


SHELL 覆盖Docker中默认的shell,用于RUNCMDENTRYPOINT指令。