详细介绍如何使用 Docker Hardened Images 编写生产级多阶段 Dockerfile,并配置 GitHub Actions 自动完成镜像构建、DHI 策略检查与流水线失败机制。
通过本博客,你将掌握:
一套简洁、可投入生产的多阶段 Dockerfile,正确使用 Docker Hardened Images
一套 GitHub Actions 工作流,具备以下能力:
这将此前所有博客中的内容转化为可重复、自动化的实践。
仅有本地可用的 Dockerfile 是不够的。在真实团队中,镜像必须以完全相同的方式构建,安全检查也必须自动化。
如果策略检查只在开发者的笔记本上运行,那它在压力下就会被跳过。如果 CI 无法从 dhi.io 拉取镜像,构建就会随机失败。如果 Dockerfile 仍然使用臃肿的基础镜像或以 root 身份运行,那加固后的基础镜像就会失去大部分价值。
本博客正是为了解决这些缺口。
以下是我为大多数语言框架推荐的模式(Python 示例):
# syntax=docker/dockerfile:1
# ---------- Build stage ----------
FROM dhi.io/python:3.13-dev AS builder
ENV PYTHONDONTWRITEBYTECODE=1 \
PYTHONUNBUFFERED=1 \
PATH="/app/venv/bin:$PATH"
WORKDIR /app
# Create isolated environment
RUN python -m venv /app/venv
COPY requirements.txt .
RUN --mount=type=cache,target=/root/.cache/pip \
pip install --no-cache-dir -r requirements.txt
# ---------- Runtime stage ----------
FROM dhi.io/python:3.13
ENV PYTHONDONTWRITEBYTECODE=1 \
PYTHONUNBUFFERED=1 \
PATH="/app/venv/bin:$PATH"
WORKDIR /app
# Copy only what is required
COPY --from=builder /app/venv /app/venv
COPY app.py .
# Runtime image already defaults to non-root
EXPOSE 8000
CMD ["python", "app.py"]

所有需要包管理器或编译器的东西都留在第一阶段。只有最终的产物被复制到加固后的运行时镜像中。
docker build -t my-dhi-app:local .
docker run --rm -p 8000:8000 my-dhi-app:local
# Policy check
docker scout policy my-dhi-app:local --policy-bundle dhi/policies:latest
在推送之前修复任何失败。
创建 .github/workflows/dhi-build.yml:
name: Build and check with Docker Hardened Images
on:
push:
branches: [ "main" ]
pull_request:
env:
IMAGE_NAME: my-dhi-app:${{ github.sha }}
jobs:
build-and-policy:
runs-on: ubuntu-latest
steps:
- name: Check out code
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to Docker Hub (for Scout + policy bundle)
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USER }}
password: ${{ secrets.DOCKER_PAT }}
- name: Log in to dhi.io
uses: docker/login-action@v3
with:
registry: dhi.io
username: ${{ secrets.DOCKER_USER }}
password: ${{ secrets.DOCKER_PAT }}
- name: Build image
uses: docker/build-push-action@v6
with:
context: .
load: true
tags: ${{ env.IMAGE_NAME }}
cache-from: type=gha
cache-to: type=gha,mode=max
- name: Evaluate against DHI policies
uses: docker/scout-action@v1
with:
command: policy
image: ${{ env.IMAGE_NAME }}
policy-bundle: dhi/policies:latest
exit-code: true # fail the job if any policy is violated
在仓库设置 → Secrets and variables → Actions 中,添加:
DOCKER_USER — 你的 Docker Hub 用户名DOCKER_PAT — 具有读取权限的个人访问令牌(如果后续要推送镜像则需要写入权限):latest 以确保可重复性将最终阶段临时改回普通的 python:3.13 镜像。观察策略步骤失败(root 用户、多余的包、缺失的证明等)。再恢复到 DHI 运行时阶段,看流水线重新变绿。
在真实团队中,我会:
-dev 镜像的例外情况(几乎永远不合理的)exit-code: false 导致策略检查永远不会让构建失败:latest 标签你的机器上不会创建任何永久资源。在 GitHub 中,你可以在完成后删除工作流文件或测试分支。
-dev 构建阶段 + 纯运行时阶段的多阶段是标准模式你现在拥有了一条从代码到加固生产镜像的完整自动化路径。
在最后的博客(第 5 篇)中,我们将介绍现有应用的迁移、生产采纳清单、加固系统包概览、已知限制,以及如何将 Docker Hardened Images 与 Sandboxes 系列结合,形成完整的安全开发生 Workflow。
https://docs.docker.com/dhi/how-to/use/ — 多阶段模式和 CI 说明
https://docs.docker.com/dhi/how-to/policies/ — 策略包和 GitHub Actions 示例
https://docs.docker.com/build/cache/backends/gha/ — GitHub Actions 缓存
Official Scout GitHub Action 文档
所有命令和工作流模式均已根据当前官方文档(2026 年 8 月)进行过验证。