Docker+Flask=API application
ちょっと触っただけので大した内容ではなくて、各部分の基本構成とロジックをまとめる文章です
何がうれしい
- Dockerは、依頼関係をパッケージ化することができるもので、実行するデバイスを変えても環境設定は要らない(例えAIプログラムを実行するときに必要なモデルとInputも、パッケージ化されている)
WSLは、Windows Subsystem for Linuxで、windowsOSでLinuxを実行するように最適化された仮想マシンです。これでLinuxと同じように使える。
Flask:Python用のウェブアプリケーションフレームワークです。PythonだけでAPIを構築できる。
環境設定
一番苦労するところかも。。。
WSL2
ここは特に記憶はないから、多分難しくない
Ubuntu
普通のネットワークの下のならAppStoreから簡単に落とせるが、例えばセキュリティでStoreが使えない場合には下のリンクを参考すればいい
WSL2にUbuntuをインストール | ソフトウェア Tech Tips (softtechtips.net)
Docker
windowsにWSL2+Docker環境を構築する手順 #Windows - Qiita
整理してみて。。。
- Flask+Pythonの実行プログラム完成
- Dockerfileで依頼関係を定義して、必要なInputを一つのフォルダにまとめる
- ローカルのポートをWSL上にForwardingして、WSLのIPアドレスを固定する
- 必要な外部ファイルをマウントして、DockerContainerを実行する
Flask
基本構成
from flask import Flask, request, jsonify |
@
マーク:デコレーターです。下の関数を引数として受け取る。ここの
@app.route
はFlaskのルーティングデコレーターで、ユーザの関数と特定のURLをマッピングしていて、/predict
にPOSTリクエストが来ると、Flaskは自動的にpredict
関数を呼び出す。- Note:”/predict”と“/predict/”は異なるルート
request.<extract_method>[Info]
クライアントのリクエストは、一般的にはURL情報だけではなくて、Inputの情報もある。(E.g.例えば天気APIに請求を送るときにも、いつDayの情報が欲しいかも伝える必要がある)。そのような追加情報を抽出するために、Flaskにはrequestというツールを用意している。書き方によっていろんな抽出方法があるので、具体的には:flask.request 自分用チートシート #Python - Qiita
app.run(host='0.0.0.0', port=5000)
指定されたポートに送られた情報だけを受け取る。0.0.0.0はすべてのアドレスをリッセンすることを示す。一台のPCは基本的は
- ホストアドレス(ipconfigを打って出たIP、外部からアクセス可能)
ローカルアドレス(localhostやほかのプライベートアドレス、外部アクセス不可)
のように、複数のIPアドレスを保有します。
テスト方法
cURL:さまざまなプロトコルを利用してデータ転送するコマンドラインツール
これがあればコマンドラインだけでFlaskの動作を確認できる
curl -X POST http://localhost:5000/predict -H "Content-Type: application/json" -d '{"path": "example.jpg"}'
-X POST/GET <URL:port>
: POSTまたはGETメソッドで指定したURLに情報を送る- ポートを一致しないと受け取れない
Dockerfile
Dockerの流れは以上のように、実際に動くコンテナは全く独立している容器だ。その中にあらかじめ、必要とする依頼関係(Python、pytorch…)、作業用のフォルダ(/app)、外部のファイルを作業用フォルダにコピーする(model…)
Containerで動くプログラムは外部に一切アクセスできないと考えてもいいかな
# ベースとなるイメージの指定 |
ベース:
Pythonだけを使って軽量なAPPならPythonをベースとしたDockerは十分
でも実際に使うときにUbuntuをベースとするケースが一番普通のらしい。区別はGPT先生に聞いた:
python
イメージは、Python アプリケーションに特化した環境であり、すぐに開発を開始できる軽量なベースイメージです。ubuntu
イメージは、汎用的な Linux システムで、環境を細かくカスタマイズしたい場合に適していますが、セットアップに手間がかかる場合があります。FROM ubuntu:20.04
RUN apt-get update && apt-get install -y python3 python3-pip
っと、自分もまだ理解していないです。。。
ノート:Ubuntuを利用する場合には、Python3.9は一番最後にサポートされるバージョンで、3.10以上をインストールしたいなら別のコードを追加する必要がある
WSL2
WSL2は、windowsOSと完全に異なる別のOSとして存在する仮想マシン。
なので、独立したIPアドレス、ファイルシステムを保有する。これでwindows側で書いたコードはここで動けない可能性がある。
IPアドレスの処理
参考:Windowsでwsl2(Ubuntu)上のDockerに外部から接続する #Windows10 - Qiita
- ローカルのIPアドレス上のポートを転送する
- WSL2のIPアドレスを自動で取得する(自動化しないと再起動するたびに転送する用のコマンドが変わる)
WSLのIPアドレスを確認
hostname -I
手動で転送を設定する
# ローカルPCのポートXXXXに来たパケットをwsl2のポートXXXXに転送(XXXXはDockerで使用するポート番号) |
自動化
#rootで実行 |
これで自動化したスクリプトはできたが、毎回管理者としてPSを実行して、スクリプトを開くのもめんどくさいし、さらに自動化した:
- ショットカートを作成する
- パス=
powershell -ExecutionPolicy Bypass -File "path_to_your_script.ps1"
- プロパティ➝ショットカート➝詳細➝管理者として実行☑
これで、ショットカートをクリックするだけでポート転送の設定は完了
ファイルシステム
ローカルに保存されている内容は/mnt/
で確認できる。(GUIによるアクセスできない)
アクセスするために
- DockerfileにCOPYを用いて作業フォルダにコピーしておくか
- docker containerを動かすときにファイルをマウントする:
docker run -v <local_file_path>:<workplace_path>
Dockerの実行
いよいよ最後だ。いくつかのDockerコマンドを知っておくべき。
Dockerサービスの開始、停止、再開(デフォルトは停止の状態)
sudo service docker status
sudo service docker start
sudo service docker restart
Dockerイメージをビルトする
build -t <image_name> <path_to_docker_folder>
イメージの一覧と削除
docker images
docekr rmi <images_id>
イメージでコンテナーを起動
docker run <options> <image_name>
--rm
: automatically remove the container when it stop-it
: interact with container-d
: detach mode (run in background)-p <host_port>:<container_port>
:ホストのポートをコンテナ内のポートに転送する(コンテナと外部は分離している)--gpus <numbers/all>
: use gpu to runshrconta
コンテナーの操作:一覧、停止、削除
docker ps -a
docker stop <container_id>
docker rm <container_id>
起動して、テストコマンドをローカル環境で実行して、responseが届いたら成功
以上。
追記
興味でAPIの動き方をもう少し調べた。FlaskAPIは確かにウェブアプリケーションとして動けるが、多数のリクエストが殺到すると対応できなくなる。また、セキュリティー問題もあります。
そのため、ウェブサーバーソフトを追加する必要がある(Apache、IIS)。それらとFlaskを合わせて利用するのは一般です。
あと、基本的には外部から内部アドレスにアクセスするのはできない(会社からHomePC)。それを実現したいなら、ルータのポートフォワーディングを設定するか、VPNを構築するか、が必要です。