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 runserverdocker-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
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
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With