使用 Dockerfile 构建镜像,本质就是把你的应用环境“写”进一个文件,再通过一条命令生成镜像。本文将从最核心的流程讲起,带你掌握常用指令和实用技巧,帮助你快速上手 Docker 镜像构建。
下面通过流程图来直观展示整个构建过程:
flowchart TD
A["编写 Dockerfile"] --> B["执行 docker build"]
B --> C["Docker 守护进程解析指令"]
C --> D["逐层构建镜像层"]
D --> E["输出最终镜像"]Dockerfile 是一个文本文件,里面包含了一条条构建镜像所需的指令。下面是一个基于 Node.js 应用的示例:
# 基础镜像
FROM node:18-alpine
# 设置工作目录
WORKDIR /app
# 复制依赖文件
COPY package*.json ./
RUN npm install
# 复制源码
COPY . .
# 声明端口
EXPOSE 3000
# 启动命令
CMD ["node", "app.js"]在 Dockerfile 所在目录执行以下命令即可构建镜像:
docker build -t my-app:v1 .-t:给镜像起名字和标签(name:tag).:指定构建上下文为当前目录如果文件名不叫 Dockerfile,可以用 -f 指定:
docker build -f MyDockerfile -t my-app .下表列出了 Dockerfile 中最常用的指令及其作用:
指令 | 说明 |
|---|---|
| 指定基础镜像 |
| 设定工作目录,后续命令都在此目录下执行 |
| 把宿主机文件复制到镜像中 |
| 在构建时执行命令,例如安装依赖 |
| 容器启动时的默认命令,一个 Dockerfile 中只能有一个有效 |
| 容器入口点,常与 |
| 设置环境变量 |
| 声明容器监听的端口 |
多阶段构建允许你先在一个中间阶段编译或构建应用,再将最终产物复制到更精简的运行镜像中,从而大幅减小最终镜像的体积。
# 第一阶段:构建
FROM node:18-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build
# 第二阶段:运行
FROM node:18-alpine
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
EXPOSE 3000
CMD ["node", "dist/main.js"]Docker 会逐层缓存构建结果。把不经常变动的层(如 npm install)放在前面,把改动频繁的 COPY . . 往后放,可以充分利用缓存,加快后续构建速度。
.dockerignore 文件类似于 .gitignore,.dockerignore 文件用于忽略不需要打包进镜像的文件或目录,例如 node_modules、.git 等。这不仅能加快构建速度,还能避免敏感文件泄露。
示例 .dockerignore:
node_modules
.git
.env
Dockerfile
.dockerignore在 Dockerfile 构建过程中,难免会遇到一些让人头疼的报错。下面整理了 4 个高频错误,并给出排查思路和解决方案。
错误信息示例:
COPY failed: file not found in build context or excluded by .dockerignore常见原因:
.dockerignore 排除。排查步骤:
docker build 命令末尾的上下文路径(.)指向了正确的目录。ls 或 dir 验证)。.dockerignore 文件,确认没有误排除该文件。解决方案:
COPY ./src/app.js /app/ 中 ./src/app.js 必须相对于构建上下文存在。docker build -f docker/Dockerfile -t my-app . 将上下文设为父目录,然后 Dockerfile 中使用相对路径 COPY src/app.js /app/。错误信息示例:
The command '/bin/sh -c apt-get install -y curl' returned a non-zero code: 100常见原因:
&& 连接)。排查步骤:
RUN 命令输出的详细错误信息。解决方案:
apt-get 等包管理器,构建前先执行 apt-get update,并合并为一条 RUN 指令以减少层数:RUN apt-get update && apt-get install -y curldocker build --no-cache -t my-app .。错误现象:修改了 package.json 或 requirements.txt,但 npm install / pip install 没有重新执行,镜像中依然是旧依赖。
原因:
Docker 按层缓存。如果 COPY package*.json ./ 这层没有变化(因为 Docker 认为文件内容未变),后续的 RUN npm install 就会直接使用缓存,不会重新运行。
排查步骤:
package.json 是否真的被修改(检查文件内容或时间戳)。COPY 指令是否正确复制了依赖文件,且该指令在 RUN install 之前。docker history <image> 查看镜像构建历史,确认缓存命中情况。解决方案:
COPY 指令中的文件列表与依赖文件完全一致。--no-cache 构建:docker build --no-cache -t my-app .。RUN 命令中加入版本号变量或构建参数,使其每次变化:ARG CACHEBUST=1
RUN npm install构建时传入 --build-arg CACHEBUST=$(date +%s) 可强制跳过该层缓存。错误信息示例:
Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?或
Got permission denied while trying to connect to the Docker daemon socket常见原因:
docker 用户组,没有权限访问 Docker 守护进程。排查步骤:
systemctl status docker 或 service docker statusdocker ps 能否正常执行?若报权限错误,说明用户不在 docker 组。groups 查看当前用户所属组,是否包含 docker。解决方案:
sudo systemctl start dockerdocker 组(需重新登录生效):sudo usermod -aG docker $USER
newgrp dockerDOCKER_HOST 环境变量是否设置正确,通常无需设置,保持默认即可。5. 总结通过 Dockerfile 构建镜像,你可以将应用环境标准化、版本化,实现“一次构建,到处运行”。本文介绍了 Dockerfile 的核心编写流程、常用指令以及多阶段构建等实用技巧。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。