问题
如何在容器中操作宿主机?例如,
- 重启ssh服务
- 查看网络配置等等
nsenter命令
简介
nsenter命令是一个可以在指定进程的命名空间下运行指定程序的命令。它位于util-linux包中。
用途
一个最典型的用途就是进入容器的网络命名空间。相当多的容器为了轻量级,是不包含较为基础的命令的,比如说ip address,ping,telnet,ss,tcpdump等等命令,这就给调试容器网络带来相当大的困扰:只能通过docker inspect ContainerID命令获取到容器IP,以及无法测试和其他网络的连通性。这时就可以使用nsenter命令仅进入该容器的网络命名空间,使用宿主机的命令调试容器网络。
语法
# 用法:
nsenter [选项] [<程序> [<参数>...]]
# 以其他程序的名字空间运行某个程序。
# 选项:
-a, --all enter all namespaces
-t, --target <pid> 要获取名字空间的目标进程
-m, --mount[=<文件>] 进入 mount 名字空间
-u, --uts[=<文件>] 进入 UTS 名字空间(主机名等)
-i, --ipc[=<文件>] 进入 System V IPC 名字空间
-n, --net[=<文件>] 进入网络名字空间
-p, --pid[=<文件>] 进入 pid 名字空间
-C, --cgroup[=<文件>] 进入 cgroup 名字空间
-U, --user[=<文件>] 进入用户名字空间
-S, --setuid <uid> 设置进入空间中的 uid
-G, --setgid <gid> 设置进入名字空间中的 gid
--preserve-credentials 不干涉 uid 或 gid
-r, --root[=<目录>] 设置根目录
-w, --wd[=<dir>] 设置工作目录
-F, --no-fork 执行 <程序> 前不 fork
-Z, --follow-context 根据 --target PID 设置 SELinux 环境
-h, --help display this help
-V, --version display version
示例1
运行一个nginx容器,查看该容器的pid:
# 查看容器PID
docker inspect -f {{.State.Pid}} nginx
54325
# 进入net命名空间
nsenter -n -t54325
ip addr
# 进入容器nsenter -m -u -i -n -p -t
nsenter --target 54325 --mount --uts --ipc --net --pid
root@164f44ff58d1:/bin#
# 退出命名空间
exit
示例2
在容器内部执行:
# 特权模式启动ubuntu容器
docker run -it --pid=host --privileged=true --rm ubuntu /bin/bash
# 查看宿主机所有进程,引号中的内容就是在宿主机上执行的命令
nsenter -a -t 1 sh -c "ps -ef"
操作宿主机
示例2
已非常清楚的举例说明,可以参考实现。具体操作可以参考这位大神的博客:docker容器操作宿主机执行命令。
实现原理
参考上述nsenter命令。
Docker 参数介绍
--pid=host
- 使用宿主机命名空间,方便容器获取到宿主机所有进程信息
- 把宿主机的
/proc
文件夹挂载进入容器的/proc
路径,其中/proc/1
作为nsenter
的target
,作为容器向宿主机发送命令的关键部分
--privileged=true
- 使得
docker
容器有root
权限执行宿主机命令,确保从容器执行命令的时候不会产生权限不足错误
--rm
- 退出容器时会自动将其删除
参考
- docker容器操作宿主机执行命令
- nsenter命令简介
- Linux manual page
- docker官方文档