I have a Django application which I've decided to setup in container as follows:
#docker-compose.yml
version: "3.9"
services:
web:
build: .
command: python /code/manage.py runserver 0.0.0.0:8000
volumes:
- .:/code
ports:
- 8000:8000
depends_on:
- db
db:
image: postgres:13
volumes:
- postgres_data:/var/lib/postgresql/data/
environment:
- "POSTGRES_HOST_AUTH_METHOD=trust"
volumes:
postgres_data:
with database config in settings as follows
DATABASES = {
"default": {
"ENGINE": "django.db.backends.postgresql",
"NAME": "postgres",
"USER": "postgres",
"PASSWORD": "postgres",
"HOST": "db",
"PORT": 5432,
}
}
And when I run the containers, the app works correctly with me being able to migrate and insert data into database.
However when I try to run the project outside of the container by following steps:
python -m venv venv
source venv/bin/activate
pip install -r requirements.txt
python manage.py runserver
I am getting an error:
Traceback (most recent call last):
File "/home/jdoni/code/work/tasks/venv/lib64/python3.10/site-packages/django/db/backends/base/base.py", line 244, in ensure_connection
self.connect()
File "/home/jdoni/code/work/tasks/venv/lib64/python3.10/site-packages/django/utils/asyncio.py", line 26, in inner
return func(*args, **kwargs)
File "/home/jdoni/code/work/tasks/venv/lib64/python3.10/site-packages/django/db/backends/base/base.py", line 225, in connect
self.connection = self.get_new_connection(conn_params)
File "/home/jdoni/code/work/tasks/venv/lib64/python3.10/site-packages/django/utils/asyncio.py", line 26, in inner
return func(*args, **kwargs)
File "/home/jdoni/code/work/tasks/venv/lib64/python3.10/site-packages/django/db/backends/postgresql/base.py", line 203, in get_new_connection
connection = Database.connect(**conn_params)
File "/home/jdoni/code/work/tasks/venv/lib64/python3.10/site-packages/psycopg2/__init__.py", line 122, in connect
conn = _connect(dsn, connection_factory=connection_factory, **kwasync)
psycopg2.OperationalError: could not translate host name "db" to address: Name or service not known
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/usr/lib64/python3.10/threading.py", line 1016, in _bootstrap_inner
self.run()
File "/usr/lib64/python3.10/threading.py", line 953, in run
self._target(*self._args, **self._kwargs)
File "/home/jdoni/code/work/tasks/venv/lib64/python3.10/site-packages/django/utils/autoreload.py", line 64, in wrapper
fn(*args, **kwargs)
File "/home/jdoni/code/work/tasks/venv/lib64/python3.10/site-packages/django/core/management/commands/runserver.py", line 137, in inner_run
self.check_migrations()
File "/home/jdoni/code/work/tasks/venv/lib64/python3.10/site-packages/django/core/management/base.py", line 576, in check_migrations
executor = MigrationExecutor(connections[DEFAULT_DB_ALIAS])
File "/home/jdoni/code/work/tasks/venv/lib64/python3.10/site-packages/django/db/migrations/executor.py", line 18, in __init__
self.loader = MigrationLoader(self.connection)
File "/home/jdoni/code/work/tasks/venv/lib64/python3.10/site-packages/django/db/migrations/loader.py", line 58, in __init__
self.build_graph()
File "/home/jdoni/code/work/tasks/venv/lib64/python3.10/site-packages/django/db/migrations/loader.py", line 235, in build_graph
self.applied_migrations = recorder.applied_migrations()
File "/home/jdoni/code/work/tasks/venv/lib64/python3.10/site-packages/django/db/migrations/recorder.py", line 81, in applied_migrations
if self.has_table():
File "/home/jdoni/code/work/tasks/venv/lib64/python3.10/site-packages/django/db/migrations/recorder.py", line 57, in has_table
with self.connection.cursor() as cursor:
File "/home/jdoni/code/work/tasks/venv/lib64/python3.10/site-packages/django/utils/asyncio.py", line 26, in inner
return func(*args, **kwargs)
File "/home/jdoni/code/work/tasks/venv/lib64/python3.10/site-packages/django/db/backends/base/base.py", line 284, in cursor
return self._cursor()
File "/home/jdoni/code/work/tasks/venv/lib64/python3.10/site-packages/django/db/backends/base/base.py", line 260, in _cursor
self.ensure_connection()
File "/home/jdoni/code/work/tasks/venv/lib64/python3.10/site-packages/django/utils/asyncio.py", line 26, in inner
return func(*args, **kwargs)
File "/home/jdoni/code/work/tasks/venv/lib64/python3.10/site-packages/django/db/backends/base/base.py", line 243, in ensure_connection
with self.wrap_database_errors:
File "/home/jdoni/code/work/tasks/venv/lib64/python3.10/site-packages/django/db/utils.py", line 91, in __exit__
raise dj_exc_value.with_traceback(traceback) from exc_value
File "/home/jdoni/code/work/tasks/venv/lib64/python3.10/site-packages/django/db/backends/base/base.py", line 244, in ensure_connection
self.connect()
File "/home/jdoni/code/work/tasks/venv/lib64/python3.10/site-packages/django/utils/asyncio.py", line 26, in inner
return func(*args, **kwargs)
File "/home/jdoni/code/work/tasks/venv/lib64/python3.10/site-packages/django/db/backends/base/base.py", line 225, in connect
self.connection = self.get_new_connection(conn_params)
File "/home/jdoni/code/work/tasks/venv/lib64/python3.10/site-packages/django/utils/asyncio.py", line 26, in inner
return func(*args, **kwargs)
File "/home/jdoni/code/work/tasks/venv/lib64/python3.10/site-packages/django/db/backends/postgresql/base.py", line 203, in get_new_connection
connection = Database.connect(**conn_params)
File "/home/jdoni/code/work/tasks/venv/lib64/python3.10/site-packages/psycopg2/__init__.py", line 122, in connect
conn = _connect(dsn, connection_factory=connection_factory, **kwasync)
django.db.utils.OperationalError: could not translate host name "db" to address: Name or service not known
I don't really understand why django is unable to recognize the database host outside of container. Any ideas?
CodePudding user response:
You need to make the "db" container available locally, just map a local port, like this:
db:
image: postgres:13
volumes:
- postgres_data:/var/lib/postgresql/data/
ports:
- '5432:5432'
environment:
- "POSTGRES_HOST_AUTH_METHOD=trust"
now you can check connection with:
psql -h localhost -p 5432
to access it from Django locally, you need to change a config to:
DATABASES = {
"default": {
"ENGINE": "django.db.backends.postgresql",
"NAME": "postgres",
"USER": "postgres",
"PASSWORD": "postgres",
"HOST": "localhost", # <----- HERE IS THE CHANGE
"PORT": 5432,
}
}
CodePudding user response:
In your Django setup, I'd use an environment variable to specify the database location. You can set a default value for it, and I'd generally use a developer-friendly default.
DATABASES = {
"default": {
"HOST": os.getenv("PGHOST", "localhost"),
...
}
}
So long as your database container publishes ports:
, you can use this with a host-based development setup
docker-compose up -d db
. ./venv/bin/activate
./manage.py runserver
This means you need to set the environment variable in your Compose setup as well.
version: '3.8' # most recent 3.x Compose file version
services:
web:
build: .
ports:
- 8000:8000
depends_on:
- db
environment: # add
PGHOST: db # add
# (should not need volumes: or command: override)
db:
image: postgres:13
volumes:
- postgres_data:/var/lib/postgresql/data/
environment:
- "POSTGRES_HOST_AUTH_METHOD=trust"
ports: # add
- '5432:5432' # add
volumes:
postgres_data:
If your host system is already using port 5432 for a different database, you need to change the first ports:
number to something else that doesn't conflict; the second must be fixed at the standard port 5432. You also will need to make the database port number configurable in the same way.