user6072865
user6072865

Reputation: 83

Docker compose - port forward from host IP to specific IP in container

I have a container that sits in multiple networks, and specifically two "external" networks.

The host also has two NICs and I need to forward from one host IP to a specific IP on the container, and then forward the other host IP to the other IP on the container.

For example, take this docker compose segment:

services:
  server:
    image: image
    networks:
      internal_net:
        ipv4_address: 1.0.0.1
      ext1_net:
        ipv4_address: 1.1.1.1
      ext2_net:
        ipv4_address: 2.2.2.2

And say on the host on eth0 I have 3.3.3.3 and on eth1 I have 4.4.4.4

I would then want to forward 80 from 3.3.3.3 on the host to 1.1.1.1 on the container, I would then want to forward 80 from 4.4.4.4 on the host to 2.2.2.2 on the container

However, the ports option doesn't seem to allow forwarding to a specific container interface.

How do I achieve this? Do I need to do the iptables rules manually?

Many thanks

Upvotes: 2

Views: 2460

Answers (1)

larsks
larsks

Reputation: 311238

When Docker sets up the forwarding rule to publish a container port on the host, it looks like it always chooses the address of the first interface. So given a configuration like this:

services:
  server:
    image: image
    ports:
      - "8080:8080"
    networks:
      internal_net:
        ipv4_address: 1.0.0.1
      ext1_net:
        ipv4_address: 1.1.1.1
      ext2_net:
        ipv4_address: 2.2.2.2

Docker would create something like this rule in the nat table:

-A DOCKER ! -i br-439dfcc4c0d7 -p tcp -m tcp --dport 8080 -j DNAT --to-destination 1.0.0.1:8080

If you wanted to explicitly target a different address, you would exclude the ports entry from your docker-compose.yaml and add your own rules to the PREROUTING chain of the nat table. For example:

iptables -A PREROUTING -p tcp --dport 8080 -j DNAT --to-destination
1.1.1.1:8080

Communication from your container back to your host is going to be governed by the routing table inside the container. Typically, the default route will be via eth0, so your container will not necessarily reply over the interface you expect. Because Docker creates MASQUERADE rules for all the addresses in your container this should not be a problem.

Upvotes: 1

Related Questions