主题
Docker 安全
容器并非天然隔离的沙箱,错误配置可能带来严重风险。本文聚焦镜像与运行时层面的安全基线。
以非 root 用户运行
默认容器内进程以 root(uid 0)运行,一旦容器逃逸将威胁宿主机。Dockerfile 中显式切换用户:
dockerfile
# 创建非 root 用户
RUN addgroup -S app && adduser -S app -G app
USER app
# 或直接使用 UID
USER 1000运行时强制(即使镜像未设置):
bash
docker run --user 1000:1000 myapp注意:非 root 用户写某些目录(如
/var/run)会失败,需在 Dockerfile 中chown相应目录。
最小化基础镜像
基础镜像越大,攻击面越大。优先选择:
alpine:轻量,但使用 musl libc,部分二进制不兼容。slim:官方精简版(如python:3.12-slim)。distroless:仅含运行时与 CA 证书,几乎无 shell,极难被植入后门。scratch:完全空镜像,适合静态编译二进制(Go/Rust)。
dockerfile
FROM gcr.io/distroless/static-debian12
COPY server /server
USER nonroot:nonroot
ENTRYPOINT ["/server"]只读文件系统与降权
bash
# 根文件系统只读,仅 tmpfs 可写
docker run --read-only --tmpfs /tmp myapp
# 禁止特权模式(默认即为 false,注意不要设 true)
docker run --privileged=false myapp
# 删除 Linux 能力(capabilities),仅保留必要项
docker run --cap-drop ALL --cap-add NET_BIND_SERVICE myapp资源限制
防止单一容器耗尽宿主机资源:
bash
docker run -d \
--cpus 2 \
--memory 512m \
--memory-swap 512m \
--pids-limit 200 \
myappCompose 中:
yaml
services:
app:
deploy:
resources:
limits:
cpus: "2"
memory: 512M镜像漏洞扫描
构建后扫描镜像,发现已知 CVE:
bash
# Trivy(开源,推荐)
trivy image myapp:v1
# 仅扫描高危及以上
trivy image --severity HIGH,CRITICAL myapp:v1
# Docker Scout(官方)
docker scout cves myapp:v1CI 中建议将扫描失败设为构建阻断条件(见 容器与 CI/CD 集成)。
其他加固项
- 固定基础镜像 digest:
FROM node:20-alpine@sha256:xxxx,防止底层被悄然变更。 - 不使用
--privileged,确需设备访问用--device。 - 限制内核能力:
--cap-drop ALL+ 按需--cap-add。 - 启用用户命名空间重映射(userns-remap),降低 root 逃逸影响。
- ** secrets 管理**:敏感配置用 Docker/Swarm secret 或外部密钥管理,勿写进镜像。
- 更新 Docker 版本:及时修补 daemon 已知漏洞。
最佳实践清单
- 非 root 运行 + 只读根文件系统。
- 最小化基础镜像(distroless / scratch)。
- 每次构建跑漏洞扫描。
- 限制 CPU/内存/PID。
- 固定镜像 digest,定期更新基础镜像。
- 密钥不进镜像,使用 secret 机制。