Accessing Container Network from Host or Other Container

In my network based or related to network projects, for debugging I execute another shell at same container and I install network tools to these container.

Ex.

docker exec --privileged -it Netherland.Amsterdam1  bash
~> apt update && apt install tcpdump

This method is bored to me due to install same tools after each container building. Also some container is only have a one executable file, installing new tools is impossible with regular or basic methods.

So I have to access container inside network from host to prevent installing anything for my service container.

Here is the normal method for Accessing From host.

Firstly we have to make a symbolic link from container netns to regular netns folder.

container_name="Netherland.Amsterdam1"  # Replace with Your container name
container_pid=$(docker inspect -f '' $container_name) # Getting Container pid from docker
ln -s /proc/$container_pid/ns/net /var/run/netns/$container_name # Make a symbolic link

Now you can see your container network with ip netns command.

[email protected]~>ip netns
Netherland.Amsterdam1 (id: 4)
dockernet

You can enter container network with again ip command.

ip netns exec $container_name bash
# Example command
[email protected]~>ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.19.0.2  netmask 255.255.0.0  broadcast 172.19.255.255
        inet6 2001:db8:1234:900d:c0fe:e  prefixlen 80  scopeid 0x0<global>
        inet6 fe80::00:11:22:3  prefixlen 64  scopeid 0x20<link>
        ether 00:11:22:33:44:55  txqueuelen 0  (Ethernet)
        RX packets 368  bytes 58880 (58.8 KB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 439  bytes 66308 (66.3 KB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<host>
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 72  bytes 9760 (9.7 KB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 72  bytes 9760 (9.7 KB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

Accessing from host is some times is not enough. For example I have a net-tools-service container to serve my looking-glass services. I want to add Teredo network to this service. Should i make a another container with Teredo capabilities and push to register and also other network projects. Adding one by one is not efficient to managing for each repo for timing to engineer cost and also this takes many spaces on my servers.

Prohibiting to this ve can give a first container network to second container network.

container_name="Netherland.Amsterdam1" # Replace with Your container name
docker run -it --rm --privileged -v /proc/$(docker inspect -f '' $container_name)/ns/net:/var/run/netns/container alpine
~>apk add iproute2    # Default busybox iproute does not support namespaces in alpine
~>ip netns
container
~>ip netns exec container ifconfig  # Here is other container network
eth0      Link encap:Ethernet  HWaddr 00:11:22:33:44:55
          inet addr:172.10.0.2  Bcast:172.19.255.255  Mask:255.255.0.0
          inet6 addr: 2001:db8:1234:900d:c0fe::e/80 Scope:Global
          inet6 addr: fe80::00:11:22:3/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:408 errors:0 dropped:0 overruns:0 frame:0
          TX packets:476 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:63847 (62.3 KiB)  TX bytes:73114 (71.4 KiB)

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:78 errors:0 dropped:0 overruns:0 frame:0
          TX packets:78 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:10450 (10.2 KiB)  TX bytes:10450 (10.2 KiB)
~> ifconfig     # Current Container network
eth0      Link encap:Ethernet  HWaddr 00:11:22:33:44:66
          inet addr:172.15.0.3  Bcast:172.17.255.255  Mask:255.255.0.0
          inet6 addr: 2001:db8:1234:900d::code/80 Scope:Global
          inet6 addr: fe80::00:33:22:4/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:387 errors:0 dropped:0 overruns:0 frame:0
          TX packets:238 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:3413869 (3.2 MiB)  TX bytes:21510 (21.0 KiB)

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)

Example with my neighbor network supported containers.

container_name="Netherland.Amsterdam1" # Replace with Your container name
# For adding Teredo
docker run -it --rm --privileged -v /proc/$(docker inspect -f '' $container_name)/ns/net:/var/run/netns/container ahmetozer/docker-teredo
# Or make a network inspect on container
docker run -it --rm --privileged -v /proc/$(docker inspect -f '' $container_name)/ns/net:/var/run/netns/container ahmetozer/cna
# SOURCE Code for ahmetozer/cna https://gitlab.com/ahmetozer/container-network-admin

NOTE: After restarting first server, your second container is unable to access first container. Container pids are changes by every restart.
You have to execute second container after each first container startup.

container_name="Netherland.Amsterdam1" # Replace with Your container name
[email protected]~>docker inspect -f '' $container_name
95321
[email protected]~>docker restart $container_name
Netherland.Amsterdam1
[email protected]~>docker inspect -f '' $container_name
321736

This problem can also has a solution. First method is make a first container as a service and execute second container after first container. If you don’t want to create service, the way for solving this issue is make a full /proc/ folder mirror to inside container and make link netns in each startup at container, but adding proc volume is not secure way to do this. Which container has a this method, it can be access every namespace and might be break security. You can only use this method to trusted containers.

docker run -it --rm --privileged -v /proc/:/proc2 -v /var/run/docker.sock:/var/run/docker.sock alpine
container_name="Netherland.Amsterdam1" # Replace with Your container name
apk add iproute2 curl
mkdir -pv /var/run/netns
rm /var/run/netns/neighbornet # in first time you can get a err.
container_pid=$(curl --unix-socket /var/run/docker.sock http/containers/$container_name/json -s | awk -v RS=',' -F: '{ if ( $1 == "\"Pid\"") {print $2}}')
ln -s /proc2/$container_pid/ns/net /var/run/netns/neighbornet
ip netns exec neighbornet bash

Here is example Container which is used this method.

container_name="Netherland.Amsterdam1" # Replace with Your container name
docker run -it --rm --privileged -e container_name=$container_name -v /proc/:/proc2/ -v /var/run/docker.sock:/var/run/docker.sock --name teredo ahmetozer/docker-teredo
# SOURCE Code for ahmetozer/docker-teredo https://github.com/ahmetozer/docker-teredo

Thank you for reading this blog.