Docker无法事后将已运行的流氓进程“锁死”进Namespace,只能在启动新容器时通过PID、USER、MNT、NET等Namespace预设隔离边界,结合--cap-drop=ALL、--userns-remap、--read-only等配置实现源头防护。

直接说结论:不能“锁死”流氓进程,但可以从启动源头阻止它逃出 Namespace——Docker 本身不接管已运行的进程,它只对新创建的容器进程施加 Namespace 隔离。所谓“遗留系统的流氓进程”,如果已在宿主机上运行,Docker 无法 retroactively(事后)将其塞进某个 Namespace。
真正可行的路径:用 Namespace 预防而非补救
重点不是“锁死已有进程”,而是让该遗留系统以容器方式重启,并强制启用全套隔离机制。关键在于启动时就绑定到专属 Namespace 集合:
- PID Namespace 独立化:容器内 PID 1 是它的 init 进程,宿主机看不到其子进程树;外部 ps/top 查不到容器内进程,反过来也一样
-
User Namespace 映射 root 权限:配置
"userns-remap": "default"后,容器里 UID 0(root)实际映射为宿主机上非特权 UID(如 100000),即使进程提权也无法操作宿主机文件或设备节点 -
Mount Namespace 切断挂载传播:禁用
shared挂载(默认是private),防止容器内mount --bind或umount影响宿主机或其他容器的文件系统视图 -
Network Namespace 严格收口:不加
--network=host,默认 bridge 模式下容器只有 veth 接口和 docker0 路由;额外加--cap-drop=NET_ADMIN可禁止容器内修改路由、iptables 或创建新网络接口
针对遗留服务的最小改造建议
无需重写代码,只需封装启动逻辑:
使用 Python 脚本下载 Docker 镜像并打包为 tar 文件。用户说“下载镜像”“拉取镜像”“pull xxx”“帮我下载 nginx 镜像”等时触发。支持 SOCKS5 代理直连(推荐)和国内镜像站加速两种模式。
- 把原服务的启动脚本(如
/opt/legacy/start.sh)打包进一个精简镜像,基础镜像选scratch或alpine:latest - Dockerfile 中用
USER 1001:1001显式降权,避免默认 root 启动 - 运行时加上:
docker run -d \<br> --name legacy-guard \<br> --userns=auto:uidmap=0-65535:100000 \<br> --cap-drop=ALL \<br> --security-opt=no-new-privileges \<br> --read-only \<br> --tmpfs /tmp:rw,size=10m \<br> your-legacy-image
辅助加固:用 Linux 原生命令验证隔离效果
进入容器后快速确认是否生效:
-
ls /proc/self/ns/—— 应显示多个pid、net、user等符号链接,且 inode 号与宿主机不同 -
cat /proc/self/uid_map—— 若启用了 user namespace,应看到类似0 100000 65536的映射行 -
ip link show—— 只有lo和eth0,没有docker0或宿主机网卡名(如ens33) -
find / -writable 2>/dev/null | head -5—— 在--read-only下应基本无输出,/tmp是唯一可写点
本质是把遗留系统“请进玻璃房”,而不是给野马套缰绳。Docker 的 Namespace 隔离能力强大,但只在进程诞生那一刻起效。

















