【Windows10でDocker環境構築】python3 + nginx + Django + PostgreSQL

**Windows10でDockerを使用してDjango環境を構築**

##PCのスペック

| 項目 | スペック |
|:-----------|:------------|
| CPU | COREi7 |
| Memory | 8G |
| Storage | SSD |

今のところ、普通に動作し開発できています。

#Editor
VSCodeを使用
フォルダやファイル作成からTerminalとしてコマンド入力も行っています。

##準備
#####1.Dockerを使用するにはHpyer-Vを有効化する必要があるため、下記の対応が必要です。

- BIOSの設定変更:<br>　Intel VTをEnabledにする。
- OS:<br>　Windows10 Pro 64bit(Hpyer-Vを有効化できるのはWindows10 Proのみのため)

#####2.Python3.8.2(64bit版)のインストール
Pipenvを使用しますので、PCにPythonをインストールします。
***意図的に64bit版をダウンロードしないと、34bit版がダウンロードされますの注意が必要です。***

https://www.python.org/downloads/windows/

から、

***Python 3.8.2 - Feb. 24, 2020
->Download Windows x86-64 executable installer***

を選択してダウンロードする必要があります。

#####3.環境変数の設定
PathにPythonのインストール先ディレクトリを設定してください。
Pythonのデフォルトインストール先はProgram Files配下ではなく、

```
C:\Users\ユーザー名\AppData\Local\Programs\Python\Python38
```

になります。

##バージョン
インストールしたソフトウェアのバージョン

- Docker:2.3.0.3
- Docker-compose:1.25.5
- ubunts:20.04
- python:3.8.2
- Django:3.0.6
- gunicorn:20.0.4
- psycopg2:2.8.5
- PostgeSQL:12.3
- nginx:1.17.10

##dockerインストール
下記のサイトなどからDocker Desktopをダウンロードしてインストール

https://www.docker.com/get-started
https://hub.docker.com/editions/community/docker-ce-desktop-windows/

##ディレクトリ構成

```
test
├── app
│   ├── .venv ※配下にフォルダがあります
│   ├── mysite
│   │   ├── __init__.py
│   │   ├── settings.py
│   │   ├── urls.py
│   │   └── wsgi.py
│   ├── manage.py
│   ├── Dockerfile
│   ├── Pipfile
│   └── Pipfile.lock
├── db
│   ├── dbdata
│   ├── initdb.d
│   └── Dockerfile
│       └── init.sql
├── nginx
│   └── default.conf
│   ├── Dockerfile
│   └── nginx.conf
└── docker-compose.yml
```
##構成
構成は
　***Clien<-(Port:80)->nginx<-(Proxy/Port:8000)->Gunicorn<-->Django<-(Port:5423)->PostgreSQL***
となります。

**構築していきます**
##1.PipenvによるPython仮想環境の構築
Pythonということもあり、Pipenvを利用します。

#####1-1.Pipfileを作成

``` python:.\test\app\Pipfile
[[source]]
name = "pypi"
url = "https://pypi.org/simple"
verify_ssl = true

[dev-packages]

[packages]
django = "==3.0.6"
gunicorn = "==20.0.4"
psycopg2 = "==2.8.5"

[requires]
python_version = "3.8.2"
```
#####1-2.Python仮想環境の構築
.\test\appに移動して、コマンドを実行します。
正常に構築が完了していれば指定したバージョンのPackageがインストールされています。
[]は接続先環境になります。

```
[Powershell]>pip install pipenv
[Powershell]>pipenv install
[Powershell]>pipenv shell
[pipenv]>python -V
Python 3.8.2
[pipenv]>pip list
Package    Version
---------- -------
asgiref    3.2.10
Django     3.0.6
gunicorn   20.0.4
pip        20.1.1
psycopg2   2.8.5
pytz       2020.1
setuptools 49.2.0
sqlparse   0.3.1
wheel      0.34.2
```
(1)VSCodeはTerminalウィンドウの右上に接続環境が表示されます。pipenvと表示されていればPythonの仮想環境に入っています。
(2)pipenv installが完了する.\test\app配下に
　　・.envフォルダ
　　・Pipfile.lockファイル
　が作成されます。

#####1-3.Djangoの動作確認
Djangoプロジェクトを作成します。

```
[pipenv]>django-admin startproject mysite .
```

プロジェクトの作成が完了すると.\test\app配下に
　・mysiteフォルダ
　・manage.pyファイル
が作成されます。

#####4.Djangoプロジェクトの確認
Djangoを立ち上げます。

```
[pipenv]>python manage.py runserver localhost:8000
```

ブラウザから http://localost:8000 にアクセスし

![django.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679829/80e3218c-a587-4c89-0bda-a56a74fa8269.png)

が表示されれば正常に動作していることになります。
確認できればexitし、VSCodeのDockerから該当のCONTAINERSを削除。

##2.Django用Dockerファイルの作成
#####フォルダ.\test\app配下にDockerファイルを作成します。

```Dockerfile:.\test\app\Dockerfile
FROM ubuntu:20.04

SHELL ["/bin/bash", "-c"]

RUN apt-get update -y \
    && apt-get upgrade -y \
    && apt-get install -y python3.8 python3.8-dev \
    && source ~/.bashrc \
    && apt-get -y install vim

WORKDIR /usr/src/test/app

ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1
ENV DEBIAN_FRONTEND=noninteractive

RUN apt-get install -y curl \
    && curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py \
    && apt-get install -y python3.8-distutils \
    && python3.8 get-pip.py \
    && pip install -U pip \
    && apt-get install -y build-essential libssl-dev libffi-dev python-dev python3-dev libpq-dev

RUN pip install pipenv

COPY Pipfile ./

RUN pipenv install --system --skip-lock \
    && pip uninstall -y pipenv virtualenv-clone virtualenv

COPY . /usr/src/test/app/
```
##3.PostgreSQL用Dockerファイルの作成
#####3-1.フォルダ.\testに移動して.\test\dbフォルダを作成し、.\test\dbの配下に下記のフォルダを作成します。
　・.\test/db\dbdata
　・.\test\db\initdb.d

#####3-2.フォルダ.\test\Dockerfileを作成します。

```dockerfile:.\test\db\Dockerfile
FROM postgres:12.3
RUN localedef -i ja_JP -c -f UTF-8 -A /usr/share/locale/locale.alias ja_JP.UTF-8
ENV LANG ja_JP.utf8
```

#####3-3.初期設定が必要な場合、.\test\db\initdb.d配下にSQLを配置します。

#####3-4.フォルダ.\test\app\mysite\setting.pyにPostgreSQLのDATABASE設定を記載します。

```python:.\test\app\mysite\setting.py
---(中略)----

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'NAME': 'postgres',
        'USER': 'postgres',
        'HOST': 'db',
        'PORT': 5432,
        'PASSWORD' : 'postgres'
    }
}

---(中略)----
```

##4.nginx用Dockerファイルの作成
#####4-1.フォルダ.\testに移動して.\test\nginxフォルダを作成します。

#####4-2.フォルダ.\test\nginx配下にDockerfileファイルを作成します。

```dockerfile:.\test\nginx\Dockerfile
FROM nginx:1.17.10
RUN rm /etc/nginx/conf.d/default.conf
COPY nginx.conf /etc/nginx/conf.d/
COPY default.conf /etc/nginx/
RUN ln -sf  /usr/share/zoneinfo/Asia/Tokyo /etc/localtime
```

#####4-3.フォルダ.\test\nginx配下にnginx.confファイル、default.confファイルを作成します。
nginx経由でDjangoサーバーにアクセスするので、proxyの設定をします。

```nginx:.\test\nginx\nginx.conf
upstream mysite {
    server app:8000;
}

server {
    listen 80;
    location / {
        proxy_pass http://mysite;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_redirect off;
    }
}
```
```nginx:.\test\nginx\default.conf
user  nginx;
worker_processes  1;
http {
    log_format main '$remote_addr - $remote_user [$time_local]  "$status"' 
                    '"$request" $body_bytes_sent "$http_referer" '
                    '"$http_user_agent" "$http_x_forwarded_for"';
    access_log  /var/log/nginx/access.log  main;
}
```

##5.docker-compose.ymlファイルの作成
#####フォルダ.\testに移動して直下にdocker-compose.ymlファイルを作成します。

```docker:.\test\docker-compose.yml
version: "3.7"
services:
  web:
    container_name: nginx
    build: ./nginx
    ports:
      - 80:80
    depends_on:
      - app
    restart: always

  app:
    container_name: devapp
    build: ./app
    command: gunicorn mysite.wsgi:application --bind 0.0.0.0:8000
    volumes:
      - ./app:/usr/src/test/app/
    ports:
      - 8000:8000
    depends_on:
      - db
    restart: always

  db:
    container_name: devdb
    build: ./db
    volumes:
      - ./db/dbdata:/var/lib/postgresql
    ports:
      - 5432:5432
    environment: 
      POSTGRES_PASSWORD: 'postgres'
    restart: always

volumes:
    dbdata:
```

##6.動作確認
#####6.1.フォルダ.\testに移動し、仮想環境を立ち上げます。

```
[Powershell]>docker-compose up -d --build
```

#####6-2.http://localhost にアクセスし、

![localhost.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679829/df4b33b3-df38-5b4c-f613-a0a32c9aead8.png)

が表示されれば完了です。