Docker container cannot connect to other container’s public exposed port

dockernetworking

I've got two docker containers that are not linked (SMTP + webserver). The SMTP container exposes port 25 to all interfaces. (docker run -p 25:25 smtp). I can reach it from outside.

My web container is unable to connect to the SMTP's container port 25, though (via the host's public IP address). Shouldn't it be able to connect to it? The port is exposed to the world.

What is the technical reason for this connection problem?


Someone else asked this on reddit, but no sensible answer was given there.

Best Answer

If the containers aren't on the same docker network they won't be able to communicate directly.

Containers on the default network aren't able to communicate either without using the old --link syntax (currently, see this). Since yours aren't on linked (as you mention) and I assume are just on the default docker network they will not being able to directly interact.

Your Web container should be able to communicate with the SMTP server via the docker host's port 25 as you have setup that map between the host and the SMTP container. By using the hosts public address, your web container will be able to communicate with the SMTP container.

Update: I've written a test case which works for me, could you confirm this doesn't work in your environment. Feel free to change server ports from 5000 to anything you want by make sure you replace all instances. In the client app.py add your IP in the big [YOUR PUBLIC IP] bit. You don't need python on your machine to test this - but the alpine image is only about 80MB.

Server

app.py

from xmlrpc import server

serv = server.SimpleXMLRPCServer(('0.0.0.0', 5000))

 def echo(word):
    return "echo: {}".format(word)

serv.register_function(echo)
serv.serve_forever()

Dockerfile

FROM python:3-alpine
WORKDIR /app
COPY app.py .
EXPOSE 5000
ENTRYPOINT python app.py

Build with docker build -t server:tobyd

Run with docker run -d -p 5000:5000 server:tobyd

Client

app.py

from xmlrpc import client
proxy = client.ServerProxy('http://[YOUR PUBLIC IP]:5000')

for i in range(10):
    print(proxy.echo('cats'))

Dockerfile

FROM python:3-alpine
WORKDIR /app
COPY app.py .
ENTRYPOINT python app.py

Build with docker build -t client:tobyd

Run with docker run -d --name client_tobyd client:tobyd

Expectations
docker logs client_tobyd should have cats printed 10 times.