生成AI×システム構築 〜構築編〜

AI

前回の製造編で以下のファイルを作成してもらいました。
・データベース(MySQL)用のCreateTable文
・バックエンド(Flask)用のPythonファイル
・フロントエンド(HTML+JavaScript)用のHTMLファイル

これらを用いて動作する環境を構築して行きましょう。
構築にはDockerを使ってみたいと思います。

❓️Dockerとは?
アプリケーションと、その実行に必要な環境を「コンテナ」という軽量なパッケージにまとめて
動かすプラットフォームです。
環境構築の手間を削減し、やり直しも手軽にできます。

Docker環境構築

それでは構築に必要なファイルを聞いてみましょう。

宗一郎
宗一郎

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

ChatGPT
ChatGPT

フォルダ構成(提案)

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をダウンロードできるようにしてください

ChatGPT
ChatGPT

Flaskで構築したバックエンドの app.py を作成しました。
こちらからダウンロードできます。

📄 app.py

最終的に作成したファイル構成はこんな感じです。

VisualStudioCodeでの表示結果

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

実行結果

あ、エラーが出てしまいました。
inventory_dbとあるので、MySQLの構築に失敗したようです。

エラー解決

どうすればよいか聞いてみましょう。

宗一郎
宗一郎

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

ChatGPT
ChatGPT

エラーのポイントは
「依存先(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 variablemy.cnf 関連
  → 設定の不整合

(省略)

教えてもらったとおり、ログに何か出ていないか見てみます。

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

宗一郎
宗一郎

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

ChatGPT
ChatGPT

原因は 初期化SQLファイルの文字エンコード不一致 です。
ログの ��品マスタ ( の“文字化け”が典型で、/docker-entrypoint-initdb.d/01_schema.sqlUTF-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に変更して、既存のものと置き換えます。

それではもう一度構築してみます。

再びエラーとなってしまいました。
今回はメッセージが直接出ていますね。ポート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″に変更して再実行します。

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

無事、表示されましたね。
各機能の登録や検索も問題ありませんでした。

まとめ

途中でエラーが発生したものの、無事に解決できました。
エラー内容も生成されたものが問題となっているのではなく、事前に懸念と思っていた箇所だったり、環境依存といったことが原因でした。

普段、エラー調査や解決に普段AIを使うことが多いですが、やはり有用ですね。
少ない情報から状況説明や確認事項を示してくれるのが非常に助かります。

ソース生成については、正直なところ一度で動作するものが出力されるとは思っていませんでした。
全体的な整合性もとられ、結合もしっかりしていましたね。
ちなみに機能ごとにファイルをコピーして手動作成していましたが、これらも全て作ってもらうことも可能でした。(どうしても機能やファイル単位で考えてしまってて、後から気づきました・・・)

宗一郎
宗一郎

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

ChatGPT
ChatGPT

必要なファイルをすべて含めた inventory-system フォルダを作成し、ZIP化しました。
こちらからダウンロードできます。
📦 inventory-system.zip


動きを見ていると、日付の書式が想定と違ったり、商品コードの検索は難しかったりと、気になる点もあったりします。(このあたりは後々修正していきたいと思います。)
ですが、エラーが発生したり、動作がおかしかったりはせず、正常に機能しています。
フロントエンド ↔ バックエンド ↔ データベース の連携も問題ありませんでした。

構築も大きなトラブルなく成功しました。労力もそこまでかかっていない印象です。
ちなみに自分はDocker Desktop使用していましたが、docker-compose.ymlを使用した構築は初めてでした。環境をコードで示してくれるのは認識齟齬がなくて助かりますね。
コード内容を全て理解できてはいないので、今後勉強したいと思います。

構築編としては以上です。

コメント

タイトルとURLをコピーしました