Public source IP for connections between different docker-compose projects?

I’ve got two docker-compose projects: one for

  • “mail-out” outgoing email, and one for
  • “mail-in” incoming email.

Now, if I send an email to myself, mail-out connects to mail-in to relay the mail. However, since both composes are running on the same host, the source IP of that connection is a Docker-internal IP. This is problematic, as the source IP is checked against an SPF record these days. The SPF record only has my servers public IP, and I think it would be wrong to add the Docker internal IP ranges to that record.

My question is: How can I make connections from one compose to the other appear as if they were coming from my hosts public IP? (That would be the case if the composes were running on different machines.) I assume it would need more IP masquerading. Is this perhaps something I can instruct Docker to manage for me?

1 Like

Since you write compose-project, I assume you use a bridge network.

Some thoughts on the subject:

  • Problem 1: In a docker bridge network, the source ip will always be the ip of the container network’s gateway, and won’t retain the original source ip (unless mode: host in the publish long syntax is finally implemented for compose projects like it is for swarm stacks: https://docs.docker.com/compose/compose-file/05-services/#long-syntax-3).
  • Problem 2: A bridge network can use options to set a default host ip when binding ports, but the egress ip can’t be configured.

Using network_mode: host would not suffer from both problems, but network wise the container wouldn’t be isolated from the network namespace of the host itself.

If publishing mode: host would work with compose project, it might be sufficient to just use the public ip to communicate from one service to the other. As the egress ip can’t be fixed, I am not entirely sure if this would work, but it might be worth a shot.

Apart from that I am not aware of any docker configuration that would help the situation.

Yes, I use the default bridge networks that docker-compose creates for my projects. There is two of them, because there is two projects (mail-out, mail-in, as described above). To clarify: The connection goes from a container in mail-out to a container in mail-in (via a published port 25).

Ad 1) I think both IP of container and IP of network gateway is not what I want. Mail-in expects the public IP of my server, as that’s what’s allowlisted in the SPF record.
Ad 2) “egress IP” sounds like what I need.

I would probably try to configure a proxy server that listens on the host network and its only job is to forward the requests from one host port to another. I would try this, because when you send a request from the host to a host port that is forwarded to a container IP in a compose project, the container sees the host IP.

So for example your mail-out could send the request to $HOST_IP:1025 which would be the port of the proxy server and the proxy would forward it to $HOST_IP:25. I never tried this with emails, so I don’t know how exactly it would work, but maybe this could help:

Or iptables could possibly help too, but I have no idea how I would do it with that.

1 Like