この記事の対象読者
- Djangoアプリケーションを本番環境でどうやって動かしたらいいか見当もつかない方
- Gunicornで動かしたもののCSSやJavaScriptがきちんと動作しなくなってしまった方
- DockerでGunicornを動かせなくてハマっている方
この記事を読んで得られるメリット
- DjangoアプリケーションをGunicornを動かす方法がわかります。
- 静的ファイルを収集してWebサーバにデプロイし、CSSやJavaScriptが動作するようになります。
- DockerでGunicornを動かせるようになります。
事前手順
事前手順として以下記事にあるバックエンドの開発環境を構築し、djangoイメージを作成しましょう。
構成
PCから直接バックエンド(アプリケーションサーバ)にアクセスする構成とします。
アプリケーションサーバは、Djangoアプリケーションを提供し、Docker、Gunicorn、Djangoという構成で、localhostの8000番ポートで待ち受けます。
Webサーバは、Djangoの静的コンテンツ(画像ファイル、CSS、JavaScript)を提供し、DockerおよびNginxという構成で、localhostの80番ポートで待ち受けます。
今回はバックエンドサーバへのアクセスをメインとしていますので、PCからはアプリケーションサーバ向けにアクセスします。
手順
本記事ではターミナルを複数使うので、ターミナル1とターミナル2という形で分けて書いております。
ターミナル1
cd ~/repos/django
docker run -it --rm -v $(pwd):/app -p 8000:8000 --name django django:latest /bin/bash
Gunicornのインストール
Pipenvを使ってGunicornをインストールします。
コマンド(ターミナル1)
pipenv install gunicorn
出力結果(ターミナル1)
Installing gunicorn...
Resolving gunicorn...
Added gunicorn to Pipfile's [packages] ...
✔ Installation Succeeded
Pipfile.lock (52085a) out of date, updating to (adadca)...
Locking [packages] dependencies...
Building requirements...
Resolving dependencies...
✔ Success!
Locking [dev-packages] dependencies...
Updated Pipfile.lock (f916eb14fb3e523249f1b43b24f00e1687ffd513f7f6820b320fb58254adadca)!
Installing dependencies from Pipfile.lock (adadca)...
To activate this project's virtualenv, run pipenv shell.
Alternatively, run a command inside the virtualenv with pipenv run.
Pipenv管理パッケージをシステムインストール
本番環境用Dockerイメージを作成する場合は、こちらの手順を行います。
これを行うことにより、Pipenv管理パッケージをシステムにインストールすることができ、pipenv runなしで(PATHが通った状態で)コマンドを実行することができるようになります。
コマンド(ターミナル1)
pipenv install --system --deploy
Gunicornイメージの作成
ターミナル1のプロンプトにあるものがコンテナIDです。
コンテナIDの確認方法については自分で作るDocker/Djangoバックエンド開発環境構築手順を参照してください。
コマンド(ターミナル2)
docker commit -a '名前 <メールアドレス>' -m 'Install gunicorn' [コンテナID] gunicorn:latest
出力結果(ターミナル2)
sha256:f197fefb98a6847fea66ec9e5875ba6db90b7f70a3abfd1b00b54db60d23bde1
gunicornコンテナからのログアウト
コマンド(ターミナル1)
exit
Gunicornの起動
アプリケーションのディレクトリを/appにマウントしつつ、8000番ポートで待ち受け、gunicornを起動します。
この際「-b」オプションが非常に重要です。
これがないとローカルホスト(Dockerコンテナ内)で待ち受けてしまうため、gunicornコンテナにアクセスできません。
コマンド(ターミナル1)
docker run -d --rm -v $(pwd):/app -p 8000:8000 --name gunicorn gunicorn:latest gunicorn project.wsgi -b 0.0.0.0:8000
出力結果(ターミナル1)
8e6c4bdeb90ab8ed8b6dc6d35c3ddf37e3283b75c39807ac4618922981ae03d6
Gunicornへのアクセス
バックエンドへのアクセス
ブラウザを起動しアドレスバーにhttp://localhost:8000と入力し、Enterキーを押します。
表示結果
スタイルシートが崩れてしまいました。
これは何故かというと、Djangoは本番環境にて静的ファイルを取り扱う際にWebサーバやCDNなど外部のサービスに配置することを想定しています。
これはWebサーバやCDNは基本的にアプリケーションサーバの前段にあり、静的なコンテンツを素早くユーザーに返すことができるようにするためのものだと、私が勝手に思っています(真実の程はわからないので詳しい方教えてください)。
Djangoではcollectstaticコマンドを使うことで静的ファイルを一箇所に収集し、それをWebサーバもしくはCDNなどで配信することでこの問題を解消することができます。
静的ファイルの収集
設定ファイルの修正
project/settings.pyのSTATIC_URLを修正し、STATIC_ROOTファイルを保存します。
STATIC_URL = 'http://localhost/static/'
STATIC_ROOT = 'static'
コマンド(ターミナル1)
collectstaticを使ってSTATIC_ROOTに指定したディレクトリに静的ファイルを集めます。
docker run -it --rm -v $(pwd):/app gunicorn python manage.py collectstatic
出力結果(ターミナル1)
162 static files copied to '/app/static'.
Nginxの起動
今回はDockerでNginxを起動し、静的ファイルを配信します。
コマンド(ターミナル1)
collectstaticコマンドで集めた静的ファイルをNginx起動時に直接マウントしWebサーバで配信できるようにします。
docker run -d --rm -v $(pwd)/static:/usr/share/nginx/html/static:ro -p 80:80 --name nginx nginx
ログイン
http://localhost:8000/api-auth/login/?next=/users/ にアクセスし、Username、Posswordを入力して「Log in」ボタンをクリックします。
表示結果
ユーザー一覧が表示できました。
まとめ
- Gunicornを使ってDjangoアプリケーションを動かせるようになりました。
- Dockerを使ってGunicornを動かすこともできました。
- 静的ファイルが見れなくなってしまう問題も解決しました。
参考
最後に
本記事の内容では本番環境で動作させるには程遠いです。
Dockerコンテナをいちいちdockerコマンドで起動したりすることはないからです。
ローカル開発環境だとDocker Composeを使うのが一般的でしょうか。
本番環境で動かすには、Kubernetes環境やマネージドコンテナ環境で動かすようにすべきです。
またデータベース部分がDjangoのデフォルトのSQLite3なのでここもPostgreSQLやMySQLなどのRDBMSに変更する必要があるでしょう。
フロントエンドを作る必要があるならNginxにReactやVue.jsなどで作成したフロントエンドアプリも載せる必要があります。
セキュリティ対策やパフォーマンステストなどやることはいっぱいあるので、本記事の内容だけで本番稼働ができるとは思わないようご注意ください。
コメント