跳转至

镜像与 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"]
docker build -t example/app:1.0.0 .
docker run --rm -p 8000:8000 example/app:1.0.0

构建建议

  • 将依赖安装步骤放在前面,利用构建缓存。
  • 使用明确版本的基础镜像,定期更新并扫描漏洞。
  • .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

.git
.env
*.log
**/__pycache__
.venv
node_modules
target
build

.dockerignore 减少构建上下文、避免缓存无谓失效,也降低密钥和本地文件误入镜像风险。它不是 Secret 管理方案,敏感文件仍不应放在构建目录。

BuildKit Secret

私有依赖凭据不要通过 ARG/ENV 传入,使用 BuildKit Secret Mount:

RUN --mount=type=secret,id=pip_conf,target=/etc/pip.conf \
    pip install -r requirements.txt
docker build --secret id=pip_conf,src=./pip.conf -t app:1.0.0 .

检查与验证

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 practicesMulti-stage buildsBuild secrets