Docker+Apacheでシステムを汚さずにFlaskアプリを公開するメモ

2024年3月9日

Pythonで作った自作のラインボットを公開する際に、システムのPythonにpipインストールして後悔したことがあるのでDockerで公開すればシステムを汚さずに公開できることを知ったのでメモ

この記事でできること:
・ホストOSのPython環境を汚さずにアプリを公開する
・dockerコンテナで動作しているFlaskアプリをリバースプロキシ経由で外部へ公開する

具体的には、ホストOSのApacheに来たアクセスを、
dockerコンテナ内で動作するnginxへプロキシしてアプリを公開する
要するにこれはリバースプロキシの設定をnginxのconfに記述する

これにより、ホストOS側の設定としてはapacheのバーチャルホスト設定を追加するだけでアプリを公開できる

アプリ用に無駄に443以外のポート開放する必要がないのもメリット


前提:Almalinuxで環境構築 (他のCentOSとかのディストリビューションも多分流れは一緒)

Dockerインストールと起動

# dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
# dnf -y install docker-ce docker-ce-cli containerd.io
# systemctl start docker
# docker --version
Docker version 20.10.17, build 100c701

Dockerコンテナ作成とコンテナ起動

sudo docker run -it --name {適当につけたコンテナ名} -p 1000:80 {イメージタグ} bash

イメージは自分のアプリに合わせて好きなものを使う

-pオプションでホストの1000番ポートでDockerコンテナを動作させ、
Dockerコンテナ内のnginx80番ポートへ接続する(ホストOSの80番とは関係ない)
1000番は外部に開いていない他の任意のポートでOK

Apacheで外部アクセスをコンテナ内Nginxにつなげる

Apacheのインストール方法は省略

Apacheのバーチャルホスト設定で外部から来たアクセスをdockerコンテナ内のnginxへつなげる設定
以下のProxyPassでhttp://app.example.com/にきたアクセスをローカルホスト1000番(Dockerコンテナ)に渡している
これをApacheのconfファイルに追記

<VirtualHost *:80> # ← 443でもOK
    ServerName app.example.com
    ProxyRequests Off
    ProxyPass / http://localhost:1000/
    ProxyPassReverse / http://localhost:1000/
</VirtualHost>

mod_proxyが必要なので適宜有効化

以上の設定により、
apache(80番ポート) → Dockerコンテナ(1000番ポート) → コンテナ内nginx(80番ポート)
のように処理を流せる

あとはコンテナ内でFlaskアプリを外部公開するように設定すれば完了

自分のdockerコンテナ内のnginxの設定とuwsgi.iniをメモ

# nginx.conf

server {
    listen       80;
    server_name localhost;

    location / {
        include uwsgi_params;
        uwsgi_pass unix:///tmp/uwsgi.sock;
        proxy_pass http://127.0.0.1:9999/;
    }
}
# uwsgi.ini

[uwsgi]

wsgi-file=/linebot/app.py
callable=app

http=0.0.0.0:9999

socket=/tmp/uwsgi.sock
module=app
chmod-socket=666

daemonize=/linebot/uwsgi.log

コンテナ内部では、80番ポートで受け取ったリクエストを9999番で動作しているuwsgiにリクエストを渡している
詳細は別のnginx+uwsgiでアプリを外部公開しているサイトを参照していただきたい
これとか (Nginx + uWSGI + Flaskによるwebアプリの構築)

以上

ホストのApacheを生かしたいが為に周りくどい方法になったような気がしますが、
もしもっと単純にできるよって言う場合はぜひ教えていただけるとありがたいです