Skip to main content

Troubleshooting for Docker containers - Accessing the other one

Troubleshoot Docker container networking - test ports, DNS, and fix proxy issues so one container can reliably call another API on the same network.

· 7 min read
View raw
Christophe
Markdown, WSL and Docker lover ~ Insatiable curious.
Cet article existe aussi en français — lire la version française.

Troubleshooting for Docker containers - Accessing the other one

⚡
TL;DR

This article details troubleshooting steps for Docker containers unable to communicate, specifically when one container needs to access another's API on the same network. It systematically checks network configuration, port accessibility, and DNS resolution between containers. The ultimate solution involved configuring no_proxy environment variables within the consumer container to bypass an interfering proxy for internal Docker network addresses.

The situation: I have two containers; one called provider and the other one called consumer. The consumer should be able to run an API on the provider.

And ... it didn't work: something in my configuration is not correct because I get connection errors when trying to call the provider, let's start the investigation and understand the solution.

In the rest of this article, let's call them like that: provider for the first container and consumer for the second one.

First, they should be on the same network​

First, they should be on the same Docker network; otherwise, there's no chance of making it work. If you need the opposite — reaching a service running on your host from inside a container — read Using Docker network and the extra_hosts property.

By running docker ps you'll get the container_id and the name of your two containers.

The command to retrieve the name of the Docker network is docker inspect --format '{{json .NetworkSettings.Networks}}' CONTAINER_NAME | jq (jq is the Swiss-army knife for JSON on the command line) so, for the first container, please run docker inspect --format '{{json .NetworkSettings.Networks}}' provider | jq and docker inspect --format '{{json .NetworkSettings.Networks}}' consumer | jq for the second.

You'll get something like that:

{
"your_network": {
"IPAMConfig": null,
"Links": [
],
"Aliases": [
"facade",
"facade"
],
"DriverOpts": null,
"GwPriority": 0,
"NetworkID": "528b60827ec7469dfb2c604c3443ac716f8fa1f3d1934089f49e53f6e65500ca",
"EndpointID": "be75366d271b090f3d47f236ddff0236993af02a73c5d501f44fbef8f351be5e",
"Gateway": "192.168.0.1",
"IPAddress": "192.168.0.4",
"MacAddress": "62:5b:7b:9e:12:fe",
"IPPrefixLen": 24,
"IPv6Gateway": "",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"DNSNames": [
"facade",
"5abd45eecfa3"
]
}
}

This is a Docker network configuration object describing how a container named 'facade' is connected to a network. It specifies the container's IP address (192.168.0.4), gateway, MAC address, and other network identifiers that Docker uses to route traffic to and from this container.

In this example, the network is called your_network. Just make sure you have the same for both containers. Also, make sure you have the same Gateway too (192.168.0.1 in this example).

Ok, they're running on the same network.

Then, testing the internal port for both containers​

Please run docker ps --format "table {{.ID}}\t{{.Names}}\t{{.Ports}}" to get the list of running containers and their ports (extern/intern).

You'll get something like this:

CONTAINER ID NAMES PORTS
5abd45eecfa3 consumer 0.0.0.0:8001->8000/tcp, [::]:8001->8000/tcp
a95b6174beb9 provider 0.0.0.0:8888->8000/tcp, [::]:8888->8000/tcp

So they both are running port 8000 internally but the consumer is exposed on the host using port 8001 and provider on port 8888.

In the previous chapter, we just saw that the network is called your_network.

We can ensure the process running on port 8000 in both containers is running by executing docker inspect -f '{{.NetworkSettings.Networks.your_network.IPAddress}}' consumer in the console to get the IP of that container. In my case, I get 192.168.0.4 as response.

Now that we've it, we can test the internal port:

>user@machine: ~/yourproject

Press CTRL+C to quit.

Ok, both containers have a service running on their internal port.

Third, testing the external port for both containers​

We've seen containers are running on port 8000 internally but one is mapping the port 8001 on the host and 8888 for the second one.

We can run telnet 127.0.0.1 8001 and telnet 127.0.0.1 8888 to test that port. See, here, since we're accessing exposed ports, we're using our local host IP address.

If you know that the service is a web service, you can run curl -vvv 127.0.0.1:8001 to make sure the service is working fine and the delivered answer meets your expectations:

* Trying 127.0.0.1:8001...
* Connected to 127.0.0.1 (127.0.0.1) port 8001 (#0)
> GET / HTTP/1.1
> Host: 127.0.0.1:8001
> User-Agent: curl/7.76.1
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< date: Sun, 14 Dec 2025 08:17:16 GMT
< server: uvicorn
< content-length: 106
< content-type: application/json
<
* Connection #0 to host 127.0.0.1 left intact

This is a curl HTTP request trace showing a successful connection to a local server on port 8001. The client sends a GET request to the root path, and the server responds with HTTP 200 (success) and returns JSON content.

Ok, both containers are correctly exposed on their external port.

Fourthly, testing connectivity between the two containers​

Run docker ps --format "table {{.ID}}\t{{.Names}}\t{{.Ports}}" again to get the container name and its associated container ID back.

In our preamble, we've said: the consumer should be able to run an API from the provider so let's jump in the consumer by creating a console. We'll use the CONTAINER_ID of the consumer and we'll connect as root:

>user@machine: ~/yourproject

We'll first try ping to see if we can connect to the provider container:

>user@machine: ~/yourproject

Once done, try ping followed by the container name (we've already identified provider and consumer as our container names thanks to our docker ps command).

>user@machine: ~/yourproject

Press CTRL+C to stop.

Ok, our consumer can reach the provider by name (ping works).

This means that the DNS resolution is working fine.

Testing the port​

Still in the consumer container, install telnet if needed

>user@machine: ~/yourproject

Then run telnet provider 8000 i.e. the name of the container and its internal port (not the exposed one)

>user@machine: ~/yourproject

Trying the exposed port

Just rerun the last telnet command but using port 8888 this time: it'll not work.

By using the container name with telnet, we should use the internal port; not the exposed one.

Ok, the transport layer (telnet) is working too.

telnet is used to test the transport layer (layer #4 in the OSI model) and our test here is showing it's working.

Testing the application​

Now that we know containers can communicate, let's try the application layer (layer #7 in the OSI model).

In my use case, the provider container is offering an API so I should be able to reach it using curl.

>user@machine: ~/yourproject

In my situation, this is where I got an error and the dump is showing something like this:

<body><div class="message-container">
<div class="logo"></div>
<h1>504 DNS look up failed</h1>
<p>The webserver reported that an error occurred while trying to access the website. Please return to the previous page.</p>
<table><tbody>
<tr>
<td>URL</td>
<td>http://provider:8000/</td>
</tr>
</tbody></table>
</div></body>

Bingo! The problem is ... a proxy.

The request was intercepted by a proxy and that one is denying the request.

We should tell it to ignore requests made to our container.

export no_proxy="provider,192.168.0.0/24,127.0.0.1,localhost"
export NO_PROXY="provider,192.168.0.0/24,127.0.0.1,localhost"
  • provider is the name of our container,
  • 192.168.0.0/24 is the IP range for the Docker subnet (you can retrieve it by running docker network inspect your_network | jq -r '.[].IPAM.Config[0].Subnet')
  • the well-known 127.0.0.1,localhost is our localhost

The no_proxy variable

To make sure all tools (curl, wget, apt-get, ...) are well using the no_proxy variable, it's recommended to use both notation: lower and upper case.

Now, finally, the command I use to consume my API looks like curl -X POST -H 'Content-Type: application/json' -H 'Accept: application/json' http://provider:8000/api/v1/fetch.

Fifthly, finding the solution​

If you came across this article because you had the same problem as me, the solution is now simple: make sure your Docker image is configured to have a no_proxy variable with the correct values.

This can be done using a no_proxy variable in your compose.yaml file, here, just for the illustration, a sample way to do this:

services:
consumer:
image: your_image
build:
context: .
dockerfile: Dockerfile
args:
- HTTP_NO_PROXY=${HTTP_NO_PROXY:-provider,localhost,.local,127.0.0.1,192.168.0.0/24}

Now, in your Dockerfile just do something like:

# syntax=docker/dockerfile:1
ARG HTTP_NO_PROXY="localhost,.local,127.0.0.1,192.168.0.0/24"

FROM python:3.14-slim AS production

ARG HTTP_NO_PROXY

ENV no_proxy="${HTTP_NO_PROXY}" \
NO_PROXY="${HTTP_NO_PROXY}"

Create your containers again and tadaaaa! it'll work.

In our example here, we finally determined that it was not the network layer that was at fault, but rather the layer where the proxy took control: the application layer.


🦋 Join the conversation on BlueskyRequires a free Bluesky account to like, repost or comment. This block talks to Bluesky's public API directly from your browser (no cookies, no sign-in) — that means your IP address reaches Bluesky's servers just by this section loading.

Loading comments…

Was this article helpful?
Did you try the steps in this article?