构建生产级自定义镜像
从 Dockerfile 编写到镜像发布,包含多阶段构建、安全加固、镜像瘦身的完整流程
你将学到
- 编写高效的 Dockerfile
- 使用多阶段构建减小镜像体积
- 实施安全最佳实践
- 优化构建缓存
前置知识
架构设计
构建阶段 运行阶段
┌─────────────┐ ┌─────────────┐
│ 编译环境 │ │ 运行环境 │
│ (完整工具链) │ → │ (最小依赖) │
└─────────────┘ └─────────────┘
~1GB ~50MB
实现步骤
第一步:基础 Dockerfile
# 基础版本(不推荐)
FROM python:3.11
WORKDIR /app
COPY . .
RUN pip install -r requirements.txt
EXPOSE 8000
CMD ["python", "app.py"]
第二步:优化依赖安装
# 优化版本:利用缓存
FROM python:3.11-slim
WORKDIR /app
# 先复制依赖文件,利用缓存
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# 再复制代码
COPY . .
EXPOSE 8000
CMD ["python", "app.py"]
第三步:多阶段构建
# 多阶段构建:编译阶段
FROM python:3.11 AS builder
WORKDIR /app
COPY requirements.txt .
# 安装依赖到独立目录
RUN pip install --user --no-cache-dir -r requirements.txt
# 运行阶段
FROM python:3.11-slim
WORKDIR /app
# 从编译阶段复制依赖
COPY --from=builder /root/.local /root/.local
COPY . .
# 确保 PATH 包含用户安装目录
ENV PATH=/root/.local/bin:$PATH
EXPOSE 8000
CMD ["python", "app.py"]
第四步:安全加固
# 生产版本:安全加固
FROM python:3.11-slim AS builder
WORKDIR /app
COPY requirements.txt .
RUN pip install --user --no-cache-dir -r requirements.txt
FROM python:3.11-slim
# 创建非 root 用户
RUN groupadd -r appuser && useradd -r -g appuser appuser
WORKDIR /app
COPY --from=builder /root/.local /home/appuser/.local
COPY --chown=appuser:appuser . .
# 切换到非 root 用户
USER appuser
# 设置 PATH
ENV PATH=/home/appuser/.local/bin:$PATH
EXPOSE 8000
CMD ["python", "app.py"]
第五步:健康检查和元数据
# 完整生产版本
FROM python:3.11-slim AS builder
WORKDIR /app
COPY requirements.txt .
RUN pip install --user --no-cache-dir -r requirements.txt
FROM python:3.11-slim
# 元数据
LABEL maintainer="[email protected]"
LABEL version="1.0"
LABEL description="Production-ready Python app"
# 创建非 root 用户
RUN groupadd -r appuser && useradd -r -g appuser appuser
WORKDIR /app
COPY --from=builder /root/.local /home/appuser/.local
COPY --chown=appuser:appuser . .
USER appuser
ENV PATH=/home/appuser/.local/bin:$PATH
EXPOSE 8000
# 健康检查
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD python -c "import urllib.request; urllib.request.urlopen('http://localhost:8000/health')" || exit 1
CMD ["python", "app.py"]
第六步:构建和发布
# 构建镜像
docker build -t myapp:1.0 .
# 运行测试
docker run -d -p 8000:8000 --name myapp myapp:1.0
# 查看镜像大小
docker images myapp:1.0
# 打标签
docker tag myapp:1.0 username/myapp:1.0
docker tag myapp:1.0 username/myapp:latest
# 推送到 Docker Hub
docker push username/myapp:1.0
docker push username/myapp:latest
完整项目结构
myapp/
├── Dockerfile # 多阶段构建定义
├── requirements.txt # Python 依赖
├── app.py # 应用代码
└── .dockerignore # 排除文件
最佳实践
- 多阶段构建:分离编译和运行环境,减小镜像体积
- 使用 slim 基础镜像:python:3.11-slim 比 python:3.11 小很多
- 非 root 用户:避免容器以 root 权限运行
- 利用缓存:先复制依赖文件,再复制代码
- 健康检查:确保容器真正可用
常见问题
Q: 如何查看镜像层?
A: docker history myapp:1.0
Q: 如何减小镜像体积? A: 使用多阶段构建、slim 基础镜像、清理缓存。
Q: 如何扫描镜像安全漏洞?
A: 使用 docker scan myapp:1.0 或 Trivy。
扩展挑战
- 实现镜像自动构建流水线
- 添加镜像签名验证
- 实现多架构构建(amd64/arm64)
相关课程
| 课程 | 相关章节 |
|---|---|
| Docker | Dockerfile 基础 |
| Docker | 多阶段构建 |
| Docker | 层缓存优化 |
| Docker | USER 非 root |