1

I wanted to create a Docker image for my Django project mysite that has two apps tracks and users. I used docker build -t mysite to build my docker image. I have written a Dockerfile like it says on dockerhub. Then i created docker-compose.yml file and bash script entypoint.sh that I use in docker-compose file.

These are my files:

Dockerfile:

FROM django:onbuild

COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh

docker-compose.yml:

version: '3'

services:
  db:
    image: postgres
    container_name: postgres_container
    environment:
     - POSTGRES_USER=postgres
     - POSTGRES_PASSWORD=postgres
     - POSTGRES_DB=postgres
    ports:
     - 5432:5432
  web:
    image: mysite:latest
    build:
     context: .
     dockerfile: Dockerfile
    container_name: mysite_container
    ports:
      - "8000:8000"
    depends_on:
      - db
    entrypoint: /entrypoint.sh

entrypoint.sh

#!/bin/sh

python manage.py makemigrations
python manage.py migrate
python manage.py runserver 0.0.0.0:8000
exec "$@"

So when I wanted to start the whole container I used following commands

docker build .
docker-compose build
docker-compose up

And my postgres_containter starts successfully, but mysite_container throws the following error:

mysite_container | Traceback (most recent call last):
mysite_container |   File "manage.py", line 22, in <module>
mysite_container |     execute_from_command_line(sys.argv)
mysite_container |   File "/usr/local/lib/python3.4/site-packages/django/core/management/__init__.py", line 371, in execute_from_command_line
mysite_container |     utility.execute()
mysite_container |   File "/usr/local/lib/python3.4/site-packages/django/core/management/__init__.py", line 365, in execute
mysite_container |     self.fetch_command(subcommand).run_from_argv(self.argv)
mysite_container |   File "/usr/local/lib/python3.4/site-packages/django/core/management/base.py", line 288, in run_from_argv
mysite_container |     self.execute(*args, **cmd_options)
mysite_container |   File "/usr/local/lib/python3.4/site-packages/django/core/management/base.py", line 335, in execute
mysite_container |     output = self.handle(*args, **options)
mysite_container |   File "/usr/local/lib/python3.4/site-packages/django/core/management/commands/migrate.py", line 79, in handle
mysite_container |     executor = MigrationExecutor(connection, self.migration_progress_callback)
mysite_container |   File "/usr/local/lib/python3.4/site-packages/django/db/migrations/executor.py", line 18, in __init__
mysite_container |     self.loader = MigrationLoader(self.connection)
mysite_container |   File "/usr/local/lib/python3.4/site-packages/django/db/migrations/loader.py", line 49, in __init__
mysite_container |     self.build_graph()
mysite_container |   File "/usr/local/lib/python3.4/site-packages/django/db/migrations/loader.py", line 207, in build_graph
mysite_container |     self.applied_migrations = recorder.applied_migrations()
mysite_container |   File "/usr/local/lib/python3.4/site-packages/django/db/migrations/recorder.py", line 61, in applied_migrations
mysite_container |     if self.has_table():
mysite_container |   File "/usr/local/lib/python3.4/site-packages/django/db/migrations/recorder.py", line 44, in has_table
mysite_container |     return self.Migration._meta.db_table in self.connection.introspection.table_names(self.connection.cursor())
mysite_container |   File "/usr/local/lib/python3.4/site-packages/django/db/backends/base/base.py", line 255, in cursor
mysite_container |     return self._cursor()
mysite_container |   File "/usr/local/lib/python3.4/site-packages/django/db/backends/base/base.py", line 232, in _cursor
mysite_container |     self.ensure_connection()
mysite_container |   File "/usr/local/lib/python3.4/site-packages/django/db/backends/base/base.py", line 216, in ensure_connection
mysite_container |     self.connect()
mysite_container |   File "/usr/local/lib/python3.4/site-packages/django/db/utils.py", line 89, in __exit__
mysite_container |     raise dj_exc_value.with_traceback(traceback) from exc_value
mysite_container |   File "/usr/local/lib/python3.4/site-packages/django/db/backends/base/base.py", line 216, in ensure_connection
mysite_container |     self.connect()
mysite_container |   File "/usr/local/lib/python3.4/site-packages/django/db/backends/base/base.py", line 194, in connect
mysite_container |     self.connection = self.get_new_connection(conn_params)
mysite_container |   File "/usr/local/lib/python3.4/site-packages/django/db/backends/postgresql/base.py", line 168, in get_new_connection
mysite_container |     connection = Database.connect(**conn_params)
mysite_container |   File "/usr/local/lib/python3.4/site-packages/psycopg2/__init__.py", line 130, in connect
mysite_container |     conn = _connect(dsn, connection_factory=connection_factory, **kwasync)
mysite_container | django.db.utils.OperationalError: could not connect to server: Connection refused
mysite_container |      Is the server running on host "localhost" (127.0.0.1) and accepting
mysite_container |      TCP/IP connections on port 5432?
mysite_container | could not connect to server: Cannot assign requested address
mysite_container |      Is the server running on host "localhost" (::1) and accepting
mysite_container |      TCP/IP connections on port 5432?

My database in settings.py is

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

So, does anyone know why am I getting this error? My postgres is running successfully on localhost on port 5432 when I do docker-compose up, but it seems that my web container is not detecting that. What should I change in my Docker files to be able to run mysite_container properly?

EDIT: Now I added new settings_docker.py where I set my host to 'db' file and added environment variable DOCKER_SETTINGS_MODULE=mysite.settins_docker to my web service in docker-compose.yml and the container starts properly, but I don't have my database relations. So, how can I migrate those relations to docker?

5
  • What does your DATABASES setting look like in settings.py? Commented Aug 22, 2018 at 7:47
  • It's like this: DATABASES = { 'default': { 'ENGINE': 'django.db.backends.postgresql_psycopg2', 'NAME': 'postgres', 'USER': 'postgres', 'PASSWORD': 'postgres', 'HOST': 'localhost', 'PORT': '5432', } } Commented Aug 22, 2018 at 8:00
  • Also I would strongly suggest you not using the db name postgres unless you really know what you are doing connecting to the default db. stackoverflow.com/questions/2370525/… Commented Aug 22, 2018 at 8:10
  • When running postgres as a docker container, it's common practice to just have a single database. The database is called postgres by default in the official postgres docker image. What would be the problem with that? hub.docker.com/_/postgres Commented Aug 22, 2018 at 8:25
  • Do you know if I can configure docker-compose.yml in a way that I wil keep localhost in my HOST configuration in settings.py? Also I tried changing HOST to 'db' and it starts running migrations but it is also throwing the same error like before. Commented Aug 22, 2018 at 8:31

2 Answers 2

2

In the django container, the postgres container looks like a different server. You should not use localhost as the hostname. Instead use the container name. So in the django config set this:

DATABASES = {
  'default': {
    'HOST': 'db',  # container name for postgres 
     [...]

https://docs.docker.com/compose/networking/

By default Compose sets up a single network for your app. Each container for a service joins the default network and is both reachable by other containers on that network, and discoverable by them at a hostname identical to the container name.

Sign up to request clarification or add additional context in comments.

10 Comments

Thank you. Is there any other way without changing HOST from 'localhost' to 'db'?
Yes, there is always another way. But why? The solution is literally to change one single word. You could probably open up the port somehow. Read through the docker documentation. I find the structure of the docker docs quite confusing, but you can do all sorts of custom network configs. Or you could run postgresql and django in the same container, of course. But why would it be important that the hostname for the database should be localhost?
You could try to change the name of the postgres container to localhost. I'm not sure if that would be a valid name. And it would be breaking the normal expectation of what localhost is. You would probably have to change the /etc/hosts file in the django container. And something else might break. But why do it the easy way, when you can make it complicated?
I want to keep localhost because if I change localhost to db I am not able to run my Django site with python manage.py runserver anymore.
In the container? Or on the host? If your environment is different, use environment variables to configure.
|
0

I'm going to take a shot in the dark here and say your DATABASES setting is not correct in settings.py.

It needs to resemble:

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

For further reading here

EDIT: docker-compose.yml file adapted directly from the above link:

version: '3'

services:
  db:
    image: postgres
    environment:
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=postgres
      - POSTGRES_DB=postgres
  web:
    image: mysite:latest
    build:
    context: .
    dockerfile: Dockerfile
    container_name: mysite_container
    ports:
      - "8000:8000"
    depends_on:
      - db
    entrypoint: /entrypoint.sh

5 Comments

I have a similar DATABASES setting, but my host is localhost. Can i configure docker-compose.yml in a way that I wil keep localhost in my HOST configuration? Also I tried changing HOST to 'db' and it starts running migrations but it is also throwing the same error like before.
@Anzoman What happens when you remove the container_name from the compose file?
The database and the django app are running in different containers, so from the perspective inside the container, the postgres host is not localhost.
@Andrew Graham-Yooll When I remove the container_name from the compose file the containers just get different names which are like services (web_1 and db_1) but else is the same.
@Andrew Graham-Yooll thank you! The container starts successfully now. But is there any other way without changing HOST from 'localhost' to 'db'?

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.