Docker Dockerfile

什么是 Dockerfile?

Dockerfile 是一个文本文件,包含了构建 Docker 镜像的所有指令。通过定义一系列命令和参数, Dockerfile 指导 Docker 构建一个自定义的镜像。

使用 Dockerfile 定制镜像

下面以定制一个 nginx 镜像为例,构建好的镜像内会有一个 /usr/share/nginx/html/index.html 文件。

创建 Dockerfile

在一个空目录下,新建一个名为 Dockerfile 文件,并在文件内添加以下内容:

FROM nginx
RUN echo '这是一个本地构建的nginx镜像' > /usr/share/nginx/html/index.html

基本指令说明

  • FROM:定制的镜像都是基于 FROM 的镜像,这里的 nginx 就是定制需要的基础镜像
  • RUN:用于执行后面跟着的命令行命令

RUN 指令的两种格式

1. shell 格式:

RUN <命令行命令>

2. exec 格式:

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

例如,下面的写法会创建 3 层镜像:

FROM centos
RUN yum -y install wget
RUN wget -O redis.tar.gz "http://download.redis.io/releases/redis-5.0.3.tar.gz"
RUN tar -xvf redis.tar.gz

可以简化为以下格式(只创建 1 层镜像):

FROM centos
RUN yum -y install wget \
    && wget -O redis.tar.gz "http://download.redis.io/releases/redis-5.0.3.tar.gz" \
    && tar -xvf redis.tar.gz

构建镜像

在 Dockerfile 文件的存放目录下,执行构建动作:

docker build -t nginx:v3 .

上下文路径

上下文路径是指 Docker 在构建镜像时可以使用的文件路径。当需要使用到本机的文件时(比如复制文件到镜像中), Docker build 命令会将这个路径下的所有内容打包。

Dockerfile 指令详解

指令说明
FROM指定基础镜像,用于后续的指令构建
MAINTAINER指定 Dockerfile 的作者/维护者(已弃用,推荐使用 LABEL)
LABEL添加镜像的元数据,使用键值对的形式
RUN在构建过程中在镜像中执行命令
CMD指定容器创建时的默认命令(可以被覆盖)
ENTRYPOINT设置容器创建时的主要命令(不可被覆盖)
EXPOSE声明容器运行时监听的特定网络端口
ENV在容器内部设置环境变量
ADD将文件、目录或远程URL复制到镜像中
COPY将文件或目录复制到镜像中
VOLUME为容器创建挂载点或声明卷
WORKDIR设置后续指令的工作目录
USER指定后续指令的用户上下文
ARG定义构建过程中的变量
ONBUILD当镜像被用作另一个构建过程的基础时,添加触发器

COPY 指令

复制指令,从上下文目录中复制文件或者目录到容器里指定路径。

COPY [--chown=<user>:<group>] <源路径1>... <目标路径>
COPY [--chown=<user>:<group>] ["<源路径1>",... "<目标路径>"]

# 示例
COPY hom* /mydir/
COPY hom?.txt /mydir/

ADD 指令

ADD 指令和 COPY 的使用格类似,但具有额外功能:

ADD vs COPY

ADD 优点:

在执行 <源文件> 为 tar 压缩文件的情况下,会自动解压到 <目标路径>

ADD 缺点:

  • 在不解压的前提下,无法复制 tar 压缩文件
  • 会令镜像构建缓存失效,可能会令镜像构建变得较慢

CMD 指令

CMD 指令用于指定容器启动时要运行的命令:

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

ENTRYPOINT 指令

ENTRYPOINT 指令用于配置容器启动时的可执行程序:

# 格式
ENTRYPOINT ["<executeable>","<param1>","<param2>",...]

# 示例
FROM nginx

ENTRYPOINT ["nginx", "-c"] # 定参
CMD ["/etc/nginx/nginx.conf"] # 变参

运行示例

1. 不传参运行:

docker run nginx:test

将执行:nginx -c /etc/nginx/nginx.conf

2. 传参运行:

docker run nginx:test -c /etc/nginx/new.conf

将执行:nginx -c /etc/nginx/new.conf

ENV 指令

设置环境变量:

# 格式
ENV <key> <value>
ENV <key1>=<value1> <key2>=<value2>...

# 示例
ENV NODE_VERSION 7.2.0

RUN curl -SLO "https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-linux-x64.tar.xz"

ARG 指令

构建参数:

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

# 示例
ARG VERSION=1.0.0
ARG BUILD_DATE

VOLUME 指令

定义匿名数据卷:

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

# 示例
VOLUME /data
VOLUME ["/data1", "/data2"]

EXPOSE 指令

声明端口:

# 格式
EXPOSE <端口1> [<端口2>...]

# 示例
EXPOSE 80 443
EXPOSE 8080

WORKDIR 指令

设置工作目录:

# 格式
WORKDIR <工作目录路径>

# 示例
WORKDIR /app
WORKDIR /usr/src/app

USER 指令

指定运行容器时的用户:

# 格式
USER <用户名>[:<用户组>]

# 示例
USER nginx
USER nginx:nginx

HEALTHCHECK 指令

配置容器健康检查:

# 格式
HEALTHCHECK [选项] CMD <命令>
HEALTHCHECK NONE

# 示例
HEALTHCHECK --interval=5m --timeout=3s CMD curl -f http://localhost/ || exit 1

ONBUILD 指令

为镜像添加触发器:

# 格式
ONBUILD <其它指令>

# 示例
ONBUILD ADD . /app/src
ONBUILD RUN /usr/local/bin/python-build --dir /app/src

LABEL 指令

为镜像添加元数据:

# 格式
LABEL <key>=<value> <key>=<value> ...

# 示例
LABEL version="1.0" description="This is my custom image"
LABEL org.opencontainers.image.authors="sean"