DockerでDocker-composeを使った本番環境(Heroku)と開発環境の切り分け
Djangoのdeploy
クラウドにdeployすることが主流なので、ローカル開発環境と本番運用環境ではDBの設定などが異なることが多いと思われる。そこで、djangoで本番環境と開発環境を切り分けるには、settings.pyを2つ作って使い分ける。これを実現するためにはdocker-composeを使うと便利だったので、設定をまとめる。
主な手順は、
- 共通設定ファイルをつくる。開発環境用設定ファイルと本番環境用設定ファイルを切り分ける
- 環境に応じて読み込む設定ファイルを環境変数で切り替える。
である。 今回は、
- 共通設定ファイルをつくり、それを継承した開発環境用設定ファイル、本番環境用設定ファイルをつくる
- Django, DB, wsgi server, web serverをdocker-composeで構成。開発環境用設定ファイルを読み込ませる
- 本番環境用設定ファイルを読み込むDocker image(Django partのみ)を作成。本番環境にpushする
今回は、Herokuを本番環境とする。しかし、他の環境でも応用可能だと思われる。
requirements.txt
以下のライブラリが必要
dj-database-url django-heroku gunicorn
wsgi serverはgunicornじゃなくても多分動きます。
共通設定ファイルと本番環境用ファイルを分割
originalのsettings.pyをbase_settings.pyにrenameする。 heroku用にDB、ログの設定をbase_settingsから上書きしたsettingsファイルを作成する。loggerについては別記事でまとめます。
settings.py (本番環境用)
from main.base_settings import * # 本番環境(heroku) DEBUG = True # loggerの設定 LOGGING = { 'version': 1, 'disable_existing_loggers': False, 'handlers': { 'console': { 'class': 'logging.StreamHandler' }, }, 'loggers': { '': { # 'catch all' loggers by referencing it with the empty string 'handlers': ['console'], 'level': os.getenv('DJANGO_LOG_LEVEL', 'INFO'), }, }, } # DB設定 import dj_database_url DATABASES = { 'default': dj_database_url.config(conn_max_age=600, ssl_require=True) } # Honor the 'X-Forwarded-Proto' header for request.is_secure() SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https') ALLOWED_HOSTS = ['*'] # Activate Django-Heroku. import django_heroku django_heroku.settings(locals())
開発環境用ファイルを作成
開発用のsettings.pyをつくる
settings_development.py (開発環境用)
from main.base_settings import * # for development DEBUG = True LOGGING = { 'version': 1, 'disable_existing_loggers': False, 'handlers': { 'console': { 'class': 'logging.StreamHandler' }, }, 'loggers': { '': { # 'catch all' loggers by referencing it with the empty string 'handlers': ['console'], 'level': 'DEBUG', }, }, } DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), } } ALLOWED_HOSTS = ['*']
Docker
開発環境
Djangoが呼び出すsettingsは環境変数DJANGO_SETTINGS_MODULEで決まっている。 docker-composeで環境変数に開発環境ようのsettingファイルであるsettings_development.pyを指定して、development用docker imageを作成する
(docker-compose-dev.yml)
... environment: - DJANGO_SETTINGS_MODULE=main.settings_development command: python manage.py runserver ...
commandは以上の設定にしておけば、pythonコードの編集の度に自動でapp serverが再起動し、更新が反映されるので開発用に適していると思われます。
本番環境用
DJANGO_SETTINGS_MODULEはdefaultでsettings.pyが設定されているので特に変わった設定は必要ない。
docker-compose.yml
version: '3.4' services: web: build: ./[dir] container_name: web volumes: - "./[dir]:/opt/backend" ports: - "8000:8000"
heroku用の設定
non-root userの作成 gunicorn, uwsgi or mod_wsgiいずれの場合でもport番号は$PORTで指定する。docker-compose.ymlはimageのbuildにしか使わない。heroku上ではDockerfile内のCMD以降のコマンドが呼ばれる。portをべた書きしてしまうとherokuでは動かないので注意が必要
in Dockerfile
... RUN useradd -m myuser USER myuser CMD exec gunicorn -b 0.0.0.0:$PORT main.wsgi
docker imageの作成
$ docker-compose build
herokuへのdocker image deploy
$ heroku login $ heroku container:login $ docker tag [img name] registry.heroku.com/[app name]/web $ docker push registry.heroku.com/[app name]/web $ heroku container:release web -a [app name]
heroku上でDatabase migrate
Databaseを使う場合はmigrateを初めに行う。
$ heroku run python manage.py migrate $ heroku run python manage.py createsuperuser
docker-composeで環境の切り替え
開発環境でapp起動
$ docker-compose -f docker-compose-dev.yml up
本番環境でimage build
$ docker-compose build
deploy時にsettings.pyに手を加えなくて良くなるので、deployの手間も減り、思わぬバグが混入する機会も減ると思います