Django+Docker+PostgreSQLへの接続をpgfileで設定する
DjangoでDB接続設定を書く場合、 settings.py にDATABASEの設定を行うことになりますが、平文でパスワードを置いてしまうとGitHubでソース管理がしづらくなってしまいます。
.env に記載する方法もありますが、下記ページにある通り、pgpassに設定する方法を試したので、備忘録を兼ねて記録を残します。
今回の環境
python:3.9
django:4.0
django作業環境の作成
poetryを使用します。
djangoでのPostgreSQLへの接続は psycopg2 が必要なので、パッケージに追加しておきます。(psycopg3はdjango 4.0では未対応)
# 作業ディレクトリを任意の場所に作成します
mkdir ~/django-test
# poetryをインストールしていない場合
pip install poetry
poetry init # project.tomlを作成するための質問に答えます
# [tool.poetry]
# name = "django-test"
# version = "0.1.0"
# description = ""
# authors = ["DecoPon"]
# [tool.poetry.dependencies]
# python = "^3.9,<=3.10"
# [tool.poetry.dev-dependencies]
# [build-system]
# requires = ["poetry-core>=1.0.0"]
# build-backend = "poetry.core.masonry.api"
# packageを追加
poetry add django
poetry add psycopg2
# packageをインストールし、仮想環境を作成する
poetry install
djangoプロジェクトを作成します。
poetry run django-admin startproject mysite
# projectが作成されていると以下のようになっているはず
django-test
|-mysite
|-poetry.lock
|-pyproject.toml
今回はdocker-composeでpostgresqlとの連携を行うため、Dockerfileとdocker-compose.ymlを追加します。
Dockerfileはpostgresqlとの接続確認を行う為にpostgresql-clientをインストールしておきます。また、docker内のpython環境で先ほど作成したpoetry設定を流用してパッケージをインストールする為、poetryをインストールし、仮想環境ではなく、直接インストールする設定を入れておきます。
FROM python:3.9
RUN apt -y update && apt -y upgrade
RUN apt -y install postgresql-client
ENV PIP_NO_CACHE_DIR=off
RUN pip install poetry
WORKDIR /app
COPY ./pyproject.toml ./
RUN poetry config virtualenvs.create false
RUN poetry install
CMD ["bash"]
docker-compose.ymlを作成します。
(今回は検証なので、開発用としてwsgiなどは設定しません。)
version: "3.9"
services:
web:
build:
context: .
container_name: web
restart: unless-stopped
tty: true
working_dir: /opt/apps
volumes:
- ./mysite:/opt/apps/
- .pgpass:/root/.pgpass
- .pg_service.conf:/root/.pg_service.conf
entrypoint: "./entrypoint.sh"
command: "python manage.py runserver 0.0.0.0:8000"
ports:
- "8000:8000"
depends_on:
- db
db:
image: postgres
container_name: db
environment:
POSTGRES_USER: ${DB_USER}
POSTGRES_PASSWORD: ${DB_PASSWORD}
ports:
- ${DB_PORT}:5432
docker-compose.ymlでpostgresqlのパスワード等を含めたくないため、.envに切り出します。
.env
DB_USER=postgres
DB_PASSWORD=postgres
DB_HOST=db
DB_PORT=5432
ここまでで以下のようなフォルダ構成になっているはずです。
django-test
├── Dockerfile
├── docker-compose.yml
├── mysite
│ ├── manage.py
│ └── mysite
│ ├── __init__.py
│ ├── asgi.py
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
├── poetry.lock
└── pyproject.toml
次に、PostgreSQLへの接続情報を追加します。
.pg_service.conf と .pgpass の2ファイルを追加します。
これらのファイルは通常、ホームディレクトリに配置する為、docker-compose.yml上でコンテナホーム(rootディレクトリ)にマウントしています。
.pg_service.conf
[DB]
host=db
user=postgres
dbname=postgres
port=5432
今回はdockerコンテナ同士での接続のため、 host には docker-compose.ymlで指定したサービス名を設定します。
.pgpass
# hostname:port:database:username:password の順番で記載する
db:5432:postgres:postgres:postgres
.pg_service.conf と .pgpass は上記リンクにある通り、 600 のパーミッションが設定されていなければ無視されます。
今回はコンテナにマウントする為、ホスト側で変更しても良いですが、念の為、entrypointにより、処理するようにします。
entrypoint.sh を mysite 内(manage.pyと同じ階層)に作成します。
#!/bin/bash
set -e
chmod 600 /root/.pg_service.conf
chmod 600 /root/.pgpass
cmd="$@"
exec $cmd
ここまでで、以下のディレクトリ構成になります。
django-test
├── .env
├── .pg_service.conf
├── .pgpass
├── Dockerfile
├── docker-compose.yml
├── mysite
│ ├── db.sqlite3
│ ├── entrypoint.sh
│ ├── manage.py
│ └── mysite
├── poetry.lock
└── pyproject.toml
標準ではdjangoはsqlite3を使用する設定になっているので、PostgreSQLを使用するように設定を変更します。
django_tutorial/mysite/mysite/settings.py の以下の部分を編集します。
# 元
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': BASE_DIR / 'db.sqlite3',
}
}
# 変更後
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'OPTIONS': {
'service': 'DB', #.pg_service.conf のサービス名
'passfile': '/root/.pgpass', #パスワードファイル (.pgpass)パスを指定
},
}
}
コンテナを作成します。
ログを確認し、以下のように問題なければ、ctrl + c で表示を終了します。
docker compose up -d
[+] Running 2/2
⠿ Container db Running 0.0s
⠿ Container web Started
# ログを確認し、以下のような表示になっていればdjangoコンテナ(web)が正常に起動しています
docker compose logs -f web # -f オプションはログの常時表示
web | You have 18 unapplied migration(s). Your project may not work properly until you apply the migrations for app(s): admin, auth, contenttypes, sessions.
web | Run 'python manage.py migrate' to apply them.
web | April 24, 2022 - 03:12:22
web | Django version 4.0.4, using settings 'mysite.settings'
web | Starting development server at http://0.0.0.0:8000/
マイグレーションを行い、PostgreSQLにdjango関連のテーブルができていることを確認します。
# migration
docker compose exec web python manage.py migrate
# Output
Operations to perform:
Apply all migrations: admin, auth, contenttypes, sessions
Running migrations:
Applying contenttypes.0001_initial... OK
Applying auth.0001_initial... OK
Applying admin.0001_initial... OK
Applying admin.0002_logentry_remove_auto_add... OK
Applying admin.0003_logentry_add_action_flag_choices... OK
Applying contenttypes.0002_remove_content_type_name... OK
Applying auth.0002_alter_permission_name_max_length... OK
Applying auth.0003_alter_user_email_max_length... OK
Applying auth.0004_alter_user_username_opts... OK
Applying auth.0005_alter_user_last_login_null... OK
Applying auth.0006_require_contenttypes_0002... OK
Applying auth.0007_alter_validators_add_error_messages... OK
Applying auth.0008_alter_user_username_max_length... OK
Applying auth.0009_alter_user_last_name_max_length... OK
Applying auth.0010_alter_group_name_max_length... OK
Applying auth.0011_update_proxy_permissions... OK
Applying auth.0012_alter_user_first_name_max_length... OK
Applying sessions.0001_initial... OK
コンテナからPostgreSQLに接続し、テーブルができていることを確認します。
docker compose exec web psql -h db -p 5432 -U postgres -d postgres ✔ django-test 12:20:11
# output
psql (13.5 (Debian 13.5-0+deb11u1), server 14.1 (Debian 14.1-1.pgdg110+1))
WARNING: psql major version 13, server major version 14.
Some psql features might not work.
Type "help" for help.
# djangoテーブルが作成されていることを確認
postgres=# \dt
List of relations
Schema | Name | Type | Owner
--------+----------------------------+-------+----------
public | auth_group | table | postgres
public | auth_group_permissions | table | postgres
public | auth_permission | table | postgres
public | auth_user | table | postgres
public | auth_user_groups | table | postgres
public | auth_user_user_permissions | table | postgres
public | django_admin_log | table | postgres
public | django_content_type | table | postgres
public | django_migrations | table | postgres
public | django_session | table | postgres
(10 rows)
WEBで調べても、settings.pyに直書きする方法ばかりヒットするので、備忘録を兼ねて作成しました。
おつかれさまでした。
この記事が気に入ったらサポートをしてみませんか?