docker run helloworld
lrwxrwxrwx 1 root root 0 Nov 26 14:10 ipc -> ipc:[4026532155]
lrwxrwxrwx 1 root root 0 Nov 26 14:10 mnt -> mnt:[4026532153]
lrwxrwxrwx 1 root root 0 Nov 26 14:08 net -> net:[4026532215]
lrwxrwxrwx 1 root root 0 Nov 26 14:10 pid -> pid:[4026532156]
lrwxrwxrwx 1 root root 0 Nov 26 14:11 user -> user:[4026531837]
lrwxrwxrwx 1 root root 0 Nov 26 14:10 uts -> uts:[4026532154]
setns() net /bin/sh
lrwxrwxrwx 1 root root 0 Nov 26 14:17 ipc -> ipc:[4026531839]
lrwxrwxrwx 1 root root 0 Nov 26 14:17 mnt -> mnt:[4026531840]
lrwxrwxrwx 1 root root 0 Nov 26 14:17 net -> net:[4026532215]
lrwxrwxrwx 1 root root 0 Nov 26 14:17 pid -> pid:[4026531836]
lrwxrwxrwx 1 root root 0 Nov 26 14:17 user -> user:[4026531837]
lrwxrwxrwx 1 root root 0 Nov 26 14:17 uts -> uts:[4026531838]
宿主机 sleep
lrwxrwxrwx 1 root root 0 Nov 26 14:12 ipc -> ipc:[4026531839]
lrwxrwxrwx 1 root root 0 Nov 26 14:12 mnt -> mnt:[4026531840]
lrwxrwxrwx 1 root root 0 Nov 26 14:12 net -> net:[4026531956]
lrwxrwxrwx 1 root root 0 Nov 26 14:12 pid -> pid:[4026531836]
lrwxrwxrwx 1 root root 0 Nov 26 14:12 user -> user:[4026531837]
lrwxrwxrwx 1 root root 0 Nov 26 14:12 uts -> uts:[4026531838
docker --net=host
lrwxrwxrwx 1 root root 0 Nov 26 14:24 ipc -> ipc:[4026532159]
lrwxrwxrwx 1 root root 0 Nov 26 14:24 mnt -> mnt:[4026532157]
lrwxrwxrwx 1 root root 0 Nov 26 14:24 net -> net:[4026531956]
lrwxrwxrwx 1 root root 0 Nov 26 14:24 pid -> pid:[4026532160]
lrwxrwxrwx 1 root root 0 Nov 26 14:24 user -> user:[4026531837]
lrwxrwxrwx 1 root root 0 Nov 26 14:24 uts -> uts:[4026532158]
docker exec
lrwxrwxrwx 1 root root 0 Nov 26 06:40 ipc -> 'ipc:[4026532155]'
lrwxrwxrwx 1 root root 0 Nov 26 06:40 mnt -> 'mnt:[4026532153]'
lrwxrwxrwx 1 root root 0 Nov 26 06:40 net -> 'net:[4026532215]'
lrwxrwxrwx 1 root root 0 Nov 26 06:40 pid -> 'pid:[4026532156]'
lrwxrwxrwx 1 root root 0 Nov 26 06:40 user -> 'user:[4026531837]'
lrwxrwxrwx 1 root root 0 Nov 26 06:40 uts -> 'uts:[4026532154]'
上面的实验我一个个的来解释下:
一、宿主机 sleep
这个就是我们平常运行的一些脚本,通过查看ll /proc/进程号/ns可以查看到宿主机的默认namespace
二、docker run helloworld
docker inspect --format '{{ .State.Pid }}' 4ddf4638572d 查到pid
你会发现只有user跟宿主机是一致的。
三、setns() net /bin/sh
其实也就是docker的--net=container:4ddf4638572d的原理,你执行ifconfig会发现看到的就是和helloworld一致的网卡信息。
四、docker --net=host
会发现net跟宿主机的进程一致
五、docker exec
这个时候在容器里面查看ls /proc/xx/ns和helloworld的完全一致,也就是exec的原理了,加入到一个已经存在的 Namespace 当中
总结:
- docker 默认是没有做user的单独namespace的
- docker通过namespace的做隔离,也就是在clone进程的时候加入一些特殊的参数
- 加入一个已经存在的Namespace通过setns()加上 namespace文件路径 + 需要执行的命令例如 /proc/25686/ns/net /bin/bash