docker-composeでNginx + Django + MySQLのWeb三階層を構成する
Kubernetesクラスタの構築方法など、インフラ観点での記事を書くことが多い本ブログですが、Kubernetesを学んでみると
- インフラエンジニアもアプリケーションエンジニアの気持ちがわかったほうがいい!
というお気持ちになるのです。CI/CDとか考えると特に。
そんなことでOSにも標準でインストールされている意味でメジャーな言語であるPythonを、そのWebフレームワークであるDjangoを通して勉強しているわけなのですが、DjangoでSQLiteとか、python manage.py runserver
とか使っていると、「本番環境だとこれどう変わるのん?」というインフラエンジニアならではの疑問が沸々と湧き上がってくるのです。
そこで、Pythonのお勉強のわき道にそれて、Nginx + Django + MySQLでWeb三階層を組んでみました。せっかくDockerコンテナのことも知っているので、docker-composeを使い、コンテナでWeb三階層を組んでみました。そのときのdocker-compose.yml
をさらしたいと思います。
いきなりdocker-compose.yml
をさらす前に、プロジェクトのディレクトリ構成を示しておきます。
. ├── docker-compose.yml ├── mysite ← Djangoプロジェクトのルート │ ├── Dockerfile チュートリアルアプリであるpollsアプリを作成 │ ├── docker-entrypoint.sh │ └── mysite │ ├── manage.py │ ├── mysite │ ├── polls │ └── static ├── mysql ← MySQLプロジェクトのルート │ └── Dockerfile mysql:5.7イメージを使うだけ └── nginx ← Nginxプロジェクトのルート ├── Dockerfile 基本的にはnginx:1.15.alpineを使うだけだが、 ├── docker-entrypoint.sh Djangoと連携するためのUWSGI接続設定を組み込む └── mysite_nginx.conf
この前提の下で、docker-compose.yml
は以下のように書きました。
version: '3' services: mysite: build: mysite image: bbrfkr0129/mysite environment: MYSQL_DATABASE: mysite MYSQL_USER: mysite MYSQL_PASSWORD: password MYSQL_HOSTNAME: mysql networks: - mysite mysql: build: mysql image: bbrfkr0129/mysql environment: MYSQL_ROOT_PASSWORD: password MYSQL_DATABASE: mysite MYSQL_USER: mysite MYSQL_PASSWORD: password volumes: - "mysql_data:/var/lib/mysql" networks: - mysite nginx: build: nginx image: bbrfkr0129/nginx ports: - "80:80" environment: UWSGI_HOST: mysite volumes: - "./mysite/mysite/static:/static" networks: - mysite volumes: mysql_data: driver: local networks: mysite: driver: bridge
mysql
サービスは、公式の使い方に準拠しているので、説明を省きます。
mysite
サービスではDjangoをuWSGI接続で動作させます。バックエンドDBにMySQLを使うので、あらかじめsettings.py
にMySQL接続用のパラメータを置換用文字列で書き換えておき、コンテナ起動時にdocker-entrypoint.sh
の処理内で実際のパラメータに置換します。Dockerfile
、docker-entrypoint.sh
は以下のような感じです。
FROM python:3.6-alpine3.8 # install django uwsgi and PyMySQL RUN apk --no-cache --virtual .requirements add g++ make linux-headers && \ apk --no-cache add libffi-dev mysql-dev mysql-client && \ pip install Django uwsgi mysqlclient && rm -rf ~/.cache/pip && \ apk del .requirements # install mysite RUN mkdir /mysite COPY ./mysite/ /mysite/ WORKDIR /mysite EXPOSE 8001 COPY docker-entrypoint.sh /usr/bin/ ENTRYPOINT ["docker-entrypoint.sh"] CMD ["uwsgi", "--socket", ":8001", "--module", "mysite.wsgi"]
#!/bin/sh sed -i "s/MYSQL_DATABASE/$MYSQL_DATABASE/g" /mysite/mysite/settings.py sed -i "s/MYSQL_USER/$MYSQL_USER/g" /mysite/mysite/settings.py sed -i "s/MYSQL_PASSWORD/$MYSQL_PASSWORD/g" /mysite/mysite/settings.py sed -i "s/MYSQL_HOSTNAME/$MYSQL_HOSTNAME/g" /mysite/mysite/settings.py export connected="no" while [ $connected = "no" ] do mysql \ -u$MYSQL_USER -p$MYSQL_PASSWORD -h$MYSQL_HOSTNAME \ -e "show tables;" $MYSQL_DATABASE if [ $? -eq 0 ] ; then export connected="yes" fi sleep 1 done python manage.py makemigrations polls python manage.py migrate python manage.py shell -c "\ from django.contrib.auth import get_user_model;\ User = get_user_model();\ User.objects.create_superuser('admin', 'admin@example.com', 'admin')\ " exec "$@"
nginx
サービスでは基本的にnginx:1.15-alpine
イメージを使いますが、DjangoのuWSGIに接続するための情報が必要なので、このための設定ファイルをdocker buildで埋め込み、コンテナ起動時にdocker-entrypoint.sh
の処理内でパラメータに置換します。Dockerfile
、mysite_nginx.conf
、docker-entrypoint.sh
は以下のような感じです。
# the upstream component nginx needs to connect to upstream django { # server unix:///mysite/mysite.sock; # for a file socket server UWSGI_HOST:8001; # for a web port socket (we'll use this first) } # configuration of the server server { # the port your site will be served on listen 80; # the domain name it will serve for server_name example.com; # substitute your machine's IP address or FQDN charset utf-8; # max upload size client_max_body_size 75M; # adjust to taste location /static { alias /static; } # Finally, send all non-media requests to the Django server. location / { uwsgi_pass django; include /etc/nginx/uwsgi_params; # the uwsgi_params file you installed } }
FROM nginx:1.15-alpine RUN rm -f /etc/nginx/conf.d/* COPY mysite_nginx.conf /etc/nginx/conf.d/mysite_nginx.conf COPY docker-entrypoint.sh /usr/bin/ RUN chmod 755 /usr/bin/docker-entrypoint.sh RUN mkdir /static ENTRYPOINT ["docker-entrypoint.sh"] CMD ["nginx", "-g", "daemon off;"]
#!/bin/sh sed -i "s/UWSGI_HOST/$UWSGI_HOST/g" /etc/nginx/conf.d/mysite_nginx.conf exec "$@"
Webサービスを起動するときは以下のコマンドを叩けばOKです。上がったらhttp://localhost/admin|でDjangoの管理者サイトにアクセスできるはずです。
docker-compose up -d
すべてきれいさっぱり消すときは...(永続データも消えるのでちゅうい)
docker-compose down -v