Docker 安全加固:生产环境必须检查的清单
目录
背景
大多数 Docker 安全事件不是黑客发现了什么 0day,是你忘了关特权模式、用了 root 运行容器、或者开放了不必要的端口。
这篇文章是实战清单,不讲原理,直接告诉你做什么检查。
基础配置检查
1. 不要用 root 运行容器
# ❌ 错误:容器内用 root
FROM node:20
WORKDIR /app
COPY . .
RUN npm install
CMD ["node", "server.js"]
# ✅ 正确:创建非 root 用户
FROM node:20
WORKDIR /app
COPY --chown=node:node . .
USER node
CMD ["node", "server.js"]# Kubernetes 里也适用
securityContext:
runAsNonRoot: true
runAsUser: 10002. 只读文件系统
# docker-compose.yml
services:
app:
read_only: true
# 需要写入的地方用 tmpfs
tmpfs:
- /tmp
- /var/run容器内文件系统是只读的,恶意代码无法写入。
3. 限制 Capabilities
Linux capabilities 是root权限的精细切分。容器不需要 CAP_SYS_ADMIN。
# docker-compose.yml
services:
app:
cap_drop:
- ALL
cap_add:
- NET_BIND_SERVICE # 仅添加需要的# 检查当前容器 capabilities
docker inspect container_name | grep -i cap镜像安全
4. 用 distroless 或 alpine
# ❌ 不用 ubuntu/debian(200+MB,系统漏洞面大)
FROM ubuntu:22.04
# ✅ 用 distroless(最小化,只有运行时需要的)
FROM gcr.io/distroless/static-debian12
# ✅ 或 alpine(轻量,只有 5MB)
FROM alpine:3.195. 不缓存依赖(构建时)
# ❌ 错误:把整个项目 COPY 进去再装依赖
COPY . .
RUN npm install
# ✅ 正确:先复制 package.json,装依赖,再复制代码
COPY package.json package-lock.json* ./
RUN npm ci --only=production
COPY . .好处:
- 依赖安装失败时能快速定位
- Docker 构建缓存利用更高效
- 减少镜像层大小
6. 设置 health check
FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
EXPOSE 3000
HEALTHCHECK --interval=30s --timeout=3s \
CMD wget --no-verbose --tries=1 --spider http://localhost:3000/health || exit 1
CMD ["node", "server.js"]网络隔离
7. 网络最小化
services:
app:
networks:
- backend-network
db:
networks:
- backend-network
# DB 不需要暴露到外部
networks:
backend-network:
driver: bridge应用只暴露 API 端口,数据库完全在内网。
8. 不用 host 网络模式
# ❌ 危险:容器直接用宿主机网络
network_mode: "host"
# ✅ 正确:默认 bridge,必要时用端口映射
services:
app:
ports:
- "8080:3000"host 模式绕过了 Docker 的网络隔离,容器可以直接访问宿主机网络。
密钥管理
9. 不用环境变量存密钥
# ❌ 危险:密钥写在环境变量里
environment:
DATABASE_PASSWORD: "supersecret"
# ✅ 正确:用 Docker secrets(Swarm 模式)
secrets:
db_password:
file: ./db_password.txt
services:
app:
secrets:
- source: db_password
target: db_password
mode: 0400
# ✅ 或者用外部密钥管理(Vault、AWS Secrets Manager)# Kubernetes 用 external secrets
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: app-secrets
spec:
secretStoreRef:
name: vault-backend
target:
name: app-secrets
data:
- secretKey: db-password
remoteRef:
key: prod/database/password运行时安全
10. 用 AppArmor / seccomp 限制系统调用
# 默认 seccomp 配置已经屏蔽了 44 个危险系统调用
# 但有些场景需要更严格
# 查看默认 seccomp
docker run --rm \
alpine \
cat /proc/sys/kernel/seccomp/action_on_sigfault生产环境建议用非特权容器:
security_opt:
- no-new-privileges:true11. 资源限制
services:
app:
deploy:
resources:
limits:
cpus: '0.5'
memory: 512M
reservations:
cpus: '0.25'
memory: 256M防止容器耗尽宿主机资源。
CI/CD 安全检查
12. Trivy 扫描镜像漏洞
# .github/workflows/ci.yml
- name: Scan image for vulnerabilities
uses: aquasecurity/trivy-action@master
with:
image-ref: ${{ env.IMAGE_TAG }}
format: 'sarif'
severity: 'CRITICAL,HIGH'
exit-code: '1' # 发现漏洞就 fail# 本地也跑一下
trivy image your-image:tag
# 扫描已知 CVE
trivy image -- vuln-type=os,library your-image:tag13. 不要用 :latest
# ❌ :latest 意味着你不知道实际版本
image: myapp:latest
# ✅ 用确定版本
image: myapp:v2.3.1
image: myapp@sha256:abc123...总结清单
生产环境 Docker 必须做:
□ 非 root 用户运行
□ 文件系统只读
□ Capabilities 最小化
□ distroless/alpine 基础镜像
□ health check
□ 网络隔离
□ 不用 host 模式
□ 密钥不用 env 存
□ 资源限制
□ CI/CD 漏洞扫描
□ 固定镜像版本这条清单过一遍,大多数 Docker 安全事件可以避免。