乐趣区

关于linux:docker容器操作宿主机执行命令

需要

失常状况下这种操作比拟反设计,须要审慎应用
有些时候咱们应用 docker 的时候会须要用到宿主机命令操作,比方

  • 执行 netplan apply失效机器网络配置
  • 查看宿主机网络信息应用 ifconfig 或者 ip addr
  • 从容器收回命令重启宿主机

具体实现

最简略的实现
应用 docker 运行一个 ubuntu 容器
进入容器之后执行 nsenter 命令查看宿主机网络配置信息

$ sudo docker run -it --pid=host --privileged=true ubuntu /bin/bash
# 进入容器外部之后执行

/# nsenter -a -t 1 sh -c "ip addr"

实现原理

docker run 参数

--pid=host

  • 应用宿主机命名空间,不便容器获取到宿主机所有过程信息
  • 把宿主机的 /proc 文件夹挂载进入容器的 /proc 门路,其中 /proc/1 作为 nsentertarget,作为容器向宿主机发送命令的要害局部

--privileged=true

  • 使得 docker 容器有 root 权限执行宿主机命令,确保从容器执行命令的时候不会产生权限有余谬误

nsenter命令

nsenter命令是一个能够在指定过程的命令空间下运行指定程序的命令

$ nsenter --help

用法: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

更多信息请参阅 nsenter(1)。

具体执行

$ nsenter -a -t 1 sh -c "ip addr"
  • -a示意进入宿主机的所有命名空间
  • -t 1示意获取 /proc/1 过程,就是 pid=1 的过程,这个过程是 docker 应用 --pid=host 参数挂载进入容器外部的宿主机过程
  • sh -c "ip addr"就示意发送给宿主机的命令是ip addr

理论应用过程中如果呈现宿主机和容器命名空间不统一问题,次要产生起因是宿主机内核版本和容器
所默认的加载内核版本不统一

比方 cgroup 是在 Linux4.6 版本退出的,如果应用 Ubuntu20 或者其余 python3.10 等比拟新的镜像启动容器的时候,当 nsenter 应用参数 -a,容器会加载所有命名空间,然而cgroup 命名空间在旧版本的零碎外面因为内核版本比拟旧,所以该命名空间是没有的,最终 nsenter 命令就会报错

须要依照宿主机有的命名空间来调整 nsenter 参数,能够调整如下

$ nsenter -m -u -i -n -p  -t 1 sh -c "ip addr"

比方能够把 -a 参数替换成 -m -u -i -n -p,明确指定进入mount, UTS,System V IPC, 网络 ,pid 命名空间
这几个命名空间蕴含了绝大多数的空间环境,linux的大部分命令都能够失常执行

命名空间阐明

namespaceLinux 中一些过程的属性的作用域,应用命名空间,能够隔离不同的过程

Linux在一直的增加命名空间,目前有

  • mount:挂载命名空间,使过程有一个独立的挂载文件系统,始于Linux 2.4.19
  • ipcipc命名空间,使过程有一个独立的ipc,包含音讯队列,共享内存和信号量,始于Linux 2.6.19
  • utsuts命名空间,使过程有一个独立的 hostnamedomainname,始于Linux 2.6.19
  • netnetwork命令空间,使过程有一个独立的网络栈,始于Linux 2.6.24
  • pidpid命名空间,使过程有一个独立的 pid 空间,始于Linux 2.6.24
  • useruser命名空间,是过程有一个独立的 user 空间,始于Linux 2.6.23,完结于Linux 3.8
  • cgroupcgroup命名空间,使过程有一个独立的 cgroup 控制组,始于Linux 4.6

参考浏览

  • nsenter 命令简介
  • Linux manual page
  • docker 官网文档
退出移动版