0

I am following this tutorial on 'Dockerizing' Django + PgSQL + gunicorn + nginx .

Relevant info

  1. host machine OS is Ubuntu 20.0.4 LTS
  2. Docker-desktop: Docker version 20.10.16, build aa7e414

This is my setup so far:

(relevant portions of) settings.py

import os

from pathlib import Path
from decouple import config
import dj_database_url

# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent


# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = config('DEBUG', cast=bool)

ALLOWED_HOSTS = config('ALLOWED_HOSTS', cast=lambda v: [s.strip() for s in v.split(',')])


# Database
# https://docs.djangoproject.com/en/3.2/ref/settings/#databases

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': config('DATABASE_NAME'),
        'USER': config('DB_USER_NAME'),
        'PASSWORD': config('DB_USER_PWD'),
        'HOST': config('DB_HOST'),
        'PORT': config('DB_PORT'),
    }
}

# required for db to work on Heroku
db_from_env = dj_database_url.config(conn_max_age=600)
DATABASES['default'].update(db_from_env)

my-django-proj/my-django-proj/.env

ALLOWED_HOSTS=0.0.0.0,localhost,127.0.0.1,www.example.com,example.com,example.herokuapp.com

# Docker compose seems to need this
DJANGO_ALLOWED_HOSTS=localhost 127.0.0.1 [::1]

DEBUG=True

DATABASE_NAME=thedbname
DB_USER_NAME=myusername
DB_USER_PWD=thepassword
DB_HOST=localhost
DB_PORT=5432

Dockerfile

# pull official base image
FROM python:3.9.6-alpine

# set work directory
WORKDIR /usr/src/app

#############################
# set environment variables #
#############################

# Prevents Python from writing pyc files to disc (equivalent to python -B option)
ENV PYTHONDONTWRITEBYTECODE 1

# Prevents Python from buffering stdout and stderr (equivalent to python -u option)
ENV PYTHONUNBUFFERED 1


# install psycopg2 dependencies
RUN apk update \
    && apk add postgresql-dev gcc python3-dev musl-dev


# install dependencies
RUN pip install --upgrade pip
COPY ./my-django-proj/requirements.txt ./my-django-proj/
RUN pip install -r ./my-django-proj/requirements.txt

# copy project
COPY ./my-django-proj ./my-django-proj

compose.yml

services:
  web:
    build: .
    command: python my-django-proj/manage.py runserver 0.0.0.0:8000
    volumes:
      - ./my-django-proj/:/usr/src/app/my-django-proj/
    ports:
      - 8000:8000
    env_file:
      - ./my-django-proj/my-django-proj/.env

    depends_on:
      - db

  db:
    image: postgres:14.3-alpine

    restart: always
    container_name: postgres14_3
    #user: postgres

    ports:
      - 5432:5432    
    volumes:
      - postgres_data:/var/lib/postgresql/data/
    environment:
      - POSTGRES_USER=myusername
      - POSTGRES_PASSWORD=thepassword
      - POSTGRES_DB=thedbname


volumes:
  postgres_data:      

Output log from sudo docker compose up -d --build

postgres14_3  | 
postgres14_3  | 2022-06-01 12:03:35.017 UTC [1] LOG:  starting PostgreSQL 14.3 on x86_64-pc-linux-musl, compiled by gcc (Alpine 11.2.1_git20220219) 11.2.1 20220219, 64-bit
postgres14_3  | 2022-06-01 12:03:35.017 UTC [1] LOG:  listening on IPv4 address "0.0.0.0", port 5432
postgres14_3  | 2022-06-01 12:03:35.017 UTC [1] LOG:  listening on IPv6 address "::", port 5432
postgres14_3  | 2022-06-01 12:03:35.022 UTC [1] LOG:  listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432"
postgres14_3  | 2022-06-01 12:03:35.028 UTC [50] LOG:  database system was shut down at 2022-06-01 12:03:34 UTC
postgres14_3  | 2022-06-01 12:03:35.032 UTC [1] LOG:  database system is ready to accept connections

Migration attempt output by running: sudo docker compose exec web python my-django-proj/manage.py migrate --noinput

Traceback (most recent call last):                                                                                                            
  File "/usr/local/lib/python3.9/site-packages/django/db/backends/base/base.py", line 219, in ensure_connection                               
    self.connect()                                                                                                                            
  File "/usr/local/lib/python3.9/site-packages/django/utils/asyncio.py", line 26, in inner                                                    
    return func(*args, **kwargs)                                                                                                              
  File "/usr/local/lib/python3.9/site-packages/django/db/backends/base/base.py", line 200, in connect                                         
    self.connection = self.get_new_connection(conn_params)                                                                                    
  File "/usr/local/lib/python3.9/site-packages/django/utils/asyncio.py", line 26, in inner                                                    
    return func(*args, **kwargs)                                                                                                              
  File "/usr/local/lib/python3.9/site-packages/django/db/backends/postgresql/base.py", line 187, in get_new_connection                        
    connection = Database.connect(**conn_params)                                                                                              
  File "/usr/local/lib/python3.9/site-packages/psycopg2/__init__.py", line 122, 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 "localhost" (127.0.0.1) and accepting                                                                   
        TCP/IP connections on port 5432?             

could not connect to server: Address not available
        Is the server running on host "localhost" (::1) and accepting
        TCP/IP connections on port 5432?

So I decided to do a bit of investigation on my host machine

output of sudo netstat -tulpn | grep LISTEN

tcp        0      0 0.0.0.0:8000            0.0.0.0:*               LISTEN      118855/docker-proxy                                           
tcp        0      0 127.0.0.1:6379          0.0.0.0:*               LISTEN      1017/redis-server 1                                           
tcp        0      0 127.0.0.1:11211         0.0.0.0:*               LISTEN      934/memcached                                                 
tcp        0      0 127.0.0.53:53           0.0.0.0:*               LISTEN      754/systemd-resolve 
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      997/sshd: /usr/sbin 
tcp        0      0 127.0.0.1:631           0.0.0.0:*               LISTEN      72912/cupsd         
tcp        0      0 0.0.0.0:5432            0.0.0.0:*               LISTEN      118727/docker-proxy 
tcp6       0      0 :::44543                :::*                    LISTEN      58417/code          
tcp6       0      0 :::8000                 :::*                    LISTEN      118862/docker-proxy 
tcp6       0      0 ::1:6379                :::*                    LISTEN      1017/redis-server 1 
tcp6       0      0 :::22                   :::*                    LISTEN      997/sshd: /usr/sbin 
tcp6       0      0 ::1:631                 :::*                    LISTEN      72912/cupsd         
tcp6       0      0 :::5432                 :::*                    LISTEN      118734/docker-proxy

PG is obviously running on port 5432 (so the Django message is misleading - I think). I try to connect to the Db on the container as follows:

sudo docker compose exec db psql -U myusername thedbname

psql (14.3) Type "help" for help.

thedbname=#

So clearly, PG is running in the container - so, what is causing the Db connection to be refused? - and how do I fix it, so that I can run my migrations, and access the Django project on http://localhost:8000 on my local machine?

Homunculus Reticulli
  • 65,167
  • 81
  • 216
  • 341

1 Answers1

0

If you do not need to access postgres from your host then no need for the port mapping.

Containers can communicate together as they should be part of the same network using the service name, in your case you can try db which is the name of your postgres container instead of localhost.

To answer your exact question, to access the host machine from a docker container then you need to access host.docker.internal. host.docker.internal would point to your host localhost.

See this SO post

For Linux you might still need to add:

extra_hosts:
    - "host.docker.internal:host-gateway"

to your docker-compose's web service.

I would still recommend using the first approach.

Mounir
  • 11,306
  • 2
  • 27
  • 34
  • Actually, my objective is to be able to access the web page from localhost:8000 (as shown in the tutorial I linked to). However, the database connection is failing (during migration), so I can't access the web page. I need to solve the database connection issue, SO that I can access the web page. Sorry if my question didn't make that clear. – Homunculus Reticulli Jun 01 '22 at 20:17