Dockerfile指令

本文来自技术分享

1. COPY 复制文件

格式:

shell 格式:COPY <源路径>... <目标路径>

exec 格式:COPY ["<源路径1>",... "<目标路径>"]

说明:

两种格式,一种类似于命令行,一种类似于函数调用。

COPY 指令将从构建上下文目录中<源路径>的文件/目录复制到新的一层的镜像内的 <目标路径> 位置。

示例:

COPY package.json /usr/src/app/

<源路径>可以是多个,甚至可以是通配符,其通配符规则要满足 Go 的 filepath.Match 规则,如:

COPY hom* /mydir/

COPY hom?.txt /mydir/

2. ADD 更高级的复制文件

格式:

ADD <源路径>... <目标路径>

ADD ["<源路径1>",... "<目标路径>"]

说明:

ADD 指令和 COPY 的格式和性质基本一致。但是在COPY 基础上增加了一些功能。

<源路径> 可以是一个 URL ,这种情况下,Docker引擎会试图去下载这个链接的文件放到 <目标路径> 去。下载后的文件权限自动设置为 600 ,如果这并不是想要的权限,那么还需要增加额外的一层 RUN 进行权限调整,另外,如果下载的是个压缩包,需要解压缩,也一样还需要额外的一层 RUN 指令进行解压缩。不推荐使用。

如果<源路径>为一个 tar 压缩文件的话,压缩格式为 gzip , bzip2 以及 xz 的情况下, ADD 指令将会自动解压缩这个压缩文件到 <目标路径> 去。

示例:

ADD mqtt-service.sh $MQTT_SERVICE/

3. CMD 容器启动命令

格式:

CMD 指令的格式和 RUN 相似,也是两种格式:

l shell 格式: CMD <命令>

l exec 格式: CMD ["可执行文件", "参数1", "参数2"...]

l 参数列表格式: CMD ["参数1", "参数2"...] 。在指定了 ENTRYPOINT 指令后,用 CMD 指定具体的参数

说明:

Docker 不是虚拟机,容器就是进程。既然是进程,那么在启动容器的时候,需要指定所运行的程序及参数。 CMD 指令就是用于指定默认的容器主进程的启动命令的。

在运行时可以指定新的命令来替代镜像设置中的这个默认命令,比如, ubuntu 镜像默认的CMD 是 /bin/bash ,如果我们直接 docker run -it ubuntu 的话,会直接进入 bash 。我们也可以在运行时指定运行别的命令,如 docker run -it ubuntu cat /etc/os-release 。这就是用 cat /etc/os-release 命令替换了默认的 /bin/bash 命令了,输出了系统版本信息。在指令格式上,一般推荐使用 exec 格式,这类格式在解析时会被解析为 JSON 数组,因此一定要使用双引号 " ,而不要使用单引号。

如果使用 shell 格式的话,实际的命令会被包装为 sh -c 的参数的形式进行执行。比如:

CMD echo $HOME

在实际执行中,会将其变更为:

CMD [ "sh", "-c", "echo $HOME" ]

4. ENTRYPOINT入口点

格式:

l shell 格式: ENTRYPOINT <命令>

l exec 格式: ENTRYPOINT ["可执行文件", "参数1", "参数2"...]

说明:

ENTRYPOINT 的格式和 RUN 指令格式一样,分为 exec 格式和 shell 格式。

ENTRYPOINT的目的和CMD 一样,都是在指定容器启动程序及参数。ENTRYPOINT 在运行时也可以替代,不过比 CMD 要略显繁琐,需要通过 docker run 的参数 --entrypoint 来指定。

当指定了 ENTRYPOINT 后, CMD 的含义就发生了改变,不再是直接的运行其命令,而是将CMD 的内容作为参数传给 ENTRYPOINT 指令,换句话说实际执行时,将变为:

" "

示例:

ENTRYPOINT ["./mqtt-service.sh"]

5. ENV设置环境变量

格式:

ENV

ENV = =

说明:

这个指令很简单,就是设置环境变量而已,无论是后面的其它指令,如 RUN ,还是运行时的应用,都可以直接使用这里定义的环境变量。

下列指令可以支持环境变量展开:

ADD 、 COPY 、 ENV 、 EXPOSE 、 LABEL 、 USER 、 WORKDIR 、 VOLUME 、 STOPSIGNAL 、 ONBUILD 。

6. ARG构建参数

格式:

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

说明:

构建参数和 ENV 的效果一样,都是设置环境变量。所不同的是, ARG 所设置的构建环境的环境变量,在将来容器运行时是不会存在这些环境变量的。

Dockerfile 中的 ARG 指令是定义参数名称,以及定义其默认值。该默认值可以在构建命令docker build 中用 --build-arg <参数名>=<值> 来覆盖。

7. VOLUME定义匿名卷

格式:

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

VOLUME <路径>

说明:

容器运行时应该尽量保持容器存储层不发生写操作,对于数据库类需要保存动态数据的应用,其数据库文件应该保存于卷(volume)中。为了防止运行时用户忘记将动态文件所保存目录挂载为卷,在Dockerfile 中,我们可以事先指定某些目录挂载为匿名卷,这样在运行时如果用户不指定挂载,其应用也可以正常运行,不会向容器存储层写入大量数据。

VOLUME /data

这里的 /data 目录就会在运行时自动挂载为匿名卷,任何向 /data 中写入的信息都不会记录进容器存储层,从而保证了容器存储层的无状态化。当然,运行时可以覆盖这个挂载设置。比如:

docker run -d -v mydata:/data xxxx

在这行命令中,就使用了 mydata 这个命名卷挂载到了 /data 这个位置,替代了Dockerfile 中定义的匿名卷的挂载配置。

8. EXPOSE声明端口

格式:

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

说明:

EXPOSE 指令是声明运行时容器提供服务端口,这只是一个声明,在运行时并不会因为这个声明应用就会开启这个端口的服务。在 Dockerfile 中写入这样的声明有两个好处,一个是帮助镜像使用者理解这个镜像服务的守护端口,以方便配置映射;另一个用处则是在运行时使用随机端口映射时,也就是 docker run -P 时,会自动随机映射 EXPOSE 的端口。

示例:

EXPOSE 8080/tcp

9. WORKDIR指定工作目录

格式:

WORKDIR <工作目录路径>

说明:

使用 WORKDIR 指令可以来指定工作目录( 或者称为当前目录) ,以后各层的当前目录就被改为指定的目录,如该目录不存在, WORKDIR 会帮你建立目录。

示例:

WORKDIR ${MQTT_SERVICE}

10. USER指定当前用户

格式:

USER <用户名>

说明:

USER 指令和 WORKDIR 相似,都是改变环境状态并影响以后的层。 WORKDIR 是改变工作目录, USER 则是改变之后层的执行 RUN , CMD 以及 ENTRYPOINT 这类命令的身份。

如果以 root 执行的脚本,在执行期间希望改变身份,比如希望以某个已经建立好的用户来运行某个服务进程,不要使用 su 或者 sudo ,这些都需要比较麻烦的配置,而且在 TTY 缺失的环境下经常出错。建议使用 gosu 。

# 建立 redis 用户,并使用 gosu 换另一个用户执行命令

RUN groupadd -r redis && useradd -r -g redis redis

# 下载 gosu

RUN wget -O /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/1.7/gosu-amd64" 
&& chmod +x /usr/local/bin/gosu 
&& gosu nobody true

# 设置 CMD,并以另外的用户执行

CMD [ "exec", "gosu", "redis", "redis-server" ]

11. HEALTHCHECK健康检查

格式:

HEALTHCHECK [选项] CMD <命令> :设置检查容器健康状况的命令

HEALTHCHECK NONE :如果基础镜像有健康检查指令,使用这行可以屏蔽掉其健康检查指令

说明:

HEALTHCHECK 指令是告诉 Docker 应该如何进行判断容器的状态是否正常,这是 Docker 1.12引入的新指令。

HEALTHCHECK 支持下列选项:

--interval=<间隔> :两次健康检查的间隔,默认为 30 秒;

--timeout=<时长> :健康检查命令运行超时时间,如果超过这个时间,本次健康检查就被 视为失败,默认 30 秒;

--retries=<次数> :当连续失败指定次数后,则将容器状态视为 unhealthy ,默认 3次。

示例:

FROM nginx

RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/*

HEALTHCHECK --interval=5s --timeout=3s CMD curl -fs http://localhost/ || exit 1

健康检查命令的输出( 包括 stdout 以及 stderr ) 都会被存储于健康状态里,可以用 docker inspect 来查看

$ docker inspect --format '{{json .State.Health}}' web | python -m json.tool

12. ONBUILD为他人做嫁衣

格式:
ONBUILD <其它指令>
说明:
ONBUILD 是一个特殊的指令,它后面跟的是其它指令,比如 RUN , COPY 等,而这些指令,在当前镜像构建时并不会被执行。只有当以当前镜像为基础镜像,去构建下一级镜像的时候才会被执行。
示例:

FROM node:slim

RUN mkdir /app

WORKDIR /app

ONBUILD COPY ./package.json /app

ONBUILD RUN [ "npm", "install" ]

ONBUILD COPY . /app/

CMD [ "npm", "start" ]

构建镜像my-node

FROM my-node

这个镜像构建时会执行以上ONBUILD中的三个命令。

相关文章
相关标签/搜索