docker run --rm --cap-drop=net_bind_service --publish 8080:80 --name nginx nginx
ps --forest -fC nginx
UID PID PPID C STIME TTY TIME CMD
root 449870 449847 0 12:38 ? 00:00:00 nginx: master process nginx -g daemon off;
101 449929 449870 0 12:38 ? 00:00:00 \_ nginx: worker process
101 449930 449870 0 12:38 ? 00:00:00 \_ nginx: worker process
101 449931 449870 0 12:38 ? 00:00:00 \_ nginx: worker process
101 449932 449870 0 12:38 ? 00:00:00 \_ nginx: worker process
101 449933 449870 0 12:38 ? 00:00:00 \_ nginx: worker process
101 449934 449870 0 12:38 ? 00:00:00 \_ nginx: worker process
101 449935 449870 0 12:38 ? 00:00:00 \_ nginx: worker process
101 449936 449870 0 12:38 ? 00:00:00 \_ nginx: worker process
101 449937 449870 0 12:38 ? 00:00:00 \_ nginx: worker process
101 449938 449870 0 12:38 ? 00:00:00 \_ nginx: worker process
101 449939 449870 0 12:38 ? 00:00:00 \_ nginx: worker process
101 449940 449870 0 12:38 ? 00:00:00 \_ nginx: worker process
所以这个过程没有网络绑定服务,但它能够启动并绑定到端口 80。
getpcaps 449870
449870: cap_chown,cap_dac_override,cap_fowner,cap_fsetid,cap_kill,cap_setgid,cap_setuid,cap_setpcap,cap_net_raw,cap_sys_chroot,cap_mknod,cap_audit_write,cap_setfcap=ep
看到这个:
docker run --rm --privileged --pid container:nginx --network container:nginx -it --volumes-from nginx --name debug nixery.dev/shell/gnugrep/ps/libcap/htop/lsof/iproute2 bash
bash-5.2# ps aufx
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
0 112 0.0 0.0 4936 4184 pts/0 Ss 19:55 0:00 bash
0 123 0.0 0.0 7240 2324 pts/0 R+ 19:56 0:00 \_ ps aufx
0 1 0.0 0.0 8940 6052 ? Ss 19:38 0:00 nginx: master process nginx -g daemon off;
101 29 0.0 0.0 9328 2564 ? S 19:38 0:00 nginx: worker process
101 30 0.0 0.0 9328 2564 ? S 19:38 0:00 nginx: worker process
101 31 0.0 0.0 9328 2564 ? S 19:38 0:00 nginx: worker process
101 32 0.0 0.0 9328 2564 ? S 19:38 0:00 nginx: worker process
101 33 0.0 0.0 9328 2564 ? S 19:38 0:00 nginx: worker process
101 34 0.0 0.0 9328 2564 ? S 19:38 0:00 nginx: worker process
101 35 0.0 0.0 9328 2564 ? S 19:38 0:00 nginx: worker process
101 36 0.0 0.0 9328 2564 ? S 19:38 0:00 nginx: worker process
101 37 0.0 0.0 9328 2564 ? S 19:38 0:00 nginx: worker process
101 38 0.0 0.0 9328 2564 ? S 19:38 0:00 nginx: worker process
101 39 0.0 0.0 9328 2564 ? S 19:38 0:00 nginx: worker process
101 40 0.0 0.0 9328 2568 ? S 19:38 0:00 nginx: worker process
bash-5.2# ss -ltnp
State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
LISTEN 0 511 0.0.0.0:80 0.0.0.0:* users:(("nginx",pid=40,fd=6),("nginx",pid=39,fd=6),("nginx",pid=38,fd=6),("nginx",pid=37,fd=6),("nginx",pid=36,fd=6),("nginx",pid=35,fd=6),("nginx",pid=34,fd=6),("nginx",pid=33,fd=6),("nginx",pid=32,fd=6),("nginx",pid=31,fd=6),("nginx",pid=30,fd=6),("nginx",pid=29,fd=6),("nginx",pid=1,fd=6))
LISTEN 0 511 [::]:80 [::]:* users:(("nginx",pid=40,fd=7),("nginx",pid=39,fd=7),("nginx",pid=38,fd=7),("nginx",pid=37,fd=7),("nginx",pid=36,fd=7),("nginx",pid=35,fd=7),("nginx",pid=34,fd=7),("nginx",pid=33,fd=7),("nginx",pid=32,fd=7),("nginx",pid=31,fd=7),("nginx",pid=30,fd=7),("nginx",pid=29,fd=7),("nginx",pid=1,fd=7))
那么为什么容器能够启动并绑定到端口 80 但未net_bind_service
列出该进程帽子?
答案1
Docker 不是启用特权绑定到低端口(和其他功能),而是将需要特权的低端口值降低为 0,从而消除障碍并允许任何非特权进程绑定到任何端口:
// allow opening any port less than 1024 without CAP_NET_BIND_SERVICE if sysctlExists("net.ipv4.ip_unprivileged_port_start") { s.Linux.Sysctl["net.ipv4.ip_unprivileged_port_start"] = "0" }
除非是主机的网络或配置另有说明。与上面的几行类似,在非无根容器上允许 ping(过去需要特权)。