Created 2018年5月24日22:17
Updated 2018年5月24日23:34
Categories
Django
Python
Docker
自宅サーバー
自宅サーバーのDockerクラスタにDjangoで作ったサービスを展開する際に少しハマったのでメモ。
本記事の成果物はこちらに上げてあります。
ちなみに、Docker公式のチュートリアルがありますが、こちらはDjango内蔵のWebサーバーを使っており開発環境向けです。
また、swarmクラスタに展開する場合はもう少し調整が必要です。
基本的には A Production-ready Dockerfile for Your Python/Django App を参考に設定していますが、こちらはPostgreSQL向けの情報なので、MySQL向けに変更しました(主にライブラリの追加などを行っています)。
また、/vnevをpython -m venv
から作るよう変更しています。
試行錯誤の過程でイメージの軽量化を諦めたので、ベストな手法とは程遠いかもしれません。
# This Dockerfile is based on https://www.caktusgroup.com/blog/2017/03/14/production-ready-dockerfile-your-python-django-app/
FROM python:3.5-alpine
# Copy in your requirements file
ADD requirements.txt /requirements.txt
# Install build deps, then run `pip install`, then remove unneeded build deps all in a single step. Correct the path to your production requirements file, if needed.
RUN set -ex \
&& apk add --no-cache \
gcc \
make \
libc-dev \
musl-dev \
linux-headers \
mariadb-dev \
pcre-dev
RUN python -m venv /venv
RUN /venv/bin/pip install -U pip
RUN /bin/sh -c "/venv/bin/pip install --no-cache-dir -r /requirements.txt"
# Copy your application code to the container (make sure you create a .dockerignore file if any large files or directories should be excluded)
RUN mkdir /code/
WORKDIR /code/
ADD dockerized_project /code/
ADD start_uwsgi.sh /code/
ADD uwsgi_conf.ini /code/
RUN mkdir -p /code/dockerized_project/static
# uWSGI will listen on this port
EXPOSE 12345
# Add any custom, static environment variables needed by Django or your settings file here:
ENV DJANGO_SETTINGS_MODULE=dockerized_project.settings.production
CMD ["sh", "/code/start_uwsgi.sh"]
django-cors-headers
mysqlclient
uwsgi
Djangoのstaticファイルを収集した後に、uwsgiを起動しています。
#!/bin/sh
/venv/bin/python manage.py collectstatic --noinput
/venv/bin/uwsgi --ini uwsgi_conf.ini
uwsgi_conf.iniはDockerfileでADDしていますが、volumesでマウントして上書きしても良いと思います。
設定内容は How to use Django with uWSGI を参照しました。
[uwsgi]
socket = 0.0.0.0:12345
master = true
processes = 5
chdir = /code
module = dockerized_project.wsgi:application
pidfile = /tmp/project-master.pid
uid = 1000
gid = 2000
harakiri = 20
max-requests = 5000
vacuum = true
設定はjsonとかにも書けるらしいのですが、uwsgi起動時に--jsonパラメータが無いと言われてしまいうまく動きませんでした・・・
コンテナの構成は Scaling Django を参考にしました。
version: "3"
services:
uwsgi:
build:
context: .
environment:
- DJANGO_SETTINGS_MODULE=dockerized_project.settings.production
volumes:
- ./docker_volumes/static:/code/dockerized_project/static
db:
image: mysql
command: mysqld --character-set-server=utf8 --collation-server=utf8_unicode_ci
volumes:
- ./docker_volumes/mysql:/var/lib/mysql
environment:
- MYSQL_ROOT_PASSWORD=root_password
- MYSQL_DATABASE=db_name
- MYSQL_USER=db_user
- MYSQL_PASSWORD=db_password
app:
image: nginx
volumes:
- ./nginx/app.conf:/etc/nginx/nginx.conf
ports:
- 5000:80
static:
image: nginx
volumes:
- ./nginx/static.conf:/etc/nginx/nginx.conf
- ./docker_volumes/static:/static
uwsgi: Djangoアプリケーションのソケット
app: ソケットにアクセスするnginx
static: 静的ファイルを提供するnginx
db: データベース
nginxのコンテナが2つあり、appとstaticというサービス名になっています。
ユーザーはappにアクセスし、そこからuwsgiとstaticにリクエストを振り分けます。
nginxイメージから取ってきたnginx.confをちょっと変更しているだけなのでコードの掲載は割愛します。
Djangoのstartprojectを実行したまま、ほぼデフォルトの状態です(管理画面のログイン画面を出すくらいしかできることがありません・・・)。
変更点として、settingsをディレクトリ化しproduction.pyとdevelopment.pyを追加してDBの設定を行っています。
docker-compose up -d
これで、http://localhost:5000/adminにアクセスすると動作していることが確認できます。
せっかく起動しても管理画面を出すだけではつまらないので、manage.pyで管理ユーザーを作ってみましょう。
DjangoのuwsgiコンテナはPythonイメージがベースになっており、シェルはashが使えます。
docker-compose exec
で入ってからvenvを有効にすれば、manage.pyが実行できます。
$ docker-compose exec -it uwsgi /bin/ash
/code # source /venv/bin/activate
(venv) /code # python manage.py migrate --settings=dockerized_project.settings.production
(venv) /code # python manage.py createsuperuser --settings=dockerized_project.settings.production
もちろんmakemigrationsなども同じように実行できます。
Djangoはローカルで試すのは簡単ですが、実際にプロダクション環境で動作させるのは結構大変ですね。
Dockerなら簡単にできると思いましたが、意外とひな形を動かすのに苦労してしまいました。
イメージの作成についてもまだまだ不十分なので、もう少し知見が欲しいところです。