ConoHa VPSでbottle
前回
に引き続き、VALUE SERVERからConoHa VPSに移行して動かなくなってたところを直していきます。今回はコレですね。
bottleです。Hello, worldしただけなんですけどね。VALUE SERVERではpython3自体がインストールされていたので、Apacheのmod_cgiを使い、CGIでpythonを起動して動かしていました。
これを今回はdockerコンテナ上のnginxからWSGIで別のdockerコンテナ上のpythonに繋ぎ、bottleを動かします。まあ最近bottle聞かなくなりましたけど。。。
bottleの設置
サブドメインの追加
せっかくnginxのリバースプロキシ置いて、dockerコンテナで分離しているので、いつでもサーバーを動かせるようにサブドメインで動かします。ConoHaのDNSでpythonというCNAMEレコードを追加しました。ドメインはpython.elephantcat.workになります。
タイプ | 名称 | TTL | 値 |
---|---|---|---|
CNAME | python | 3600 | elephantcat.work |
関連記事
SSL証明書の取得
Let’s Encryptで先程追加したサブドメイン(python.elephantcat.work)のSSL証明書を取得しました。certbotのあるディレクトリで以下のファイルを作成して…
DOMAIN="python.elephantcat.work"
EMAIL="更新通知を受け取りたいメールアドレス"
登録用のシェルスクリプトを実行しました。
$ bash register.sh python
成功すると「Congratulations! Your certificate and chain have been saved at:」と表示されて、証明書の位置を教えてくれます。
関連記事
nginxの設定追加
コンテナの修正
nginx用のdocker-compose.ymlを以下のように修正し、hostにmountするディレクトリとファイルを追加しています。
...
services:
nginx:
...
volumes:
...
- ./../python/html:/var/www/html_python
- ./python.conf:/etc/nginx/conf.d/python.conf
...
./../python/htmlは、https://python.elephjantcat.work/用の静的ファイルのルートフォルダです。mkdir ./../python/htmlしておきます。
./python.confは、https://python.elephjantcat.work/bottle用のnginx設定ファイルです。
設定増えてきたので、そろそろconf.dからマウントした方がいいかもしれません。
nginxの設定追加
先ほど追加したpython.confの中身です。
server {
listen 443 ssl;
server_name python.elephantcat.work;
ssl_certificate /etc/letsencrypt/live/python.elephantcat.work/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/python.elephantcat.work/privkey.pem;
location / {
root /var/www/html_python;
index index.html index.htm;
}
location /bottle {
resolver 127.0.0.11 valid=30s;
include uwsgi_params;
set $variable python;
uwsgi_pass $variable:3031;
}
}
/bottle以下のリクエストはpythonという名前のホストのポート3031にwsgiで転送しています。
resolverが設定されていたり、ホスト名が$variable経由になっていたりするのは、名前解決できないときにサーバーごと落とさないための配慮です。
起動確認
これだけの設定で、ホストpythonがいなくてもnginxは起動するので、確認しました。
$ docker-compose up -d
この時点でhttps://python.elephantcat.work/bottleにアクセスすると、502 Bad Gatewayを返します。
pythonコンテナ追加
docker-compose.yml
version: '3'
services:
python:
image: python
restart: always
volumes:
- ./python:/home/python
- ./initial_data:/home/initial_data
networks:
- frontend
entrypoint: /home/initial_data/docker-entrypoint.sh
networks:
frontend:
external: true
※2021/10/17 リブート時に自動起動しない不具合が見つかったので restart: always
追加
イメージはpythonの公式最新イメージを使います。マウントは2箇所で、./pythonと./initial_dataです。./pythonは実行環境を実際に作成する場所で、最初は空です。./initial_dataにあるデータとスクリプトを使って、実行環境を構築します。実際に動かすスクリプトはdocker-entrypoint.shです。
docker-entrypoint.sh
./initial_data/docker-entrypoint.sh
#!/bin/sh
if [ ! -f /home/python/bottle/env/bin/uwsgi ]; then
cd /home/python
mkdir bottle
cd bottle
python3 -m venv env
. env/bin/activate
pip install -U pip
pip install bottle uwsgi
cp -p /home/initial_data/uwsgi.ini .
cp -p /home/initial_data/app.py .
cd ..
chown -R 1000:1000 .
fi
exec /home/python/bottle/env/bin/uwsgi /home/python/bottle/uwsgi.ini
※このファイルは実行可能属性が必要です(chmod u+x initial_data/docker-entrypoint.sh)
/home/python/bottleにvenvの実行環境を作成し、pipでbottleとuwsgiをインストールしてuwsgiを起動しています。既にインストールされている場合はインストールがスキップされます。
uwsgiはWSGIなどのインターフェースを実装したサーバーで、pythonなどで書かれたWSGIアプリを動かせます。上のスクリプトで、uwsgi.iniがuwsgiの設定ファイルで、app.pyがpythonで書かれたWSGIアプリになります。既にインストールされている場合にvenvのactivateがされていませんが、venv環境のpipでインストールされたuwsgiを使っているので、activateしなくてもvenv環境が使用されます。
uwsgi.ini
https://uwsgi-docs.readthedocs.io/en/latest/WSGIquickstart.html
この辺を参考に、以下のような設定にしています。
./initial_data/uwsgi.ini
[uwsgi]
socket = :3031
uid = 1000
gid = 1000
chdir = /home/python/bottle
wsgi-file = app.py
#master = true
最初にポートの指定、次がユーザーとグループの指定(rootだと危険と怒られるため適当に設定)、実行ディレクトリとあとアプリの指定だけです。masterを指定すると、落ちたときなどに再起動などを期待できますが、その分余計にメモリを食うので、実験用のアプリしか動かさない今の環境では不要と判断してコメントにしています。
app.py
./initial_data/app.py
from bottle import route, default_app
@route('/bottle')
def hello():
return 'Hello, World!'
application = default_app()
https://python.elephantcat.work/bottleにアクセスされたら、Hello, World!を返すだけのアプリです。bottleを使った今回のプログラム本体です。
起動
$ docker-compose up -d
確認
https://python.elephantcat.work/bottle
できてる模様。
まとめ
Apache -> CGI -> bottleからnginx -> WSGI -> bottle(かつdocker使用)に書き換えることが出来た。
次回は同様の作業をdjangoでやる予定。
ディスカッション
コメント一覧
まだ、コメントがありません