はじめに
こんにちは!ITスクールRareTECHにてCS(Customer Support)を担当している池村です。今回の記事はDocker Composeの続きの記事になります。
連続した記事なので先に前回の記事を見ていただけますと幸いです。
複数コンテナの連携
早速本題です。前回までは単一のコンテナをComposeで動かすことを行いました。
ただ、やはりアプリを作るときはプログラムが動くコンテナ、データベースのコンテナなどを連携させたいと思います。⑥のネットワークの記事で二つのコンテナ間通信を実現していたわけですが、それをDocker Composeで実現したいと思います。
ではまず今回作成する環境のdocker-compose.ymlファイルの構成を見ていきましょう。
services:
flask:
build:
context: .
ports:
- "5000:5000"
volumes:
- ./src:/app
environment:
FLASK_DEBUG: 1
depends_on:
- db
db:
image: mysql:latest
ports:
- "3306:3306"
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: test_db
MYSQL_USER: user
MYSQL_PASSWORD: password
volumes:
- db_data:/var/lib/mysql
- ./sql:/docker-entrypoint-initdb.d/
volumes:
db_data:
前回の記事では紹介しなかったいくつかの項目があります。
1. environment
これは環境変数を設定する部分です。環境変数とは、プログラムとかPCとかが動く際に使う設定情報のようなものとお考えください。
FLASK_DEBUG: 1
これはFlaskの設定としてデバッグモードで起動してね!と設定しておく値です。コンテナの中でこの値が読み込まれて、Flaskアプリが動く際に使われています。自動リロードがされるようになって、コードの変更などを察知してくれるものです。
開発環境前提のお話です。
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: test_db
MYSQL_USER: user
MYSQL_PASSWORD: password
同様に、MySQLでも環境変数としてこちらの値が使われます。
これはデータベースの設定ですね。
MySQLの詳細は省きます。
2. depends_on
では次にdepends_on
ですが、こちらはコンテナの作成順を決めている記述です。なので、MySQLのコンテナが作成された後にFlaskのコンテナが動くということです。
depends_on:
- db
db
というのはservices
の名前ですね。
ハンズオン環境を作って動かしてみよう
このセクションでは、先ほどのdocker-compose.ymlファイルと、コンテナを動かすためのファイル類を作っていきましょう。そして実行までしていきます。
mkdir -p flask_project/src flask_project/sql && touch flask_project/src/app.py flask_project/src/requirements.txt flask_project/sql/init.sql flask_project/docker-compose.yml flask_project/Dockerfile
flask_project/
├── src/
│ ├── app.py
│ ├── requirements.txt
├── sql/
│ ├── init.sql
├── docker-compose.yml
├── Dockerfile
上記のようなディレクトリができていればOKです。
次にDockerfileです。
# ベースイメージ
FROM python:3.9-slim
# 作業用のディレクトリを設定しています
WORKDIR /app
# 必要なファイル類をコピーしてライブラリをインストールしています
COPY src/ /app/
RUN pip install -r requirements.txt
# コンテナがリッスンするポート番号を指定してます
EXPOSE 5000
# Flaskアプリを起動します
CMD ["python", "app.py"]
ではapp.pyに移ります。前の記事よりも少しだけ難しく作成します。
from flask import Flask, request, jsonify
import mysql.connector
from mysql.connector import Error
app = Flask(__name__)
# データベースの接続情報
DB_HOST = "db" # ここはdocker-compose.yml の `services` で指定した名前を
DB_USER = "user"
DB_PASSWORD = "password"
DB_NAME = "test_db"
# データベースとの接続をするための関数
def get_db_connection():
try:
connection = mysql.connector.connect(
host=DB_HOST,
user=DB_USER,
password=DB_PASSWORD,
database=DB_NAME
)
return connection
except Error as e:
print(f"エラー: {e}")
return None
# ここからがAPI
@app.route('/')
def home():
return "Welcome to the Flask-MySQL App!"
@app.route('/add', methods=['POST'])
def add_data(): # データベースに名前を登録する関数
data = request.get_json()
if not data or 'name' not in data:
return jsonify({"error": "Invalid input"}), 400
connection = get_db_connection()
if connection is None:
return jsonify({"error": "Database connection failed"}), 500
try:
cursor = connection.cursor()
cursor.execute("INSERT INTO users (name) VALUES (%s)", (data['name'],))
connection.commit()
return jsonify({"message": f"User {data['name']} added successfully"}), 200
except Error as e:
return jsonify({"error": f"Database error: {e}"}), 500
finally:
connection.close()
@app.route('/users', methods=['GET'])
def get_users(): # データベースから登録されている名前を全て取得する関数
connection = get_db_connection()
if connection is None:
return jsonify({"error": "Database connection failed"}), 500
try:
cursor = connection.cursor(dictionary=True)
cursor.execute("SELECT * FROM users")
rows = cursor.fetchall()
return jsonify(rows), 200
except Error as e:
return jsonify({"error": f"Database error: {e}"}), 500
finally:
connection.close()
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000)
requirements.txtも作成します。
Flask
mysql-connector-python==8.0.32
最後にinit.sqlの中身を書いていきましょう。
init.sqlはデータベースの設定を書き込んでおくことで、コンテナ起動時などにデータベースとその中のテーブルを作っておけるファイルです。
※もちろんDocker関連の設定ファイルに書き込むことが前提です。
CREATE DATABASE IF NOT EXISTS test_db;
USE test_db;
CREATE TABLE IF NOT EXISTS users (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255) NOT NULL
);
MySQLの公式イメージでは、/docker-entrypoint-initdb.d/
に置いたSQLファイル(init.sqlとか)を起動時に自動で実行する仕組みがあります。
最後にdocker-compose.ymlですが。
docker-compose.ymlファイルは記事の最初に書いたものを使って下さい。
では実行しましょう!
docker compose up
docker-compose.ymlファイルのあるディレクトリで実行して下さい。
では実際にGETリクエストである/
にリクエストを送ってみましょう。
次にユーザー登録をしていきます。
これはcurlコマンドを使ってPOSTリクエストを送っていきます。
curl -X POST -H "Content-Type: application/json" -d '{"name": "TestName"}' http://localhost:5000/add
{
"message": "User TestName added successfully"
}
こうなっていれば問題ありません。
では最後に登録されたユーザーの一覧を出してみましょう。
無事登録ができていました!
あれ?これはどこでコンテナ同士が繋がってるの?
と思う人は勘がいいです。
Docker Composeではネットワークは内部的に作成されて勝手に連携されています。
勝手にやってくれるのはとてもいいことなんですが、中で何が行われているかわからないのは怖いですね。
docker network ls
この実行結果にあるflask_project_default
というのが、今回自動的に作られたネットワークです。ではこのネットワークの詳細を見てみましょう。
docker network inspect flask_project_default
Dockerネットワークの記事でこの中身については記述しているので、がっつり説明する気はありませんが、ラベル情報が追記されていますね。これも勝手に書き込まれているようです。
おわりに
さて、ここまでの読了お疲れ様でした。初学者が学ぶべきDocker基礎の記事はここまででおしまいです。新しい技術を最初から深ぼろうとはせず、さらっと全体をなぞるのが大事だと思っています。
ただ、Dockerは難しい技術です。Linuxの集大成のような技術ですし、各言語ごとの環境構築方法もわかっていないといけません。私のDocker記事は通してPython(Flask)を使ってきましたが、他の言語の場合はその環境構築方法、フレームワークの使い方を覚えてから応用してみて下さい。
まとめ記事に戻るにはこちら👇
余談
フルリモートフルフレックスの会社にいるのに、家では仕事や学習をできないタイプなので、コワーキングかカフェにいることが多い人間です。PRONTカフェが好きです☕️