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.