Linux の Network Namespace を ip netns exec で操作しているうちに「docker exec の正体」がなんとなく見えてきた。
Bridge Networking Deep Dive — Docker Kubernetes Lab 0.1 documentation
デフォルトでは docker はコンテナの Network Namespace を見せないようにしている。これは docker exec からのみコンテナの Network Namespace にアクセスを許可するように意図しているものに感じられる。OOP でクラスのメンバを private や protected で保護することと似ているかもしれない。
$ docker run --rm -d --name b1 busybox sh -c "while true; do sleep 3600; done" $ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 0e3030605661 busybox "sh -c 'while true..." About an hour ago Up About an hour b1
いつも操作を忘れてしまうので、シェル関数を作っておく。docker-netns show [CONTAINER-NAME]
で ip netns 経由で exec できるようになる。隠蔽された状態に戻したい時は docker-netns stash [CONTAINER-NAME]
を実行する。
function docker-netns () { local action=$1 local cname=$2 case ${action} in show) docker inspect ${cname} | jq ".[].State.Pid" | xargs -i sudo ln -s /proc/{}/ns/net /var/run/netns/${cname} echo "Network namespace for container ${cname} is visible now." ;; stash) sudo rm /var/run/netns/${cname} echo "Network namespace for container ${cname} is invisible now." ;; *) : ;; esac ls -l /var/run/netns/${cname} }
$ sudo ip netns list $ $ docker-netns show b1 Network namespace for container b1 is visible now. lrwxrwxrwx 1 root root 18 Jan 31 00:30 /var/run/netns/b1 -> /proc/11385/ns/net $ sudo ip netns list b1 $ sudo ip netns exec b1 ip a # 以下 docker exec と内容が同じ 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever 91: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff inet 172.17.0.2/16 scope global eth0 valid_lft forever preferred_lft forever $ docker exec -it b1 ip a 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever 91: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff inet 172.17.0.2/16 scope global eth0 valid_lft forever preferred_lft forever $ docker-netns stash b1 Network namespace for container b1 is invisible now. ls: cannot access /var/run/netns/b1: No such file or directory $ sudo ip netns list $ $ sudo ip netns exec b1 ip route Cannot open network namespace "b1": No such file or directory
ただ ip netns exec b1 ip a
でなく ip netns exec b1 hostname
だとコンテナのホスト名 0e3030605661
は返ってこずに docker host のホスト名が返ってくるので、あくまでネットワークに限定した名前空間である感覚がしている。その意味では docker exec は Network Namespace だけでなく Process Namespace やその他の名前空間をまとめて隔離した空間に対するインターフェイスなのではないか。
ip netns exec が docker exec の正体というのはただの個人的感覚でしかない。今度、知り合いのカーネルハッカーに聞いてみよう...。自分でソースを読めと言われるに決まっているのだけれど。ただこういった局所的な興味からカーネルソースに飛び込んでみるのも目的がはっきりしていていいかもしれない。(´▽`)