Cannot connect to containers using their names

Hi dockers,

I’m relatively new to docker, having done one or two small projects here and there, and I’m now moving on to something a bit bigger, namely a webapplication divided in microservices.

Using docker-compose, I have the following containers :

  • 1 for my database, called db
  • 1 for the core application using django, called django (not much originality here)
  • 1 for nginx, currently useless
  • 1 for my central server (called central), which the user connects to through django, and redirects data through my other services using WebSockets, running on port 7777
  • 2 other services (for now)

All containers belonging to a network called app-network.

Here’s the issue now. Django has no issues connecting to the db using “db” as a hostname, so it means it can resolves that, right ? However, when attempting to connect to my server using

socket = new WebSocket('ws://central:7777/ws/');

Firefox cannot open the connection to the server (Firefox can’t establish a connection to the server at ws://central:7777/ws/.). Of course, one might think the problem lies either within the Django code or the Python server, but, if I get the actual IP address of the container with docker inspect (let’s say it’s 12.13.14.15), the user can actually connect to the server and the app functions as intended. This IP changes every launch of docker, so it obviously can’t be an actual solution to use, and I’m at my wits ends about this. I’ve tried quite a bunch of solutons I found on forums :

  • Disable UFW : No change
  • Prune and restart my docker-compose : No change
  • Change the container names, using the container_name field : No change
  • Using the links field : No change

Of course, I have verified using docker network inspect :

[
    {
        "Name": "transcendence_app-network",
        "Id": "ddc4364f674ab134e28df76173c7e2ca75fd9e57a147ca936565aacd9d9ee9d9",
        "Created": "2025-01-20T10:51:05.130595115+01:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": null,
            "Config": [
                {
                    "Subnet": "172.18.0.0/16",
                    "Gateway": "172.18.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {
            "383f5398662314d64cd7f2b1a9ecff77121a0498e6f8a830445015ed5a9bc52c": {
                "Name": "1v1_classic",
                "EndpointID": "d0fb93faee2066c7f5731c44efd8e81939d2af161449b63b1c46cbb7336511bd",
                "MacAddress": "02:42:ac:12:00:05",
                "IPv4Address": "172.18.0.5/16",
                "IPv6Address": ""
            },
            "4823c901b4ada565f77890bf89c3e880ac5e362fd22c1f4ad7e8c004815a725c": {
                "Name": "nginx",
                "EndpointID": "29282c8bd1272c494b32aa130a56a354d4203b1465d97975e4d60cc569058c3f",
                "MacAddress": "02:42:ac:12:00:07",
                "IPv4Address": "172.18.0.7/16",
                "IPv6Address": ""
            },
            "ab295a222d4e9773475b00b9f0a095dd3208f2e3fa0db6f84880d05dd451b30a": {
                "Name": "central",
                "EndpointID": "c36cdb0c6e6911c8c33e92b63e79e01e8f7c1d87c0edf8f466094cb712fabe5e",
                "MacAddress": "02:42:ac:12:00:03",
                "IPv4Address": "172.18.0.3/16",
                "IPv6Address": ""
            },
            "e57f51628c924b767616c014bb20e6700d3e908e9c94221cfc4b7df5051c755b": {
                "Name": "django",
                "EndpointID": "752dc2b6b2a66cb4a4aea5c67d97219647f1b69aeb81b8070e5294038e7827e0",
                "MacAddress": "02:42:ac:12:00:04",
                "IPv4Address": "172.18.0.4/16",
                "IPv6Address": ""
            },
            "f08afc38b058455813a13e79cb22708f2d9c9821e2ce7ac6b789759ab378aab7": {
                "Name": "chat",
                "EndpointID": "7eb94b693c6c9bc86ca4315f9286f3cea3c446da9de0057c09745ba986838edb",
                "MacAddress": "02:42:ac:12:00:06",
                "IPv4Address": "172.18.0.6/16",
                "IPv6Address": ""
            },
            "f333058d5c8e74b8733ba00b89d270846d30feb013fe290d9fad3fcda094ae98": {
                "Name": "db",
                "EndpointID": "170d76f92eaea7da1312ae8cfd7984988b4d8c785c9cc511cb445c2eeede639c",
                "MacAddress": "02:42:ac:12:00:02",
                "IPv4Address": "172.18.0.2/16",
                "IPv6Address": ""
            }
        },
        "Options": {},
        "Labels": {
            "com.docker.compose.config-hash": "c18ef3d7cc2a42c68a4e12bebbf66e96eea5f33c564b38517c31c5be6b72e090",
            "com.docker.compose.network": "app-network",
            "com.docker.compose.project": "transcendence",
            "com.docker.compose.version": "2.32.3"
        }
    }
]

Connecting to my django container using docker exec -it django bash, and looking at /etc/hosts :

:/app# cat /etc/hosts
127.0.0.1	localhost
::1	localhost ip6-localhost ip6-loopback
fe00::0	ip6-localnet
ff00::0	ip6-mcastprefix
ff02::1	ip6-allnodes
ff02::2	ip6-allrouters
172.18.0.4	e57f51628c92

No ‘central’ there.
Of course, here’s my docker-compose :

version: '3'

services:
  db:
    image: postgres:17
    container_name: db
    environment:
      POSTGRES_DB: ${DATABASE_NAME}
      POSTGRES_USER: ${DATABASE_USERNAME}
      POSTGRES_PASSWORD: ${DATABASE_PASSWORD}
    ports:
      - "5432:5432"
    volumes:
      - postgres_data:/var/lib/postgresql/data
    env_file:
      - .env
    networks:
      - app-network

  django:
    build: ./djang/
    container_name: django
    ports:
      - "8000:8000"
    depends_on:
      - db
    environment:
      DJANGO_SECRET_KEY: ${DJANGO_SECRET_KEY}
      DEBUG: ${DEBUG}
      DJANGO_LOGLEVEL: ${DJANGO_LOGLEVEL}
      DJANGO_ALLOWED_HOSTS: ${DJANGO_ALLOWED_HOSTS}
      DATABASE_ENGINE: ${DATABASE_ENGINE}
      DATABASE_NAME: ${DATABASE_NAME}
      DATABASE_USERNAME: ${DATABASE_USERNAME}
      DATABASE_PASSWORD: ${DATABASE_PASSWORD}
      DATABASE_HOST: ${DATABASE_HOST}
      DATABASE_PORT: ${DATABASE_PORT}
    env_file:
      - .env
    networks:
      - app-network

  nginx:
    build: ./nginx/
    image: nginx
    container_name: nginx
    ports:
      - '443:443'
    restart: always
    depends_on:
         - django
    networks:
      - app-network
  
  central:
    build: ./central/
    container_name: central
    restart: always
    ports:
      - "7777:7777"
    networks:
      - app-network

  chat:
    build: ./chat/
    container_name: chat
    restart: always
    depends_on:
      - central
    ports:
      - "7878:7878"
    networks:
      - app-network

  1v1_classic:
    container_name: 1v1_classic
    build: ./back_1v1/
    restart: always
    depends_on:
      - central
    ports:
      - "8001:8001"
    networks:
      - app-network

volumes:
  postgres_data:

networks:
  app-network:
    driver: bridge

(worth nothing that the main server and the microservices do manage to communicate with each others, using the ip 172.17.0.1 : await connect("ws://172.17.0.1:8001/", ping_interval=10, ping_timeout=None))

I might be repeating myself, but the project fully works using “hard coded” IPs, so I think we can safely exclude the problem coming from my code. Did I miss something extremely obvious ? This is tearing me apart

Thanks in advance for your time and help.

Docker provided DNS for the containers, so they can connect via service names to each other. Your browser can not access Docker DNS, therefore the service names can not be resolved.

Make sure to use command docker compose without the dash in between, the old version is deprecated.

I do user docker compose inside a makefile :

#launches the project in the foreground
all:
	export COMPOSE_PROJECT_NAME=""
	docker compose up --build

#launches the project in the background
silent:
	export COMPOSE_PROJECT_NAME=""
	docker compose up --build -d
	docker ps

#Make the migrations
migrate:
	docker compose run django-web python manage.py makemigrations
	docker compose run django-web python manage.py migrate
	
#Launch the superuser creation procedure
superuser:
	docker compose run django-web python manage.py createsuperuser	

#Take down the project cleanly
down:
	docker compose down
	
#Take down then restart in background
re:
	docker compose down
	docker compose up --build -d

#Print docker's statuses
status:
	docker ps
	docker network ls
	docker volume ls

#Nuke it all
clean:
	docker stop $$(docker ps -qa);\
	docker rm $$(docker ps -qa);\
	docker rmi -f $$(docker images -qa);\
	docker volume rm $$(docker volume ls -q);\
	docker network rm $$(docker network ls -q);\
	docker system prune

.PHONY: all clean down re

If the browsers can’t access it, how should I handle it then ? Somehow store the IP associated with central somewhere in the db and recover it when opening my websockets ?

Either use DNS (local router?) or add the domain and IP to a local hosts file.

Manually adding the host is impossible, as it loops back to the start of the problem - I’d need to update the host everytime the Docker container is relaunched.

I found a solution by taking the long road around the problem :
I made a bash script that adds the IP associated to my computer inside the .env file, then simply recover it within my containers. Might not be the best solution, but eh, it works

I once created a project based on the template system behind the nginx proxy to update the hosts file on Linux automatically. But you can also run a browser on the same network in a container:

https://dev.to/rimelek/docker-network-and-network-namespaces-in-practice-5h9#testing-a-webbased-application-without-internet-in-a-container

But if you don’t want to run a browser in a container, you can run a browser installed on your host through the network namespace of the container. I don’t have a desktop Linux to try and share, but I did that too. Of course the static IP solution is the easiest, just not the coolest :smiley:

1 Like

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.