テスト実行時にデータベースコンテナだけ動かしたい、シェルスクリプトの挙動を確かめたい。そういった「コマンドを1回実行して終わり」の作業は、開発やCI パイプラインで頻繁に発生します。
その用途に設計されているのが docker compose run です。
この記事では、docker compose run の基本的な使い方から、docker compose exec・up との違い、データベースマイグレーションとテスト実行への応用まで解説します。Ubuntu 24.04 LTS および Docker Compose v2 系(compose-plugin)を想定環境として説明します。
この記事のポイント
・docker compose run はコンテナを1回起動してコマンドを実行・終了する命令
・--rm フラグを付けると実行後にコンテナが自動削除される
・exec は「起動済みのコンテナ」への接続で、run とは用途が異なる
・マイグレーション実行・テスト実行のCI設計に活用できる
でも安心してください。プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
docker compose run が解決する問題
docker compose up は、定義されたサービスを継続的に起動・維持するための命令です。Webサーバー・データベース・キャッシュサーバーを一括で起動するには便利ですが、「データベースのマイグレーションを走らせたい」「テストを1回実行したい」という用途には向いていません。サービスを継続稼働させずに「コマンドを1回実行する」ための命令が docker compose run です。
主な用途は次のとおりです。
・データベースのマイグレーション(例: flask db migrate、php artisan migrate)
・テストスイートの実行(例: pytest、phpunit)
・データのシードや初期化スクリプト
・使い捨ての調査用コンテナ(bash起動)
docker compose run は、compose ファイルで定義されたサービスの設定(イメージ・ボリューム・環境変数・ネットワーク)を引き継ぎながら、指定したコマンドを実行します。これにより、開発環境と同じ設定でコマンドを走らせられます。
docker compose run の基本的な書き方
1. サービスを指定してコマンドを1回実行する
docker compose run の基本構文は次のとおりです。docker compose run SERVICE COMMAND [ARGS...]
# docker-compose.yml services: web: image: python:3.12-slim volumes: - .:/app working_dir: /app depends_on: - db db: image: postgres:16 environment: POSTGRES_DB: myapp POSTGRES_USER: myuser POSTGRES_PASSWORD: secret
docker compose run web python manage.py migrate
2. --rm フラグで使い捨てコンテナにする
実行のたびに停止コンテナが溜まるのを防ぐには、--rm フラグを付けます。docker compose run --rm web python manage.py migrate
3. エントリポイントと環境変数を上書きする
docker compose run は、起動時にコンテナのエントリポイントとコマンドを上書きできます。bash でコンテナ内を調査するには次のように書きます。
docker compose run --rm --entrypoint /bin/bash web
docker compose run --rm -e APP_ENV=test web python manage.py test
docker compose run --rm --no-deps web python -m pytest tests/unit/
docker compose exec・up との使い分け
1. exec は起動済みコンテナへの接続
docker compose exec は、すでに起動しているコンテナ内でコマンドを実行します。docker compose exec web bash
・run: 新しいコンテナを起動してコマンドを実行する
・exec: 起動済みのコンテナ内でコマンドを実行する(コンテナを新規作成しない)
docker compose up でサービスが稼働中のときに調査・設定の確認をしたい場合は exec を使います。逆に、サービスが起動していない状態でコマンドを実行したい場合は run を使います。exec を使おうとしてサービスが起動していないとエラーになるため、ここを混同するとトラブルの原因になります。
2. up --no-deps で単一サービスを起動する
docker compose up --no-deps SERVICE は、指定したサービスだけを起動して維持します。docker compose up --no-deps -d web
3つの命令の使い分けを整理すると次のようになります。
・コマンドを1回実行して終わる → docker compose run --rm
・起動中コンテナに接続して調査する → docker compose exec
・サービスを継続稼働させる(依存なし)→ docker compose up --no-deps
Dockerコンテナの設計パターンについて体系的に学びたい場合は、Dockerセミナー(linuxmaster.jp)のカリキュラムも参考になります。
実践:マイグレーションとテスト実行のCompose設計
1. データベースマイグレーションを docker compose run で自動化する
データベースコンテナが起動している状態で、マイグレーションコマンドを実行するパターンです。healthcheck を使うと、db が準備完了になるまで待ってから web を起動できます。
# docker-compose.yml services: db: image: postgres:16 environment: POSTGRES_DB: myapp POSTGRES_USER: myuser POSTGRES_PASSWORD: secret healthcheck: test: ["CMD-SHELL", "pg_isready -U myuser"] interval: 5s retries: 5 web: build: . depends_on: db: condition: service_healthy environment: DATABASE_URL: postgresql://myuser:secret@db:5432/myapp volumes: - .:/app working_dir: /app
docker compose run --rm web python manage.py migrate
Dockerfile のエントリポイントにマイグレーションを組み込む設計もありますが、マイグレーション失敗時にアプリが起動できなくなる問題が発生しやすいです。run で分離しておくほうが、失敗の原因が明確になります。
出力例(環境により異なります):
Operations to perform: Apply all migrations: auth, contenttypes, myapp, sessions Running migrations: Applying myapp.0001_initial... OK Applying myapp.0002_add_user... OK
2. テストスイートの実行とCI連携
テスト用のサービスを Compose ファイルに定義して run で呼び出す設計がCI では一般的です。# docker-compose.yml services: db: image: postgres:16 environment: POSTGRES_DB: testdb POSTGRES_USER: testuser POSTGRES_PASSWORD: testpass test: build: . depends_on: - db environment: DATABASE_URL: postgresql://testuser:testpass@db:5432/testdb APP_ENV: test volumes: - .:/app working_dir: /app
# .github/workflows/test.yml 抜粋 - name: テストを実行する run: docker compose run --rm test pytest tests/ - name: コンテナを片付ける run: docker compose down -v
終了コードの扱いにも注意が必要です。docker compose run は実行したコマンドの終了コードをそのまま返します。pytest がテスト失敗で終了コード 1 を返せば、CI パイプラインは失敗として扱います。これにより、テスト失敗時に自動でデプロイを止める設計が自然に実現できます。
よくある問題と対処法
問題1: 実行後に停止コンテナが溜まっている原因: --rm を付けずに run を繰り返した場合、停止したコンテナが残り続けます。
対処: --rm を常に付けるか、docker compose rm で停止コンテナをまとめて削除します。
# 停止済みコンテナをまとめて削除する docker compose rm -f
原因: --no-deps を付けると depends_on に指定したサービスは起動しません。db が必要なコマンドで --no-deps を使うと、接続先がないためエラーになります。
対処: db が必要な場合は --no-deps を外します。db だけを先に起動しておく方法もあります。
# db だけを先に起動する docker compose up -d db # その後 web サービスでマイグレーションを実行する docker compose run --rm web python manage.py migrate
原因: docker compose run はデフォルトでポートをホストに公開しません。compose ファイルの ports 設定は run 時には自動適用されません。
対処: -p オプションでポートを明示的に指定します。
docker compose run --rm -p 8080:8080 web python manage.py runserver 0.0.0.0:8080
まとめ
docker compose run の主なオプションをまとめます。| やりたいこと | コマンド |
|---|---|
| コマンドを1回実行する | docker compose run SERVICE COMMAND |
| 実行後にコンテナを自動削除する | docker compose run --rm SERVICE COMMAND |
| 依存サービスを起動せずに実行する | docker compose run --rm --no-deps SERVICE COMMAND |
| エントリポイントを上書きしてbashを起動する | docker compose run --rm --entrypoint /bin/bash SERVICE |
| 環境変数を一時的に変更して実行する | docker compose run --rm -e VAR=value SERVICE COMMAND |
| ポートを指定して実行する | docker compose run --rm -p HOST:CONTAINER SERVICE COMMAND |
| 起動済みコンテナにコマンドを実行する | docker compose exec SERVICE COMMAND |
マイグレーション・テスト実行・初期化スクリプトをすべて run で統一しておくと、CI パイプラインの組み立てがシンプルになります。
Dockerコンテナの設計から本番運用まで、体系的に学べるセミナーを開催しています。
詳細・日程は >> https://docker.linuxmaster.jp/ からご確認ください。
3,100名以上が実践した「型」を無料で公開中
プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
その「型」を図解60Pにまとめた入門マニュアルを、完全無料でプレゼントしています。
姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら
- 前のページへ:NVIDIAのGPUをDockerfileで活用する|CUDA環境コンテナ構築の実践手順
- この記事の属するカテゴリ:Dockerへ戻る

無料メルマガで学習を続ける
Linuxの実践スキルをメールで毎週お届け。
登録は30秒、解除もいつでも可。
登録無料・いつでも解除できます