26

My django project cannot connect to postgres database container. What I should to do?

It crashes on commands python manage.py collectstatic --noinput && python manage.py makemigrations blog && python manage.py migrate. I know docker run command creates a new container but I have more commands as one by bash in docker-compose.yml. It should works, shouldn't it?

my Dockerfile:

FROM python:3.6-alpine
MAINTAINER Name <name@domain>

ENV PYTHONUNBUFFERED 1
ENV INSTALL_PATH /heckblog
RUN mkdir -p $INSTALL_PATH

WORKDIR $INSTALL_PATH


COPY requirements.txt requirements.txt

# make available run pip install psycopg2
RUN apk update && \
    apk add --virtual build-deps gcc python3-dev musl-dev && \
    apk add postgresql-dev
RUN pip3 install -r requirements.txt

# add bash into alpine linux
RUN apk add --update bash && rm -rf /var/cache/apk/*

COPY ./heckblog .
#RUN pip install .

CMD gunicorn -b 0.0.0.0:8000 --access-logfile - "config.wsgi:application"

my docker-compose.yml:

version: '2'


services:
    db:
        image: postgres:alpine
        environment:
            POSTGRES_USER: blogdmin
            POSTGRES_PASSWORD: password
            POSTGRES_DB: heckblog
            PGDATA: /tmp/pgdata
        volumes:
            - postgres_data:/tmp/pgdata

    web:
        build: .
        command: >
            bash -c "sleep 10 &&
            python manage.py collectstatic --noinput && 
            python manage.py makemigrations blog && 
            python manage.py migrate &&
            echo \"from django.contrib.auth.models import User; User.objects.create_superuser('admin', '[email protected]', 'pass')\" | python manage.py shell &&
            gunicorn -b 0.0.0.0:8000 --access-logfile - --reload \"config.wsgi:application\""                
        volumes:
            - ./heckblog:/heckblog
        depends_on:
            - db
        environment: 
            IN_DOCKER: 1
        ports:
            - "80:8000"


volumes:
    postgres_data:

settings.py:

...

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'NAME': 'heckblog',
        'USER': 'blogdmin',
        'PASSWORD': 'password',
        'HOST': 'localhost',
        'PORT': '', # default port
    }
}

...

Output of docker-compose up --build:

web_1  |        TCP/IP connections on port 5432?
web_1  | could not connect to server: Connection refused
web_1  |        Is the server running on host "localhost" (127.0.0.1) and accepting
web_1  |        TCP/IP connections on port 5432?
web_1  |
heckblog_web_1 exited with code 1

I use: Windows 10 Docker 17.03.0-ce-win1-(10296) docker-compose version 1.11.2 Django==1.10.6 psycopg2==2.7.1.

Thanks for answers

4 Answers 4

47

Each container in docker by default gets its own hostname and IP. When compose spins up the containers for you, it also places all of the containers on a network by default to permit DNS based discovery.

What this means is that your database is not reachable on localhost, but you can reach it by the service name "db". Change this line in your settings.py:

    'HOST': 'localhost',

to:

    'HOST': 'db',
Sign up to request clarification or add additional context in comments.

5 Comments

Yes, that is what I missed. Thank you very much.
I am running postgres on the host i.e. my MacOS. I have network_mode: host in my docker-compose.yml but my dockerized django app is still failing in spite of postgres running, with the same error, even though my HOST is localhost.
@saadi the question and answer here do not apply when using host networking. I'd also strongly recommend against host networking if you can avoid it.
@BMitch can you pls suggest any other alternative of using network_host? Like if a postgres service is installed in OS, and I want to use it in a docker image, what do I put next to host instead of localhost because localhost clearly won't work as it's installed in OS not docker
@saadi move your dependencies into docker first. Them use docker networking. Your comment here appears to be a different question rather than clarifying the answer to the one asked above. Please use the "ask question" link to ask a new question or search for questions covering accessing a host service from inside the container.
4

Here's what worked for me:

in compose:

version: '3.7'
services: 
  web:
    build: .
    command: python /code/manage.py runserver 0.0.0.0:8000
    volumes: 
        - .:/code
    ports: 
        - 8000:8000
    environment: 
        - DB_HOST=db
        - DB_NAME=web
        - DB_USER=postgres
        - DB_PASSWORD=postgres

    depends_on: 
        - db

  db:
    image: postgres:12-alpine
    volumes: 
        - postgres_data:/var/lib/postgresql/data/
    environment: 
        - POSTGRES_DB=web
        - POSTGRES_USER=postgres
        - POSTGRES_PASSWORD=postgres
volumes:
   postgres_data:

in settings:

DATABASES = {
'default': {
    'ENGINE': 'django.db.backends.postgresql',
    'NAME': os.environ.get('DB_NAME'),
    'USER':os.environ.get('DB_USER'),
    'PASSWORD': os.environ.get('DB_PASSWORD'),
    'HOST':os.environ.get('DB_HOST'),
    'PORT':5432,
 }
}

Comments

0

Django settings.py -> Database={host:db} . Other database option remain same. Like

DATABASE_ENGINE=django.db.backends.postgresql
DATABASE_USER=postgres
DATABASE_PASSWORD=1234
DATABASE_NAME=pos
DATABASE_HOST=db
DATABASE_PORT=5432

Docker compose yml file: This settings created for Django, Nginx, Postgres

version: '3.8'
services:
  nginx:
    restart: unless-stopped
    build:
      context: .
      dockerfile: ./docker/nginx/Dockerfile
    ports:
      - '81:81'
    volumes:
      - static_volume:/home/pos/static/
      - ./docker/nginx/development:/etc/nginx/conf.d
    depends_on:
      - backend
  backend:
    restart: unless-stopped
    build:
      context: .
      dockerfile: ./docker/backend/Dockerfile
    image: pos-backend:backend # image_name: image_tag
    container_name: pos_backend
    volumes:
      - ./backend:/home/pos/
      - static_volume:/home/pos/static
      - media_volume:/home/pos/media
    environment:
      DJANGO_SETTINGS_MODULE: pos.settings
    ports:
      - "8000:8000"
    command: python manage.py runserver 0.0.0.0:8000
    expose:
      - 8000
    env_file:
      - ./backend/.env.dev
    depends_on:
      - db
  db:
    image: postgres:12
    container_name: pos_db
    volumes:
      - postgres_data:/var/lib/postgresql/data
    environment:
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=1234
      - POSTGRES_DB=pos
    ports:
      - '5432:5432'
    expose:
      - 5432
    networks:
      - default
volumes:
  static_volume: {}
  media_volume:
  postgres_data:

Comments

0

I had the similar problem. So when I try to makemigrations and migrate in RUN, it looks like the psql container has not yet been initialized and is not listening on the network. Two days later I noticed that when I run makemigrations and migrate in CMD it works great, Django connects to the psql container. But if I run these commands with RUN in Dockerfile it raises error.

Firstly in your settings.py:

DATABASES = {
    
    'default': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        ...
        'HOST': 'db' -> name of psql container,
        'PORT': 5432 -> container port. (expose parametr or second parametr in ports)
    }

}

Secondly in django Dockerfile:

CMD python3 manage.py makemigrations \
    && python3 manage.py migrate

But not this:

RUN python3 manage.py makemigrations \
    && python3 manage.py migrate

By the way I trie to make wait-for-db.sh and obviously depends on with healtry condition. It doesn't work anyway if u try to RUN these commands. Hope it helped for you.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.