docker『Command Not Found』の原因と対処法

docker『Command Not Found』の原因と対処法

「Command Not Found」は、docker コマンドそのものが見つからない場合と、コンテナ内で実行しようとしたコマンドが見つからない場合の両方で発生する。ホスト側の PATH 設定ミス、Docker の未インストール、ENTRYPOINT/CMD の書き方ミス、ベースイメージにコマンドが入っていない、シェルが存在しないイメージを前提にしている、などが主な原因になる。どのレイヤ(ホスト / コンテナ / ENTRYPOINT)で「見つからない」のかを切り分けると、原因にたどり着きやすくなる。

代表的なエラーメッセージと発生条件

「Command Not Found」に相当する代表的なメッセージは次のようなもの。

# ホスト側
docker: command not found
/usr/bin/docker: No such file or directory

# コンテナ内(ENTRYPOINT/CMD や docker exec の実行時)
/bin/sh: npm: not found
/bin/bash: python: command not found
sh: 1: ./start.sh: not found
exec: "app": executable file not found in $PATH

発生条件として多いものは以下。

・ホストに Docker がインストールされていない / PATH が通っていない。

・ENTRYPOINT / CMD で指定したコマンドがイメージ内に存在しない。

・ベースイメージが極端にミニマルで、想定していたシェルやツールが入っていない。

・スクリプトファイルに実行権限がない / 改行コードが CRLF。

・docker exec で実行しているコマンドがコンテナに入っていない。

ホスト側で「docker: command not found」が出る場合

ホスト側で docker コマンドが見つからないケース。

$ docker ps
bash: docker: command not found

主な原因は次の通り。

・Docker Engine / Docker Desktop がそもそもインストールされていない。

・インストールされているが PATH に含まれていない。

・別ユーザーでインストールされていて、今のユーザーから見えない。

対処例。

# 実行ファイルの場所を探す(インストール済みか確認)
which docker
type docker

# Linuxの場合、必要ならPATHを追加
export PATH="/usr/bin:/usr/local/bin:$PATH"

# インストールされていない場合はディストリの手順に従って導入
# 例: Debian/Ubuntu系
sudo apt-get update
sudo apt-get install -y docker.io

Windows/Mac では Docker Desktop のインストール・起動状態もあわせて確認する。

コンテナ内で「/bin/sh: xxx: not found」が出る場合

コンテナ自体は起動するが、ENTRYPOINT / CMD や docker exec で実行したコマンドが見つからないパターン。

# 例: Dockerfile
FROM alpine:3.19
CMD ["npm", "start"]

# 実行時
/bin/sh: npm: not found

この場合の原因は「イメージ内に npm がインストールされていない」だけ。

対処は、Dockerfile にインストール手順を追加すること。

FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
CMD ["npm", "start"]

既存のベースイメージに追加でコマンドを入れたい場合。

FROM alpine:3.19
RUN apk add --no-cache curl bash
CMD ["bash"]

イメージを pull して中身を確認するだけでも、コマンドの有無がすぐにわかる。

docker run --rm -it alpine:3.19 sh
# コンテナ内で
which bash   # → 何も出ない(未インストール)

ENTRYPOINT / CMD の書き方ミスによる「exec: … not found」

ENTRYPOINT / CMD を shell 形式で書くか exec 形式で書くかによって、コマンド解釈が大きく変わる。

よくあるNGパターン。

# NG: exec形式で1文字のスペースを含んだ文字列をそのまま第一引数にしている例
ENTRYPOINT ["npm start"]

# こうなっているのと同じ扱い → "npm start" という名前のコマンドを探してしまう

正しい書き方は、コマンドと引数を配列で分割する。

# OK: exec形式
ENTRYPOINT ["npm", "start"]

# OK: shell形式(/bin/sh -c 経由で実行)
ENTRYPOINT npm start

exec 形式を使う場合は、文字列を split してくれない点に注意する。

# NG
CMD ["python app.py"]

# OK
CMD ["python", "app.py"]

エラーメッセージ例。

exec: "npm start": executable file not found in $PATH

この場合は「npm start」という1つのコマンドを探しに行っている状態。

PATH 設定が原因でコマンドが見つからない場合

イメージ内にコマンドファイル自体は存在するが、PATH に通っていないため「not found」になるケース。

# コンテナ内
/app/bin/app
/app/bin/helper

# しかしPATHには /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin しかない
echo $PATH

# 実行時
app: command not found

対処としては、PATH を通すか、絶対パスで呼び出す。

# Dockerfile で PATH を通す例
ENV PATH="/app/bin:${PATH}"

# CMD / ENTRYPOINT で絶対パスを使う例
CMD ["/app/bin/app"]

docker exec で手作業するときも、PATH に頼るのではなく、存在確認と絶対パス実行を組み合わせると安全。

docker exec -it app sh -lc "ls -l /app/bin && /app/bin/app --version"

ベースイメージに期待コマンドやシェルが存在しない場合

alpine・distroless・scratch など、極端にミニマルなイメージでは、/bin/bash や sh すら存在しないことがある。

よくあるNG例。

# イメージはdistrolessなど
docker run --rm -it gcr.io/distroless/base bash
# → bash: not found

# Dockerfile
FROM alpine:3.19
CMD ["bash"]
# → /bin/sh: bash: not found

対処パターン。

・bash が必要なら、bashをインストールするか、最初から bash を含むベースイメージを使う。

FROM alpine:3.19
RUN apk add --no-cache bash
CMD ["bash"]

・シェルが不要なアプリ(単体のバイナリなど)なら、ENTRYPOINT をそのバイナリにする。

FROM gcr.io/distroless/base
COPY myapp /myapp
ENTRYPOINT ["/myapp"]

distroless で docker exec -it コンテナ bash/sh をしたくなるが、シェルが無いのが仕様なので、その前提で設計する。

docker exec でコンテナ内コマンドを間違えている場合

コンテナ自体は正しく動いているのに、docker exec で追加の処理をしようとして「Command Not Found」になるパターン。

# コンテナ内にcurlが入っていない
docker exec -it app curl http://localhost:8080/health
# → /bin/sh: curl: not found

この場合は、イメージの中にコマンドを追加するか、一時的にインストールしてから使う。

# 一時的にインストール(alpineの例)
docker exec -it app sh -lc "apk add --no-cache curl && curl http://localhost:8080/health"

あるいは、ホスト側からポートフォワードされたエンドポイントに curl する(コンテナ内にcurlを入れない運用にする)方法もある。

# ホスト側から
curl http://localhost:8080/health

また、exec の書き方ミスにも注意。

# NG: 引数をまとめて1つの文字列でexec形式に渡す
docker exec app "ls -l /"

# OK: シェル経由で渡す or 配列形式で渡す
docker exec app ls -l /
docker exec app sh -lc "ls -l /"

スクリプトの shebang や改行コード(bash^M: command not found)

Windows で編集したスクリプトをコンテナ内で実行すると、CRLF 改行が原因で「not found」系エラーになることがある。

./start.sh: line 1: #!/bin/bash^M: bad interpreter: No such file or directory
bash^M: command not found

対処としては、LF 改行に変換する。

# Gitでチェックアウト時にLFに変換
git config core.autocrlf false

# 既存ファイルの改行をLFへ変換(Linux)
sed -i 's/\r$//' start.sh

# Shebangが正しいか確認
head -n 1 start.sh

また、スクリプトに実行権限がない場合もコマンドとして認識されない。

chmod +x start.sh
./start.sh

Dockerfile でコピーしたスクリプトに対しても、COPY 後に chmod を付ける。

COPY start.sh /usr/local/bin/start.sh
RUN chmod +x /usr/local/bin/start.sh
ENTRYPOINT ["/usr/local/bin/start.sh"]

NG→OK 早見表(よくあるパターンと修正例)

# 1) ホスト側でdocker自体が見つからない
# NG
docker ps       # → command not found
# OK: インストール or PATH調整
sudo apt-get install -y docker.io
export PATH="/usr/bin:/usr/local/bin:$PATH"

# 2) イメージ内にコマンドがない
# NG
FROM alpine:3.19
CMD ["bash"]    # bash 無し → not found
# OK
FROM alpine:3.19
RUN apk add --no-cache bash
CMD ["bash"]

# 3) ENTRYPOINTの配列形式ミス
# NG
ENTRYPOINT ["npm start"]
# OK
ENTRYPOINT ["npm", "start"]

# 4) PATHに通っていない自作バイナリ
# NG
CMD ["app"]     # /app/appは存在するがPATHにない
# OK(絶対パス)
CMD ["/app/app"]
# または PATH を通す
ENV PATH="/app:${PATH}"

# 5) docker execで存在しないコマンド
# NG
docker exec -it app curl http://localhost
# OK(curlをイメージに入れる、またはホストからcurl)
docker exec -it app sh -lc "apk add --no-cache curl && curl http://localhost"

チェックリスト(上から順に確認する)

1) エラーが出ているのはホスト側か、コンテナ内か、ENTRYPOINT/CMDかを切り分けたか
2) ホスト側では docker がインストールされており、PATH が通っているか
3) コンテナイメージ内にそのコマンドが実際に存在するか(which / ls で確認したか)
4) ENTRYPOINT / CMD を exec形式で書く場合、コマンドと引数を配列要素に分けているか
5) PATH に通っていない独自バイナリを「コマンド名だけ」で呼び出していないか
6) ベースイメージの種類(alpine / distroless / scratch など)と、含まれているシェル・ツールを把握しているか
7) docker exec で実行しているコマンドが、本当にコンテナ内にインストールされているか
8) スクリプトの shebang・実行権限・改行コード(CRLF/LF)に問題がないか