問題の概要
誰もが経験することですが、docker run を実行してアプリが起動するのを待っていると、即座にクラッシュしてしまうことがあります。アプリケーションのログの代わりに表示されるのは、OCI (Open Container Initiative) ランタイムからの大量のテキストです。これは、Docker がコンテナの検索パス内に存在しないコマンドを実行しようとしているために発生します。
エラーは通常、以下のようになります。
OCI runtime create failed: container_linux.go:349: starting container process caused "exec: \"python\": executable file not found in $PATH": unknown
この例では「python」が指摘されていますが、node、npm、sh、あるいはイメージに追加したばかりのカスタムシェルスクリプトでも、まったく同じ現象が発生します。
TL;DR: クイック解決策
- バイナリ名を確認する: Ubuntu 22.04 や Debian Bullseye などの最新イメージでは
python3を使用します。pythonコマンドはマッピングされていないことがよくあります。 - 絶対パスを使用する: 推測に頼るのはやめましょう。
CMD ["python", "app.py"]をCMD ["/usr/bin/python3", "app.py"]に変更してください。 - ベースイメージを調査する:
alpineのような最小限のイメージ(わずか 5MB 程度)には、ほとんど何も含まれていません。ツールは手動でインストールする必要があります。 - PATH を設定する: カスタムディレクトリを使用する場合は、Dockerfile 内で
ENV PATH="/your/path:${PATH}"を使用します。
主な原因
1. Python 2 と Python 3 の名前の競合
これが最大の原因です。古い Linux ディストリビューションでは python コマンドがバージョン 2.7 にリンクされていました。Python 2 がサポートを終了して以来、最新のベースイメージからは完全に削除されています。python:3.11-slim を使用する場合、バイナリ名は通常 python です。しかし、生の ubuntu:latest イメージから開始して apt install python3 を実行した場合、システムは python3 しか認識しません。Docker が自動的にエイリアスを作成することはありません。
2. 「最小限のイメージ」という罠
Alpine Linux はその軽量さから本番環境で好まれますが、注意点があります。GNU ツールの代わりに musl libc と busybox を使用しています。スクリプトが #!/bin/bash で始まっている場合、Alpine コンテナにはデフォルトで /bin/sh しか存在しないため、「not found」エラーがスローされます。手元にない道具を使おうとしている状態です。
3. Docker はプロファイルをロードしない
Linux サーバーにログインすると .bashrc や .profile がロードされますが、Docker はこれを行いません。CMD を実行する際、非常に基本的な環境を使用します。バイナリを /opt/my-app/bin にインストールした場合、Dockerfile で明示的に PATH 変数を更新しない限り、Docker はそこを探しません。
ステップバイステップの解決策
方法 A: コマンドの構文を更新する
ログで python について指摘されている場合は、python3 に切り替えてみてください。これは Debian ベースのイメージにおける最も迅速な修正方法です。
# 修正前(エラーが発生する):
CMD ["python", "main.py"]
# 修正後(動作する):
CMD ["python3", "main.py"]
方法 B: 絶対パスを使用する
ファイルがどこにあるかを Docker に正確に伝えることで、推測を排除します。場所がわからない場合は、一時的なコンテナを実行して確認してください。
docker run --rm python:3.9-slim which python
そのパス(例:/usr/local/bin/python)がわかったら、Dockerfile を更新します。
ENTRYPOINT ["/usr/local/bin/python", "app.py"]
方法 C: 不足しているパッケージをインストールする(Alpine の場合)
Alpine を使用していて Python が必要な場合は、ビルド中に追加する必要があります。パッケージマネージャーの apk を使用します。また、python コマンドが期待どおりに動作するようにシンボリックリンクを作成することもできます。
FROM alpine:3.19
# python3 をインストールし、シンボリックリンクを作成する
RUN apk add --no-cache python3 && ln -sf python3 /usr/bin/python
WORKDIR /app
COPY . .
CMD ["python", "app.py"]
方法 D: 手動で PATH を設定する
カスタムバイナリの場合は、その場所を環境変数に明示的に追加します。これにより、Docker が探索を諦める前にカスタムフォルダを確認するようになります。
FROM node:20-slim
WORKDIR /app
COPY . .
# カスタムスクリプトを検出可能にする
ENV PATH="/app/scripts:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
CMD ["run-custom-task"]
修正の検証方法
CI/CD パイプライン全体を再構築して時間を無駄にしないでください。イメージを対話的にデバッグして、ファイルシステム内で実際に何が起きているかを確認しましょう。
docker run --rm -it --entrypoint /bin/sh your-image-name
コンテナ内に入ったら、次の 3 つのコマンドを実行します。
echo $PATH: アプリが存在するフォルダが含まれていますか?which python3: OS は実際にバイナリを認識していますか?ls -l /usr/bin/python*: インストールされているバージョンを正確に確認します。
まとめチェックリスト
- パッケージは実際に Dockerfile でインストールされていますか?
CMDやENTRYPOINTにスペルミスはありませんか?- イメージに
python3しかないのにpythonを呼び出していませんか? - スクリプトのシバン(例:
#!/bin/bash)は、イメージ内に存在するシェルと一致していますか? - 「exec 形式」(JSON の角括弧)を使用していますか?
["cmd"]はシェルを使用しないため、生の文字列のようにエイリアスや変数を解決しないことに注意してください。

