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
注意镜像层数
Dockerfile 的指令每执行一次都会在 Docker 上新建一层。所以过多无意义的层,会造成镜像膨胀过大。
例如,下面的写法会创建 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 .
构建说明
- -t 参数用于指定镜像名称和标签
- 最后的 . 表示构建上下文路径
上下文路径
上下文路径是指 Docker 在构建镜像时可以使用的文件路径。当需要使用到本机的文件时(比如复制文件到镜像中), Docker build 命令会将这个路径下的所有内容打包。
为什么需要上下文?
由于 Docker 的运行模式是 C/S,我们本机是 C,Docker 引擎是 S。实际的构建过程是在 Docker 引擎下完成的,所以这个时候无法直接用到本机的文件。这就需要把本机指定目录下的文件打包提供给 Docker 引擎使用。
注意
上下文路径下不要放无用的文件,因为会一起打包发送给 Docker 引擎,如果文件过多会造成构建过程缓慢。
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 指令指定的程序提供默认参数
CMD vs RUN
- CMD 在 docker run 时运行
- RUN 是在 docker build 时运行
- 如果 Dockerfile 中存在多个 CMD 指令,仅最后一个生效
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
ENV vs ARG
- ARG 设置的变量仅在构建过程中有效
- ENV 设置的变量在容器运行时仍然存在
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"