Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django can't connect to Postgres in Docker setup

I'm setting up an application in Docker that uses Django and Postgres. I'm unable to connect to Postgres from the app. When I run either:

  • docker-compose run web python manage.py runserver
  • docker-compose run web python manage.py migrate

I get the following error:

django.db.utils.OperationalError: could not connect to server: No such file or directory
    Is the server running locally and accepting
    connections on Unix domain socket "/var/run/postgresql/.s.PGSQL.5432"?

Here's my Dockerfile:

FROM python:2.7

ADD requirements.txt /app/requirements.txt

WORKDIR /app/

RUN pip install -r requirements.txt

My docker-compose.yml:

version: '2'
services:
  db:
    image: postgres:9.4
    hostname: db
    environment:
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=postgres
      - POSTGRES_DB=postgres
    ports:
      - "5432:5432"

  web:
    build:
      context: .
      dockerfile: Dockerfile
    hostname: web
    volumes:
      - .:/app
    ports:
      - "8000:8000"
    links:
      - db
    depends_on:
      - db
    command:
      python manage.py runserver 0.0.0.0:8000

and the database settings in Django:

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

docker ps -a shows:

e9df7e1644ce        web             "python manage.py ..."   About a minute ago   Up About a minute          0.0.0.0:8000->8000/tcp   web_1
60801d3256e4        postgres:9.4        "docker-entrypoint..."   About a minute ago   Up About a minute          0.0.0.0:5432->5432/tcp   db_1

Django v1.10.5
Docker for Mac v1.13.1
docker-compose v 1.11.1

Here are the logs:

  • web: https://gist.github.com/steven-mercatante/912ca964fd05bee2c835b1ac5586c154

  • db: https://gist.github.com/steven-mercatante/4c9a03bfc4f2e90f4b9931bdc185652f

like image 256
Steven Mercatante Avatar asked Feb 17 '17 20:02

Steven Mercatante


1 Answers

Turns out the issue was that Postgres hadn't fully spun up before starting the Django app. This was easily solved by waiting a few seconds before starting the web server. I set the command for my web service to ./bin/boot.sh, and the contents of that file are:

#!/bin/sh

# wait for Postgres to start
sleep 10

python manage.py migrate

python manage.py runserver 0.0.0.0:8000

Edit

This method might not be good enough depending on your application - sleeping for 10 seconds works for me, most of the time, but it's possible that postgres will take 11 seconds to spin up. Here's an improved bash file, with a function I took from this example.

#!/bin/bash

# wait for Postgres to start
function postgres_ready(){
python << END
import sys
import psycopg2
try:
    conn = psycopg2.connect(dbname="postgres", user="postgres", password="postgres", host="postgres")
except psycopg2.OperationalError:
    sys.exit(-1)
sys.exit(0)
END
}

until postgres_ready; do
  >&2 echo "Postgres is unavailable - sleeping"
  sleep 1
done

python manage.py migrate

gunicorn pft.wsgi:application -w 2 -b 0.0.0.0:8000 --reload
like image 129
Steven Mercatante Avatar answered Oct 21 '22 18:10

Steven Mercatante