Docker 容器安全加固实战:非 root、只读根文件系统、drop capabilities 与最小攻击面

Docker 容器安全加固实战:非 root、只读根文件系统、drop capabilities 与最小攻击面

大部分 Dockerfile 默认以 root 跑进程------一旦应用被 RCE(远程代码执行),攻击者拿到的是容器里的 root,再叠加一个容器逃逸漏洞,就能威胁到宿主机。容器安全的核心思路很朴素:假设进程一定会被攻破,那就让它被攻破后什么也干不了。 这篇把几个立刻能落地、性价比最高的加固手段串起来:换非 root 用户、只读根文件系统、砍掉多余的 Linux capabilities、禁止提权。全是几行配置的事,却能把攻击面砍掉一大半。

第一刀:别用 root 跑进程

默认容器里 USER 是 root。验证一下:

bash 复制代码
docker run --rm alpine id
# uid=0(root) gid=0(root) groups=0(root)

在 Dockerfile 里建一个普通用户并切过去。注意顺序:装依赖等需要 root 权限的操作放前面,USER 指令放在最后,这样运行时进程才是非 root:

dockerfile 复制代码
FROM python:3.12-slim

WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

COPY . .

# 建一个固定 uid 的非 root 用户(指定 uid 便于宿主机侧对齐文件权限)
RUN groupadd -g 10001 appuser && \
    useradd -u 10001 -g 10001 -m -s /usr/sbin/nologin appuser

# 关键:切换到非 root,后续进程都以 appuser 身份运行
USER 10001:10001

CMD ["python", "main.py"]

用数字 uid(USER 10001)而不是用户名,好处是即便镜像里 /etc/passwd 被改,Kubernetes 的 runAsNonRoot 也能正确识别。运行时也能强制不许用 root 起:

bash 复制代码
# 即使镜像里写了 USER root,这行也会让容器拒绝启动
docker run --user 10001:10001 myapp

第二刀:只读根文件系统

进程被攻破后,攻击者第一件事往往是往磁盘写马、改二进制、留后门。给容器一个只读根文件系统,让它根本写不进去:

bash 复制代码
docker run --read-only myapp

但很多程序要写临时文件、日志、pid 文件,一上来会崩。正确做法不是放弃只读,而是只给需要写的目录挂上可写的 tmpfs,其余全只读:

bash 复制代码
docker run \
  --read-only \
  --tmpfs /tmp:rw,noexec,nosuid,size=64m \
  --tmpfs /run:rw,noexec,nosuid,size=8m \
  myapp

noexec 尤其关键:它让写进 /tmp 的东西不能被执行 。攻击者就算把 payload 写进 /tmp,也运行不起来。在 Docker Compose 里等价写法:

yaml 复制代码
services:
  app:
    image: myapp
    read_only: true
    tmpfs:
      - /tmp:rw,noexec,nosuid,size=64m
    user: "10001:10001"

排查思路:开只读后如果容器崩了,docker logs 会看到 Read-only file system 报错,顺着报错路径把那个目录加进 tmpfs(或挂一个具名 volume)即可,一个个补,别直接退回可写。

第三刀:砍掉用不到的 capabilities

Linux capabilities 把「root 的超能力」拆成了几十个细粒度权限(改系统时间、绑定低端口、加载内核模块......)。Docker 默认就给了容器一串 capabilities,但绝大多数 Web 应用一个都用不到。正确姿势是先全砍光,再按需加回来:

bash 复制代码
docker run \
  --cap-drop=ALL \
  --cap-add=NET_BIND_SERVICE \
  myapp

--cap-drop=ALL 先清空所有 capabilities,--cap-add=NET_BIND_SERVICE 只在「进程确实要监听 80/443 这类 1024 以下端口」时加回来。如果你的服务监听的是 8080 这种高端口,那连这个都不用加,直接 --cap-drop=ALL 就行。

顺带禁止提权------阻止进程通过 setuid 二进制拿到更高权限:

bash 复制代码
docker run \
  --cap-drop=ALL \
  --security-opt=no-new-privileges \
  myapp

no-new-privileges 会让容器里任何 setuid 程序都无法提权,把「从普通用户偷偷变 root」这条路彻底堵死。

第四刀:镜像本身要小、要干净

攻击面也包括镜像里那些用不到的东西------一个装了 curlbash、编译器的镜像,给了攻击者一堆现成工具。两个方向:

用多阶段构建,只把产物拷进最终镜像,构建工具全不带:

dockerfile 复制代码
# 构建阶段:有完整工具链
FROM golang:1.22 AS build
WORKDIR /src
COPY . .
RUN CGO_ENABLED=0 go build -o /app/server .

# 运行阶段:distroless,连 shell 都没有
FROM gcr.io/distroless/static:nonroot
COPY --from=build /app/server /server
USER nonroot:nonroot
ENTRYPOINT ["/server"]

distroless 镜像不含包管理器、不含 shell,攻击者进来连 sh 都没有,docker exec 也进不去交互式终端。它自带 nonroot 用户,直接 USER nonroot 即可。

再用 trivy 扫一遍镜像里依赖的已知漏洞,纳入 CI:

bash 复制代码
# 扫出 HIGH/CRITICAL 级别漏洞就让流水线失败
trivy image --severity HIGH,CRITICAL --exit-code 1 myapp:latest

一份「全加固」的运行配置

把上面几刀合起来,一个典型的加固运行命令长这样:

bash 复制代码
docker run -d \
  --user 10001:10001 \
  --read-only \
  --tmpfs /tmp:rw,noexec,nosuid,size=64m \
  --cap-drop=ALL \
  --security-opt=no-new-privileges \
  --pids-limit=200 \
  --memory=512m \
  myapp

额外两个 --pids-limit(限制进程数,防 fork 炸弹)和 --memory(内存上限,防单容器吃光宿主机),属于「限制爆炸半径」的兜底,顺手加上。

小结

  • 非 root :Dockerfile 里建普通用户、USER 数字uid 放最后;运行时 --user 强制。
  • 只读根文件系统 :--read-only + 给需要写的目录挂 --tmpfs(带 noexec),让攻击者写不进也执行不了。
  • capabilities :--cap-drop=ALL 先全砍,只按需 --cap-add;配 --security-opt=no-new-privileges 禁提权。
  • 最小镜像:多阶段构建 + distroless(无 shell 无包管理器),trivy 扫漏洞纳入 CI。
  • 兜底:--pids-limit--memory 限制爆炸半径。

一句话记忆:容器安全的心法是「假设它一定会被攻破」------那就让被攻破的进程不是 root、写不了盘、没有超能力、也没有趁手的工具。

相关推荐
鹤落晴春1 小时前
有状态应用 vs 无状态应用
运维·云原生·k8s
码--到成功2 小时前
Docker、Kubernetes安装系列 二
docker·容器·kubernetes
华普微HOPERF2 小时前
数字隔离器,光伏微型逆变系统中的安全核“芯”
安全
DM今天肝到几点?3 小时前
AI 安全进入「攻防同频」:Gemini 3.8 Flash Cyber 上线、Astra 触及关键级、HiddenLayer 融资 1 亿美元
网络·人工智能·深度学习·安全·语言模型·开源·知识图谱
M--Y3 小时前
Docker镜像与仓库管理详解
docker·容器
mohesashou3 小时前
k8s的service
云原生·容器·kubernetes
starzy19903 小时前
虚拟化解决方案全景:软件虚拟化、硬件虚拟化与 Docker 的位置
运维·docker·容器
来让爷抱一个3 小时前
2026 智能体安全实战:把护栏写进SPEC,MonkeyCode 云端跑通
人工智能·安全·机器学习
sungtv4 小时前
大型厂房钢结构施工安全生产动画聚焦哪些风险点
安全·安全生产动画