【Docker】コンテナがすぐ終了する(Exited)原因と解決策まとめ

Dockerエラー対処

Dockerコンテナがすぐ終了してしまう現象とは?

Dockerを使い始めたばかりの方が最初につまずきやすいのが、コンテナを起動してもすぐに止まってしまうという現象です。

docker ps でコンテナ一覧を確認しても何も表示されず、docker ps -a を実行すると以下のように「Exited」と表示されている――そんな経験はありませんか?

$ docker ps -a
CONTAINER ID   IMAGE     COMMAND       CREATED          STATUS                     PORTS   NAMES
a1b2c3d4e5f6   ubuntu    "/bin/bash"   10 seconds ago   Exited (0) 8 seconds ago           my-container

「コンテナがすぐ落ちる」「動かない」と感じる原因はいくつかのパターンに分類できます。この記事では、代表的な原因と具体的な解決策をコード例付きで解説します。

原因1:フォアグラウンドプロセスがない(Exited (0))

なぜ終了するのか

Dockerコンテナは、メインプロセス(PID 1)が終了するとコンテナ自体も終了する仕組みです。これはコンテナのライフサイクルにおける最も基本的なルールです。詳しくはコンテナのライフサイクルの記事で解説しています。

たとえば以下のコマンドでUbuntuコンテナを起動した場合、デフォルトのコマンド(/bin/bash)は入力を受け付ける端末がないため即座に終了します。

$ docker run ubuntu
# → 何も表示されず、すぐにプロンプトに戻る

docker ps -a で確認すると Exited (0) と表示されます。終了コード 0 は「正常終了」を意味するため、エラーではなく「やることがなくなったから終了した」という状態です。

解決策

方法1:-it オプションで対話モードにする

コンテナ内で対話的に操作したい場合は、-it オプションを付けて起動します。-i は標準入力を開いたままにし、-t は疑似端末を割り当てます。

$ docker run -it ubuntu /bin/bash
root@a1b2c3d4e5f6:/# 

これでコンテナ内のシェルに入り、操作できるようになります。docker run -it の詳しい使い方はこちらの記事を参照してください。

方法2:-d オプション + 常駐プロセスでバックグラウンド実行する

Webサーバーなどを動かす場合は、-d(デタッチモード)で起動します。ただし、コンテナ内でフォアグラウンドで動き続けるプロセスが必要です。

# Nginxはフォアグラウンドで動くため、コンテナが維持される
$ docker run -d --name web nginx

# 起動確認
$ docker ps
CONTAINER ID   IMAGE   COMMAND                  STATUS         PORTS     NAMES
b2c3d4e5f6a7   nginx   "/docker-entrypoint.…"   Up 5 seconds   80/tcp    web

docker run -d についてはdocker run -d の記事で詳しく解説しています。

💡 補足:単にコンテナを起動し続けたいだけなら、以下のように tail -f /dev/null を実行させる方法もあります。

$ docker run -d ubuntu tail -f /dev/null

原因2:コマンドやスクリプトにエラーがある(Exited (1) / Exited (2))

なぜ終了するのか

コンテナ起動時に指定したコマンドやDockerfileの CMD / ENTRYPOINT で実行されるスクリプトにエラーがあると、コンテナはすぐに終了します。このとき Exited (1)Exited (2) のようにゼロ以外の終了コードが表示されます。

$ docker run ubuntu cat /nonexistent-file
cat: /nonexistent-file: No such file or directory

$ docker ps -a
CONTAINER ID   IMAGE    COMMAND                    STATUS                    NAMES
c3d4e5f6a7b8   ubuntu   "cat /nonexistent-fi…"   Exited (1) 2 seconds ago   bold_pike

解決策

手順1:ログを確認する

docker logs コマンドでコンテナの出力を確認し、エラーの原因を特定します。

$ docker logs c3d4e5f6a7b8
cat: /nonexistent-file: No such file or directory

手順2:コマンドを修正して再実行する

エラー内容を確認したら、正しいコマンドやパスに修正して再度実行します。

# 正しいファイルパスに修正
$ docker run ubuntu cat /etc/os-release

⚠️ 注意:Dockerfileの CMDENTRYPOINT に記述されたコマンドが原因の場合は、Dockerfileを修正してイメージを再ビルドする必要があります。

原因3:Dockerfileの CMD / ENTRYPOINT の記述ミス

なぜ終了するのか

Dockerfileで CMDENTRYPOINT の書き方を間違えると、意図したプロセスが起動せずにコンテナがすぐ終了します。よくあるミスを以下にまとめます。

ミスの内容 問題点
コマンドのパスが間違っている CMD ["/usr/bin/myap"] ファイルが見つからずエラー終了
シェル形式とexec形式の混同 ENTRYPOINT /app/start.sh シェル形式だとシグナル処理に問題が出る場合がある
実行権限がない CMD ["./start.sh"] permission denied で終了

解決策

手順1:コンテナに入ってデバッグする

エントリポイントを上書きしてコンテナに入り、問題を調査します。

# エントリポイントを /bin/bash に上書きして対話シェルに入る
$ docker run -it --entrypoint /bin/bash my-image

# コンテナ内でスクリプトの存在と権限を確認
root@container:/# ls -la /app/start.sh
root@container:/# cat /app/start.sh

手順2:Dockerfileを修正する

# 修正前(権限なし)
COPY start.sh /app/start.sh
CMD ["./app/start.sh"]

# 修正後(実行権限を付与 + パスを正しく指定)
COPY start.sh /app/start.sh
RUN chmod +x /app/start.sh
CMD ["/app/start.sh"]

修正後はイメージを再ビルドします。

$ docker build -t my-image .
$ docker run -d my-image

原因4:依存サービスの起動前にアプリが接続を試みている(Exited (1))

なぜ終了するのか

Docker Composeで複数のコンテナを連携させる場合、アプリケーションコンテナがデータベースなどの依存サービスより先に起動し、接続に失敗してすぐ終了するケースがあります。

$ docker compose up
db_1   | Initializing database...
app_1  | Error: connect ECONNREFUSED 172.18.0.2:5432
app_1 exited with code 1

depends_on を設定していても、これは「起動順序」を保証するだけで「依存サービスが準備完了している」ことは保証しません。

解決策

方法1:depends_oncondition を指定する(Docker Compose v2)

services:
  db:
    image: postgres:15
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 5s
      timeout: 5s
      retries: 5
  app:
    build: .
    depends_on:
      db:
        condition: service_healthy

方法2:アプリ側でリトライロジックを入れる

エントリポイントのスクリプトで、データベースが応答するまで待つ処理を追加します。

#!/bin/bash
# wait-for-db.sh
echo "Waiting for database..."
until pg_isready -h db -U postgres; do
  sleep 2
done
echo "Database is ready!"
exec "$@"

原因5:メモリ不足でプロセスが強制終了される(Exited (137))

なぜ終了するのか

終了コード 137 は、プロセスが SIGKILL(シグナル番号9)によって強制終了されたことを示します(128 + 9 = 137)。多くの場合、コンテナに割り当てられたメモリの上限を超えた(OOM: Out Of Memory)ことが原因です。

$ docker ps -a
CONTAINER ID   IMAGE    STATUS                      NAMES
d4e5f6a7b8c9   my-app   Exited (137) 5 seconds ago   my-app

解決策

手順1:メモリ制限を確認する

# コンテナのメモリ使用状況を確認
$ docker stats --no-stream

# メモリ制限の詳細を確認
$ docker inspect my-app | grep -i memory

手順2:メモリ制限を緩和する

# メモリ上限を増やして起動
$ docker run -d --memory=512m --name my-app my-image

# Docker Composeの場合
services:
  app:
    image: my-image
    deploy:
      resources:
        limits:
          memory: 512M

💡 補足:根本的には、アプリケーション自体のメモリ使用量を最適化することも重要です。例えばJavaアプリであれば -Xmx オプションでヒープサイズを適切に設定しましょう。

デバッグに役立つコマンドまとめ

コンテナがすぐ終了する問題を調査するとき、以下のコマンドが役立ちます。Docker主要コマンドの一覧はこちらの記事も参考にしてください。

コマンド 用途
docker ps -a 停止中のコンテナも含めて一覧表示。STATUS欄で終了コードを確認
docker logs コンテナ名 コンテナの標準出力・標準エラー出力を確認
docker inspect コンテナ名 コンテナの詳細設定(メモリ制限、環境変数など)を確認
docker run -it --entrypoint /bin/bash イメージ名 エントリポイントを上書きしてコンテナ内を調査
docker stats 実行中コンテナのCPU・メモリ使用状況をリアルタイム表示

まとめ

Dockerコンテナがすぐ終了(Exited)する主な原因と対処法を振り返ります。

  • Exited (0):フォアグラウンドプロセスがない → -it-d オプション、常駐プロセスの指定で解決
  • Exited (1) / Exited (2):コマンドやスクリプトのエラー → docker logs で原因を確認して修正
  • Exited (1) + 依存サービス:接続先が未準備 → ヘルスチェックやリトライロジックで対応
  • Exited (137):メモリ不足(OOM Kill) → メモリ制限の見直しやアプリの最適化
  • 共通の調査手順:まず docker ps -a で終了コードを確認し、docker logs で詳細を調べる

コンテナがすぐ止まる・すぐ落ちるときは、まず終了コードの数字を確認するところから始めましょう。終了コードがわかれば、この記事で紹介した対処法で多くのケースを解決できます。

Dockerの基礎を動画で体系的に学びませんか?

実務で使う基礎だけを3時間に凝縮。環境構築から丁寧に解説しています。

Udemy Docker入門講座 クーポン割引で講座を見る →

コメント

タイトルとURLをコピーしました