To configure Postgres, we'll need to add a new service to the docker-compose.yml file, update the Django settings, and install Psycopg2.
First, add a new service called db to docker-compose.yml:
version: '3.7'
services:
web:
build: ./app
command: python manage.py runserver 0.0.0.0:8000
volumes:
- ./app/:/usr/src/app/
ports:
- 8000:8000
env_file:
- ./.env.dev
depends_on:
- db
db:
image: postgres:12.0-alpine
volumes:
- postgres_data:/var/lib/postgresql/data/
environment:
- POSTGRES_USER=hello_django
- POSTGRES_PASSWORD=hello_django
- POSTGRES_DB=hello_django_dev
volumes:
postgres_data:
To persist the data beyond the life of the container we configured a volume. This config will bind postgres_data to the "/var/lib/postgresql/data/" directory in the container.
We also added an environment key to define a name for the default database and set a username and password.
Review the "Environment Variables" section of the Postgres Docker Hub page for more info.
We'll need some new environment variables for the web service as well, so update .env.dev like so:
DEBUG=1
SECRET_KEY=foo
DJANGO_ALLOWED_HOSTS=localhost 127.0.0.1 [::1]
SQL_ENGINE=django.db.backends.postgresql
SQL_DATABASE=hello_django_dev
SQL_USER=hello_django
SQL_PASSWORD=hello_django
SQL_HOST=db
SQL_PORT=5432
Update the DATABASES dict in settings.py:
DATABASES = {
"default": {
"ENGINE": os.environ.get("SQL_ENGINE", "django.db.backends.sqlite3"),
"NAME": os.environ.get("SQL_DATABASE", os.path.join(BASE_DIR, "db.sqlite3")),
"USER": os.environ.get("SQL_USER", "user"),
"PASSWORD": os.environ.get("SQL_PASSWORD", "password"),
"HOST": os.environ.get("SQL_HOST", "localhost"),
"PORT": os.environ.get("SQL_PORT", "5432"),
}
}
Here, the database is configured based on the environment variables that we just defined. Take note of the default values.
Update the Dockerfile to install the appropriate packages required for Psycopg2:
# pull official base image
FROM python:3.8.3-alpine
# set work directory
WORKDIR /usr/src/app
# set environment variables
ENV PYTHONDONTWRITEBYTECODE 1
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 ./requirements.txt .
RUN pip install -r requirements.txt
# copy project
COPY . .
Add Psycopg2 to requirements.txt:
Django==3.0.7
psycopg2-binary==2.8.5
Review this GitHub Issue for more info on installing Psycopg2 in an Alpine-based Docker Image.
Build the new image and spin up the two containers:
$ docker-compose up -d --build
Run the migrations:
$ docker-compose exec web python manage.py migrate --noinput
Get the following error?
django.db.utils.OperationalError: FATAL: database "hello_django_dev" does not exist
Run docker-compose down -v to remove the volumes along with the containers. Then, re-build the images, run the containers, and apply the migrations.
Ensure the default Django tables were created:
$ docker-compose exec db psql --username=hello_django --dbname=hello_django_dev
psql (12.0)
Type "help" for help.
hello_django_dev=# \l
List of databases
Name | Owner | Encoding | Collate | Ctype | Access privileges
------------------+--------------+----------+------------+------------+-------------------------------
hello_django_dev | hello_django | UTF8 | en_US.utf8 | en_US.utf8 |
postgres | hello_django | UTF8 | en_US.utf8 | en_US.utf8 |
template0 | hello_django | UTF8 | en_US.utf8 | en_US.utf8 | =c/hello_django +
| | | | | hello_django=CTc/hello_django
template1 | hello_django | UTF8 | en_US.utf8 | en_US.utf8 | =c/hello_django +
| | | | | hello_django=CTc/hello_django
(4 rows)
hello_django_dev=# \c hello_django_dev
You are now connected to database "hello_django_dev" as user "hello_django".
hello_django_dev=# \dt
List of relations
Schema | Name | Type | Owner
--------+----------------------------+-------+--------------
public | auth_group | table | hello_django
public | auth_group_permissions | table | hello_django
public | auth_permission | table | hello_django
public | auth_user | table | hello_django
public | auth_user_groups | table | hello_django
public | auth_user_user_permissions | table | hello_django
public | django_admin_log | table | hello_django
public | django_content_type | table | hello_django
public | django_migrations | table | hello_django
public | django_session | table | hello_django
(10 rows)
hello_django_dev=# \q
You can check that the volume was created as well by running:
$ docker volume inspect django-on-docker_postgres_data
You should see something similar to:
[
{
"CreatedAt": "2020-06-13T18:43:56Z",
"Driver": "local",
"Labels": {
"com.docker.compose.project": "django-on-docker",
"com.docker.compose.version": "1.25.4",
"com.docker.compose.volume": "postgres_data"
},
"Mountpoint": "/var/lib/docker/volumes/django-on-docker_postgres_data/_data",
"Name": "django-on-docker_postgres_data",
"Options": null,
"Scope": "local"
}
]
Next, add an entrypoint.sh file to the "app" directory to verify that Postgres is healthy before applying the migrations and running the Django development server:
#!/bin/sh
if [ "$DATABASE" = "postgres" ]
then
echo "Waiting for postgres..."
while ! nc -z $SQL_HOST $SQL_PORT; do
sleep 0.1
done
echo "PostgreSQL started"
fi
python manage.py flush --no-input
python manage.py migrate
exec "$@"
Update the file permissions locally:
$ chmod +x app/entrypoint.sh
Then, update the Dockerfile to copy over the entrypoint.sh file and run it as the Docker entrypoint command:
# pull official base image
FROM python:3.8.3-alpine
# set work directory
WORKDIR /usr/src/app
# set environment variables
ENV PYTHONDONTWRITEBYTECODE 1
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 ./requirements.txt .
RUN pip install -r requirements.txt
# copy entrypoint.sh
COPY ./entrypoint.sh .
# copy project
COPY . .
# run entrypoint.sh
ENTRYPOINT ["/usr/src/app/entrypoint.sh"]
Add the DATABASE environment variable to .env.dev:
DEBUG=1
SECRET_KEY=foo
DJANGO_ALLOWED_HOSTS=localhost 127.0.0.1 [::1]
SQL_ENGINE=django.db.backends.postgresql
SQL_DATABASE=hello_django_dev
SQL_USER=hello_django
SQL_PASSWORD=hello_django
SQL_HOST=db
SQL_PORT=5432
DATABASE=postgres
Test it out again:
댓글 영역