ちょっとしたサービスを作りたいと思い、勉強しながらConoHa VPS上でDocker環境を構築中です。
docker-composeを使って、「https-portal+Django+postgreSQL」を立ち上げることができたので、備忘録としてその方法をまとめたいと思います。
※「https-portal」は自動でhttpsの証明書の更新をしてくれる便利なコンテナです。「https-portal」内にnginxがあるので、プロキシの機能はそれを使うことにします。
環境は以下です。
- ConoHa VPS (メモリ 1GB/CPU 2Core/SSD 100GB)
- Ubuntu 18.04.4 LTS
- Docker: 19.03.8 (2020/3/22 執筆時点の最新)
- Docker Compose: 1.25.4 (2020/3/22 執筆時点の最新)
- https-portal: 1 (2020/3/22 執筆時点の最新)
- Python: 3.8 (2020/3/22 執筆時点の最新)
- Django: 3.0.4 (2020/3/22 執筆時点の最新)
- psycopg: 2.8.4 (2020/3/22 執筆時点の最新)
- uWSGI: 2.0.18 (2020/3/22 執筆時点の最新)
- postgres: latest (2020/3/22 執筆時点では、12.2が最新)
目次
事前準備
事前に以下の準備が必要です。
- Docker、Docker ComposeをインストールしたLinuxサーバ
もし、まだ準備されていないようなら、以下に導入方法をまとめたので、よろしければご覧になってください。
※仮想専用サーバのConoHa VPS上での構築を想定していますが、Linuxであれば同じ手順を踏襲することができると思います。
docker-composeで「https-portal+Django+postgreSQL」を立ち上げる
作業ディレクトリとしてホームディレクトリに「work」を作成し、以下のようなディレクトリ構成を作成していきます。
work
|-- db
| `-- dbdata
|-- django
| |-- Dockerfile
| `-- requirements.txt
|-- docker-compose.yml
|-- nginx
| |-- conf
| | `-- mysite_nginx.conf
| |-- ssl_certs
| `-- uwsgi_params
`-- src
|-- manage.py
|-- mysite
| |-- __init__.py
| |-- asgi.py
| |-- settings.py
| |-- urls.py
| `-- wsgi.py
`-- static
ホスト側のサーバとコンテナ側の構成イメージは以下のような関係となります。
「docker-compose.yml」を作成する
以下のコマンドで「docker-compose.yml」を作成します。
このファイルはDocker Composeで立ち上げるコンテナの定義をしています。
$ vi ~/work/docker-compose.yml
【編集内容】
version: '3.5'
services:
web:
image: steveltn/https-portal:1
container_name: web
restart: always
volumes:
- ./nginx/ssl_certs:/var/lib/https-portal
- ./nginx/conf/mysite_nginx.conf:/etc/nginx/conf.d/mysite_nginx.conf
- ./nginx/uwsgi_params:/etc/nginx/uwsgi_params
- ./src/static:/static
ports:
- '80:80'
- '443:443'
environment:
DOMAINS: '[ドメイン名] -> http://web:8080/'
STAGE: 'production'
depends_on:
- django
django:
build: ./django
container_name: django
volumes:
- ./src:/code
expose:
- '8001'
command: uwsgi --socket :8001 --module mysite.wsgi
depends_on:
- db
db:
image: postgres:latest
container_name: db
volumes:
- ./db/dbdata:/var/lib/postgresql/data
expose:
- '5432'
environment:
- POSTGRES_USER=hogehoge
- POSTGRES_PASSWORD=password
- POSTGRES_DB=testDB
image: steveltn/https-portal:1
、image: postgres:latest
でhttps-portalとPostgreSQLの最新のイメージをDocker Hubから自動でダウンロードしてくれます。build: ./django
は./djangoにあるDockerfileからDockerイメージをビルドしてくれます。web:
の[ドメイン名]については、ご自分の環境に合わせてください。https-portalによって、この[ドメイン名]に対して、httpsで接続できるようになります。web:
のenvironment:
のSTAGE
は証明書の種類を指定できます。STAGE: 'staging'
でhttps-portalは指定したドメインに対してオレオレ証明書を作成してくれます。STAGE: 'production'
にすれば、https-portalは指定したドメインに対してLet's EncryptでDV証明書を作成してくれます。volumes:
でホスト側からコンテナ側へボリュームをマウントすることができます。(ホスト側とコンテナ側で共有ディレクトリを作るイメージ) 後で作成するnginxコンフィグなどをマウントしています。django:
の- ./src:/code
とweb:
の- ./src/static:/static
でdjango:
の/codeとweb:
の/staticをホスト側の./srcを介してつなげています。これにより、static関連のファイルをDjangoにアクセスせず、nginxから取得できるようにしています。ports:
でホスト側のポートとコンテナ側のポートをつなげることができます。https-portalは- "80:80"
と- "443:443"
とすることで、HTTPの80番ポートとHTTPSの443番ポートに対して、ホスト側とコンテナ側をつなげています。expose:
はコンテナ側でのみ公開するポートを指定できます。django:
とdb:
はホスト側からの接続はしないため、expose:
でコンテナ側のみ公開するポートを指定します。environment:
で環境変数を指定できます。db:
にはDB接続するためのユーザ名やパスワード、DB名を指定しています。depends_on:
は依存関係を定義することができます。docker-containerコマンドを実施したときに、依存関係のコンテナが出来上がるのを待って、自コンテナの立ち上げをすることができます。
「django/Dockerfile」を作成する
以下のコマンドで「django/Dockerfile」を作成します。
このファイルはdjangoコンテナのイメージを定義するファイルになります。
$ mkdir -p ~/work/django/
$ vi ~/work/django/Dockerfile
【編集内容】
FROM python:3.8
ENV PYTHONUNBUFFERED 1
RUN mkdir /code
WORKDIR /code
COPY requirements.txt /code/
RUN pip install -r requirements.txt
COPY . /code/
FROM python:3.8
でpythonのバージョン3.8のDockerイメージをDocker Hubからダウンロードします。RUN pip install -r requirements.txt
で「requirements.txt」で定義されたライブラリをインストールする。※「requirements.txt」は下記で作成する。
「django/requirements.txt」を作成する
以下のコマンドで「django/requirements.txt」を作成します。
このファイルはdjangoコンテナのイメージにインストールするライブラリを定義するファイルになります。
$ vi ~/work/django/requirements.txt
【編集内容】
Django==3.0.4
psycopg2==2.8.4
uwsgi==2.0.18
「nginx/conf/mysite_nginx.conf」を作成する
以下のコマンドで「nginx/conf/mysite_nginx.conf」を作成します。
「docker-compose.yml」のhttps-portalコンテナのDOMAINS: '[ドメイン名] -> http://web:8080/'
によって、指定ドメインへのアクセスを受けたら、web:8080/
に転送してくれます。ここで、web
とはhttps-portalコンテナを示しますが、そのアクセスを受け付けるのはhttps-portalコンテナ内で動いているnginxです。そのnginxの設定を行うのが、「 mysite_nginx.conf」です。
$ mkdir -p ~/work/nginx/conf/
$ vi ~/work/nginx/conf/mysite_nginx.conf
【編集内容】
upstream django {
ip_hash;
server django:8001;
}
server {
listen 8080;
server_name dockerhost;
charset utf-8;
client_max_body_size 75M;
location /static {
alias /static;
}
location / {
uwsgi_pass django;
include /etc/nginx/uwsgi_params;
}
}
- 指定ドメインへのアクセスを受けたら、https-portalコンテナに8080番ポートで転送されるので、nginxが監視するのは8080番ポートを設定します。
server_name
にはホスト側のIPアドレスを設定する必要があるのですが、dockerhost
という変数がホスト側のIPアドレスを格納しているので、それを使用します。location /static
でアクセスがあったら、/staticを返すようにしています。これで、staticファイルはDjangoまでアクセスしないようにしています。location /
でアクセスあったら、uwisgiを介してdjango:8001
へ通信が引き継がれます。ここら辺の書き方は、Djangoにuwisgiを使ってアクセスするときの一般的な書き方です。(自分もあまり詳しくないです。。。)
「nginx/uwsgi_params」を作成する
以下のコマンドで「nginx/uwsgi_params」を作成します。
このファイルはuwsgiサーバで使用するパラメータを定義するファイルになります。
$ vi ~/work/nginx/uwsgi_params
【編集内容】
uwsgi_param QUERY_STRING $query_string;
uwsgi_param REQUEST_METHOD $request_method;
uwsgi_param CONTENT_TYPE $content_type;
uwsgi_param CONTENT_LENGTH $content_length;
uwsgi_param REQUEST_URI $request_uri;
uwsgi_param PATH_INFO $document_uri;
uwsgi_param DOCUMENT_ROOT $document_root;
uwsgi_param SERVER_PROTOCOL $server_protocol;
uwsgi_param REQUEST_SCHEME $scheme;
uwsgi_param HTTPS $https if_not_empty;
uwsgi_param REMOTE_ADDR $remote_addr;
uwsgi_param REMOTE_PORT $remote_port;
uwsgi_param SERVER_PORT $server_port;
uwsgi_param SERVER_NAME $server_name;
その他で使用するディレクトリを作成する
あとは、以下のコマンドで、DBマウント用の「~/work/db/dbdata」、Djangoのプロジェクトファイル格納用の「~/work/src」、httpsの証明書関連を格納する「~/work/nginx/ssl_certs」ディレクトリを作成します。
$ mkdir -p ~/work/db/dbdata
$ mkdir -p ~/work/src
$ mkdir -p ~/work/nginx/ssl_certs
- 「~/work/db/dbdata」配下のファイルはPosreSQLのコンテナ生成時に自動でできあがります。ただし、コンテナ側で実行する権限がroot権限のため、dbdata配下はroot権限となってしまうことに注意です。
- 「~/work/src」配下のファイルは、コマンドを入力することで Djangoのプロジェクトファイルを作成します。やり方は後述します。
- 「~/work/nginx/ssl_certs」配下のファイルはhttps-portalのコンテナ生成時に自動でできあがります。
Djangoのプロジェクトを作成する(/src配下のファイルを作成する)
/src配下にはDjangoのプロジェクトファイルが入るので、ここではその設定を行います。
Djangoのプロジェクトファイルを作成するには、Djangoの環境が構築されたサーバ上で「django-admin startproject
」というコマンドを実行する必要があります。
そのため、上で定義したdjangoコンテナを一度立ち上げて、djangoコンテナ上でDjangoプロジェクトを作成する「django-admin startproject
」というコマンドを実行する。
djangoコンテナ上でコマンドを打つのは、以下のようなコマンドをホスト側で実行すればOK
$ cd ~/work/
$ docker-compose run django django-admin startproject mysite .
docker-compose run django
で、djangoコンテナを立ち上げています。- その後、
django-admin startproject mysite .
がdjangoコンテナ 上で実行されるコマンドです。
【実行結果】
これを実行後、/srcディレクトリを確認すれば、Djangoのプロジェクトファイルが出来上がっているはずです。
`-- src
|-- manage.py
`-- mysite
|-- __init__.py
|-- asgi.py
|-- settings.py
|-- urls.py
`-- wsgi.py
Djangoのプロジェクトファイルを編集する
Djangoのデフォルトの設定では、外部からのアクセスが禁止されているので、外部からのアクセスを有効にします。また、DjangoからDBにアクセスできるように、DBの設定やstaticファイルをnginxからアクセスできるように、 staticファイルをsrc/staticに統合する設定を行います。
以下のコマンドで、「~/work/src/mysite/settings.py」を変更します。
$ sudo vi ~/work/src/mysite/settings.py
【変更点】
ALLOWED_HOSTS = ["*"]
# ~~~~
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': 'testDB',
'USER': 'hogehoge',
'PASSWORD': 'password',
'HOST': 'db',
'PORT': 5432,
}
}
# ~~~~
STATIC_ROOT = os.path.join(BASE_DIR, 'static/')
また、以下のコマンドで、staticファイルを/src/staticに集約させます。
$ docker-compose run django ./manage.py collectstatic
コンテナを起動させる
これで、設定は終了です。
最後に、Docker Composeを実行して、コンテナを起動させます。
$ cd ~/work
$ docker-compose up
【実行結果】
以下のように表示されればOK
Starting db ... done
Starting django ... done
Starting nginx ... done
Djangoにアクセスしてみる
ブラウザから、「https://サーバのIPアドレス」にアクセスしてみてください。
ドメインを設定しているなら、「https://ドメイン名」でもアクセスできるはずです。
以下のように、ロケットが表示されればうまくDjangoが起動しています。また、URLの横に鍵マークがあることが確認できれば、httpsでアクセスも成功しています。
関連情報
本記事では、「https-portal+Django+postgreSQL」の構成を構築する手順を記載しましたが、ユーザ名やパスワード、さらにはドメイン名、IPアドレス、ポート番号などのような環境依存するものは、環境変数で定義するのが一般的です。「https-portal+Django+postgreSQL」の構成に対して、環境変数を考慮したうえで構成を見直したものを以下の記事でまとめました。よろしければご覧になってください。
その他、ConoHa上でDockerを導入したり、Webアプリを立ち上げたりした内容を以下の記事でまとめました。こちらもよろしければご覧になってください。
参考
- Quickstart: Compose and Django(公式ドキュメント)
- 全自動Let's Encrypt Dockerコンテナ "https-portal" を使ってウェブサイトをHTTPS化する | Qiita
広告
Dockerをやるなら以下の書籍がオススメです。
Dockerとは何か?から複数のコンテナを管理することができるDocker Compose、Kubernetesまでまとめられています。
ConoHa VPS
は初期費用不要で月に数百円で利用できる仮想サーバのサービスです。以下のような方には非常にオススメのサービスとなっています!
- 勉強がてらLinuxの環境をちょっと触ってみたい
⇒管理者権限が実行可能なLinuxサーバ環境が構築可能です! - スモールスタートでサービスを提供して、うまくいったら規模をスケールアップしたい
⇒後からメモリサイズやCPU数などのスケールアップ/スケールダウン可能です! - AWSやGCPなどのクラウドサービスは高いので、もっと安くサーバ構築したい
⇒初期費用なし、月数百円(1時間単位も可)で利用可能です!
以上!
コメント