在docker容器中的服务是通过docker命令将端口暴露给宿主机的用户使用。有时候出于安全考虑,容器没有暴露其中的一些服务。运维人员为了调试就得登录到容器中,一些精简的容器bash命令不全,管理起来很不方便。目前有两种方法访问容器网络中的服务。

通过nsenter访问容器网络

# 获取容器的pid
pid=$(docker inspect -f '{{.State.Pid}}' ${container_id})
# 进入pid对应的namespace
sudo nsenter --target $pid --uts --ipc --net --pid

这种方法可以直接在宿主机上暴露容器网络的命名空间,进而通过宿主机的一些命令行工具调试网络。

另外一种方法就是本文重点介绍的。

通过ip netns访问容器网路

这种操作的好处是可以通过类似socat的工具将容器网络中的服务暴露到宿主机网络中。具体操作如下:

首先要求管理员把容器的网络映射到/var/run/netns供ip命令使用。

ln -s /var/run/docker/netns  /var/run/netns 
# 部分容器版本需要运行 1000 是运行docker的userid
ln -s /run/user/1000/docker/netns var/run/netns

其次是通过socatip netns结合转发端口

# 通过以下命令找到netns id
ns_id=$(docker inspect $container_name | grep SandboxKey | awk -F '/' '{print $NF}' | awk -F '"' '{print $1}')
# 通过以下命令将宿主机监听的33060端口转发到容器的3306端口
sudo socat tcp-listen:33060,fork,reuseaddr \
  exec:'ip netns exec $ns_id socat STDIO "tcp-connect:127.0.0.1:3306"',nofork

这样管理员就把一个容器中的服务暴露到宿主机上了。是不是很实用!