This error occurs when Docker tries to execute a command or binary that doesn't exist in the container's filesystem or isn't in the PATH. It commonly happens with minimal base images like Alpine or when using the scratch base image that lacks shell utilities.
The "command not found" error in Docker containers indicates that the container runtime cannot locate the executable you're trying to run. This typically manifests as "/bin/sh: 1: mycommand: not found" and occurs when Docker uses /bin/sh to parse your CMD or ENTRYPOINT instructions but cannot find either the shell itself or the command you want to execute. Docker containers are isolated environments with their own filesystem. Unlike your host system, they only contain files explicitly added through your Dockerfile (via base image, COPY, ADD, or RUN commands). If you reference a binary that wasn't included in the image build, the container has no way to execute it. This error is particularly common when using minimal base images (scratch, Alpine, distroless) that intentionally exclude utilities to reduce image size, or when switching from full-featured base images like Ubuntu to lighter alternatives without adjusting your Dockerfile commands accordingly.
First, determine exactly what command is missing. Check your Dockerfile's CMD or ENTRYPOINT instruction and note which executable is failing.
If the error mentions '/bin/sh' itself is not found, you're using a base image without a shell (like scratch). If it's '/bin/sh: 1: mycommand: not found', the shell exists but can't find your command.
Run this to inspect your image and check what's actually in it:
docker run --rm -it your-image-name ls /binIf this fails with the same error, your base image is too minimal to support shell commands.
If you're using FROM scratch or other minimal base images, switch from shell form to exec form in your Dockerfile. This removes the dependency on /bin/sh.
Before (shell form - requires /bin/sh):
CMD myapp --port 8080After (exec form - direct binary execution):
CMD ["myapp", "--port", "8080"]The exec form passes arguments as a JSON array and Docker executes the binary directly without invoking a shell. This works with scratch and distroless images.
Similarly for ENTRYPOINT:
ENTRYPOINT ["/app/myapp"]
CMD ["--config", "/etc/config.yaml"]If your application needs specific utilities, install them during the image build. For Alpine Linux base images:
FROM alpine:3.19
# Install common utilities
RUN apk add --no-cache bash curl wget git
# Install your application dependencies
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . /app
WORKDIR /app
CMD ["python", "app.py"]For Debian/Ubuntu images:
FROM ubuntu:22.04
RUN apt-get update && apt-get install -y \
curl \
git \
wget \
&& rm -rf /var/lib/apt/lists/*Make sure installations happen before you try to use the commands.
If you're copying a binary into your image, either place it in a directory that's already in PATH, or update PATH to include your binary's location.
Option 1: Copy to standard location
COPY myapp /usr/local/bin/myapp
RUN chmod +x /usr/local/bin/myapp
CMD ["myapp"]Option 2: Update PATH environment variable
COPY myapp /app/bin/myapp
RUN chmod +x /app/bin/myapp
ENV PATH="/app/bin:$PATH"
CMD ["myapp"]Option 3: Use absolute path
COPY myapp /app/myapp
RUN chmod +x /app/myapp
CMD ["/app/myapp"]Note the chmod +x command to ensure execute permissions are set.
In multi-stage builds, files from earlier stages don't automatically carry over. If you installed binaries in an earlier stage, you must explicitly copy them to the final stage.
# Build stage
FROM golang:1.21 AS builder
WORKDIR /build
COPY . .
RUN go build -o myapp
# Final stage - scratch has no shell/utilities
FROM scratch
# Copy the binary from builder stage
COPY --from=builder /build/myapp /myapp
ENTRYPOINT ["/myapp"]If your app needs shared libraries, copy those too:
FROM alpine:3.19 AS final
COPY --from=builder /build/myapp /usr/local/bin/myapp
COPY --from=builder /lib/x86_64-linux-gnu/libc.so.6 /lib/x86_64-linux-gnu/
CMD ["myapp"]If you're running shell scripts, ensure the shebang line matches available interpreters in your container.
Check what's available in your base image:
docker run --rm alpine:3.19 ls -l /bin/sh /bin/bashAlpine has /bin/sh but not /bin/bash by default. Update your scripts:
Before:
#!/bin/bash
echo "Hello"After (for Alpine):
#!/bin/sh
echo "Hello"Or install bash in your Dockerfile:
RUN apk add --no-cache bashVolumes can overlay directories in your image. If you mount a volume at /app and your binary is in /app/myapp, the volume will hide the binary.
Problematic docker-compose.yml:
volumes:
- ./src:/app # This hides everything in /app from the imageSolution 1: Mount at subdirectory
volumes:
- ./src:/app/src # Only overlay the src subdirectorySolution 2: Keep binaries outside mounted path
COPY myapp /usr/local/bin/myapp
WORKDIR /app
# Now mounting at /app won't hide the binaryMissing Dynamic Libraries: If your binary was compiled on a different system, it may depend on shared libraries not present in your minimal Docker image. Use ldd /path/to/binary on the host to see dependencies, or switch to static compilation:
# Go static binary
CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o myapp
# Rust static binary
cargo build --release --target x86_64-unknown-linux-muslDistroless Images: Google's distroless images provide a middle ground between scratch and full distros. They include minimal runtime dependencies (libc, SSL certs) but no shell, package managers, or utilities. Use exec form commands exclusively.
Debugging Minimal Images: You can't docker exec into scratch or distroless images to debug. Instead, temporarily switch your Dockerfile to use the debug variant:
# FROM gcr.io/distroless/static-debian11
FROM gcr.io/distroless/static-debian11:debugThe debug tag includes a busybox shell for troubleshooting. Remove it before production.
Platform Architecture Issues: If you build on Apple Silicon (ARM64) but deploy to AMD64, ensure you specify the platform:
docker build --platform linux/amd64 -t myapp .Or use buildx for multi-platform builds.
dockerfile parse error line 5: unknown instruction: RRUN
How to fix 'unknown instruction' Dockerfile parse error in Docker
Error response from daemon: manifest for nginx:nonexistent not found: manifest unknown: manifest unknown
How to fix 'manifest for image:tag not found' in Docker
Error response from daemon: invalid reference format: repository name must be lowercase
How to fix 'repository name must be lowercase' in Docker
Error response from daemon: No such image
How to fix 'No such image' in Docker
Error response from daemon: Container is not running
How to fix 'Container is not running' when using docker exec