有时候容器内没有ifconfig、route等命令,给网络调试带来了很大的困难。我们知道,容器有自已的网络命名空间,所以我们只需要进入到容器的网络命名空间,再利用主机上的命令进行调试就可以了。
接下来给一个例子
准备
1、运行一个容器
$ docker run -itd --name nginx nginx:1.16.1
4ac2dc3735d6134112806667745cac916596132655c099499950d9307481166b
2、找到容器中PID为1的进程在root命名空间下的PID
$ docker inspect -f {{.State.Pid}} nginx
18809
我们可以在root命名空间下(即在主机的shell下),查看这个进程的相关信息
$ ps -ef | grep 18809
root 18809 18781 0 17:49 pts/0 00:00:00 nginx: master process nginx -g daemon off;
101 18854 18809 0 17:49 pts/0 00:00:00 nginx: worker process
3、nsenter命令如下
$ nsenter --help
Usage:
nsenter [options] [...]
Run a program with namespaces of other processes.
Options:
-t, --target target process to get namespaces from
-m, --mount[=] enter mount namespace
-u, --uts[=] enter UTS namespace (hostname etc)
-i, --ipc[=] enter System V IPC namespace
-n, --net[=] enter network namespace
-p, --pid[=] enter pid namespace
-U, --user[=] enter user namespace
-S, --setuid set uid in entered namespace
-G, --setgid set gid in entered namespace
--preserve-credentials do not touch uids or gids
-r, --root[=] set the root directory
-w, --wd[=] set the working directory
-F, --no-fork do not fork before exec'ing
-Z, --follow-context set SELinux context according to --target PID
进入网络命名空间
进入到PID为18809这个进程的网络命名空间
$ nsenter -t 18809 -n
然后,查看网络命名空间下的相关资源:网卡应该是容器内看到的网卡
$ ifconfig
eth0: flags=4163 mtu 1500
inet 172.17.0.2 netmask 255.255.0.0 broadcast 172.17.255.255
ether 02:42:ac:11:00:02 txqueuelen 0 (Ethernet)
RX packets 28 bytes 2152 (2.1 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
lo: flags=73 mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
loop txqueuelen 1000 (Local Loopback)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
进入PID命名空间
先执行exit命令从上面的网络命名空间退出来,然后执行以下命令进行到PID命令空间
$ nsenter -t 18809 -p
我们查看PID命名空间下的相关资源,这里看到的进程应该只有容器内的进程
$ ps
PID TTY TIME CMD
14377 pts/0 00:00:01 bash
18809 pts/0 00:00:00 nginx
52630 pts/0 00:00:00 nsenter
52631 pts/0 00:00:00 bash
52646 pts/0 00:00:00 ps
上面有点奇怪的是,PID没有显示为1,而且执行ps -ef
的话,会看到很多主机上很多其他的进程,暂时未明白原因
进入mount命名空间
先执行exit命令从上面的PID命名空间退出来,然后执行以下命令进行到mount命令空间
$ nsenter -t 18809 -m
然后我们ls发现,看到是的容器里面的文件,查看/etc/hostname
就是容器ID的前几位(就是docker ps看到的容器ID)
$ cat /etc/hostname
4ac2dc3735d6