DockerでFlaskが動き、簡単なテストが通る状態を作る(Flaskで簡単なWebサービスを作ってみる[第3回])
はじめに
PythonのWebアプリケーションフレームワークFlaskを使って、「消耗品買い物リスト」を作ってみます。
ついにFlaskのコードを書き始めました。
前回まで
- 0回 : Flaskで簡単なWebサービスを作ってみる
- 1回 : スプレッドシート+Google Apps Scriptでプロトタイプを作る
- 2回 : FigmaでUI制作をしてみたが早々に次のフェーズに進んだ件
環境構築(Docker+Flask)
本記事のテーマは環境構築です。
本プロジェクトでは、アプリケーションフレームワークとしてFlaskを使いますが、開発環境にDockerを使ってみることにしました。
Dockerとは
一言でいうと手軽に仮想環境を構築できるサービスです。
VitrualBoxなどのVMとの違いとしては、VMが環境をまるごとホストOSの上に構築して動かすのに対し、Dockerでは、OSはホストOSのものを使いつつ、その上に必要な部分だけ構築する点です。
メリットとしては環境の構築・破棄が非常に手軽に行える点、設定ファイルを共有することで同一環境の再現ができる点です。「環境構築に半日かかる」や「環境が違うからバグが再現できない」のようなめんどくさい課題を解決してくれるサービスです。
上記メリットを認識しつつも、これまでちゃんと使ったことは無かったため、この機会にガッツリと触ってみようと思います。
Flaskとは
Pythonで動く軽量なWebアプリケーションフレームワークです。
Web開発で必要な機能群から、最小限のものを提供してくれています。
同じPythonのWebアプリケーションフレームワークであるDjangoと比較し、機能を絞った分軽量で、セットアップが楽だという利点があります。
本プロジェクトでは、素早くサービスを構築したい点と作るものがシンプルな買い物リストである点から、Flaskを採用します。
環境構築の進め方
本記事のゴールは、「ローカルにDockerコンテナを作成し、コンテナ上でFlaskを動かしてWebページを表示すること」とします。
Dockerのインストール
Docker公式サイトから。
Dockerfileの作成
最小構成の設定にしておきます。プロジェクトディレクトリ直下に保存。
Dockerfile
# ベースイメージ作成
FROM python:3.7
# pipアップグレード
RUN pip install --upgrade pip
RUN pip install flask
# 作業ディレクトリ指定
WORKDIR /workdir
# 公開ポート指定
EXPOSE 8080
Dockerイメージの作成
ログインしてビルドします。コマンド実行はプロジェクトディレクトリ直下にて。
$ docker login
$ docker build -t flask-app .
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
flask-app latest 619c347dc0dd 10 seconds ago 929MB
python 3.7 22c70bba8283 2 days ago 920MB
Dockerコンテナの作成
共有用フォルダ作成
コンテナで共有するための作業ディレクトリを作っておきます。
$ mkdir src
コンテナを起動して入る
$ docker container run -it -p [Host Port]:[Guest Port] -v [共有用フォルダのパス]:[コンテナ内の絶対パス] --name [コンテナ名] [イメージ名] /bin/bash
例
$ docker container run -it -p 8080:5000 -v ~/Developments/to-buy-list/src:/workdir --name to-buy-list flask-app /bin/bash
root@a25d6b02fc8b:/workdir#
root@a25d6b02fc8b:/workdir# pwd
/workdir
-pオプション
ホストOSのポートをコンテナのポートにマッピングします。
これで、ホストOSでlocalhost:8080にアクセスしたときに、コンテナの5000(Flaskのデフォルトポート)につながります。
マッピングはrun時にしか設定できないらしく、
設定を忘れるとrunし直しになりますので注意してください。(参考)
-vオプション
コンテナ内の/workdirの中身と、ホストOSの作業用ディレクトリの中身を同期しています。
コンテナを抜けるとき
コンテナを抜けるときは以下のコマンドを使い分けます。
- control + d : コンテナを停止して抜ける(exit)
- control + p -> control + q : コンテナを起動したまま抜ける(detach)
次回以降は
$ docker start to-buy-list # 起動
$ docker exec -it to-buy-list bash # 入る
でコンテナに入ります。
エラー
runコマンド実行時にこんなエラーが。
docker: Error response from daemon: OCI runtime create failed: container_linux.go:349: starting container process caused "exec: \"bin/bash\": stat bin/bash: no such file or directory": unknown.
ただのタイポでした… : bin/bash => /bin/bash
ちなみにこのとき、コンテナ自体は作られているので、$ docker rm [container_id]
で一度コンテナを削除してやり直すか、execコマンドで入りましょう。
ファイルの同期・配置(VSCode : Remote Containerのインストール)
コンテナ内のファイルを編集するのに、VSCodeのRemote Containerを使います。
大まかな流れとしては:
- VSCodeのプラグインでRemote – Containersをインストール
- コンテナと接続
- 必要な拡張機能をインストール
- Python
- Linter など
- デバッグ→実行ができることを確認
- ブレイクポイントの設定なども
詳しくは以下の記事をご参照ください。
DockerでPythonの開発環境を作成してみる その2 – ITエンジニア日記 ~NO SKILL, NO LIFE~
Flaskの起動・表示確認
アプリケーションの作成
Hello, worldするだけの簡単なアプリを書きます。
一旦/workdir配下に配置します。
app.py
from flask import Flask
app = Flask(__name__)
@app.route('/')
def index():
return "Hello world!"
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000)
テストの作成
ついでにただ通るだけのテストも書いておきます。
test_app.py
import os
import app
import unittest
import tempfile
class AppTestCase(unittest.TestCase):
def test_do(self):
self.assertEqual(1,1)
if __name__ == '__main__':
unittest.main()
動作確認
先にテストを動かしてみます。
root@1caa75e54efb:/workdir# python -m unittest test_app.py
.
----------------------------------------------------------------------
Ran 1 test in 0.000s
OK
当然通ります。
次にFlaskを起動してWebページで表示します。
root@1caa75e54efb:/workdir# python app.py
* Serving Flask app "app" (lazy loading)
* Environment: production
WARNING: This is a development server. Do not use it in a production deployment.
Use a production WSGI server instead.
* Debug mode: off
* Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
ブラウザでhttp://localhost:8080
にアクセスすると、無事「Hello world!」が表示されました。
未解決 : ソースコードの変更がリアルタイムに反映されない問題
現状では、Flaskを動かしたまま、ソースコードの内容を書き換えても反映されず、Flaskを起動し直す必要があります。
コンテナを使わずローカルでFlaskを実行したときも同じ挙動のため、コンテナではなくFlask側の仕様のようです…
終わりに
本記事では、「Dockerイメージを作成し、コンテナを起動してその上でFlaskを動かし、Webページで表示されることを確認する」までを行いました。
次回は本番環境へのデプロイを行います。
ディスカッション
コメント一覧
初めまして、最近嫁からの要望で
買い物リストをWeb化+Google HomeやAmazon Echoから音声で追加できるように
Flaskを用いた買い物リストアプリの開発を進めています。
既にTodoMVCというフレームワークをFlask上で用いて、
これからAPI周りを触る予定ですが、
管理者様の技も盗めないかと思い楽しみにブログを拝見させていただいております。
記事内にありました、
> 未解決 : ソースコードの変更がリアルタイムに反映されない問題
こちらについては、FlaskのDebugモードをTrueにしていないためと思われます。
起動時に有効にすることによってソースコードを更新した度に自動読み込みを行ってくれます。
※当方はDocker環境ではなく、VMware上にある仮想マシンで動いているUbuntuへVSCode : Remote Containerで接続しているため、絶対とは言えません。。。
ぜひ、ご参考にしていただければ幸いです。
https://a2c.bitbucket.io/flask/quickstart.html
高橋さん
コメントありがとうございます!
そして未解決問題の解決策の共有ありがとうございます!試してみます。
> 管理者様の技も盗めないかと思い楽しみにブログを拝見させていただいております。
とても嬉しいのですが、最近全く触れておらず申し訳無いです…
ようやく仕事が落ち着きそうなので、また更新再開したいと思います。
引き続きよろしくおねがいします。