Dockerfile(四)
4.Dockerfile
Dockerfile 是用于构建 Docker 镜像的脚本文件,里面包含一组指令,用来定义如何生成镜像。
Docker 构建镜像时,会将 Dockerfile 中的每条指令生成一个镜像层,最终组合成完整镜像。分层结构使镜像更易复用、缓存更高效。
在实际开发中,官方镜像通常只提供基础环境,而应用依赖、配置和代码需要通过 Dockerfile 自定义构建。

一、简单使用
示例:基于官方 nginx 镜像自定义网页。
- 创建目录并新建 Dockerfile:
myweb/
└─ Dockerfile- Dockerfile 内容:
FROM nginx:latest
RUN echo '<h1>My Custom Nginx Page</h1>' > /usr/share/nginx/html/index.html
EXPOSE 80说明:
FROM nginx:latest:选择基础镜像RUN:写入自定义网页EXPOSE 80:声明端口
- 构建镜像:
docker build -t my-web .- 查看镜像:
docker images- 启动容器并访问:
docker run -d -p 80:80 my-web访问浏览器 http://localhost 即可看到自定义网页。
二、常用指令
常用指令速查表
| 指令 | 简要说明 |
|---|---|
FROM |
指定基础镜像(必须第一行) |
LABEL |
添加元数据(键值对) |
RUN |
构建时执行的命令 |
CMD |
容器启动默认命令(可被覆盖) |
ENTRYPOINT |
容器启动主命令(不可被覆盖) |
SHELL |
修改默认 Shell |
EXPOSE |
声明监听端口 |
ENV |
设置环境变量(持久化) |
COPY |
复制文件/目录到镜像 |
ADD |
增强版 COPY(支持解压、URL) |
WORKDIR |
切换工作目录 |
VOLUME |
创建挂载点/匿名卷 |
USER |
切换执行用户 |
ARG |
构建时变量(构建阶段有效) |
ONBUILD |
触发器(子镜像构建时执行) |
STOPSIGNAL |
设置停止容器时的系统信号 |
HEALTHCHECK |
定义容器健康检查命令 |
1. FROM
作用:指定基础镜像,必须是 Dockerfile 第一条指令。
格式:
FROM 镜像[:标签] [AS 阶段名]示例:
FROM nginx:1.23 FROM python:3.9-alpine AS builder注意:可使用多个 FROM 实现多阶段构建,最终只保留最后一个阶段。
2. LABEL
作用:添加元数据(如版本、维护者)。
格式:
LABEL 键=值示例:
LABEL version="1.0.1" LABEL maintainer="admin@example.com"
3. RUN
作用:构建时执行命令,每条 RUN 生成一个新层。
格式:
- Shell 格式(推荐):
RUN <命令> - Exec 格式:
RUN ["可执行文件", "参数1", "参数2"]
- Shell 格式(推荐):
示例:
RUN apt-get update && apt-get install -y git RUN ["yum", "-y", "install", "wget"]最佳实践:多个命令用
&&合并,减少镜像层数。
4. CMD
作用:容器启动时的默认命令(可被
docker run后的命令覆盖)。格式:
- Exec 格式(推荐):
CMD ["可执行文件", "参数1"] - Shell 格式:
CMD 命令 参数1 - 作为 ENTRYPOINT 参数:
CMD ["参数1", "参数2"]
- Exec 格式(推荐):
示例:
# Shell 格式示例: 运行 Python 脚本 CMD python app.py # Exec 格式示例: 运行 Nginx CMD ["nginx", "-g", "daemon off;"] # 作为 ENTRYPOINT 参数 CMD ["--port=8080"]注意:一个 Dockerfile 只能有一个有效 CMD。
5. ENTRYPOINT
作用:容器启动主命令,不会被
docker run后面的命令覆盖(但可追加参数)。格式:
- Shell 格式:
ENTRYPOINT 命令 参数 - Exec 格式:
ENTRYPOINT ["可执行文件", "参数"]
- Shell 格式:
示例:
# Shell 格式示例: 运行 Python 脚本 ENTRYPOINT python app.py # Exec 格式示例: 运行 Nginx ENTRYPOINT ["nginx", "-g", "daemon off;"]与 CMD 搭配:ENTRYPOINT 定义固定命令,CMD 提供默认参数。
6. SHELL
作用:覆盖默认 Shell(Linux 默认
/bin/sh -c,Windows 默认cmd)。格式:
SHELL ["可执行文件", "参数"]示例:
# 切换为 PowerShell SHELL ["powershell", "-command"] # 切换回默认 shell SHELL ["/bin/sh", "-c"]
7. EXPOSE
作用:声明容器监听的端口(文档说明,不实际映射端口)。
格式:
EXPOSE 端口号[/协议]示例:
# 声明单个端口 EXPOSE 80 # 声明多个端口 EXPOSE 80 443 # 指定协议 EXPOSE 53/udp提示:运行时仍需用
-p映射端口。
8. ENV
作用:设置环境变量(构建和运行时均生效)。
格式:
- 单变量:
ENV 键 值 - 多变量:
ENV 键1=值1 键2=值2
- 单变量:
示例:
# 设置单个变量 ENV NODE_VERSION=18.15.0 # 设置多个变量 ENV NODE_VERSION=18.15.0 NODE_ENV=production
9. COPY
作用:将构建上下文中的文件/目录复制到镜像中(保留元数据)。
格式:
COPY <源路径>... <目标路径>示例:
# 复制单个文件 COPY requirements.txt /app/ # 复制整个目录 COPY src /app/src # 使用通配符复制多个文件 COPY *.sh /scripts/注意:源路径必须是相对路径,不支持自动解压。
10. ADD
作用:功能类似 COPY,额外支持:
- 自动解压本地
.tar、.gz等压缩包 - 从 URL 下载文件
- 自动解压本地
格式:
ADD <源路径>... <目标路径>示例:
# 添加本地文件 ADD app.jar /opt/app/ # 自动解压压缩包 ADD project.tar.gz /app # 从 URL 下载文件 ADD https://example.com/data.json /data建议:除非需要解压或下载,否则优先使用 COPY。
11. WORKDIR
作用:设置工作目录(不存在则自动创建),后续指令基于此目录。
格式:
WORKDIR <路径>示例:
WORKDIR /usr/src WORKDIR app # 最终路径为 /usr/src/app
12. VOLUME
作用:创建挂载点或匿名卷,用于数据持久化。
格式:
VOLUME ["路径1", "路径2"]示例:
# 声明单个卷 VOLUME /data # 声明多个卷 VOLUME ["/data", "/config"]注意:构建阶段无法向 VOLUME 写入数据(运行时会被覆盖)。
13. USER
作用:切换后续指令的执行用户(用户必须已存在)。
格式:
USER 用户名[:用户组]示例:
RUN groupadd -r app && useradd -r -g app appuser USER appuser
14. ARG
作用:定义构建时的变量(仅构建阶段有效,可通过
docker build --build-arg <name>=<value>覆盖)。格式:
ARG 变量名[=默认值]示例:
ARG NODE_VERSION=14 FROM node:${NODE_VERSION}
15. ONBUILD
作用:设置触发器,当当前镜像被用作其他镜像的基础时自动执行。
格式:
ONBUILD <其他指令>示例:
ONBUILD COPY . /app ONBUILD RUN npm install
16. STOPSIGNAL
作用:设置
docker stop时发送给容器的系统信号。格式:
STOPSIGNAL <信号>示例:
STOPSIGNAL SIGQUIT
17. HEALTHCHECK
作用:定义容器健康检查命令,Docker 定期执行。
格式:
HEALTHCHECK [选项] CMD <命令>常用选项:
--interval=<间隔>(默认 30s)--timeout=<超时>(默认 30s)--start-period=<启动宽限期>(默认 0s)--retries=<重试次数>(默认 3)
示例:
HEALTHCHECK --interval=30s --timeout=3s \ CMD curl -f http://localhost/ || exit 1
使用建议
基础镜像:优先选择官方最小化镜像(如
alpine)以减小体积。层数控制:将多个
RUN命令合并为一个,避免产生过多镜像层。COPY vs ADD:优先使用
COPY,除非确实需要自动解压或下载。CMD vs ENTRYPOINT:
- 需要固定主程序 + 允许追加参数 →
ENTRYPOINT +CMD - 允许完全覆盖启动命令 → 仅用
CMD
- 需要固定主程序 + 允许追加参数 →
安全性:避免使用 root 用户运行容器,通过
USER切换至非特权用户。健康检查:为长期运行的服务配置
HEALTHCHECK,便于自动化运维。
三、实际使用
核心思路
每个 Dockerfile 都遵循相同的通用流程:
- 选择合适的基础镜像(尽量轻量)
- 设置工作目录
- 复制必要文件
- 安装依赖 / 构建应用
- 声明端口
- 定义启动命令
1.构建 Python Web 应用镜像
Dockerfile 示例:
FROM python:3.9-slim
WORKDIR /app
COPY . .
RUN pip install --no-cache-dir -r requirements.txt
EXPOSE 5000
ENV FLASK_APP=app.py
ENV FLASK_ENV=production
CMD ["flask", "run", "--host=0.0.0.0"]关键步骤说明:
| 步骤 | 指令 | 说明 |
|---|---|---|
| 基础镜像 | FROM python:3.9-slim |
使用官方 Python 轻量版 |
| 工作目录 | WORKDIR /app |
后续操作都在 /app 下 |
| 复制代码 | COPY . . |
将本地所有文件复制到容器 /app |
| 安装依赖 | RUN pip install --no-cache-dir -r requirements.txt |
不保留缓存以减小镜像体积 |
| 端口声明 | EXPOSE 5000 |
Flask 默认端口 |
| 环境变量 | ENV FLASK_APP=app.py FLASK_ENV=production |
指定应用入口及运行环境 |
| 启动命令 | CMD ["flask", "run", "--host=0.0.0.0"] |
监听所有地址 |
构建与运行:
# 构建镜像(注意最后的 . 表示当前目录为构建上下文)
docker build -t my-python-app .
# 运行容器(后台运行,映射宿主机 5000 端口)
docker run -d -p 5000:5000 my-python-app2.构建 Node.js 应用镜像
Dockerfile 示例:
FROM node:16-alpine
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build
EXPOSE 3000
CMD ["npm", "start"]关键步骤说明:
| 步骤 | 指令 | 说明 |
|---|---|---|
| 基础镜像 | FROM node:16-alpine |
基于 Alpine 的 Node.js 轻量镜像 |
| 工作目录 | WORKDIR /usr/src/app |
标准 Node 应用目录 |
| 分层复制(优化缓存) | 先复制 package*.json,再复制源码 |
利用 Docker 缓存,避免依赖每次重新安装 |
| 安装依赖 | RUN npm install |
安装所有依赖包 |
| 复制源码 | COPY . . |
复制剩余代码 |
| 构建应用 | RUN npm run build |
执行前端/后端构建脚本 |
| 端口声明 | EXPOSE 3000 |
常见 Node 应用端口 |
| 启动命令 | CMD ["npm", "start"] |
运行生产启动脚本 |
构建与运行:
docker build -t my-node-app .
docker run -d -p 3000:3000 my-node-app3.构建 Nginx 静态网站镜像
Dockerfile 示例:
FROM nginx:alpine
RUN rm -rf /etc/nginx/conf.d/default.conf
COPY nginx.conf /etc/nginx/conf.d/
COPY dist/ /usr/share/nginx/html/
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]关键步骤说明:
| 步骤 | 指令 | 说明 |
|---|---|---|
| 基础镜像 | FROM nginx:alpine |
极轻量的 Nginx 镜像 |
| 清理默认配置 | RUN rm -rf /etc/nginx/conf.d/default.conf |
移除默认站点配置 |
| 复制自定义配置 | COPY nginx.conf /etc/nginx/conf.d/ |
放入自定义虚拟主机配置 |
| 复制静态文件 | COPY dist/ /usr/share/nginx/html/ |
将构建好的静态网站复制到 Nginx 默认目录 |
| 端口声明 | EXPOSE 80 |
HTTP 标准端口 |
| 启动命令 | CMD ["nginx", "-g", "daemon off;"] |
前台运行 Nginx(容器必须前台进程) |
配套 nginx.conf 示例:
server {
listen 80;
server_name localhost;
location / {
root /usr/share/nginx/html;
index index.html;
try_files $uri $uri/ /index.html;
}
}构建与运行:
docker build -t my-static-site .
docker run -d -p 8080:80 my-static-site # 宿主8080映射容器80最佳实践要点
- 基础镜像:优先选择
-alpine、-slim等轻量版本,减小最终镜像体积。 - 缓存利用:Node.js 示例中先复制
package.json再安装依赖,可避免代码变更导致依赖重装。 - 前台进程:容器启动命令必须保持前台运行(如 Nginx 的
daemon off;),否则容器会立即退出。 - 端口映射:
EXPOSE 仅为文档说明,真正映射端口需要在docker run 时使用-p。 - 构建上下文:
docker build 命令最后的. 表示当前目录为构建上下文,Dockerfile 中的COPY只能访问上下文内的文件。