解説
Docker Composeのexecとrunは何が違う?起動中と一回用の実行先を比べよう
Docker Composeでコマンドを実行したいとき、execとrunは似て見えるよね。でも、一番大きな違いは**どのコンテナーで動くか**。起動中のものへ入るのか、一時的な別コンテナーを作るのかを分けよう。

Docker Composeでコマンドを実行したいとき、execとrunは似て見えるよね。でも、一番大きな違いはどのコンテナーで動くか。起動中のものへ入るのか、一時的な別コンテナーを作るのかを分けよう。
実行先の違い
| コマンド | 主な実行先 |
|---|---|
| docker compose exec | すでに起動しているサービスのコンテナー |
| docker compose run | サービス設定を使って新しく作る一回用コンテナー |
execは対象が動いている必要がある。runは通常のサービスコンテナーそのものを開く操作ではないため、「同じサービス名だから同じ作業ファイルがある」とは限らないよ。
カウンターの値で考える
例えば、コンテナー内部だけの/tmpにメモを作った場合、execで同じコンテナーを読むと、そのメモを確認できる。一方、新しく作ったrunのコンテナーでは、共有ボリュームなどに置いていなければ、そのメモはない。
docker compose exec -T app cat /tmp/practice-note
docker compose run --rm --no-deps app cat /tmp/practice-note
これは実行先を示す例で、appというサービスやファイルが自動で用意されるわけではないよ。既存の本番サービスへそのまま貼らず、後述の練習構成で試そう。
使い捨ての構成で試す
練習用Compose設定は、Nodeのコンテナーを待機させるだけの構成。ソースや秘密情報のマウント、ホスト向けポートの公開は含めていない。Dockerが使える専用の空フォルダーへ保存して実行する。
docker compose -p exec-run-practice up -d
docker compose -p exec-run-practice exec -T app sh -c 'printf "inside\n" > /tmp/practice-note'
docker compose -p exec-run-practice exec -T app cat /tmp/practice-note
docker compose -p exec-run-practice run --rm --no-deps app sh -c 'test ! -e /tmp/practice-note && echo separate'
docker compose -p exec-run-practice down
起動済みの側ではinside、一回用の側ではseparateとなる。編集部では隔離した練習プロジェクトで同じ違いを確認したよ。最後のdownは、この練習プロジェクトのコンテナーとネットワークを片付ける操作だよ。
runのポートにも注意
公式のrun説明は、サービスに設定されたポートを通常そのまま公開しないと説明している。通常起動と同じ通信経路だと思い込まないでね。--rmは一回用コンテナーの終了後の削除、--no-depsは依存サービスを起動しない指定。
起動中の状態を調べたいならexec、独立した一回の処理ならrunが候補。どちらも、共有ボリュームやDBへ接続する設定なら、外部のデータへ影響し得ることは変わらないよ。

みんなのコメント 0
感想や、試してみたことを聞かせてね。コメント・返信は承認後に公開されます。
最初のコメントをどうぞ。