Docker に Django/PostgreSQL の環境を構築

環境構築はこちらのページとほぼ同様です。
[Quickstart: Compose and Django](https://github.com/docker/awesome-compose/tree/master/official-documentation-samples/django/)
Web と DB の2つのコンテナを作成します。

## 環境構築

```bash
mkdir proj01
cd proj01/
```

次の３つのファイルが必要です。

```text
Dockerfile
requirements.txt
docker-compose.yml
```

フォルダー構造

```text
$ tree proj01
proj01
├── docker-compose.yml
├── Dockerfile
└── requirements.txt
```

```text:Dockerfile
# syntax=docker/dockerfile:1
FROM python:3
ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONUNBUFFERED=1
WORKDIR /code
COPY requirements.txt /code/
RUN pip install -r requirements.txt
COPY . /code/
```

```text:requirements.txt
Django>=3.0,<4.0
psycopg2>=2.8
```

```text:docker-compose.yml
services:
  db:
    image: postgres
    volumes:
      - ./data/db:/var/lib/postgresql/data
    environment:
      - POSTGRES_DB=postgres
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=postgres
  web:
    build: .
    command: python manage.py runserver 0.0.0.0:8000
    volumes:
      - .:/code
    ports:
      - "8000:8000"
    environment:
      - POSTGRES_NAME=postgres
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=postgres
    depends_on:
      - db
```


プロジェクトの作成

```bash
docker-compose run web django-admin startproject proj01 .
```

実行後のフォルダー構造

```text
$ tree proj01
proj01
├── data
│   └── db [error opening dir]
├── docker-compose.yml
├── Dockerfile
├── manage.py
├── proj01
│   ├── asgi.py
│   ├── __init__.py
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
└── requirements.txt
```

## この時点でサーバーの起動

```bash
docker-compose up -d
```

Web サーバーと DB サーバーが動いていることを確認

```text
$ docker ps
CONTAINER ID   IMAGE        COMMAND                   CREATED          STATUS         PORTS                                       NAMES
e0a8f67628b5   proj01-web   "python manage.py ru…"   9 minutes ago    Up 8 minutes   0.0.0.0:8000->8000/tcp, :::8000->8000/tcp   proj01-web-1
271991b53965   postgres     "docker-entrypoint.s…"   11 minutes ago   Up 8 minutes   5432/tcp                                    proj01-db-1
```

又は

```text
$ docker-compose ps
NAME                IMAGE               COMMAND                  SERVICE             CREATED             STATUS              PORTS
proj01-db-1         postgres            "docker-entrypoint.s…"   db                  12 minutes ago      Up 9 minutes        5432/tcp
proj01-web-1        proj01-web          "python manage.py ru…"   web                 10 minutes ago      Up 9 minutes        0.0.0.0:8000->8000/tcp, :::8000->8000/tcp
```

ブラウザーで http://localhost:8000/ にアクセス
![docker_aa.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/8830c0ad-8f78-8a66-d07d-b5f044a59440.png)

ファイル属性の変更

```bash
sudo chown -R uchida:uchida .
```

Web サーバーにアクセス

```text
$ docker exec -it proj01-web-1 bash
root@e0a8f67628b5:/code#
```

DB サーバーにアクセス

```text
$ docker exec -it proj01-db-1 bash
root@271991b53965:/#
```

## Django のプログラムを改造してみます。
こちらと同様の変更を行います。
[Django で Hello World](https://qiita.com/ekzemplaro/items/ef63edfa93caaab4071e)

```bash
python manage.py migrate
python manage.py startapp home
```

フォルダー構造

```text
$ tree -L 1 proj01
proj01
├── data
├── db.sqlite3
├── docker-compose.yml
├── Dockerfile
├── home
├── manage.py
├── proj01
└── requirements.txt
```



次を作成または編集します。

```text
home/views.py
home/urls.py
proj01/settings.py
proj01/urls.py
```

```py:home/view.py
from django.http import HttpResponse

def index(request):
    str_out = "<p>Good Afternoon</p>"
    str_out += "<p>こんにちは</p>"
    str_out += "<blockquote>"
    str_out += "<p>Mar/06/2023</p>"
    str_out += "</blockquote>"
    return HttpResponse(str_out)
```

```py:home/urls.py
from django.urls import path

from . import views

urlpatterns = [
    path('', views.index, name='index'),
]
```

```py:proj01/urls.py
from django.contrib import admin
from django.urls import include
from django.urls import path

urlpatterns = [
    path('', include('home.urls')),
    path('admin/', admin.site.urls),
]
```
>proj01/settings.py の編集
>'home' を加えます。

```py:proj01/settings.py
（省略）
INSTALLED_APPS = [
    'home',
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]
（省略）
```

ブラウザーで http://localhost:8000/ にアクセス

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/8c96ded6-2414-ae7e-20c1-dbb4516900fc.png)

## PostgreSQL を使ってみます。
>ユーザーの作成
>データベースの作成
>psql を起動してデータベースの選択

```text
$ docker exec -it proj01-db-1 bash
root@4c30256e6c8e:/# su postgres
postgres@4c30256e6c8e:/$ createuser scott -P
Enter password for new role: 
Enter it again: 
postgres@4c30256e6c8e:/$ createdb city
postgres@4c30256e6c8e:/$ psql
psql (13.3 (Debian 13.3-1.pgdg100+1))
Type "help" for help.

postgres=# \c city;
You are now connected to database "city" as user "postgres".
city=#
```

>テーブルの作成
>データの入れ込み
>データの表示

```text
city=# create table cities (id varchar(10) primary key, name text, population int, date_mod date);
CREATE TABLE
city=# insert into cities values ('t3461','広島',72814,'2001-6-14');
INSERT 0 1
city=# insert into cities values ('t3462','福山',81738,'2001-7-11');
INSERT 0 1
city=# insert into cities values ('t3463','東広島',93513,'2001-6-12');
INSERT 0 1
city=# select * from cities;
  id   |  name  | population |  date_mod  
-------+--------+------------+------------
 t3461 | 広島   |      72814 | 2001-06-14
 t3462 | 福山   |      81738 | 2001-07-11
 t3463 | 東広島 |      93513 | 2001-06-12
(3 rows)

city=#
```

psql の終了

```text
city=# exit
postgres@4c30256e6c8e:/$ 
```

参考
ユーザーにテーブルへのアクセス権限をつける方法

```text
city=# grant all on cities to scott;
GRANT
```