Docker で「OCI runtime exec failed: exec failed: container_linux.go」エラーが出る原因と対処法

Docker を日常的に使っていると、docker exec を使ってコンテナに入ろうとした際に以下のようなエラーに出会うことがあります。

OCI runtime exec failed: exec failed: container_linux.go:380: starting container process caused: exec: "bash": executable file not found in $PATH: unknown

一見すると複雑そうなメッセージですが、実際の原因は 「コンテナの中に bash が存在しない」 または 「ENTRYPOINT の設定が干渉している」 といった単純な構成ミスであることがほとんどです。

本記事では、この「OCI runtime exec failed」エラーの意味を分解し、Docker イメージ・コンテナ設定・環境依存要因の観点から再現例と対処法を詳しく解説します。

1. エラーの発生原因を理解する

まず、エラーメッセージの中身を分解してみましょう。

OCI runtime exec failed: exec failed: container_linux.go:380: starting container process caused: exec: "bash": executable file not found in $PATH: unknown

このメッセージは、Docker の実行環境である OCI Runtime (runc など) が、指定されたコマンドをコンテナ内で実行できなかったことを示しています。
特に次のようなケースで発生します。

  • コンテナに bash がインストールされていない
  • ENTRYPOINT の設定が sh や別のバイナリに置き換えられている
  • コンテナがすでに終了している
  • docker exec の対象が存在しないプロセス状態

このようなとき、Docker はホスト側でシェルを見つけられず、実行を中断します。

確認コマンド例

まず、対象コンテナが実行中かどうかを確認しましょう。

docker ps

もし Exited 状態なら、コンテナがすでに終了しています。その場合は、再起動が必要です。

docker start -ai <container_id>

2. bash が存在しないイメージの例

軽量な Linux ベースイメージ(特に alpine 系)は、bash を含まないことが多いです。代わりに sh しか入っていません。

以下の例では、Alpine イメージを使ってコンテナを作成しています。

docker run -it alpine

ここで次のように bash を実行するとエラーになります。

docker exec -it <container_id> bash

結果として、次のようなエラーが出ます。

OCI runtime exec failed: exec failed: container_linux.go:380: exec: "bash": executable file not found in $PATH: unknown

対処法

代わりに /bin/sh を指定することでコンテナに入れます。

docker exec -it <container_id> sh

もし bash が必要なら、Dockerfile に以下を追記して再ビルドします。

RUN apk add --no-cache bash

これで bash がインストールされ、エラーが解消します。

3. ENTRYPOINT 設定による干渉

Dockerfile の ENTRYPOINTCMD の設定が適切でない場合、docker exec のコマンドが正しく解釈されないことがあります。

例えば以下のような Dockerfile を考えます。

FROM node:20-alpine
ENTRYPOINT ["node"]

この設定では、コンテナの実行時に node が常に実行されるため、docker exec -it <id> sh を実行しても失敗します。

対処法

ENTRYPOINT を明示的に上書きして起動することで回避できます。

docker run -it --entrypoint sh node:20-alpine

または ENTRYPOINT をスクリプトに委譲し、環境変数で切り替える方法もあります。

ENTRYPOINT ["/entrypoint.sh"]
#!/bin/sh
if [ "$RUN_MODE" = "shell" ]; then
  exec sh
else
  exec node "$@"
fi

このように柔軟な起動方式をとることで、docker exec のデバッグ性を保ちながら本番運用にも耐えられる設計になります。

4. container_linux.go エラーの内部構造

container_linux.go は Docker の実行エンジン(runc)が Linux コンテナを起動・操作する際に利用する Go ソースコードです。
そのため、このエラーは Docker の内部実装 から出ているもので、直接修正することはできません。

ただし、エラー行数やモジュール名はデバッグの手掛かりになります。
たとえば次のようなパターンです。

  • container_linux.go:380: 実行バイナリが見つからない
  • container_linux.go:370: 権限不足(permission denied)
  • container_linux.go:345: 環境変数または PATH 設定が壊れている

もし権限の問題が疑われる場合は、--user オプションの指定や Dockerfile のユーザー設定を見直します。

docker exec -u root -it <container_id> sh

5. CI/CD 環境での再現と対策

このエラーは CI/CD パイプライン(GitHub Actions, GitLab CI, CircleCI など)でも発生します。特に以下のケースが多いです。

  • 実行中のコンテナが sleep 等で保持されておらず既に終了している
  • docker exec を呼び出す前に docker run が完了している
  • CI 環境で ENTRYPOINT が上書きされている

例: GitHub Actions での対処法

- name: Run container
  run: docker run -d --name app node:20-alpine sleep infinity

- name: Execute command inside container
  run: docker exec app sh -c "echo Hello"

CI では「コンテナを常駐させる」ために sleep infinitytail -f /dev/null を ENTRYPOINT に設定しておくのが定番です。これで docker exec 実行時にコンテナが存在し続けるため、OCI runtime exec failed を回避できます。

6. 実務でのチェックリスト

このエラーに遭遇した場合、以下の項目を順に確認してください。

  1. コンテナが実行中か (docker ps)
  2. 対象のコマンド(bash, sh)がコンテナに存在するか (docker exec <id> which bash)
  3. ENTRYPOINT が正しく設定されているか
  4. CI/CD 環境でコンテナが終了していないか
  5. ベースイメージが軽量な Alpine 系かどうか

よくある回避パターン

  • Alpine → sh で入る
  • Debian/Ubuntu → bash 利用可
  • ENTRYPOINT → sleep infinity に差し替え
  • デバッグ時 → docker run -it --entrypoint sh イメージ名

まとめ

「OCI runtime exec failed: container_linux.go」エラーは、Docker の実行プロセスがコンテナ内でコマンドを起動できなかったことを示しています。
多くの場合、bash の不在や ENTRYPOINT の衝突、またはコンテナ終了が原因です。
軽量イメージでは /bin/sh を使い、CI/CD 環境ではコンテナを長時間保持するよう工夫することで、安定した動作が得られます。

参考

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