前回の製造編で以下のファイルを作成してもらいました。
・データベース(MySQL)用のCreateTable文
・バックエンド(Flask)用のPythonファイル
・フロントエンド(HTML+JavaScript)用のHTMLファイル
これらを用いて動作する環境を構築して行きましょう。
構築にはDockerを使ってみたいと思います。
❓️Dockerとは?
アプリケーションと、その実行に必要な環境を「コンテナ」という軽量なパッケージにまとめて
動かすプラットフォームです。
環境構築の手間を削減し、やり直しも手軽にできます。
Docker環境構築
それでは構築に必要なファイルを聞いてみましょう。

このシステムをDockerで構築したいです。
追加で必要なファイルとファイル構成を教えて下さい。

✅ フォルダ構成(提案)
csharpコピーする編集するinventory-system/
├─ docker-compose.yml
├─ .env # 環境変数(DB接続など)
├─ backend/
│ ├─ Dockerfile
│ ├─ requirements.txt
│ ├─ app.py # これまでのAPI(商品/入出庫/履歴/在庫)+静的配信
│ └─ static/ # フロントHTMLをここに置く
│ ├─ menu_frame.html # サイドメニュー(親)
│ ├─ product.html # 商品マスタ登録
│ ├─ stock_in.html # 入庫登録
│ ├─ stock_out.html # 出庫登録
│ ├─ stock_list.html # 現在庫照会
│ └─ history.html # 入出庫履歴参照
└─ db/
└─ init/
└─ 01_schema.sql # CREATE TABLE(起動時に自動適用)
フロントの各HTMLは、これまでお渡ししたファイル内容を backend/static/
に保存してください。
1) docker-compose.yml
コード
version: "3.9"
services:
db:
image: mysql:8.0
container_name: inventory_db
environment:
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
MYSQL_DATABASE: ${MYSQL_DATABASE}
TZ: Asia/Tokyo
command: --default-authentication-plugin=mysql_native_password
ports:
- "3306:3306"
volumes:
- db-data:/var/lib/mysql
- ./db/init:/docker-entrypoint-initdb.d
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "-p${MYSQL_ROOT_PASSWORD}"]
interval: 5s
timeout: 3s
retries: 20
api:
build: ./backend
container_name: inventory_api
depends_on:
db:
condition: service_healthy
environment:
FLASK_ENV: development
TZ: Asia/Tokyo
MYSQL_HOST: db
MYSQL_USER: root
MYSQL_PASSWORD: ${MYSQL_ROOT_PASSWORD}
MYSQL_DB: ${MYSQL_DATABASE}
ports:
- "5000:5000"
volumes:
- ./backend/static:/app/static # HTMLのホットリロード用
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:5000/health"]
interval: 10s
timeout: 3s
retries: 10
volumes:
db-data:
2) .env(プロジェクト直下)
MYSQL_ROOT_PASSWORD=your_password MYSQL_DATABASE=inventory_db
3) backend/Dockerfile
コード
FROM python:3.11-slim WORKDIR /app # OSツール RUN apt-get update && apt-get install -y --no-install-recommends \ curl gcc default-libmysqlclient-dev pkg-config && \ rm -rf /var/lib/apt/lists/* # 依存ライブラリ COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt # アプリ本体 COPY app.py ./app.py COPY static ./static # 起動 EXPOSE 5000 CMD ["python", "app.py"]
4) backend/requirements.txt
flask==3.0.3 flask-cors==4.0.0 flask-mysqldb==2.0.0 mysqlclient==2.2.4
5) db/init/01_schema.sql
先にお渡しした create_tables.sql
の内容を、そのまま 01_schema.sql
として置いてください(MySQLは docker-entrypoint-initdb.d
配下の .sql
を初回起動時に自動実行します)。
6) backend/app.py(要点のみ)
Pythonコード
import os from flask import Flask, request, jsonify, send_from_directory from flask_mysqldb import MySQL from flask_cors import CORS import MySQLdb.cursors app = Flask(__name__, static_folder="static") CORS(app) # --- MySQL接続設定 --- app.config['MYSQL_HOST'] = os.getenv('MYSQL_HOST', 'localhost') app.config['MYSQL_USER'] = os.getenv('MYSQL_USER', 'root') app.config['MYSQL_PASSWORD'] = os.getenv('MYSQL_PASSWORD', '') app.config['MYSQL_DB'] = os.getenv('MYSQL_DB', 'inventory_db') app.config['MYSQL_CURSORCLASS'] = 'DictCursor' mysql = MySQL(app) # ---------- ここに既存の API 実装(/api/products, /api/stock/in, /api/stock/out, # /api/stock, /api/history の各エンドポイント)を貼り付けてください ---------- # --- ヘルスチェック --- @app.route('/health') def health(): try: cur = mysql.connection.cursor() cur.execute("SELECT 1") cur.fetchone() return "ok", 200 except Exception as e: return str(e), 500 # --- 静的画面(サイドメニューをデフォルト表示) --- @app.route('/') def root(): return send_from_directory(app.static_folder, 'menu_frame.html') # 静的ファイルをそのまま返す(/product.html 等に直接アクセスできる) @app.route('/<path:path>') def static_proxy(path): return send_from_directory(app.static_folder, path) if __name__ == '__main__': # 0.0.0.0 で公開し、Docker外からもアクセス可 app.run(host='0.0.0.0', port=5000, debug=True)
起動手順
# プロジェクト直下で docker compose up -d --build # 初回はDB初期化(01_schema.sql)→ API起動 → ブラウザで open http://localhost:5000
Docker用のファイルがいくつか出てきました。
これらを提案のあったフォルダ構成を参考に、コピーして作って行きます。
「app.py」が少し変更になったようなので、こちらは再作成してもらいましょう。

app.pyをダウンロードできるようにしてください

Flaskで構築したバックエンドの app.py
を作成しました。
こちらからダウンロードできます。
📄 app.py
最終的に作成したファイル構成はこんな感じです。

それではいよいよ構築します!
アプリは Docker Desktop を使って、インストール済の状態から説明となっています。
ターミナル/コマンドプロンプトでプロジェクトフォルダへ移動後、下記のコマンドを実行しましょう。
docker compose up -d --build

あ、エラーが出てしまいました。
inventory_dbとあるので、MySQLの構築に失敗したようです。
エラー解決
どうすればよいか聞いてみましょう。

docker compose u -d –build 実行時に下記のエラーが発生しました。
何が原因でしょうか。
#エラー
dependency failed to start: container inventory_db exited (1)

エラーのポイントは
「依存先(DB)が起動に失敗:inventory_db
が exit code 1で終了」 です。
まずは“なぜ落ちたか”をログで特定しましょう。以下の順で確認してみてください。
1) まずは原因を特定(ログ確認)
# コンテナ名が inventory_db の場合
docker logs inventory_db
# もしくはサービス名が db の場合(compose経由)
docker compose logs db
ログに以下のどれかが出ていないか見てください:
・Database is uninitialized and password option is not specified
→ .env が読めておらず MYSQL_ROOT_PASSWORD
が未設定の典型です。
・ERROR: ... in /docker-entrypoint-initdb.d/01_schema.sql
→ 初期化SQLの文法エラーや実行順依存で失敗。
・Access denied
/ Can't open .../var/lib/mysql
→ データディレクトリの権限/破損。
・unknown variable
や my.cnf
関連
→ 設定の不整合。
(省略)
教えてもらったとおり、ログに何か出ていないか見てみます。
docker logs inventory_db

文字化けしてしまってますね。日本語のテーブル名はやはり問題あったようです。
半角に修正してもよいのですが、ログの内容を貼り付けて対策を聞いてみましょう。

docker logs inventory_dbを確認したところ、下記のエラーが出ていました。
ERROR 1064 (42000) at line 2: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ‘��品マスタ (
商品コード VARCHA’ at line 1

原因は 初期化SQLファイルの文字エンコード不一致 です。
ログの ��品マスタ (
の“文字化け”が典型で、/docker-entrypoint-initdb.d/01_schema.sql
が UTF-16やShift_JIS、あるいはUTF-8(BOM付き) で保存されていると、MySQL 初期化時に構文エラー(1064)が出ます。
直し方(最短ルート)
1. こちらで UTF-8(BOMなし)・安全なバッククォート付き のスキーマを用意しました:
📄 01_schema_utf8.sql
2. 既存のDBボリュームを初期化してやり直し
# プロジェクト直下で docker compose down -v # 上の 01_schema_utf8.sql を db/init/01_schema.sql として置き換え # 例: cp ~/Downloads/01_schema_utf8.sql db/init/01_schema.sql docker compose up -d --build
既存ファイルを自分で直す場合
・エディタ(VSCode等)で 01_schema.sql
を開く
→ エンコードを「UTF-8(BOMなし)」に変換して保存
→ 先頭に以下を入れるとより安全です:
SET NAMES utf8mb4; SET time_zone = '+09:00';
日本語のテーブル名/カラム名はバッククォートで囲む(例:`商品マスタ`、`商品コード`)
末尾にテーブルごとに DEFAULT CHARSET = utf8mb4
を付与
修正ファイルを先んじて用意してくれましたね。せっかくなので使ってみましょう。
ダウンロードしたsqlファイル名を01_schema.sqlに変更して、既存のものと置き換えます。
それではもう一度構築してみます。
docker compose up -d --build

再びエラーとなってしまいました。
今回はメッセージが直接出ていますね。ポート5000が使用済だったようです。
先ほどと同じように解決方法を聞いてみます。

inventory_dbはOKでしたが、inventory_apiで下記のエラーが発生しました。
どのようにすればよいでしょうか。
#エラー内容
Error response from daemon: ports are not available: exposing port TCP 0.0.0.0:5000 -> 127.0.0.1:0: listen tcp 0.0.0.0:5000: bind: address already in use

原因はポート5000がすでに他のプロセスで使用中なことです。
Dockerは inventory_api
コンテナの 5000 ポートをホストにバインドしようとしていますが、すでに同じポートがホスト側で占有されているため起動できません。
1. ポートを使っているプロセスを終了する
(省略)
2. docker-compose.yml のポート設定を変更する
もし他アプリが5000を使っていて終了できない場合は、docker-compose.yml
の該当サービスの ports
を例えば 5001:5000
に変更します。
services: inventory_api: ports: - "5001:5000"
この場合、ブラウザやAPI呼び出しは http://localhost:5001
を使う必要があります。
docker-compose.ymlを修正すれば良さそうですね。
portsを”5001:5000″に変更して再実行します。
docker compose up -d --build

ようやく上手くいきました。
ブラウザで「http://localhost:5001」に接続してみます。

無事、表示されましたね。
各機能の登録や検索も問題ありませんでした。
まとめ
途中でエラーが発生したものの、無事に解決できました。
エラー内容も生成されたものが問題となっているのではなく、事前に懸念と思っていた箇所だったり、環境依存といったことが原因でした。
普段、エラー調査や解決に普段AIを使うことが多いですが、やはり有用ですね。
少ない情報から状況説明や確認事項を示してくれるのが非常に助かります。
ソース生成については、正直なところ一度で動作するものが出力されるとは思っていませんでした。
全体的な整合性もとられ、結合もしっかりしていましたね。
ちなみに機能ごとにファイルをコピーして手動作成していましたが、これらも全て作ってもらうことも可能でした。(どうしても機能やファイル単位で考えてしまってて、後から気づきました・・・)

必要なファイル全てを含めてinventory-systemフォルダ配下のファイルをzip化してください。

必要なファイルをすべて含めた inventory-system
フォルダを作成し、ZIP化しました。
こちらからダウンロードできます。
📦 inventory-system.zip
動きを見ていると、日付の書式が想定と違ったり、商品コードの検索は難しかったりと、気になる点もあったりします。(このあたりは後々修正していきたいと思います。)
ですが、エラーが発生したり、動作がおかしかったりはせず、正常に機能しています。
フロントエンド ↔ バックエンド ↔ データベース の連携も問題ありませんでした。
構築も大きなトラブルなく成功しました。労力もそこまでかかっていない印象です。
ちなみに自分はDocker Desktop使用していましたが、docker-compose.ymlを使用した構築は初めてでした。環境をコードで示してくれるのは認識齟齬がなくて助かりますね。
コード内容を全て理解できてはいないので、今後勉強したいと思います。
構築編としては以上です。
コメント