当サイトは、アフィリエイト広告を利用しています

【Docker × Flask】コンテナでFlask製のREST APIを実装する~基本~

作成日:2024月03月09日
更新日:2024年04月16日

Pythonの軽量フレームワークであるflaskの開発環境を
dockerを使ってコンテナで構築し、VScodeからコンテナ内で flask製の基本的なREST APIを実装、動作させる方法をまとめる

この記事を読めばflaskでREST API開発をする際、基本となる

  • 開発環境構築
  • REST API実装
  • サーバー起動
  • 動作確認
  • デバッグ方法

が理解できると思う。

今回はコンテナはflask製のREST APIの開発環境として使うので、
コンテナデプロイは行わない。
※そのうちコンテナデプロイについても試してみる

作成するflask製のREST APIについて

作成するflask製のREST APIはどんなものかを
先にまとめておく。

APIのルート実装方法

flask製のREST APIのルートの実装方法には
下記の二つがある。

  • 関数ベースのルート
  • クラスベースのルート

今回は両方のパターンを実装する

またFlaskのREST APIを効率的に実装するためのライブラリである
「Flask RESTful」を使って実装することもできる

「Flask RESTful」での実装については下記記事でまとめています

関数ベースのルート

関数ベースのルート実装は下記のようになる。

関数ベース
from flask import Flask
# flaskアプリケーションインスタンス作成
flask_api = Flask(__name__)
@flask_api.route('/')
def hello():
return "Hello from Flask!!!"

関数ベースのルート実装は直観的で見やすい

クラスベースのルート

クラスベース
from flask import Flask
from flask.views import MethodView
# flaskアプリケーションインスタンス作成
flask_api = Flask(__name__)
class HelloAPI(MethodView):
def get(self):
return "Hello from Flask!!!"
flask_api.add_url_rule('/', view_func=HelloAPI.as_view('hello_api'))

クラスベースのルーティングはより複雑なロジックや複数のHTTPメソッド(GET、POST、PUT、DELETEなど)を
同じクラス内で処理する場合に便利に使える。

大規模なアプリケーションや複雑なルーティングロジックを扱う場合、
クラスベースのルートはコードの再利用しやすいと思う。

実装するHTTPメソッドに対応した処理

作成するREST APIはHTTPメソッドの

  • POST:登録
  • GET:参照
  • PUT:更新
  • DELETE:削除

を受け付けるように作る
※REST APIなので

また

  • パスパラメータ
  • クエリパラメータ(URLパラメータ)
  • JSON形式データ

が含まれたHTTP通信が来た場合の送受信も実装する

パスパラメータやクエリパラメータについては下記記事で書いている。
REST APIの基本的なことについてもまとめているのでご参照ください。

REST APIを起動するサーバー

flask製のREST APIを動かすためのサーバーだが
flaskには簡易的な内部サーバーが付属しているので
それで動かすことにする。

外部サーバーであるGunicornを使う方法もある。
Gunicornで動かす場合の方法は下記記事でまとめています

dockerコンテナの作成について

VSCodeとDockerを使ったflaskの開発環境構築時の
Dockerコンテナの作成は

  • docker-composeを使ってコンテナ作成
  • VSCodeの拡張機能Dev Containersを使ってコンテナ作成

の2パターンで行うことができる。

また開発環境内のflask製のREST APIを
dockerのどこで永続化するかについても

  • バインドマウント
  • 名前付きボリュームを使う

の2パターンがある

今回は、上記の方法のうち

  • コンテナ作成はdocker-compose
  • 永続化はバインドマウント

で行っていく。

またdockerコンテナの永続化を行うvolumeの設定について詳しくは下記記事参照

コンテナ作成はdocker-compose

docker-composeコマンドで作ったコンテナに VScodeからアタッチする形になる。

その際にVSCodeの拡張機能であるDevcontainerを使う。
使い方については下記記事で紹介しています

環境

下記の環境で行う

  • Windows10
  • Docker version 24.0.2(Docker for Windows)
  • VScode
  • Remote Development(VScodeの拡張機能)
  • Docker for Windows
  • Flask 3.0.2

Docker for Windowsのインストール方法については下記記事で 紹介しています

構成

全体的な構成は下記のようになる

bash
|-- .env
|-- .vscode
| |-- launch.json
| `-- tasks.json
|-- Dockerfile
|-- api
| |-- __init__.py
| |-- api.py
| `-- wsgi.py
|-- docker-compose.yml
|-- requirements.txt
`-- vscode_ex_install.sh

開発環境関連ファイル

FlaskのREST APIを開発するためのコンテナ環境を作るためのファイル

  • .env
  • Dockerfile
  • docker-compose.yml
  • requirements.txt

詳細は後述する

VScode関連ファイル

下記がVSCodeの機能を使うための設定ファイルになる

  • launch.json
  • tasks.json
  • vscode_ex_install.sh

詳細は後述する

REST API関連ファイル

下記がFlaskのREST APIの実装ファイルになる

  • api.py
  • wsgi.py

詳細は後述する

開発コンテナ作成

dockerを使ってFlaskのREST APIを実装し、実行するための
コンテナを作成する。

上記でも記載したが、コンテナの作成自体はdocker composeコマンドで
行い、VScodeの拡張機能を使って作成したコンテナにアタッチして実装する

コンテナ作成ファイルの詳細

docker composeを使ってコンテナ作成するので
コンテナ作成するためのファイルについて解説する

.env

.env
FLASK_APP=api.wsgi:api # Flaskがどのアプリケーションを実行するか指定(パッケージ.モジュール:flaskインスタンス)
FLASK_ENV=development # Flaskがどの環境で動作するか指定
FLASK_DEBUG=true #デバッグモードの指定
# PYTHONPATH=/workspace/api #Pythonがモジュールを検索するためのパスを指定

Flaskアプリケーションの設定や動作を制御するための環境変数を設定する

PYTHONPATHにPythonがモジュールを検索するためのパスを指定する。
指定するとPythonがモジュールを探す際に、この環境変数で指定されたパスを優先的に検索するようになる
PYTHONPATHに「/workspace/api」を追加しておかないと
flask run実行時にflaskインスタンスを見つけられずエラーになる。

「FLASK_APP=wsgi:api」についてはwsgi.pyはapiディレクトリ配下にあるが
PYTHONPATHに「/workspace/api」を設定しているため、apiディレクトリの記載は不要になる

__init__.pyを作成すればPYTHONPATHの設定は不要でした。

Dockerfile

Pythonの環境をセットアップし、必要な依存関係をインストールするDockerイメージを作成する

Dockerfile
FROM python:3.12
# workspaceディレクトリ作成、移動
WORKDIR /workspace
# プロジェクトディレクトリにコピー
COPY requirements.txt /workspace
# 必要モジュールのインストール
RUN pip install --upgrade pip
RUN pip install -r requirements.txt

requirements.txtを読み込み必要なパッケージをインストールする

docker-compose.yml

docker-compose.yml
version: "3"
services:
sample-api:
container_name: "sample-api"
build:
context: .
dockerfile: Dockerfile
ports:
- "5000:5000"
volumes:
# バインドマウント
- .:/workspace
# 環境変数読み込み
env_file:
- .env
tty: true
  • DockerfileをbuildしたDockerイメージを元にコンテナを作成
  • volumeはバインドマウントにする
  • 環境変数を.envから読み込み設定する

requirements.txt

インストールするパッケージを設定

requirements.txt
Flask==3.0.2

必須なのはFlaskのみ

コンテナ作成実行

実際にコンテナを作っていく。
「Docker for Windows」を起動しておく。
※起動しておかないとできないので

コンテナ作成
$ docker compose up -d
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
c9050742de6a flask-sample-restapi-sample-api "python3" About a minute ago Up About a minute 0.0.0.0:5000->5000/tcp sample-api

「docker ps」コマンドで作成できていることも確認しておく。

コンテナにアタッチする

拡張機能を使ってコンテナにアタッチする 2024-03-09-00-35-32

アタッチするとコンテナの画面が開く
2024-03-09-00-37-24

永続化をバインドマウントにしているので
「docker compose」を実行したディクショナリ配下が
コンテナにコピーされている

またコンテナ内での変更はホスト側にも反映される。

必要な拡張機能をインストールする

「docker compose」を使ってコンテナを作成した場合
拡張機能はインストールされないので、スクリプトを使って
インストールする

vscode_ex_install.sh

vscode_ex_install
#!/bin/bash
# 拡張機能のIDリスト
extensions=(
"ms-python.python"
"ms-python.vscode-pylance"
"ms-python.debugpy"
"mhutchie.git-graph"
)
# 各拡張機能をインストール
for extension in "${extensions[@]}"; do
code --install-extension $extension
done

このスクリプトを実行することで
拡張機能がインストールされる

詳しくは下記記事でまとめています

REST APIの実装

開発環境が構築できたのでREST APIを実行していく。

api/__init__.py

中身は空白でOK
apiをパッケージとして認識させるために作成

api/wsgi.py

flaskのREST APIを起動するためのファイル

wsgi.py
# flaskインスタンスをimport
# apiパッケージ.apiモジュール.apiインスタンス
from api.api import api
if __name__ == "__main__":
# flaskサーバーを起動
api.run()

wsgi.pyは本番環境でのデプロイメントにおいて、WSGI互換のサーバー(例えばGunicornやuWSGIなど)と
アプリケーションを接続するために使用される
※wsgi.pyはWSGIサーバーがアプリケーションオブジェクトを認識するためのエントリポイントとして機能し、
多くのサーバーとフレームワークがこのファイルをデフォルトで探しにくる。

開発中やテスト段階ではwsgi.pyを使わずにFlaskの内部サーバーを直接起動することもできる(むしろそっちが主流)が
本番環境にデプロイ前には作る必要はあるので、Flaskの内部サーバーもwsgi.py経由で起動させておく

api/api.py

flaskのREST APIのルーティングと処理を実装している
一旦、全体を載せる。

api.py
from flask import Flask, request, jsonify
from flask.views import MethodView
import copy
# flaskインスタンス作成
api = Flask(__name__)
# ディクショナリ
users = [
{"user_id": "1", "name": "tujimura", "age": 11},
{"user_id": "2", "name": "mori", "age": 20},
{"user_id": "3", "name": "shimada", "age": 50},
{"user_id": "4", "name": "kyogoku", "age": 70}]
# 関数ベースのルーティング
# 取得
# HTTPリクエストにクエリパラメータあり
# 全件取得 or ageフィルタリング
@api.route('/functionalBase', methods=['GET'])
def get_users():
# GETリクエストを処理
age = request.args.get('age')
if age:
return jsonify(list(filter(lambda user: user['age'] == int(age), users)))
return jsonify(users)
# 登録
# HTTPリクエストからJSONを受け取る
# JSONデータを新規登録
@api.route('/functionalBase', methods=['POST'])
def post_user():
# POSTリクエストを処理
data = request.get_json()
res_users = copy.deepcopy(users)
res_users.append(data)
return jsonify(res_users), 201
# 更新
# HTTPリクエストにパスパラメータあり
# パスパラメータをkeyにしてJSONデータで更新
@api.route('/functionalBase/<user_id>', methods=['PUT'])
def put_user(user_id):
# PUTリクエストを処理
data = request.get_json()
res_users = copy.deepcopy(users)
res_users = list(map(lambda user: user.update(data) or user if user['user_id'] == user_id else user, res_users))
return jsonify(res_users)
# 削除
# HTTPリクエストにパスパラメータあり
# パスパラメータをkeyにして削除
@api.route('/functionalBase/<user_id>', methods=['DELETE'])
def delete_user(user_id):
# DELETEリクエストを処理
res_users = list(filter(lambda user: user['user_id'] != user_id, users))
return jsonify(res_users)
# クラスベースのルーティング
class UserAPI(MethodView):
# 取得
# HTTPリクエストにクエリパラメータあり
# 全件取得 or ageフィルタリング
def get(self):
age = request.args.get('age')
if age:
return jsonify(list(filter(lambda user: user['age'] == int(age), users)))
return jsonify(users)
# 登録
# HTTPリクエストからJSONを受け取る
# JSONデータを新規登録
def post(self):
data = request.get_json()
res_users = copy.deepcopy(users)
res_users.append(data)
return jsonify(res_users), 201
# 更新
# HTTPリクエストにパスパラメータあり
# パスパラメータをkeyにしてJSONデータで更新
def put(self, user_id):
data = request.get_json()
res_users = copy.deepcopy(users)
res_users = list(map(lambda user: user.update(data) or user if user['user_id'] == user_id else user, res_users))
return jsonify(res_users)
# 削除
# HTTPリクエストにパスパラメータあり
# パスパラメータをkeyにして削除
def delete(self, user_id):
res_users = list(filter(lambda user: user['user_id'] != user_id, users))
return jsonify(res_users)
# クラスベースのビューを関数ベースのビューに変換
user_view = UserAPI.as_view('user_api')
# エンドポイントを設定
api.add_url_rule('/classBase', view_func=user_view, methods=['GET',])
api.add_url_rule('/classBase', view_func=user_view, methods=['POST',])
api.add_url_rule('/classBase/<string:user_id>', view_func=user_view, methods=['PUT', 'DELETE'])

ディクショナリに対して、参照、登録、更新、削除を行うAPIを実装した
動きを見やすいように、それぞれのhttpメソッドの関数は編集後ディクショナリをjsonで返却するようにした。
※敢えて元のディクショナリは変更しないようにしている。

実際にすることはないと思うが、動作を見るため

  • 関数ベースのルート
  • クラスベースのルート

の両方の書き方でルートを書いている。

関数ベースルートについて

関数ベースルートの実装部分について解説する

api.py(関数ベースルート部分)
# 関数ベースのルーティング
# 取得
# HTTPリクエストにクエリパラメータあり
# 全件取得 or ageフィルタリング
@api.route('/functionalBase', methods=['GET'])
def get_users():
# GETリクエストを処理
age = request.args.get('age')
if age:
return jsonify(list(filter(lambda user: user['age'] == int(age), users)))
return jsonify(users)
# 登録
# HTTPリクエストからJSONを受け取る
# JSONデータを新規登録
@api.route('/functionalBase', methods=['POST'])
def post_user():
# POSTリクエストを処理
data = request.get_json()
res_users = copy.deepcopy(users)
res_users.append(data)
return jsonify(res_users), 201
# 更新
# HTTPリクエストにパスパラメータあり
# パスパラメータをkeyにしてJSONデータで更新
@api.route('/functionalBase/<user_id>', methods=['PUT'])
def put_user(user_id):
# PUTリクエストを処理
data = request.get_json()
res_users = copy.deepcopy(users)
res_users = list(map(lambda user: user.update(data) or user if user['user_id'] == user_id else user, res_users))
return jsonify(res_users)
# 削除
# HTTPリクエストにパスパラメータあり
# パスパラメータをkeyにして削除
@api.route('/functionalBase/<user_id>', methods=['DELETE'])
def delete_user(user_id):
# DELETEリクエストを処理
res_users = list(filter(lambda user: user['user_id'] != user_id, users))
return jsonify(res_users)

関数ベースルートは@api.routeでエンドポイントとHTTPメソッドを指定する
直観的にわりやすい。

クラスベースのルート

クラスベースルートの実装部分について解説する

api.py(クラスベースルート部分)
# クラスベースのルーティング
class UserAPI(MethodView):
# 取得
# HTTPリクエストにクエリパラメータあり
# 全件取得 or ageフィルタリング
def get(self):
age = request.args.get('age')
if age:
return jsonify(list(filter(lambda user: user['age'] == int(age), users)))
return jsonify(users)
# 登録
# HTTPリクエストからJSONを受け取る
# JSONデータを新規登録
def post(self):
data = request.get_json()
res_users = copy.deepcopy(users)
res_users.append(data)
return jsonify(res_users), 201
# 更新
# HTTPリクエストにパスパラメータあり
# パスパラメータをkeyにしてJSONデータで更新
def put(self, user_id):
data = request.get_json()
res_users = copy.deepcopy(users)
res_users = list(map(lambda user: user.update(data) or user if user['user_id'] == user_id else user, res_users))
return jsonify(res_users)
# 削除
# HTTPリクエストにパスパラメータあり
# パスパラメータをkeyにして削除
def delete(self, user_id):
res_users = list(filter(lambda user: user['user_id'] != user_id, users))
return jsonify(res_users)
# クラスベースのビューを関数ベースのビューに変換
user_view = UserAPI.as_view('user_api')
# エンドポイントを設定
api.add_url_rule('/classBase', view_func=user_view, methods=['GET',])
api.add_url_rule('/classBase', view_func=user_view, methods=['POST',])
api.add_url_rule('/classBase/<string:user_id>', view_func=user_view, methods=['PUT', 'DELETE'])

クラスベースのルートは

  • クラスでエンドポイントごとにメソッドを定義
  • クラスベースのビューを関数ベースのビューに変換
  • エンドポイントを設定

を行う必要がある。

クラスでエンドポイントのメソッド名については

  • def get()
  • def post()
  • def put()
  • def delete()

とHTTPメソッドと合わせる。

各メソッドについて

HTTPメソッドは

  • GET:参照
  • POST:登録
  • PUT:更新
  • DELETE:削除

があり、それに対して

  • パスパラメータ
  • クエリパラメータ(URLパラメータ)
  • JSON形式データ

が組み合わされてでリクエストされていくるので
それぞれサンプルとして実装した

関数ベースルートのコードを元に解説する

GET + クエリパラメータ(URLパラメータ)

HTTPメソッドがGETでクエリパラメータがある場合の実装

GET
# 取得
# HTTPリクエストにクエリパラメータあり
# 全件取得 or ageフィルタリング
@api.route('/functionalBase', methods=['GET'])
def get_users():
# GETリクエストを処理
age = request.args.get('age')
if age:
return jsonify(list(filter(lambda user: user['age'] == int(age), users)))
return jsonify(users)

クエリパラメータ(age)がある場合は、usersディクショナリをageでフィルタリングして
json形式でレスポンスを返却する

POST + JSONデータ

HTTPメソッドがPOSTでリクエストボディにJSONがある場合の実装

POST
# 登録
# HTTPリクエストからJSONを受け取る
# JSONデータを新規登録
@api.route('/functionalBase', methods=['POST'])
def post_user():
# POSTリクエストを処理
data = request.get_json()
users.append(data)
return jsonify(users), 201

リクエストからJSONを取得してusersディクショナリに
新規登録する

HTTPステータスコードは201(Created)で返却する
※他メソッドは成功の場合はデフォルトの200で返却している

PUT + パスパラメータ + JSONデータ

HTTPメソッドがPUTでパスパラメータあり、リクエストボディにJSONがありの場合の実装

PUT
# 更新
# HTTPリクエストにパスパラメータあり
# パスパラメータをkeyにしてJSONデータで更新
@api.route('/functionalBase/<user_id>', methods=['PUT'])
def put_user(user_id):
# PUTリクエストを処理
data = request.get_json()
res_users = list(map(lambda user: user.update(data) or user if user['user_id'] == user_id else user, users))
return jsonify(res_users)

リクエストからのパスパラメータをメソッドの引数として使うことができる。
JSONデータを取得し、usersディクショナリの中からパスパラメータと一致する
レコードを探して、更新している。

DELETE + パスパラメータ

HTTPメソッドがDELETEでパスパラメータありの場合の実装

DELETE
# 削除
# HTTPリクエストにパスパラメータあり
# パスパラメータをkeyにして削除
@api.route('/functionalBase/<user_id>', methods=['DELETE'])
def delete_user(user_id):
# DELETEリクエストを処理
res_users = list(filter(lambda user: user['user_id'] != user_id, users))
return jsonify(res_users)

リクエストからのパスパラメータをメソッドの引数として使うことができる。
usersディクショナリの中からパスパラメータと一致するレコードを探して、削除している。

Flaskサーバー起動について

実装したコードをFlaskサーバーで起動する。

Flaskサーバーを「flask run」コマンドで起動する際には

  • FLASK_APP:Flaskがどのアプリケーションを実行するか指定
  • FLASK_ENV:Flaskがどの環境で動作するか指定
  • FLASK_DEBUG:デバッグモードの指定

が設定されている必要がある。

コンテナを作成する際に.envファイルをdocker-compose.ymlで
読み込んで設定しているので確認する。

コンテナにアタッチしているVScodeのターミナルで確認しておく

flask環境変数確認
$ echo $FLASK_APP
api.wsgi:api
$ echo $FLASK_ENV
development
$ echo $FLASK_DEBUG
true

Flaskサーバー起動

コンテナにアタッチしているVScodeのターミナルで起動する

Flaskサーバー起動
$ flask run --host=0.0.0.0
* Tip: There are .env or .flaskenv files present. Do "pip install python-dotenv" to use them.
* Serving Flask app 'api.wsgi.py'
* Debug mode: on
WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
* Running on all addresses (0.0.0.0)
* Running on http://127.0.0.1:5000
* Running on http://172.23.0.2:5000
Press CTRL+C to quit
* Restarting with stat
* Tip: There are .env or .flaskenv files present. Do "pip install python-dotenv" to use them.
* Debugger is active!
* Debugger PIN: 123-556-262

flask runでは環境変数FLASK_APPに指定されているflaskインスタンスを実行する。
下記の「api.run()」が実行されるイメージ。

api/wsgi.py
# flaskインスタンスをimport
from api.api import api
if __name__ == "__main__":
# flaskサーバーを起動
api.run()

flask run --host=0.0.0.0について

Dockerのコンテナは、コンテナがそれぞれ独立した環境を持っているため
デフォルトではホストOSからアクセスできない状態になっている

そしてflaskサーバーがデフォルトで待ち受けるIPアドレスが127.0.0.1(localhost)
のためIP、ポート番号なしで起動してもホストからはアクセスできない。

そのため起動時に

  • IPアドレスを0.0.0.0(すべてのIPアドレス)に設定

を指定して起動することでホストからアクセス可能になる。

サーバー起動をショートカット実行する

いちいちコマンドで「flask run --host=0.0.0.0」を入力して
実行するのは面倒なので、VScodeのタスクに登録しておく。

タスク作成

F1でコマンドパレットを出し、タスクの構成を選択 2024-03-09-01-38-23

テンプレートからtask.jsonを生成を選択 2024-03-09-01-39-21

Othersを選択(後で書き換えるので別に何でもいい) 2024-03-09-01-40-23

実行すると.vscode/task.jsonがプロジェクトルートに作成される

タスク編集

下記のように書き換える

task.json
{
"version": "2.0.0",
"tasks": [
{
"label": "Flask Run",
"type": "shell",
"command": "flask run --host=0.0.0.0",
"group": {
"kind": "build",
"isDefault": true
},
"presentation": {
"reveal": "always"
},
"problemMatcher": []
}
]
}

タスク実行

F1のコマンドパレットでタスクの実行を選択 2024-03-09-01-43-39

作成したタスクを実行
2024-03-09-01-44-37

これでコマンドを打たずともサーバーを起動できる

このタスクはこのプロジェクトでしか使わないため
カスタムタスクとして登録したが
全体で使うコマンド(docker compose系)などはユーザータスクとして
登録しておくと便利だと思う

詳しくは下記記事参照

REST APIの動作確認

flaskサーバーを起動して
作成したREST APIの動作を確認する

ブラウザで確認

ブラウザのアドレスバーから直接送信できるのはGETリクエストのみになる

GETリクエストを送ってみる

2024-03-09-17-25-50 結果が取得できることがわかる

Postmanで確認

GET,POST,PUT,DELETEの全て動作を確認するためには
ブラウザからはできないのでツールやプログラムを使う必要がある

今回はPostmanを使う
Postmanはpostmanから入手できる

関数ベースのルートで確認してみる。
クラスベースのルートでも同様のやり方で確認できる

GET

GETリクエストでusersディクショナリの全件が取得できる 2024-03-25-23-18-55

GET(クエリパラメータあり)

GETリクエストにクエリパラメータをつけて送ると
usersディクショナリのageでフィルタリングしたでーたが取得できる 2024-03-25-23-19-15

POST

POSTリクエストをボディにJSONデータをつけて送信すると
JSONデータのuserがusersディクショナリに追加された結果が取得できる
またコード201が帰ってくる
2024-03-25-23-20-54

PUT

PUTリクエストをパスパラメータつけ、ボディにJSONデータをつけて送信すると
パスパラメータのuser_idと一致したuserディクショナリのレコードが
送付したJSONデータで更新される
2024-03-25-23-21-49

DELETE

DELETEリクエストをパスパラメータつけて送信すると
パスパラメータのuser_idと一致したuserディクショナリのレコードが削除される 2024-03-25-23-22-35

デバッグ

最後にVScodeでデバッグする方法を記載する

VScodeではデバッグする際はデバッグ設定用のファイルである

  • launch.json

を作る必要がある。

launch.jsonを作る

flaskデバッグ用のlaunch.jsonを作成する

launch.json
{
"version": "0.2.0",
"configurations": [
{
"name": "Python デバッガー: Flask",
"type": "debugpy",
"request": "launch",
"module": "flask",
"env": {
"FLASK_APP": "api.wsgi:api",
"FLASK_DEBUG": "1"
},
"args": [
"run",
"--debugger",
"--reload",
"--host=0.0.0.0"
],
"jinja": true
}
]
}
  • サーバー起動時と同様に「host=0.0.0.0」で起動させる

デバッグ実行

実際にデバッグを実行してみる

作成したlaunch.jsonのnameに設定した値が表示されるので
選択して実行する 2024-03-09-17-53-18

GETのルートにブレークポイントを打っておく 2024-03-09-17-55-56

Postmanでリクエストを繰る

2024-03-09-17-59-40

ブレークポイントで止める
2024-03-09-18-00-22

まとめ

dockerコンテナでflaskの開発環境を作成し、そのコンテナ内で
flaskのREST APIを実装し、動作させるまでの手順をまとめてみた。

動作を見るために作成したapi.pyなどは実際使用する時に書き換える
必要がある。※関数ベースとクラスベースの併用とかは普通はしないと思うので

またAPIとしてほぼルーティング機能しか持たせていないので
そのほかのビジネスロジックやデータベースを使う場合はプロジェクト構成を
考える必要がありそう。

今回はREST APIの作り方と動かし方について重きをおいて作ったので
次は応用偏としてもう少し凝ったREST APIを作ってみる。

関連記事

新着記事

目次
タグ別一覧
top