この記事で分かること
- compose.yaml の基本構文と services / volumes / networks の書き方
- Rocky Linux 9 + SELinux環境でPermission denied を回避するボリュームマウント設定
- depends_on + healthcheck でデータベースの起動完了を待ってからアプリを起動する方法
docker run コマンドでコンテナを1つずつ起動している方は多いと思います。しかし、Webアプリ + データベース + リバースプロキシのように複数コンテナを組み合わせる構成では、毎回長いコマンドを打つのは大変です。ネットワークやボリュームの作成も手動になり、ミスが起きやすくなります。
Docker Compose を使えば、1つの設定ファイル(compose.yaml)に全コンテナの構成を記述し、docker compose up -d の一発で起動できます。この記事では、Rocky Linux 9 環境を前提に、基本構文から実践的なテクニックまでを順番に解説していきます。
Docker Composeとは?docker runとの違いと導入メリット
docker run の繰り返し問題
たとえば WordPress + MySQL の環境を docker run で構築する場合、以下のようなコマンドが必要になります。
# ネットワーク作成
docker network create wp-net
# MySQLコンテナ起動
docker run -d \
--name mysql \
--network wp-net \
-e MYSQL_ROOT_PASSWORD=rootpass \
-e MYSQL_DATABASE=wordpress \
-e MYSQL_USER=wpuser \
-e MYSQL_PASSWORD=wppass \
-v mysql-data:/var/lib/mysql \
mysql:8.0
# WordPressコンテナ起動
docker run -d \
--name wordpress \
--network wp-net \
-p 8080:80 \
-e WORDPRESS_DB_HOST=mysql \
-e WORDPRESS_DB_USER=wpuser \
-e WORDPRESS_DB_PASSWORD=wppass \
-e WORDPRESS_DB_NAME=wordpress \
wordpress:latestこれを毎回入力するのは手間ですし、コマンドの順序を間違えると起動に失敗します。停止・削除するときも個別にコマンドを実行する必要があります。
Docker Compose なら compose.yaml 1ファイルで完結
Docker Compose は、複数のコンテナ・ネットワーク・ボリュームの定義を1つの YAML ファイルにまとめて管理するツールです。上記の構成は compose.yaml に記述しておけば、docker compose up -d 一発で起動、docker compose down 一発で停止・削除できます。
docker compose v2 と旧版 docker-compose v1 の違い
現在は2種類の Docker Compose が存在しますが、v2(docker compose)を使うのが正解です。
- v2(推奨):Docker CLI のプラグインとして動作。コマンドは
docker compose(スペース区切り)。Go言語で書かれており高速 - v1(非推奨):スタンドアロンの
docker-compose(ハイフン区切り)コマンド。Python製。2023年6月にEOL(サポート終了)済み
古い記事やチュートリアルでは docker-compose(ハイフン)で書かれていることがありますが、v1はすでにサポート終了しています。必ず docker compose(スペース)を使ってください。
Rocky Linux 9 で Docker をインストール済みであれば、v2 プラグインは通常すでに含まれています。以下のコマンドでバージョンを確認しましょう。
docker compose version
# Docker Compose version v2.x.x と表示されればOKcompose.yaml の基本構文を理解する
version: フィールドは不要(廃止済み)
古い記事では version: "3.8" のような記述を見かけますが、現在の Compose Specification では version: フィールドは廃止されています。Docker Compose v2.x 以降で書いても無視されるだけで、以下のような警告が表示されます。削除することを推奨します。
WARN[0000] /path/to/compose.yaml: the attribute `version` is obsolete, it will be ignored, please remove itcompose.yaml の3大要素:services / volumes / networks
compose.yaml はトップレベルに以下の3つの要素を記述します。
- services:起動するコンテナの定義(必須)
- volumes:名前付きボリュームの定義(データの永続化に使用)
- networks:カスタムネットワークの定義(省略するとデフォルトネットワークが自動作成される)
services で使う主要キー
- image:使用するDockerイメージを指定(例:
nginx:latest) - build:Dockerfileからイメージをビルドする場合に指定(例:
build: ./app) - ports:ホスト側ポート:コンテナ側ポートのマッピング(例:
"8080:80") - volumes:ボリュームマウントの定義(例:
./html:/usr/share/nginx/html) - environment:環境変数の設定
- restart:再起動ポリシー(
no/always/unless-stopped/on-failure)
シンプルなNginx起動例
まずは最もシンプルな例として、Nginx を1コンテナだけ起動する compose.yaml を見てみましょう。
services:
web:
image: nginx:latest
ports:
- "8080:80"
volumes:
- ./html:/usr/share/nginx/html:ro
restart: unless-stoppedこのファイルを compose.yaml として保存し、同じディレクトリで以下を実行します。
# htmlディレクトリとテスト用ファイルを作成
mkdir -p html
echo "<h1>Hello from Docker Compose!</h1>" > html/index.html
# コンテナをバックグラウンドで起動
docker compose up -d
# 動作確認
curl http://localhost:8080
# 停止・削除
docker compose downRocky Linux 9 + SELinux環境でのボリュームマウント注意点
Rocky Linux 9 では SELinux(Security-Enhanced Linux)がデフォルトでenforcing(強制)モードで動作しています。この環境でホストディレクトリをコンテナにバインドマウントすると、Permission denied エラーが発生することがあります。
エラーの原因
SELinux はファイルやディレクトリに「セキュリティコンテキスト」というラベルを付けてアクセス制御を行います。ホスト上のディレクトリはデフォルトで通常ユーザー向けのラベルが付いており、コンテナプロセスからはアクセスが拒否されます。
# SELinuxが原因のエラー例
nginx: [emerg] open() "/usr/share/nginx/html/index.html" failed (13: Permission denied)「SELinux を disabled にすれば解決する」という情報を見かけますが、セキュリティリスクが高まるため非推奨です。正しい対処法は :z または :Z フラグを使うことです。
:z(共有ラベル)と :Z(プライベートラベル)の使い分け
:z(小文字):共有ラベル。container_file_tというラベルを付与し、複数のコンテナから同じディレクトリにアクセスできるようにする:Z(大文字):プライベートラベル。コンテナ固有のラベルを付与し、そのコンテナだけがアクセスできるようにする
compose.yaml での書き方は以下の通りです。
services:
web:
image: nginx:latest
ports:
- "8080:80"
volumes:
# 複数コンテナで共有する場合は :z(小文字)
- ./html:/usr/share/nginx/html:z
# このコンテナ専用の場合は :Z(大文字)・読み取り専用の場合は ,ro も追加
- ./conf/nginx.conf:/etc/nginx/nginx.conf:Z,roSELinuxの状態確認コマンド
# SELinuxの動作モードを確認
getenforce
# Enforcing と表示されれば有効
# :z/:Z 設定後のファイルラベルを確認
ls -Z ./html/
# system_u:object_r:container_file_t:s0 と表示されれば正しく設定済みコンテナの起動順序を正しく制御する(depends_on + healthcheck)
depends_on だけでは不十分な理由
depends_on を使えばコンテナの起動順序を指定できますが、これだけでは「コンテナが起動した」ことしか保証しません。データベースの場合、コンテナが起動してからMySQL/PostgreSQLのプロセスが接続を受け付けるまでに数秒〜数十秒かかることがあります。
その結果、「MySQLコンテナは起動しているのに、WordPressが接続エラーで落ちる」という問題が発生します。
# これだけでは不十分
services:
app:
depends_on:
- db # dbコンテナの「起動」は待つが「準備完了」は待たないhealthcheck + condition: service_healthy で解決する
depends_on に condition: service_healthy を指定すると、依存先のヘルスチェックが通るまで起動を待機します。これにより「データベースが実際に接続可能になってからアプリを起動する」という制御が可能になります。service_started(デフォルト)との違いは、コンテナ起動の確認だけでなく、サービスの「準備完了」まで待つ点です。
WordPress + MySQL の完全な実装例
services:
db:
image: mysql:8.0
container_name: wp-mysql
restart: unless-stopped
environment:
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
MYSQL_DATABASE: ${MYSQL_DATABASE}
MYSQL_USER: ${MYSQL_USER}
MYSQL_PASSWORD: ${MYSQL_PASSWORD}
volumes:
- db-data:/var/lib/mysql
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost",
"-u", "root", "-p${MYSQL_ROOT_PASSWORD}"]
interval: 5s
timeout: 5s
retries: 20
start_period: 10s
wordpress:
image: wordpress:latest
container_name: wp-app
restart: unless-stopped
depends_on:
db:
condition: service_healthy
ports:
- "8080:80"
environment:
WORDPRESS_DB_HOST: db
WORDPRESS_DB_USER: ${MYSQL_USER}
WORDPRESS_DB_PASSWORD: ${MYSQL_PASSWORD}
WORDPRESS_DB_NAME: ${MYSQL_DATABASE}
volumes:
- wp-data:/var/www/html
volumes:
db-data:
wp-data:healthcheck ブロックの各設定値の意味は以下の通りです。
- test:ヘルスチェックで実行するコマンド。MySQLの場合は
mysqladmin ping(認証情報付き)が確実 - interval:チェックの実行間隔(この例では5秒ごと)
- timeout:チェックのタイムアウト時間
- retries:連続失敗の許容回数。この回数を超えると unhealthy(異常)と判定
- start_period:コンテナ起動後、ヘルスチェック開始までの猶予時間
環境変数の外部化と .env ファイルの使い方
前のセクションの compose.yaml では ${MYSQL_ROOT_PASSWORD} のように変数を使っていました。パスワードなどの機密情報を compose.yaml に直接書くのはセキュリティ上好ましくありません。.env ファイルを使って環境変数を外部化しましょう。
.env ファイルの書き方と自動読み込み
compose.yaml と同じディレクトリに .env ファイルを作成します。Docker Compose は自動的にこのファイルを読み込み、compose.yaml 内の ${変数名} を置き換えます。
# .env ファイル(compose.yaml と同じディレクトリに配置)
MYSQL_ROOT_PASSWORD=my-secret-rootpass
MYSQL_DATABASE=wordpress
MYSQL_USER=wpuser
MYSQL_PASSWORD=my-secret-wppass.env ファイルにはクォーテーション(引用符)を付けないのが基本です。MYSQL_PASSWORD="pass" と書くと、ダブルクォーテーションも値の一部として解釈される場合があります。
.gitignore でセキュリティを確保する
.env ファイルには機密情報が含まれるため、Gitリポジトリにコミットしてはいけません。.gitignore に必ず追加しましょう。
# .gitignore に追加
.env代わりに、変数名だけを記載した .env.example をリポジトリに含めておくと、他のメンバーが必要な変数を把握できます。
# .env.example(リポジトリに含める・値は空にしておく)
MYSQL_ROOT_PASSWORD=
MYSQL_DATABASE=
MYSQL_USER=
MYSQL_PASSWORD=docker compose config でデバッグする
環境変数が正しく展開されているか確認するには、docker compose config コマンドが便利です。
# 変数展開後の compose.yaml を表示(構文エラーのチェックにも使える)
docker compose configよく使う docker compose コマンド一覧
# コンテナをバックグラウンドで起動
docker compose up -d
# コンテナの状態を確認
docker compose ps
# ログを表示(リアルタイム追跡)
docker compose logs -f
# 特定サービスのログだけ表示
docker compose logs -f wordpress
# コンテナを停止(コンテナとネットワークを削除)
docker compose down
# コンテナ + ボリュームも削除(データも消える)
docker compose down -v
# イメージを再ビルドして起動
docker compose up -d --build
# 変数展開後の設定を確認
docker compose configよくある質問(FAQ)
- docker-compose と docker compose、どちらを使えばいい?
docker compose(スペース区切り・v2)を使ってください。ハイフン区切りのdocker-composeはv1であり、2023年6月にEOL(サポート終了)しています。Docker Engine をインストールすれば、v2 プラグインが自動的に利用可能です。- version: はいつまで書けばいい?
現在は不要です。削除を推奨します。Compose Specification に統一されたため、
version:を書いても無視されます。Docker Compose v2.x 以降では「obsolete(廃止)」という警告が表示されます。混乱を避けるため削除しましょう。- SELinuxを無効にしてはダメ?
セキュリティリスクが高まるため非推奨です。SELinux はコンテナからのホスト侵害を防ぐ重要なセキュリティ機構です。ボリュームマウントの Permission denied は
:zまたは:Zフラグで正しく対処しましょう。名前付きボリュームを使えば、SELinuxの問題自体が発生しません。- depends_on だけでDBが起動前にアプリが動いてしまう
healthcheckとcondition: service_healthyを組み合わせてください。depends_onのデフォルト(condition: service_started)はコンテナの起動のみを待つため、データベースプロセスの準備完了は保証しません。この記事のWordPress + MySQLの例を参考に、mysqladmin ping(認証情報付き)のヘルスチェックを設定しましょう。
まとめ
この記事では、Docker Compose の基本から実践的なテクニックまでを解説しました。重要なポイントを振り返ります。
- Docker Compose v2(
docker compose)を使う。v1(docker-compose)は2023年EOL済み - compose.yaml の
version:は廃止済み。services / volumes / networks の3要素で構成する - SELinux環境ではバインドマウントに
:z(共有)/:Z(プライベート)を付ける。名前付きボリュームなら不要 - 起動順序制御は
depends_on+healthcheck+condition: service_healthyで確実に行う - 環境変数は
.envファイルに外部化し、.gitignoreで管理する
Docker Compose を使いこなせるようになると、開発環境の構築が格段に効率化します。次のステップとして、Docker ネットワークの詳細設計やマルチステージビルドを学ぶと、より本格的なコンテナ運用に対応できるようになります。

コメント