在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
其次是通过socat
与ip 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
这样管理员就把一个容器中的服务暴露到宿主机上了。是不是很实用!