linuxdockernetwork-programmingmacvlan

Bind address in Docker macvlan


I am trying to building a macvlan with N containers binded to the same ip. Each container will expose one service. To do that:

sudo docker network create -d macvlan \
    --subnet=192.168.4.0/24 \
    --ip-range=192.168.4.0/24 \
    --gateway=192.168.4.201 \
    -o macvlan_mode=bridge \
    -o parent=eth0 macvlan70

Running containers:

sudo docker run --net=macvlan70 -P -d --name test_sshd1 eg_ssh
sudo docker run --net=macvlan70 -P -d --name test_sshd2 eg_ssh

Bridge:

sudo ip link add mymacvlan90 link eth0 type macvlan mode bridge
sudo ip addr add 192.168.4.10/24 dev mymacvlan90
sudo ifconfig mymacvlan90 up

At this point I can ping and nmap each container from host. I used inspect to check "IPAddress" of each container. Result of macvlan inspect:

"Containers": {
            "89ed3de20801bf096b389379bb546da03f3452e80dbabad89c5457bdc4dcc5fc": {
                "Name": "test_sshd1",
                "EndpointID": "6a7d774ae7e3ce3aac877523968b2ce5a026ae740c059b61162ceb170d53a0c4",
                "MacAddress": "02:42:c0:a8:04:01",
                "IPv4Address": "192.168.4.1/24",
                "IPv6Address": ""
            },
            "ca13b48ccbc267859f406084357dadcd3592cb678502b7086908d6d895728632": {
                "Name": "test_sshd2",
                "EndpointID": "98ce081e94a209838bb4281613055b32967ea85c40c2e3814fe73a88bc9cb380",
                "MacAddress": "02:42:c0:a8:04:02",
                "IPv4Address": "192.168.4.2/24",
                "IPv6Address": ""
            }

Now I am creating another container, like this:

sudo docker run --net=macvlan70 -p 192.168.4.1:66:22 -d --name test_sshd4 eg_ssh

My goal is to expose 2 generic services under the same ip and mac (trying to emulate a real machine with N services). The container is created with success. But if I run this command:

$ nmap 192.168.4.1 -p 66

Starting Nmap 7.01 ( https://nmap.org ) at 2017-12-06 16:57 WET
Nmap scan report for 192.168.4.1
Host is up (0.00021s latency).
PORT   STATE  SERVICE
66/tcp closed sqlnet

I was expecting open port at 66. But it's not.


Solution

  • You can't use -p to bind to an address of another container. That is for exposing containers on a host interface.

    You could just start your new container in the same network namespace as the existing container:

    docker run --net=container:test_sshd1 -d --name test_sshd4 eg_ssh
    

    Re: your comment:

    Well, sure, you can't have two things bound to the same port on the same address.

    One options is to configure ssh in the second container to listen on something other than port 22. Set up your image so that you can pass the listen port in as an environment variable (so you can do docker run -e SSHD_LISTEN_PORT=66 ... or something).

    A second option is to instead bind them both to a host address (such as your bridge address @ 192.168.4.10). You would start the first with -p 192.168.4.10:22:22 and the second with -p 192.168.4.10:66:22. This would expose both services on 192.168.4.10, one on port 22 and one on port 66.