0
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Djangoの開発環境をdocker-composeを利用してコンテナで起動&DockerにPostgres環境を構築する方法

Last updated at Posted at 2023-03-11

やってみたこと

  • 前回、djangoチュートリアルで作成したpollsアプリをdockerコンテナから立ち上げてみました。今回は、docker-compose.ymlにDB情報を追記して実際にテーブル作成まで行う手順を記します。

前提

.
├── docker
│   ├── docker-compose.yml
│   └── Dockerfile
└── web
    ├── mysite
    │   ├── mysite
    │   ├── polls
    │   ├── db.sqlite3
    │   └── manage.py
    └── requirements.txt
  • djangoチュートリアルで作成したものをそのまま使っていますので、settings.pyDAEABASESもそのままになっています。
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': BASE_DIR / 'db.sqlite3',
    }
}

手順

  • docker関連ファイルの準備
  • ビルド・コンテナ起動
  • コンテナの中に入ってmanage.pyを確認
  • Dockerコンテナから開発サーバを起動

docker関連ファイルの準備

  • Dockerfileは、前回記事と同様です。
# python:3.8の公式 image をベースの image として設定
FROM python:3.8

# 作業ディレクトリの作成
RUN mkdir /mysite

# 作業ディレクトリの設定(以後の RUN は WORKDIR で実行)
WORKDIR /mysite

# カレントディレクトリにある資産をコンテナ上の指定のディレクトリにコピーする
ADD web /mysite

# pipでrequirements.txtに指定されているパッケージを追加する
RUN pip install -r requirements.txt

# 起動(今回はなし)
# CMD python3 manage.py runserver 0.0.0.0:8000
  • requirements.txtも前回記事同様、必要最低限のままにしています。
Django==4.1
requests
  • docker-compose.ymlに以下のように記載します。
    • 今回も必要最低限のものしか記載していません。前回からdb-sample1以下を加えています。
  • それぞれが意味する詳細は以下記事が非常にわかりやすかったのでご参考までにぜひ。
version: '3'
services:
  mysite:
    build:
      context: ../
      dockerfile: ./docker/Dockerfile # Dockerfileのディレクトリを指定します
    volumes:
      - '../web:/mysite'
    ports:
      - "8000:8000" # 左側が外部からのアクセス時のポート番号:右側がdockerコンテナからアクセスする時のポート番号。
    container_name: docker_mysite
    tty: true  # ポート待受とかしていないコンテナの場合、trueに設定しておくとコンテナが起動し続けます
    working_dir: '/mysite'
  db-sample1: # 任意の名前を指定します
    build:
      context: ../
      dockerfile: ./docker/sample1/Dockerfile # Dockerfileのディレクトリを指定します
    ports:
      - "5438:5432" # 左側が外部からのアクセス時のポート番号:右側がdockerコンテナからアクセスする時のポート番号
    container_name: mysite_sample1_db
    environment:
      POSTGRES_USER: user
      POSTGRES_DB: sample
      POSTGRES_PASSWORD: pass
    volumes:
        - postgres-data-volume:/var/lib/postgresql/data # <名前付きvolume名>:マウントしたいコンテナ内のPATH

volumes:
    postgres-data-volume:
  • portsフィールドは、ホスト・コンテナ間のポートのマッピングを指定します。
    • 上記のservicemysiteの例だと、コンテナポートの8000番(右側)をホストポートの8000番(左側)にマッピングすることで、ブラウザでhttps://localhost:8000/へアクセスできるようになります。これを「ホストの8000番からコンテナの8000番へポートフォワードする」とも言います。db-sample1も同様に、ホストの5438からコンテナの5432にポートフォワードしています。
    • デフォルトでは、5432がPostgreSQLの利用するポートになります。

environmentフィールド

  • environment:フィールドで一点注意があります。上記のようにUSER名やDB名を指定するか、以下のように記載するか、どちらかを記載しないとError: Database is uninitialized and superuser password is not specified.エラーになります。以下のように記載した場合、デフォルトで与えられている、postgresというUSER名やDB名でログインできます。(パスワードなしで接続できるのであまり推奨されていません)
    environment:
      POSTGRES_HOST_AUTH_METHOD: trust
  • ちなみに、以下のようにどちらも記載した場合は、POSTGRES_USERなど指定したものでログインができませんでしたので、ご注意。「あれ、ちゃんと記述したのにpsql: FATAL: role "user" does not existって出てくるぞ?」という場合は、誤って重複した書き方をしていました。最初はデフォルトの方でやろうと思って記述していたので、後からPOSTGRES_USERなど指定した時に消すのを忘れてしまっていたんでしょうね。
    environment:
      POSTGRES_USER: user
      POSTGRES_DB: sample
      POSTGRES_PASSWORD: pass
    volumes:
        - postgres-data-volume:/var/lib/postgresql/data
    environment:
      POSTGRES_HOST_AUTH_METHOD: trust # こちらが優先されるのでご注意

volumesフィールド(名前付きボリュームの作成)

  • volumes:フィールドでは、トップレベルで定義したvolume名(今回でいえば一番下段に記載しているvolumesのこと)を指定してあげます。
    • このマウントの手法を「名前付きボリュームの作成」や「ボリュームマウント」と言います。(「ディレクトリのマウント(同期)」については後述)
  db-sample1: 
    # 省略
    volumes:
        - postgres-data-volume:/var/lib/postgresql/data # データボリューム名:コンテナディレクトリ
volumes:
    postgres-data-volume: # ここで名前付きボリューム名を指定します
  • 上記により、postgres-data-volumeをマウントしてデータベースを永続化しています。
    • 「データの永続化」とは、Dockerコンテナ上で作成されたデータがコンテナ削除後も残り続けている状態のこと。コンテナが削除されてもコンテナ上で作成されたデータを保持し続ける方法として知られています。
    • 上記で定義した「データボリューム」(単にボリュームともいいます)とは、1つまたは複数のDockerコンテナ内でデータの共有・再利用をするために設計された特別なディレクトリです。コンテナのライフサイクルとは別なので、コンテナを削除しても残ります。(データボリュームを削除すると永続化したデータは削除されます)
    • 何も指定しなければ『匿名(無名)ボリューム』、指定すれば『名前付きボリューム』と呼ばれます。ただし、匿名ボリュームはコンテナが新しく作成されるたびに新たに作成されるので注意が必要な時があります。
  • ちなみに、マウントで指定したのに、トップレベルのvolumesで該当のvolume定義がない場合、以下のエラーが返ってきます。
service "db-sample1" refers to undefined volume postgres-data-volume: invalid compose project
  • 今回の場合、アプリケーション名_postgres-data-volumeのボリュームの下記の名前で作成されます。
docker_postgres-data-volume
  • /var/lib/postgresql/dataはpostgresコンテナでのデフォルトのDBパスです。
    • コンテナに入ってls -aすれば、どんなデータが保管されているのか確認できます。
    • なお、mysqlコンテナならば、/var/lib/mysqlとなりますので、コンテナごとに異なります。
    • https://hub.docker.com/_/postgres
      • "The default is /var/lib/postgresql/data"と記載があります
    • https://hub.docker.com/_/mysql
      • "...(略).../var/lib/mysql inside the container, where MySQL by default will write its data files."と記載があります
  • 補足【ディレクトリのマウント(同期)】:
    • 以下のように記載しておくと、Dockerコンテナ上の/var/lib/postgresql/dataをローカルの/postgres/dataにマウントできます。コンテナ上のDBを誤って消してしまった場合やイメージを削除してしまった場合などのために、ローカルに保存しておくと後で復旧ができます。上記の例は「名前付きボリュームの作成」でしたが、下記の場合を「ディレクトリのマウント(同期)」と言います。
  db-sample1: 
    # 省略
    volumes:
      - ./postgres/data:/var/lib/postgresql/data

ビルド・コンテナ起動

  • docker-compose.ymlがあるディレクトリで以下のコマンドを実行すると、ビルド(イメージ作成)&コンテナ起動します。
$ docker compose up -d
  • 起動しているコンテナを以下のコマンドで確認できます。
$ docker ps
CONTAINER ID   IMAGE               COMMAND                  CREATED          STATUS         PORTS                    NAMES
a88071064847   docker-mysite       "python3"                10 seconds ago   Up 9 seconds   0.0.0.0:8000->8000/tcp   docker_mysite
5192dce52ff6   docker-db-sample1   "docker-entrypoint.s…"   10 seconds ago   Up 9 seconds   0.0.0.0:5438->5432/tcp   mysite_sample1_db
  • -dオプションはデーモンモードで起動し、プロセスをバックグラウンドで動作させることができます。

    • アクセスログの内容やエラーなどを確認したい場合は、-dを外して実行します。
  • $ docker compose psでもコンテナがRUNNINGかどうか分かります。

  • mysiteが8000ポートに、dbのsample1が5432ポートに、それぞれdocker-compose.ymlで指定したポートにつながっていることがわかります。

  • また、以下のコマンドにより、requirement.txtに記述したモジュールがインストールされているかどうか確認できます。

$ docker exec -it docker_mysite pip list
Package            Version
------------------ ---------
asgiref            3.6.0
backports.zoneinfo 0.2.1
certifi            2022.12.7
charset-normalizer 3.1.0
Django             4.1
idna               3.4
pip                22.0.4
requests           2.28.2
setuptools         57.5.0
sqlparse           0.4.3
urllib3            1.26.14
wheel              0.38.4

コンテナの中に入ってpostgresqlを確認

  • 以下のコマンドでmysite_sample1_dbコンテナに入ります。
$ docker exec -it mysite_sample1_db bash
  • CONTAINER IDでも入れるので、以下のコマンドでもOKです。
$ docker exec -it 5192dce52ff6 bash
  • コンテナの中に入って、/var/lib/postgresql/dataを確認してみましょう。先ほどマウントしたのは、ここにあるpostgre関連ファイルを、指定したボリュームにマウントしたという意味になります。
5192dce52ff6:/# cd /var/lib/postgresql/data
5192dce52ff6:/var/lib/postgresql/data# ls -a
.                     base                  pg_dynshmem           pg_logical            pg_replslot           pg_stat               pg_tblspc             pg_xact               postmaster.opts
..                    global                pg_hba.conf           pg_multixact          pg_serial             pg_stat_tmp           pg_twophase           postgresql.auto.conf  postmaster.pid
PG_VERSION            pg_commit_ts          pg_ident.conf         pg_notify             pg_snapshots          pg_subtrans           pg_wal                postgresql.conf
5192dce52ff6:/var/lib/postgresql/data# 

ボリューム確認

  • では、作成したボリュームが動いているか確認してみます。
    • コンテナから出る場合はexitと入力してください。
  • ボリュームの確認は、以下のコマンドで可能です。
$ docker volume ls
DRIVER    VOLUME NAME
local     docker_postgres-data-volume
  • 指定したボリュームが作成されていることがわかりました。
  • ボリュームは一度作成すれば、docker compose downされた後でも残ります。上述したように、永続化しているからですね。
  • docker inspect [データボリューム名]でデータボリュームの詳細情報が確認できます。
  • また、docker inspect [コンテナ名]でコンテナの詳細情報が確認できます。
    • Mountsフィールドを見ると、Dockerコンテナのマウント対象なども確認できます。

データベースに接続

  • それではデータベースを確認していきましょう。先ほどと同じようにまずは起動中のコンテナの中に入ります。
$ docker exec -it mysite_sample1_db bash
  • 以下psqlコマンドでuserユーザーによるsampleデータベースへのログインができます。
5192dce52ff6:/# psql -U user sample
sample=# 
  • 以下、いずれでもログイン可能です。
    • いずれもホストやポートを指定する場合のログイン方法です。
psql -h localhost sample -U user
psql sample -U user -p 5432
psql -U user -d sample
  • ちなみに、psql -U userだけだと、データベースの指定がないのでエラーになります。
psql -U user
psql: FATAL:  database "user" does not exist
  • 上記のエラーは、postgresではデフォルトではユーザー名と同じデータベースが作成されるためです。つまり、docker-compose.ymlでdbにsampleと指定していない場合は、psql -U userでもログインができます。

  • また、postgresではデフォルトでpostgresというデータベース名であればログインができます。

psql -U user postgres
postgres=# 
  • プロンプトが、sampleではなくpostgresになっていることがわかります。これは接続しているデータベースがpostgresのためです。
  • sampleに切り替えたい場合は\cコマンドで可能です。
postgres=# \c sample
You are now connected to database "sample" as user "user".
sample=# 
  • \dコマンドでテーブルを確認できますが、現状まだ何もないことがわかります。
sample=# \d
Did not find any relations.
  • ちなみに上記でuserというユーザー名を作成しこれで接続しました。これはロール(データーベースを管理するもの)といい、以下コマンドで確認できます。
sample=# \du
                                   List of roles
 Role name |                         Attributes                         | Member of 
-----------+------------------------------------------------------------+-----------
 user      | Superuser, Create role, Create DB, Replication, Bypass RLS | {}

テーブル作成

  • テーブルを作成してみましょう。
  • 以下のコマンドでpublicスキーマの中にhogeテーブルを作成できます。
create table public.hoge( id integer, name varchar(10), address varchar(10) );
CREATE TABLE
  • ちなみにpublicスキーマを選択せずにhogeaaaテーブルを作成するとどうなるでしょうか。
sample=# create table hogeaaa( id integer, name varchar(10), address varchar(10) );
CREATE TABLE
sample=# \d
        List of relations
 Schema |  Name   | Type  | Owner 
--------+---------+-------+-------
 public | hoge    | table | user
 public | hogeaaa | table | user
(2 rows)

データベースを別途作成

  • samplepostgres以外にもデータベースを作成することができます。その場合は以下コマンドを実行します。
sample=# create database hogedb;
CREATE DATABASE
  • 以下の通り、DBが新しく加わったことが確認できますね。
sample=# \l
                             List of databases
   Name    | Owner | Encoding |  Collate   |   Ctype    | Access privileges 
-----------+-------+----------+------------+------------+-------------------
 hogedb    | user  | UTF8     | ja_JP.utf8 | ja_JP.utf8 | 
 postgres  | user  | UTF8     | ja_JP.utf8 | ja_JP.utf8 | 
 sample    | user  | UTF8     | ja_JP.utf8 | ja_JP.utf8 | 
 template0 | user  | UTF8     | ja_JP.utf8 | ja_JP.utf8 | =c/user          +
           |       |          |            |            | user=CTc/user
 template1 | user  | UTF8     | ja_JP.utf8 | ja_JP.utf8 | =c/user          +
           |       |          |            |            | user=CTc/user
(5 rows)
  • データの取得したり保存したり確認したりするのも、同様にSQLコマンドで可能ですので、適当にINSERTなどしてみるのも良いと思います。

参考記事

次回記事

0
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?