Skip to content

Dockerfile 简单使用

Dockerfile 是用来构建 Docker 镜像的文本文件,它包含了一系列的指令和配置,用于告诉 Docker 如何构建一个镜像。

以 Web 开发为例,我们可以在官方 nginx 镜像基础上,添加自定义的网页文件、修改配置文件、安装必要的工具等。

具体操作如下:

  1. 创建一个新的空白目录 myweb
  2. 在目录 myweb 下创建一个文本文件,命名为 Dockerfile,并在文件中添加如下内容。
bash
# 指定使用最新版 nginx 作为基础镜像
FROM nginx:latest
# 将网页内容放到容器的 nginx 默认的网页目录中
RUN echo '<h1>My Custom Nginx Page</h1>' > /usr/share/nginx/html/index.html
# 声明容器会使用 80 端口
EXPOSE 80
  1. myweb 目录下运行命令 docker build -t my-web . 进行自定义 nginx 镜像构建。

这样就完成了自定义 nginx 镜像的构建。其中 -t my-web 是给新镜像命名为 my-web,最后的点表示使用当前目录的 Dockerfile。

构建完成后可以用 docker images 查看新构建的镜像。

bash
docker images
  1. 运行 docker run -d -p 80:80 my-web 启动容器。

这时访问主机的 80 端口就能看到自定义网页了。

Dockerfile 常用指令

FROM 指令

FROM 指令用于指定基础镜像,必须是 Dockerfile 的第一个指令。基础镜像可以是官方镜像如 ubuntu:20.04,也可以是用户自定义的镜像。如果不指定标签,默认使用 latest 标签。例如 FROM nginx 表示基于最新版 nginx 镜像构建。

FROM 指令格式:

bash
FROM <image>[:<tag>] [AS <name>]

参数说明:

  • <image>:必需,指定基础镜像名称。
  • :<tag>:可选,指定镜像版本标签。
  • AS <name>:可选,为构建阶段命名。
bash
示例:
FROM nginx:1.23
FROM python:3.9-alpine
FROM ubuntu:20.04 AS builder

LABEL 指令

用于添加元数据到镜像,采用键值对格式。

LABEL 指令格式:

bash
LABEL <key>=<value>
bash
示例:
LABEL version="1.0.1"
LABEL maintainer="admin@example.com"

RUN 指令

在镜像构建过程中执行命令,每条 RUN 指令都会创建一个新的镜像层。
RUN 有两种格式:Shell 格式(RUN <command>)和 Exec 格式(RUN ["executable", "param1", "param2"])。
Shell 格式默认使用/bin/sh -c执行,Exec 格式直接调用可执行文件。为了减少镜像层数,建议将多个命令合并到单个 RUN 指令中,用 && 连接命令,用 \ 换行。例如安装软件包时应该先更新包列表再安装,最后清理缓存。

RUN 指令格式:

bash
# Shell 格式
RUN <command>

# Exec 格式
RUN ["executable", "param1", "param2"]
bash
示例:
RUN yum -y install wget
RUN apt-get update && apt-get install -y \
    git \
    curl \
    && rm -rf /var/lib/apt/lists/*
RUN ["/bin/bash", "-c", "echo Hello, Docker!"]
RUN ["yum", "-y", "install", "wget"]

CMD 指令

指定容器启动时的默认命令,一个 Dockerfile 只能有一个有效的 CMD 指令。如果 docker run 指定了命令,CMD 会被覆盖。 CMD 有三种格式:Exec 格式(推荐)、Shell 格式和作为 ENTRYPOINT 的参数。
Exec 格式直接调用可执行文件,不经过 shell 处理环境变量;
Shell 格式会通过 /bin/sh -c 执行。例如运行 Python 应用时可以使用 CMD ["python", "app.py"]

CMD 指令格式:

bash
# Exec 格式(推荐)
CMD ["executable","param1","param2"]

# Shell 格式
CMD command param1 param2

# 作为 ENTRYPOINT 的参数
CMD ["param1","param2"]
bash
示例:
# Shell 格式示例: 运行 Python 脚本
CMD python app.py

# Exec 格式示例: 运行 Nginx
CMD ["nginx", "-g", "daemon off;"]

# 作为 ENTRYPOINT 参数
CMD ["--port=8080"]

ENTRYPOINT 指令

用于设置容器启动时的主要命令,与 CMD 不同,它不会被 docker run 后面的命令覆盖。

ENTRYPOINT 指令格式:

bash
# Shell 格式
ENTRYPOINT command param1 param2

# Exec 格式
ENTRYPOINT ["executable", "param1", "param2"]
bash
示例:
# Shell 格式示例: 运行 Python 脚本
ENTRYPOINT python app.py

# Exec 格式示例: 运行 Nginx
ENTRYPOINT ["nginx", "-g", "daemon off;"]

SHELL 指令

用于覆盖 Docker 默认的 shell 程序。默认情况下 Linux 使用 ["/bin/sh", "-c"],Windows 使用 ["cmd", "/S", "/C"]。这个指令会影响 RUN、CMD 和 ENTRYPOINT 的 shell 格式执行方式。

SHELL 指令格式

bash
SHELL ["executable", "parameters"]
bash
示例:
# 切换为 PowerShell
SHELL ["powershell", "-command"]
# 切换回默认 shell
SHELL ["/bin/sh", "-c"]

EXPOSE 指令

声明容器运行时监听的网络端口,实际端口映射需要在运行容器时通过 -p 参数设置。 EXPOSE 可以指定 TCP 或 UDP 协议,默认是 TCP。
例如 EXPOSE 80/tcp 表示容器会监听 80 端口。

EXPOSE 指令格式:

bash
EXPOSE <port> [<port>/<protocol>...]
bash
示例:
# 声明单个端口
EXPOSE 80
# 声明多个端口
EXPOSE 80 443
# 指定协议
EXPOSE 53/udp

ENV 指令

设置环境变量,这些变量会在构建阶段和容器运行时生效。

ENV 指令格式:

bash
# 定义单个变量
ENV <key> <value>
# 一次性定义多个变量
ENV <key1>=<value1> <key2>=<value2>...
bash
示例:
# 设置单个变量
ENV NODE_VERSION=18.15.0
# 设置多个变量
ENV NODE_VERSION=18.15.0 NODE_ENV=production

COPY 指令

将文件或目录从构建上下文复制到镜像中,源路径必须是相对路径(相对于 Dockerfile 所在目录),不能使用绝对路径或 ../ 父目录引用。目标路径可以是绝对路径或相对于 WORKDIR 的路径。COPY 会保留文件元数据(权限、时间戳),但不支持自动解压压缩包。

例如复制项目代码到镜像的 /app 目录。

COPY 指令格式:

bash
COPY <src>... <dest>
bash
示例:
# 复制单个文件
COPY requirements.txt /app/
# 复制整个目录
COPY src /app/src
# 使用通配符复制多个文件
COPY *.sh /scripts/

ADD 指令

ADD 指令功能类似 COPY,但增加了自动解压压缩包和处理远程 URL 的能力。当源路径是本地压缩文件(如 .tar、.gz)时,ADD 会自动解压到目标路径。源路径也可以是 URL,Docker 会下载文件到镜像中。例如 ADD https://example.com/file.tar.gz /tmp 会下载并解压文件。

ADD 指令格式:

bash
ADD <src>... <dest>
bash
示例:
# 添加本地文件
ADD app.jar /opt/app/
# 自动解压压缩包
ADD project.tar.gz /app
# 从 URL 下载文件
ADD https://example.com/data.json /data

WORKDIR 指令

设置工作目录,相当于 cd 命令的效果,如果目录不存在会自动创建。后续的 RUN、CMD、COPY 等指令都会在此目录下执行。WORKDIR 可以多次使用,路径可以是相对路径(基于前一个 WORKDIR)。例如 WORKDIR /app 后接 WORKDIR src 最终路径是 /app/src。

WORKDIR 指令格式:

bash
WORKDIR <path>
bash
示例:
WORKDIR /usr/src
WORKDIR app
RUN pwd  # 输出 /usr/src/app

VOLUME 指令

创建挂载点或声明卷,会在容器运行时自动挂载匿名卷。主要用途是保留重要数据(如数据库文件)或共享目录。例如 VOLUME /data 确保 /data 目录的数据持久化。
数据卷可以在容器间共享和重用,即使容器被删除,卷数据仍然存在
VOLUME 声明后,运行时可以通过 -v 参数覆盖,但无法在构建阶段向挂载点写入数据(会被运行时覆盖)。

VOLUME 指令格式:

bash
VOLUME ["<path1>", "<path2>", ...]
bash
示例:
# 声明单个卷
VOLUME /data
# 声明多个卷
VOLUME ["/data", "/config"]

USER 指令

切换执行后续指令的用户身份,用户必须已通过 RUN 指令创建。
例如 USER nobody 让后续命令以 nobody 身份运行,增强安全性。该用户需要有足够的权限访问所需文件。

USER 指令格式:

bash
USER <user>[:<group>]
bash
示例:
RUN groupadd -r app && useradd -r -g app appuser
USER appuser
CMD ["python", "app.py"]

ARG 指令

指令定义构建时的变量。这些变量只在构建阶段有效,不会保留到容器运行时。可以通过 docker build --build-arg <name>=<value> 覆盖默认值。
例如 ARG VERSION=latest 定义版本变量。ARG 变量可以用于控制构建流程,如选择不同的软件版本。

ARG 指令格式:

bash
ARG <name>[=<默认>]
bash
示例:
ARG NODE_VERSION=14
FROM node:${NODE_VERSION}

ONBUILD 指令

设置触发器。当当前镜像被用作其他镜像的基础时,这些指令会被触发执行。
例如 ONBUILD COPY . /app会在子镜像构建时自动复制文件。ONBUILD 常用于创建基础镜像模板,子镜像可以继承特定的构建步骤。
通过 docker inspect 可以查看镜像的 ONBUILD 触发器。

ONBUILD 指令格式:

bash
ONBUILD <其他指>
bash
示例:
ONBUILD RUN npm install
ONBUILD COPY . /app

STOPSIGNAL 指令

设置容器停止时发送的系统信号。信号可以是数字(如 9)或信号名(如 SIGKILL)。默认的信号是 SIGTERM,允许容器优雅退出。如果需要强制终止,可以设置为 SIGKILL。
例如 STOPSIGNAL SIGTERM 确保容器收到终止信号。这个设置会影响 docker stop 命令的行为。

STOPSIGNAL 指令格式:

bash
STOPSIGNAL <>
bash
示例:
STOPSIGNAL SIGQUIT

HEALTHCHECK 指令

定义容器健康检查,Docker 会定期执行检查命令判断容器是否健康。
检查命令返回 0 表示健康,1 表示不健康。
选项包括

  • -interval(检查间隔)、
  • -timeout(超时时间)、
  • -start-period(启动宽限期)
  • -retries(重试次数)。

例如 HEALTHCHECK --interval=30s CMD curl -f http://localhost/每 30 秒检查 Web 服务是否响应。健康状态可以通过 docker ps 查看。

HEALTHCHECK 指令格式:

bash
HEALTHCHECK [OPTIONS] CMD <command>
bash
示例:
HEALTHCHECK --interval=5m --timeout=3s \
  CMD curl -f http://localhost/ || exit 1
最近更新