前回までで、コンテナ(docker)の基本的な使い方を説明しました。ここからは、複数コンテナの管理に使える、docker compose
の使い方について説明していきたいと思います。
コード-> https://github.com/sogawa-yk/simple-knowledge-sharing-platform/tree/6-article
Docker Composeとは
Docker Composeは、複数のコンテナを使ったアプリケーションを定義して実行するためのツールです。設定ファイル(docker-compose.yaml)を使って、複数のコンテナとアプリケーションの構成を定義して、その構成に基づいて一括でコンテナをビルド・実行・停止などが行えます。
どんなアプリケーションに使える?
例えば、以前の記事で作成した、ウェブサーバ用のコンテナと、DBのコンテナを使ったアプリケーションにも使えます。以前の記事では、起動する順番に注意しながら各コンテナに対してdocker image build
コマンドと、docker container run
コマンドを使いましたが、docker composeを用いると、一括でこれらの操作を行うことができます。
基本的な書き方
yamlファイルなので、インデントを使って構造化して記述します。例えば以下のような具合です。
version: '3'
services:
web:
image: my-web-app:latest
build: .
ports:
- "5000:5000"
environment:
- DATABASE_URL=postgres://user:password@db:5432/mydatabase
depends_on:
- db
db:
image: postgres:13
volumes:
- db-data:/var/lib/postgresql/data
environment:
- POSTGRES_USER=user
- POSTGRES_PASSWORD=password
- POSTGRES_DB=mydatabase
volumes:
db-data:
docker-compose.yaml
に記述する内容を、上位レイヤーから順に説明していきます。
最上位レイヤー
最上位レイヤーには、version
, services
, networks
, volumes
などを記述します。
- version
composeファイルのバージョンを記述 - services
各サービスの定義を記述 - networks
カスタムネットワークの定義を記述 - volumes
カスタムボリュームの定義を記述
ここからは、この最上位レイヤーの各レイヤーごとに、その中身に記述する内容を説明します。
servicesレイヤー
ここには各サービスを定義します。各サービスには任意の名前を付けることができます。docker-compose.yamlのサンプル
の例では、以下の部分です。
services:
web: # サービス名
# サービスの詳細設定はここに続きます
db: # 別のサービス名
# サービスの詳細設定はここに続きます
サービスの詳細設定のレイヤー
各サービスの設定には、コンテナイメージ、ビルド、ポート、環境変数、依存関係などの詳細を定義します。
services:
web:
image: my-web-app:latest # 使用するDockerイメージ
build: . # Dockerfileがあるディレクトリ
ports:
- "5000:5000" # ポートマッピング
environment:
- DATABASE_URL=postgres://user:password@db:5432/mydatabase # 環境変数
depends_on:
- db # 起動順序の依存関係
networks:
- app-network # 使用するネットワーク
db:
image: postgres:13 # 使用するDockerイメージ
volumes:
- db-data:/var/lib/postgresql/data # ボリュームマッピング
environment:
- POSTGRES_USER=user # 環境変数
- POSTGRES_PASSWORD=password
- POSTGRES_DB=mydatabase
networks:
- app-network # 使用するネットワーク
ports
で行えるポートのマッピングは、docker container run
コマンド時と同様、[ホストのポート]:[コンテナのポート]
の順に指定します。
また、depends_on
で指定するのはdocker-compose.yaml
内で指定したサービス名です。ここに指定したサービスが起動するまで、depends_on
が設定されたサービスは起動しないようになります。このようにすることで、コンテナの起動順序を制御することができます。
ネットワークレイヤー
カスタムネットワークの定義を記述します。サービスの詳細設定レイヤーで、そのサービスが配置されるネットワークを指定できますが、そのネットワークはこのネットワークレイヤーで定義しておく必要があります。
networks:
app-network: # ネットワーク名を指定
driver: bridge # ネットワークドライバを指定
driver_opts: # ドライバ固有のオプションも指定可能
com.docker.network.bridge.name: my-custom-bridge
ネットワークドライバには以下のようなものが設定できます。
ネットワークドライバ | 説明 |
---|---|
bridge | デフォルトのネットワークドライバ。ネットワーク作成時にドライバを指定しなければこのネットワークが使われる。通常、スタンドアロンコンテナが通信するために使用。 |
host | スタンドアロンコンテナ用。コンテナとDockerホスト間のネットワーク隔離を解除し、ホスト側のネットワーク機能を直接使用。 |
overlay | 複数のDockerデーモンを接続し、swarmサービスが相互に通信可能にする。OSレベルのルーティング設定が不要。 |
ipvlan | IPv4とIPv6のアドレス割り当てをまとめてコントロール。レイヤー2 VLANタギングやIPvlan L3ルーティングも完全に操作可能。 |
macvlan | コンテナにMACアドレスを割り当て、物理デバイスとして見えるようにする。物理ネットワークへの直接接続が想定される場合に最適。 |
none | コンテナの全てのネットワーク機能を無効化。通常、カスタムネットワークドライバとの競合を避けるために使用。swarmサービスでは利用不可。 |
ネットワークプラグイン | サードパーティ製のネットワークプラグインをインストールして利用可能。Docker Hubやサードパーティベンダーから提供。ベンダーのドキュメントを参照。 |
ボリュームレイヤー
ボリュームレイヤーも書き方はネットワークレイヤーと同様です。
volumes:
db-data: # ボリューム名を指定
driver: local # ボリュームドライバを指定
driver_opts: # ドライバ固有のオプションを指定
type: nfs
o: addr=192.168.1.100,rw
device: ":/path/to/dir"
使用例
それでは、前回作成したウェブアプリケーションのdocker-compose.yaml
を書いてみます。
まず、作成したウェブアプリケーションを少し編集します。DBへの接続をハードコーディングしていましたが、その部分を環境変数から取得する形に変更します。
def init_db():
conn = mysql.connector.connect(
host=os.environ.get('DATABASE_HOST', 'db'),
port='3306',
user=os.environ.get('DATABASE_USER', 'root'),
password=os.environ.get('DATABASE_PASSWORD', 'password'),
database=os.environ.get('DATABASE_NAME', 'flask_app')
)
cursor = conn.cursor()
cursor.execute('CREATE TABLE IF NOT EXISTS articles (id INT AUTO_INCREMENT PRIMARY KEY, title VARCHAR(255), content TEXT)')
conn.commit()
cursor.close()
conn.close()
init_db()
def get_db_connection():
conn = mysql.connector.connect(
host=os.environ.get('DATABASE_HOST', 'db'),
port='3306',
user=os.environ.get('DATABASE_USER', 'root'),
password=os.environ.get('DATABASE_PASSWORD', 'password'),
database=os.environ.get('DATABASE_NAME', 'flask_app')
)
return conn
前回のウェブアプリケーション起動時に使ったdockerコマンドは、
$ docker network create flask-net
$ docker build -t simple-knowledge-sharing-platform .
$ docker run --name mysql -e MYSQL_ROOT_PASSWORD=password -e MYSQL_DATABASE=flask_app --network flask-net -d mysql:8.0
$ docker run -d -p 8080:5000 --network flask-net -v $(pwd)/uploads:/app/uploads simple-knowledge-sharing-platform
でした。これらの操作をdocker-compose
に落としていきます。
まず、以下のようなひな型を作成します。
version: '3.8'
services:
db:
web:
networks:
volumes:
services
MySQL
MySQLのコンテナ起動コマンドは$ docker run --name mysql -e MYSQL_ROOT_PASSWORD=password -e MYSQL_DATABASE=flask_app --network flask-net -d mysql:8.0
でした。これをdocker-compose.yaml
に落とすと、
db:
image: mysql:8.0
container_name: mysql
environment:
- MYSQL_ROOT_PASSWORD=password
- MYSQL_DATABASE=flask_app
networks:
- flask-net
volumes:
- db-data:/var/lib/mysql
restart: unless-stopped
となります。
webアプリ
webアプリ側の起動コマンドは、$ docker run -d -p 8080:5000 --network flask-net -v $(pwd)/uploads:/app/uploads simple-knowledge-sharing-platform
でした。これをdocker-compose.yaml
に落とすと、
web:
build: .
container_name: web
ports:
- "8080:5000"
networks:
- flask-net
volumes:
- ./uploads:/app/uploads
depends_on:
- db
environment:
- DATABASE_HOST=db
- DATABASE_USER=root
- DATABASE_PASSWORD=password
- DATABASE_NAME=flask_app
restart: unless-stopped
となります。environment
のDATABASE_HOST
には、docker-compose.yaml
内で定義しているサービス名を指定します。
networks
ネットワーク作成時のコマンドは、$ docker network create flask-net
でした。これをdocker-compose.yaml
に落とすと、
networks:
flask-net:
driver: bridge
となります。
volumes
アップロードされた画像ファイルを保存するために、ボリュームはウェブ側のみ用意しています。以下のように記述します。
volumes:
web-data:
driver: local
全体
ここまで加えた変更をみると、以下のようなdocker-compose.yaml
になります。
version: '3.8'
services:
db:
image: mysql:8.0
container_name: mysql
environment:
- MYSQL_ROOT_PASSWORD=password
- MYSQL_DATABASE=flask_app
networks:
- flask-net
restart: unless-stopped
web:
build: .
container_name: web
ports:
- "8080:5000"
networks:
- flask-net
volumes:
- web-data:/app/uploads
depends_on:
- db
environment:
- DATABASE_HOST=db
- DATABASE_USER=root
- DATABASE_PASSWORD=password
- DATABASE_NAME=flask_app
restart: unless-stopped
networks:
flask-net:
driver: bridge
volumes:
web-data:
driver: local
docker-compose.yamlからサービスを起動
docker-compose.yaml
があるディレクトリに移動し、以下のコマンドを実行します。
$ docker compose up -d --build #docker composeを使っている場合
$ podman-compose up -d --build #podmanを使っている場合
サービスを停止
$ docker compose down # docker composeを使っている場合
$ podman-compose down # podman-composeを使っている場合
まとめ
基本的なdocker compose (podman-compose)
の使い方を何となく理解できたかと思います。次回は、ボリュームを使ったデータ永続化について、もう少し深掘りしていきます。