Edited at

Flask+uwsgi+nginxの環境が作りたい?それ、Dockerなら1コマンドで出来るよ。

Flask使ってアプリケーション作ったのはいいけど、デプロイ面倒くさいなぁって思っている人向け。

$ python run.py 

* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)

Flaskの公式ドキュメント http://flask.pocoo.org/docs/1.0/quickstart/ には


This launches a very simple builtin server, which is good enough for testing but probably not what you want to use in production. For deployment options see Deployment Options.


開発用サーバはテスト用には十分だけど、本番環境では非推奨って書いてあるので、Dockerを使って楽をしようと思った。


TL;DR

https://github.com/lboavde1121/flaskapp

$ make run

上記コマンド1つで、Flask+uwsgi+nginxの環境をDockerに構築します。

読むのが面倒な方は、上のリポジトリをクローンしてmake runしてください。

イメージとしては、

Docker <-> nginx <-> uwsgi <-> Flask

こんな感じ。

気が向いたらお絵かきします。


動作環境


  • MacOS

  • Windows

  • Linux(EC2 AmazonLinux)

で動作確認済み。

※下記ツールversion等はMacOS

今回の主役Docker


  • Docker : 18.03.0-ce

  • Docker-compose : 1.20.1

そしてビルド→起動を1コマンドにするためにmake


  • make : GNU Make 3.81

※Windows10 Pro以外のWindowsはDocker Toolbox使おう。

https://docs.docker.com/toolbox/toolbox_install_windows/


構成

Flask部分(./app/src配下)は大したことしてないので今回触れません。

Githubに全部あげてるのでそちらからどうぞ。

.

├── Makefile
├── README.md
├── app
│   ├── Dockerfile
│   ├── requirements.txt
│   ├── src
│   │   ├── config
│   │   │   ├── __init__.py
│   │   │   └── default.py
│   │   ├── run.py
│   │   ├── server
│   │   │   ├── __init__.py
│   │   │   └── hoge
│   │   │   ├── __init__.py
│   │   │   └── hoge_api.py
│   │   └── tests
│   │   ├── __init__.py
│   │   └── test_hoge.py
│   └── uwsgi.ini
├── docker-compose.yml
└── nginx
├── Dockerfile
└── nginx.conf


docker-compose

初めは、1コンテナで構築しようと思っていたが、nginxとかPythonインストールとか面倒だったのでDocker-composeを使って


  • nginx

  • Flask+uwsgi

上記2コンテナをSocketで繋いだ。

  

以下docker-composeの設定ファイル


docker-compose.yml

version: "3"

services:

uwsgi:
build: ./app
volumes:
- ./app:/var/www/
ports:
- "3031:3031"
environment:
TZ: "Asia/Tokyo"

nginx:
build: ./nginx
volumes:
- ./nginx/nginx.conf:/etc/nginx/nginx.conf
links:
- uwsgi
ports:
- "4231:80"
environment:
TZ: "Asia/Tokyo"


Flaskコンテナ(uwsgi)にapp/*

nginxコンテナにnginx/nginx.confをマウント。

linksは


nginxコンテナ

次はnginxコンテナのDockerfile。


nginx/Dockerfile

# ベースイメージの設定

FROM nginx
CMD ["nginx", "-g", "daemon off;","-c","/etc/nginx/nginx.conf"]

nginx起動のコマンドは「RUN」ではなく「CMD」or「ENTRYPOINT」で起動する。(当たり前だけど)

※「CMD」or「ENTRYPOINT」はここ参考

Flaskとuwsgiで繋ぐためにnginxの設定ファイル(nginx.conf)を書き換える。


nginx/nginx.conf

user  nginx;

worker_processes 1;

error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;

events {
worker_connections 1024;
}

http {
include /etc/nginx/mime.types;
default_type application/octet-stream;

log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';

access_log /var/log/nginx/access.log main;

sendfile on;
#tcp_nopush on;

keepalive_timeout 65;

#gzip on;

upstream uwsgi {
server uwsgi:3031;
}

server {
listen 80;
charset utf-8;

location / {
include uwsgi_params;
uwsgi_pass uwsgi;
}

location /static {
alias /static;
}

location /media {
alias /media;
}
}
}



Flask+uwsgiコンテナ

以下FlaskコンテナのDockerfile


app/Dockerfile


# ベースイメージ
FROM python:3.6

RUN mkdir /var/www
# workdirの指定
WORKDIR /var/www

# 依存Pythonライブラリ一覧コピー
COPY requirements.txt ./

# 依存Pythonライブラリインストール
RUN pip install --no-cache-dir -r requirements.txt

WORKDIR /var/www/src

CMD ["uwsgi","--ini","/var/www/uwsgi.ini"]


Dockerのマウントのタイミングが、

起動時(ビルド時は未マウント)

のようで、ビルド時に必要なファイル(requirements.txt)はビルド時にコピー(Dockerfile内に明示的に記載する)必要がある。

そして、nginxとFlaskを繋ぐuwsgiの設定ファイル。


app/uwsgi.ini

[uwsgi]

wsgi-file = /var/www/src/run.py
callable = app
master = true
processes = 1
socket = :3031
chmod-socket = 666
vacuum = true
die-on-term = true
py-autoreload = 1

py-autoreload = 1

これを書いておくと、ソース修正したときに自動でリロードしてくれる。


Makefile

NAME=flaskapp

run:
docker-compose build
docker-compose up -d

stop:
docker stop ${NAME}_uwsgi_1 ${NAME}_nginx_1
docker rm ${NAME}_uwsgi_1 ${NAME}_nginx_1

これだけ。


さぁ! 1コマンドで実行だ!!


$ make run

docker-compose build
Building uwsgi
Step 1/7 : FROM python:3.6
---> efb6baa1169f
Step 2/7 : RUN mkdir /var/www
---> Using cache
---> 00445d785d14
Step 3/7 : WORKDIR /var/www
---> Using cache
---> 215c53d71716
Step 4/7 : COPY requirements.txt ./
---> Using cache
---> cabb91df7ca0
Step 5/7 : RUN pip install --no-cache-dir -r requirements.txt
---> Using cache
---> 62f2a1a976d4
Step 6/7 : WORKDIR /var/www/src
---> Using cache
---> aaee265830d6
Step 7/7 : CMD ["uwsgi","--ini","/var/www/uwsgi.ini"]
---> Using cache
---> db35ff6f215b
Successfully built db35ff6f215b
Successfully tagged flaskapp_uwsgi:latest
Building nginx
Step 1/2 : FROM nginx
---> b175e7467d66
Step 2/2 : CMD ["nginx", "-g", "daemon off;","-c","/etc/nginx/nginx.conf"]
---> Using cache
---> 036cf8c36459
Successfully built 036cf8c36459
Successfully tagged flaskapp_nginx:latest
docker-compose up -d
Creating flaskapp_uwsgi_1 ... done
Creating flaskapp_nginx_1 ... done


おしまい

実際はもっと設定必要だと思います。

DB等も同じようなノリでいけます。

※追記

最近k8sに手を出しました。とても便利。

とはいえ、開発環境では便利なのでまだまだ現役ですが、、

質問やフィードバックお待ちしています。

Twitter: https://twitter.com/rt_s2t


参考