E-NO
Docker CLI common errors 10 Min Read

Docker CLI Common Errors and Fixes: A Practical Troubleshooting Guide

calendar_today Published: 2026-10-09
update Last Updated: 2026-10-09
analytics SEO Efficiency: 100%
Technical guide illustration for Docker CLI Common Errors and Fixes: A Practical Troubleshooting Guide.

Intro

When Docker works, it feels invisible: a container starts, serves traffic, and shuts down on command. When it breaks, the error message can read like a riddle. This guide collects the Docker CLI errors most often seen in development and production, explains what each message actually means, and gives you the exact fix plus the command to verify it.

We cover Docker for Linux, macOS, and Windows, including Docker Desktop and Docker Engine, with special attention to docker compose and common image, container, network, and volume failures. Each section starts with the error text you will see, then shows the cause, the fix, and a later check to confirm the problem is gone.

This is not a reference manual. It is a troubleshooting path: observe first, change one thing, verify, then move on. You can use it during an incident or as a checklist before your next deploy.

1. Environment and Version Inventory

Before fixing anything, know your version and context. Many errors are version-specific: a flag that works in Docker 23 may not exist in Docker 20, and Docker Desktop behaves differently from Docker Engine on Linux.

Start with a read-only inventory:

docker version
docker info

docker version shows client and server versions. If the server version is missing, your client cannot reach the daemon. docker info prints the storage driver, logging driver, root directory, and importantly the number of running containers and images. It also shows warnings: no swap limit support, no cgroup v2, or a missing bridge network.

For Docker Context, which can silently target a remote or rootless daemon, list contexts:

docker context ls

If you see a context named remote-prod that you forgot to switch away from, every docker run command will try to use that remote daemon. Switch back with docker context use default.

Practical inventory commands:

docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"
docker images | head -n 10
docker system df

The first shows running containers with names, status, and ports; the second shows recently built or pulled images; the third shows disk usage by images, containers, volumes, and build cache. docker system df is often the first hint that a build is failing because the disk is full (error: no space left on device).

For a Compose project:

docker compose ps
docker compose config

The config command validates and prints the merged compose file, showing environment variable substitution and default values. A common mistake is to edit docker-compose.yml but run docker compose in a different directory; docker compose ps will list no containers, and you may think the service is down.

As a rule: record the output of these commands before changing anything. You need a baseline to compare against.

Quick check 1 of 2

What should you do if the Docker daemon fails to start and the error 'failed to start daemon: error initializing graphdriver' appears?

The passage states that the safe path is to revert the change and plan a migration when the error 'failed to start daemon: error initializing graphdriver: /var/lib/docker contains several valid graphdrivers' occurs.

2. Safe Configuration Path

Configuration errors are the most common source of Docker CLI failures. The fix is to change one configuration file or one environment variable at a time, then validate.

2.1 Docker daemon configuration (daemon.json)

Most daemon settings live in /etc/docker/daemon.json on Linux or under Settings > Docker Engine in Docker Desktop. A missing comma or wrong key will prevent the daemon from starting. On Linux, after editing, run:

sudo dockerd --validate

This checks the syntax without starting the daemon. Then restart Docker:

sudo systemctl restart docker

If the daemon fails to start, read the journal:

sudo journalctl -u docker --since "10 minutes ago" -f

A typical error: failed to start daemon: error initializing graphdriver: /var/lib/docker contains several valid graphdrivers. This means you changed the storage driver in daemon.json but existing data uses another driver. The safe path is to revert the change and plan a migration.

2.2 Compose files

Compose files are YAML, and indentation and version fields matter. Always run:

docker compose config --quiet

No output means the file is valid. If there is an error, it prints the line and reason. --quiet is non-destructive and fast.

Common mistakes:

  • Using a mapping for environment like VAR: value instead of a list. Compose v3 expects a list:
  environment:
    - POSTGRES_USER=myuser
    - POSTGRES_PASSWORD=mypass
  • Forgetting to quote strings with special characters, e.g. $ in passwords. Unquoted $VAR will try to expand the host environment.
  • Using version: "3.9" but the installed Compose plugin only supports up to 3.8. Remove the version field entirely for recent Docker Compose versions; it is optional and can cause a warning.

2.3 Environment variables in CLI

When passing variables to a container, docker run -e or --env-file must use key=value. A trailing space after a comma in --env-file will break parsing. Prefer:

docker run --env-file ./config.env myapp

And inside config.env, one variable per line, no spaces around =.

3. Verification and Diagnostics

After any fix, verify the component works as expected. Use read-only commands first, then logs, then an interactive shell if needed.

3.1 Check container state

docker ps --filter "status=exited" --format "{{.Names}}\t{{.ExitCode}}"

This lists exited containers and their exit codes. A non-zero exit code often points to the reason. Then inspect one:

docker inspect <container> --format '{{.State.ExitCode}} {{.State.Error}} {{.State.OOMKilled}}'

If OOMKilled is true, the container hit a memory limit. Check the limit with docker inspect <container> | grep -i memory, then raise it in the run command (--memory=2g) or in compose (mem_limit: 2g).

3.2 Read logs

docker logs <container> --tail 100 --timestamps

Use --since 10m to see only recent entries. If the container restarts rapidly, follow with docker logs -f <container> to catch the failure before the next restart (the container may be scheduled to restart by a restart policy).

For a Compose service:

docker compose logs <service> --tail 200

3.3 Run an interactive debug shell

Sometimes you need to see the filesystem or test a network connection inside the container. Do not modify the image; run a new shell with the same configuration:

docker run --rm -it --entrypoint sh <image>

This starts a fresh container from the image with an overridden entrypoint. Then you can ls, cat config files, or curl a local endpoint.

For a running container, use docker exec:

docker exec -it <container> sh

Be careful: any changes you make in an exec session are not saved to the image and will be lost when the container restarts. Use this for observation only.

3.4 Network diagnostics

To test connectivity between containers, run a tiny Alpine container with ping or curl:

docker run --rm --network <mynetwork> alpine ping <other-container-name>

If the ping fails, check that both containers are on the same network: docker network inspect <mynetwork> and look at the Containers map. Names are only resolvable on user-defined networks, not on the default bridge.

4. Failure Modes and Recovery

Here are the most common Docker CLI errors, their causes, and fixed recovery steps.

4.1 Cannot connect to the Docker daemon at unix:///var/run/docker.sock

Cause: the Docker daemon is not running, or your user lacks permission to access the socket.

Fix:

  • Check if the daemon is running: systemctl status docker on Linux, or open Docker Desktop on macOS/Windows.
  • On Linux, if the daemon is running but you get permission denied, add your user to the docker group:
  sudo usermod -aG docker $USER

Log out and back in, or run newgrp docker to refresh group membership without logging out.

  • If you use rootless Docker, set the DOCKER_HOST environment variable to the user socket: export DOCKER_HOST=unix:///run/user/1000/docker.sock.

Verify: docker info should return without error.

4.2 Pull access denied / repository does not exist

Error examples: pull access denied for myimage, repository does not exist or may require 'docker login'.

Fix:

  • For public images, ensure the name is correct: docker pull alpine (not Alpine or alpine:latest if the tag is wrong).
  • For private registries, log in first:
  docker login registry.example.com

Then pull with the full path: docker pull registry.example.com/team/myimage:tag.

  • If you are using Docker Desktop and the registry is on your host (e.g. localhost:5000), you may need to add an insecure registry entry in daemon settings or configure a TLS cert.

Verify: docker pull succeeds and the image appears in docker images.

4.3 Port already in use

Error: docker: Error response from daemon: driver failed programming external connectivity on endpoint ... Bind for 0.0.0.0:8080 failed: port is already allocated.

Fix:

  • Find what is using the port on the host: sudo ss -ltnp | grep 8080 or sudo lsof -i :8080.
  • Stop the conflicting process (if possible) or change the host port: docker run -p 8081:8080 or in compose:
  ports:
    - "8081:8080"
  • If the conflict is with another container, remove or stop that container, or use a dynamic port: docker run -P (maps container port to a random high host port).

Verify: docker ps shows your container with the chosen host port, and a curl http://localhost:8081 returns the expected response.

4.4 Container exits immediately

Your docker run command started, but docker ps shows no container. docker ps -a shows it exited with code 0 or 1.

Common causes:

  • The container's main process finished. For example, a one-shot script needs a foreground process to stay alive.
  • The command is missing. If you run docker run myimage and the image has no CMD, the container exits.
  • The app crashes due to missing environment variables, configuration, or dependency.

Fix:

  • Always run with -it for interactive testing: docker run -it myimage sh and manually start the app to see errors.
  • Check logs: docker logs <container>.
  • For a service that should stay up, ensure the command is a long-running process like nginx -g 'daemon off;' or tail -f /dev/null for testing.
  • In compose, set restart: unless-stopped to auto-restart after crashes, but still check logs for root cause.

4.5 Can't find file or directory

Errors: no such file or directory when mounting a volume, or inside the container the expected file is missing.

Cause: host path does not exist, or the path inside the container is wrong, or the file is not copied because it's in .dockerignore.

Fix:

  • For bind mounts, ensure the host directory exists before docker run. Docker will create it as root-owned if missing, leading to permission issues. Create it yourself: mkdir -p ./data.
  • For COPY in a Dockerfile, check .dockerignore does not exclude the file.
  • For volumes, check if the volume has data: docker volume inspect myvolume and look at the mountpoint. You can copy data into the volume by running a one-off container with the volume mounted.
  • Inside the container, use ls and pwd to verify the working directory. The default working directory is / unless set with WORKDIR in the Dockerfile or -w on the CLI.

Quick check 2 of 2

What is the recommended way to enable debugging for Docker on all platforms?

The passage states that the recommended approach is to set the `debug` key to `true` in the `daemon.json` file, which works for every Docker platform.

5. Common Pitfalls and How to Recover

Even experienced Docker users hit these surprises.

5.1 Editing files inside a container without a volume

You docker exec into a container, modify a config file, restart the container, and the change is gone. Why? The container filesystem is ephemeral and does not persist by default.

Avoid: never make manual changes inside a running container that you expect to survive. Instead, either:

  • Build the change into the image via Dockerfile, or
  • Mount a volume or bind mount for that file/directory, and edit the file on the host.

If you already made an emergency change and need it to survive until the next deploy, commit the container to a temporary image:

docker commit <container> myapp:hotfix

But treat this as a stopgap, not a workflow. The image lacks the build context and documentation.

5.2 Using latest tag in production

docker pull myapp:latest may get a different version tomorrow, and the deployment breaks.

Recover: always pin versions in compose files and CI/CD. Use specific tags like myapp:1.2.3 or a digest. If you used latest in a running deployment, you can inspect the exact image with docker inspect <container> --format '{{.Image}}', then find the digest and recreate the container with that digest.

5.3 Forgetting to clean up resources

Over time, dangling images, stopped containers, unused networks, and volumes accumulate and fill the disk.

Fix: schedule regular cleanup. Run these manually:

docker container prune   # remove stopped containers
docker image prune       # remove dangling images
docker network prune     # remove unused networks
docker volume prune      # remove unused volumes

Or use docker system prune -a to remove all unused resources, but be careful: this deletes all stopped containers, unused networks, and images not used by any container. It does not delete named volumes by default; add --volumes to do so. This is a destructive operation; run it only when you understand the impact.

5.4 Ignoring health checks

A container may be "running" but not ready to serve requests. Docker's HEALTHCHECK instruction in the Dockerfile or healthcheck in compose can mark a container as unhealthy.

Recover: add a health check. Example for a web service:

healthcheck:
  test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
  interval: 10s
  timeout: 5s
  retries: 3
  start_period: 30s

Then use docker inspect --format '{{.State.Health.Status}}' <container> to see healthy, unhealthy, or starting. In compose, docker compose ps shows the health status.

5.5 Not using a restart policy in production

If a container dies and nothing restarts it, your service is down until someone manually intervenes.

Add a restart policy:

docker run --restart unless-stopped myapp

Or in compose:

restart: unless-stopped

unless-stopped restarts the container unless you explicitly stopped it. always also restarts after the daemon restarts, but unless-stopped is usually safer because it respects manual maintenance.

6. Operations Checklist

Use this checklist before and after any Docker change in a shared environment.

Before the change

  • [ ] Run docker context ls and confirm you are targeting the correct daemon (default, not a remote prod).
  • [ ] Record current state: docker ps, docker images, docker system df, docker compose ps (if applicable). Save output to a file with timestamp.
  • [ ] Identify the exact resource you will change: image, container, network, volume, or configuration file.
  • [ ] Determine the blast radius: is this a single container or a whole stack? What depends on it?
  • [ ] Prepare a rollback path: can you revert the config change, redeploy the previous image tag, or restore a volume snapshot?
  • [ ] For config file changes, validate syntax first: docker compose config --quiet or dockerd --validate.

After the change

  • [ ] Run the verification command that proves the fix worked, e.g. curl http://localhost:8080/health or docker logs <container> --tail 50 shows no errors.
  • [ ] Check dependent services: do they still connect? Is the network intact? docker network inspect shows expected containers.
  • [ ] Monitor for a few minutes: docker stats <container> shows CPU and memory, docker events shows lifecycle changes.
  • [ ] Update the runbook or incident document with the error, cause, fix, and verification.
  • [ ] Schedule a review if the fix is temporary: set a reminder to revisit the issue in, for example, one week or before the next release.

Single accountable owner: in a team context, assign one person (e.g. the on-call engineer or the developer who made the change) to be responsible for completing the checklist and documenting the outcome. For recurring operational tasks, rotate this ownership weekly.

Conclusion

Docker CLI errors are usually caused by a small set of recurring issues: daemon connectivity, image pull failures, port conflicts, exiting containers, and file or volume misconfigurations. The path to recovery is the same each time: observe the state, isolate the failing component, make one surgical change, and verify with a specific command.

Keep this guide handy as a reference for the next error you see. Start with docker version and docker info, then proceed to the matching error section. After the fix, run the verification command and record what you did. That turns an incident into a lesson.

For further reading, explore the official Docker documentation on CLI commands, daemon configuration, and Compose specifications. The more you practice the observe-change-verify loop, the faster you will solve future Docker problems.

Related Research

Article Quality Score

Reader usefulness 100%
  • check_circle Reader-ready guide
  • check_circle Practical examples included
  • check_circle Clean SEO article URL