docker进程的Namespace信息是在宿主机上以文件形式存在的
查看当前正在运行的 Docker 容器的进程号(PID)
docker inspect --format '{{ .State.Pid }}' CID
查看宿主机的proc文件,可看到该进程对应的所有Namespace文件
ls -l /proc/PID/ns
通过对比各资源的namespace是否相同,可判断不同进程是否共享了同一个Namespace对应的文件,例如下面两个进程就共享了同一个网络空间
一个进程加入到某个进程的namespace中,就可以达到进入该进程所在容器的目的,就是docker exec的实现原理。加入namespace操作依赖setns()这个Linux系统调用,调用方法参考set_ns.c,argv1是当前进程要加入NS文件的路局,argv2是需要在加入NS中运行的进程,例如/bin/bash
#define _GNU_SOURCE
#include <fcntl.h>
#include <sched.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#define errExit(msg) do { perror(msg); exit(EXIT_FAILURE);} while (0)
int main(int argc, char *argv[]) {
int fd;
fd = open(argv[1], O_RDONLY);
if (setns(fd, 0) == -1) {
errExit("setns");
}
execvp(argv[2], &argv[2]);
errExit("execvp");
}
编译运行
gcc -o set_ns set_ns.c
$ ./set_ns /proc/25686/ns/net /bin/bash
$ ifconfig 通过返回结果可以判断是容器中的网络设备
eth0 Link encap:Ethernet HWaddr 02:42:ac:11:00:02
inet addr:172.17.0.2 Bcast:0.0.0.0 Mask:255.255.0.0
inet6 addr: fe80::42:acff:fe11:2/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:12 errors:0 dropped:0 overruns:0 frame:0
TX packets:10 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:976 (976.0 B) TX bytes:796 (796.0 B)
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
inet6 addr: ::1/128 Scope:Host
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)