一句话总结
Docker 镜像优化:选最小基础镜像(alpine < slim < 完整版)、多阶段构建(分离构建与运行)、合并 RUN 层(减少镜像层数)、.dockerignore(排除无关文件)。安全实践:非 root 运行(USER 指令)、镜像安全扫描(Trivy/Clair 扫描 CVE 漏洞)、镜像签名(Docker Content Trust 防篡改)、私有仓库(Harbor 提供漏洞扫描+镜像管理)、只读文件系统(--read-only)、限制资源(--memory/--cpus)。
初级理解
镜像瘦身策略
# 1. 选择最小基础镜像
# Java 应用镜像大小对比:
# openjdk:11 → ~600MB(完整 JDK)
# openjdk:11-jre → ~300MB(只有 JRE)
# openjdk:11-jre-slim → ~200MB(精简版)
# openjdk:11-jre-alpine → ~100MB(Alpine Linux)
# distroless-java:11 → ~120MB(Google 无发行版)
# 2. 多阶段构建(前面已讲)
# 构建阶段用 maven:3.8-openjdk-11
# 运行阶段用 openjdk:11-jre-slim
# 最终镜像不含 Maven/JDK 编译工具
# 3. 减少层数
# 不推荐(4层):
RUN apt update
RUN apt install -y curl
RUN apt install -y vim
RUN apt clean
# 推荐(1层):
RUN apt update && \
apt install -y curl vim && \
apt clean && \
rm -rf /var/lib/apt/lists/*
# 4. 清理临时文件
# 在同一个 RUN 中安装和清理
# 不要在单独的 RUN 中清理(前面的层已固化)
中级深入
镜像安全扫描
# Trivy(Aqua Security,推荐)
# 安装:
# Linux: curl -sfL https://raw.githubusercontent.com/... | sh
# Mac: brew install trivy
# 扫描镜像:
trivy image nginx:latest
trivy image --severity HIGH,CRITICAL myapp:latest
# 输出:CVE 编号、严重程度、影响组件、修复版本
# 集成到 CI/CD:
# GitHub Actions 示例:
- name: Scan image
uses: aquasecurity/trivy-action@master
with:
image-ref: myapp:${{ github.sha }}
format: table
exit-code: 1 # 有高危漏洞则失败
severity: CRITICAL,HIGH
# Docker Scout(Docker 官方):
docker scout quickview myapp:latest
docker scout recommendations myapp:latest
私有仓库 Harbor
# Harbor 功能:
# 1. 镜像存储与管理
# 2. 漏洞扫描(集成 Trivy/Clair)
# 3. 镜像签名(Notary)
# 4. 访问控制(项目/角色/用户)
# 5. 镜像复制(跨数据中心同步)
# 6. 镜像清理策略(保留最近 N 个版本)
# Harbor 部署(docker-compose):
wget https://github.com/goharbor/harbor/releases/...
tar xzf harbor-offline-installer-*.tgz
cd harbor
cp harbor.yml.tmpl harbor.yml
# 编辑 harbor.yml(配置域名、密码等)
./install.sh
# 使用:
docker login harbor.example.com
docker tag myapp:latest harbor.example.com/project/myapp:v1
docker push harbor.example.com/project/myapp:v1
高级进阶
容器运行时安全
# 1. 非 root 用户运行
docker run --user 1000:1000 myapp
# 或在 Dockerfile 中:
USER 1000
# 2. 只读文件系统
docker run --read-only myapp
# 需要写入的目录用 tmpfs 或 volume
docker run --read-only \
-v /tmp \
-v /var/run \
myapp
# 3. 限制容器能力(Capabilities)
# 默认容器有部分 root 能力
# 去掉不必要的能力:
docker run --cap-drop=ALL \
--cap-add=NET_BIND_SERVICE \
myapp
# 4. 禁止特权模式
# 不推荐(危险):
docker run --privileged myapp
# 推荐:只添加必要的能力
# 5. 资源限制(防资源耗尽)
docker run \
--cpus=2 \
--memory=512m \
--memory-swap=1g \
--pids-limit=100 \
myapp
# 6. 安全选项
docker run \
--security-opt=no-new-privileges \
--security-opt=seccomp=/path/to/profile.json \
myapp
镜像签名(Docker Content Trust)
# Docker Content Trust(DCT):
# 对镜像进行数字签名,确保镜像未被篡改
# 启用 DCT:
export DOCKER_CONTENT_TRUST=1
# 签名并推送:
docker trust signer add --key signer.pem alice registry.example.com
docker trust sign registry.example.com/myapp:latest
# 拉取时自动验证签名:
docker pull registry.example.com/myapp:latest
# 如果签名无效或不存在,拒绝拉取
# Notary 架构:
# 1. 开发者签名镜像
# 2. 签名存储在 Notary 服务
# 3. 拉取时验证签名
# 4. 确保镜像来源可信、未被篡改
实战场景
# 场景1:CI/CD 集成安全扫描
# Jenkinsfile / GitHub Actions:
stages:
- build
- scan # 安全扫描
- push
- deploy
# 扫描阶段:
trivy image --severity HIGH,CRITICAL \
--exit-code 1 myapp:${BUILD_ID}
# 有高危漏洞则构建失败
# 场景2:生产环境容器安全配置
docker run -d \
--name myapp \
--user 1000:1000 \ # 非 root
--read-only \ # 只读文件系统
--cap-drop=ALL \ # 去掉所有能力
--cap-add=NET_BIND_SERVICE \ # 只加绑定端口
--cpus=2 \ # CPU 限制
--memory=512m \ # 内存限制
--pids-limit=100 \ # 进程数限制
--security-opt=no-new-privileges \
myapp:latest
# 场景3:定期扫描运行中的容器
docker ps -q | xargs -I {} \
docker inspect {} --format='{{.Image}}' \
| sort -u | xargs -I {} trivy image {}
面试模拟
面试官:如何优化 Docker 镜像大小?
你:1)选最小基础镜像(alpine/slim);2)多阶段构建(分离构建和运行环境);3)合并 RUN 指令减少层数;4).dockerignore 排除无关文件;5)清理包管理器缓存(同一 RUN 中清理);6)使用 distroless 镜像(不含 shell 和包管理器)。
面试官:Docker 容器安全有哪些实践?
你:1)非 root 用户运行(USER 指令);2)镜像安全扫描(Trivy 扫描 CVE);3)镜像签名(DCT 防篡改);4)只读文件系统(--read-only);5)限制容器能力(--cap-drop);6)资源限制(--memory/--cpus);7)使用私有仓库(Harbor);8)定期更新基础镜像。