镜像与 Dockerfile¶
最小 Dockerfile¶
FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
EXPOSE 8000
CMD ["python", "app.py"]
构建建议¶
- 将依赖安装步骤放在前面,利用构建缓存。
- 使用明确版本的基础镜像,定期更新并扫描漏洞。
- 用
.dockerignore排除.git、虚拟环境、日志和密钥文件。 - 生产镜像优先使用多阶段构建,只保留运行所需内容。
FROM golang:1.24 AS build
WORKDIR /src
COPY . .
RUN go build -o app .
FROM gcr.io/distroless/base-debian12
COPY --from=build /src/app /app
ENTRYPOINT ["/app"]
镜像分层与缓存¶
Dockerfile 每个构建步骤通常产生可复用层。先复制依赖清单、安装依赖,再复制变化频繁的源码,可以避免每次都重新下载依赖。
# syntax=docker/dockerfile:1
FROM python:3.12-slim
WORKDIR /app
COPY pyproject.toml uv.lock ./
RUN --mount=type=cache,target=/root/.cache/uv \
pip install uv && uv sync --frozen --no-dev
COPY . .
构建缓存提升速度,但不会自动保证依赖最新。定期使用 --pull 获取更新后的基础镜像,并由依赖锁文件保证应用依赖可重现。
生产 Dockerfile 检查¶
- 固定基础镜像版本,重要环境记录 Digest。
- 多阶段构建分离编译工具与运行环境。
- 使用非 root 用户和明确 UID/GID。
COPY精确文件,不把整个仓库和 Secret 打入镜像。- 使用 exec 形式 ENTRYPOINT/CMD 正确接收信号。
- 不在镜像中运行 SSH、systemd 和多个无关服务。
- 运行配置、数据库地址和密码由外部注入。
- 标签记录源码版本、构建时间和项目地址。
FROM eclipse-temurin:21-jre
RUN groupadd -g 10001 app && useradd -r -u 10001 -g app app
WORKDIR /app
COPY --chown=10001:10001 app.jar /app/app.jar
USER 10001:10001
ENTRYPOINT ["java", "-jar", "/app/app.jar"]
.dockerignore¶
.dockerignore 减少构建上下文、避免缓存无谓失效,也降低密钥和本地文件误入镜像风险。它不是 Secret 管理方案,敏感文件仍不应放在构建目录。
BuildKit Secret¶
私有依赖凭据不要通过 ARG/ENV 传入,使用 BuildKit Secret Mount:
检查与验证¶
docker build --pull -t app:1.0.0 .
docker image history app:1.0.0
docker image inspect app:1.0.0
docker run --rm --read-only app:1.0.0 --version
CI 中还应运行容器健康测试、镜像漏洞扫描、Secret 扫描、SBOM 生成和签名/来源验证。镜像小不是唯一目标,可更新、可审计和具备必要诊断能力同样重要。
官方参考:Docker build best practices、Multi-stage builds、Build secrets。