Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

docker-compose with two containers: web can not connect to db

docker-compose fails to build web component because it can not connect to the previously created db component

Mac OSX 10.13.6, conda 4.5.11, Python 3.6.8, Docker version 18.09.1, docker-compose version 1.23.2

django 1.8.3 gets installed with requirements.txt from Dockerfile. Not at liberty to upgrade.

Several very similar discussions on SO did not help (like this one: Docker-compose with django could not translate host name "db" to address: Name or service not known).

I have a docker-compose.yml with a network and two components:

version: '3'
networks:
  bridge:
   driver: bridge
services:
  db:
    image: postgres:10
    container_name: myapp-db
    volumes:
      - ./postgres_data:/var/lib/postgresql/data/
    ports:
      - "5432:5432"
    environment:
     POSTGRES_DB: actionability-master
     POSTGRES_PASSWORD: postgres
     POSTGRES_USER: postgres
    networks:
      - bridge


  web:
    restart: unless-stopped
    container_name: myapp-web
    build: .
    command: /start_gunicorn.sh
    ports:
      - "8080:8080"
    environment:
      PRODUCTION: 'true'
    networks:
      - bridge

In my settings.py I have DATABASES section:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'NAME': INSTANCE_NAME,
        'USER': 'postgres',
        'PASSWORD': 'postgres',
        'HOST': 'db',
        'PORT': '5432'
    },

}

When I run $ docker-compose up -d, the first image (db) gets created and its container gets started. Can see it's running and listening on port 5432 with docker ps and lsof . The same thing happens if I remove web: component from docker-compose.yml file

Now, the second component (web) has Dockerfile that contains these two lines (among many others):

RUN python manage.py makemigrations myapp
RUN python manage.py migrate

The "migrate" like dies with this error:

Traceback (most recent call last):
File "/usr/local/lib/python3.6/site-packages/django/db/backends/base/base.py", line 130, in ensure_connection
    self.connect()
File "/usr/local/lib/python3.6/site-packages/django/db/backends/base/base.py", line 119, in connect
    self.connection = self.get_new_connection(conn_params)
File "/usr/local/lib/python3.6/site-packages/django/db/backends/postgresql_psycopg2/base.py", line 176, in get_new_connection
    connection = Database.connect(**conn_params)
File "/usr/local/lib/python3.6/site-packages/psycopg2/__init__.py", line 130, in connect
    conn = _connect(dsn, connection_factory=connection_factory, **kwasync)
psycopg2.OperationalError: could not connect to server: Connection refused
Is the server running on host "db" (37.34.32.51) and accepting TCP/IP connections on port 5432?

I tired to several tweaks. * changed version '3.7' * added to db section

expose:
    - "5432"
  • added to web component:

depends_on: - "db"

  • added to web component:

links: - "db"

  • set PRODUCTION to false

environment: PRODUCTION: 'false'

  • changed HOST in settings.py to container name, to image name, to tags, to container id, to 'localhost', to '127.0.0.1', etc.. the error is the same, just mentioning the new HOST name instead of 'db'
  • ran outside of conda env
  • ran with --build switch ( docker-compose up -d --build )
  • did docker system prune and ran again

All the same error.


UPDATE: After a sugestion that it docker-compose does not work this way I tried to split it into two separate tasks. First I build myapp-db container and make sure it's running on the correct port :

$ docker container ps


CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                      NAMES
c110e8361cda        postgres:10         "docker-entrypoint.s…"   4 hours ago         Up 4 hours          0.0.0.0:5432->5432/tcp     myapp-db

Then I build myapp-web:

docker build -t myapp-web .

The same error still happens. So, why is it not finding the db container NOW?

like image 951
SwissNavy Avatar asked Jan 24 '19 14:01

SwissNavy


1 Answers

I use the depends_on list to start the db container before the web container and the links to ensure that the host names can be resolved.

I add the following to the web:

services:
  db:
    # ...
  web:
    links:
    - "db:db" # resolve the hostname "db" with the ip of the db container
    depends_on:
    - db # start db before web

Example

like image 72
User Avatar answered Oct 28 '22 15:10

User