04.Dockerfile
1. 什么是 Dockerfile
Dockerfile 是一个文本文件,包含了构建 Docker 镜像的所有指令。就像是镜像的”菜谱”,告诉 Docker 如何一步步构建出你需要的镜像。
1 2 3 4 5 6 7 8
| FROM node:18-alpine WORKDIR /app COPY package*.json ./ RUN npm install COPY . . EXPOSE 3000 CMD ["node", "app.js"]
|
2. 常用指令详解
FROM - 基础镜像
每个 Dockerfile 必须以 FROM 开始,指定基础镜像:
1 2 3 4 5 6 7 8 9 10 11
| FROM node:18-alpine
FROM python:3.11-slim
FROM alpine:3.18
FROM scratch
|
RUN - 执行命令
在镜像构建过程中执行命令:
1 2 3 4 5 6 7 8 9 10 11 12 13
| RUN apt-get update && apt-get install -y curl
RUN ["apt-get", "install", "-y", "curl"]
RUN apt-get update && \ apt-get install -y \ curl \ vim \ git && \ rm -rf /var/lib/apt/lists/*
|
COPY vs ADD
1 2 3 4 5 6 7
| COPY package.json /app/ COPY . /app/
ADD archive.tar.gz /app/ ADD https://example.com/file.txt /app/
|
建议: 优先使用 COPY,更明确、更可预测。
WORKDIR - 工作目录
ENV - 环境变量
1 2 3 4 5 6
| ENV NODE_ENV=production ENV APP_PORT=3000
ENV NODE_ENV=production \ APP_PORT=3000
|
EXPOSE - 声明端口
1 2 3
| EXPOSE 3000 EXPOSE 80 443
|
注意:EXPOSE 不会自动发布端口,运行时仍需 -p 参数。
CMD vs ENTRYPOINT
这是最容易混淆的两个指令:
1 2 3 4 5 6
| CMD ["node", "app.js"] CMD ["npm", "start"]
ENTRYPOINT ["python", "app.py"]
|
区别对比:
| 场景 |
CMD |
ENTRYPOINT |
| 被 docker run 参数覆盖 |
完全覆盖 |
参数追加 |
| 适用场景 |
默认命令,可灵活覆盖 |
固定入口,参数化执行 |
最佳实践 - 组合使用:
1 2 3 4 5
| ENTRYPOINT ["python", "app.py"] CMD ["--port", "8080"]
|
多阶段构建
减小最终镜像体积的利器:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| FROM node:18 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/package*.json ./ RUN npm install --production EXPOSE 3000 CMD ["node", "dist/index.js"]
|
3. Dockerfile 最佳实践
减小镜像体积
1 2 3 4 5 6 7 8 9 10 11
| FROM node:18-alpine
RUN apt-get update && \ apt-get install -y curl && \ rm -rf /var/lib/apt/lists/*
|
.dockerignore 示例:
1 2 3 4 5 6 7
| node_modules npm-debug.log .git .gitignore README.md .env *.md
|
利用构建缓存
把不常变化的指令放前面:
1 2 3 4 5 6 7 8 9 10 11
| FROM node:18-alpine WORKDIR /app
COPY package*.json ./ RUN npm install
COPY . .
RUN npm run build
|
安全性考虑
1 2 3 4 5 6 7 8 9 10
| FROM node:18-alpine RUN addgroup -S appgroup && adduser -S appuser -G appgroup USER appuser
FROM node:18.19.0-alpine
|