DevOps

Understanding Docker Errors: A Developer's Troubleshooting Handbook

January 15, 2025
12 min read
By Saad Minhas
DockerDevOpsContainersTroubleshootingDeployment
Understanding Docker Errors: A Developer's Troubleshooting Handbook

Few things are more frustrating than a Docker container that won't start, crashes mysteriously, or fails silently in production. You've written perfect code, tested it locally, and pushed it to your registry — only to watch it fall apart in the wild.


I've been there countless times. After years of building containerized applications at Appzivo and helping development teams debug their Docker nightmares, I've learned that most Docker errors fall into predictable patterns. The problem isn't that Docker is difficult — it's that error messages often hide the real issue under layers of cryptic output.


This guide distills everything I've learned about troubleshooting Docker into practical, actionable advice. These aren't theoretical problems — they're real issues I encounter regularly, with solutions that actually work in production.


Why Docker Errors Are Different


Before diving into specific errors, understanding Docker's architecture helps explain why troubleshooting feels different from debugging regular applications.


A Docker container isn't a virtual machine. It's an isolated Linux process running on your host system. When something goes wrong, you're not just debugging your application — you're debugging the intersection between your application, the container runtime, the Linux kernel, and potentially orchestration systems like Kubernetes.


This layered architecture means errors can originate from multiple sources:

  • Your application code
  • Container runtime issues
  • Host system configuration
  • Network problems
  • Resource constraints

The challenge is identifying which layer is actually causing the problem. Let's systematically work through the most common Docker errors and their real-world solutions.


1. Container Exits Immediately After Starting


This is perhaps the most common and frustrating issue developers face. You start a container, it appears to launch, and immediately exits. Running docker ps shows nothing running, and docker ps -a reveals your container in "Exited" status.


Why This Happens:


Docker containers run as long as their main process runs. Once that process completes or fails, the container stops. Unlike virtual machines that idle indefinitely, containers need an active foreground process to remain alive.


Common causes include:

  • Application crashes on startup
  • Missing environment variables
  • Incorrect entrypoint or command
  • Port binding failures
  • Missing dependencies

How to Diagnose:


First, check the exit code and logs:


docker ps -a
docker logs <container-id>
docker inspect <container-id> | grep -A 5 "State"

Exit codes tell you what happened:

  • **0**: Normal exit (process completed successfully)
  • **1**: General error
  • **125**: Docker daemon error
  • **126**: Command invoked cannot execute
  • **127**: Command not found
  • **128**: Invalid exit argument
  • **137**: Killed by SIGKILL (often OOM)

How to Fix:


If logs don't reveal the issue, override the entrypoint to get inside the container:


docker run -it --entrypoint /bin/sh <image-name>
# Or for running containers
docker exec -it <container-id> /bin/sh

Once inside, manually run your application command to see the raw error output. Check:

  • Environment variables are set correctly
  • Required files exist
  • Dependencies are installed
  • Ports are available

For production containers that should run continuously, ensure your application:

  • Runs as a foreground process
  • Handles signals properly (SIGTERM, SIGINT)
  • Logs errors to stdout/stderr
  • Doesn't exit immediately

In your Dockerfile, if running a script, make sure it doesn't exit immediately. For testing, you can use tail -f /dev/null as a temporary workaround to keep the container alive.


2. Docker Daemon Connection Errors


The dreaded "Cannot connect to the Docker daemon" error stops you before you even start. This message appears when your Docker client can't communicate with the Docker daemon — the background service that actually manages containers.


Common Error Messages:

  • "Cannot connect to the Docker daemon"
  • "Is the docker daemon running?"
  • "permission denied while trying to connect to the Docker daemon socket"

Why This Happens:


The Docker daemon might not be running, or your user lacks permission to access the Docker socket.


How to Fix:


On Linux:


Check if Docker daemon is running:


sudo systemctl status docker

If stopped, start it:


sudo systemctl start docker
sudo systemctl enable docker  # Start on boot

If the daemon is running but you still get errors, it's likely a permissions issue. Add your user to the docker group:


sudo usermod -aG docker $USER

Log out and back in for changes to take effect, then verify:


docker ps

On macOS or Windows:


Ensure Docker Desktop is running. Check your system tray for the Docker icon. If it's not there, launch Docker Desktop from your applications folder.


For WSL2 on Windows, enable the WSL2 integration in Docker Desktop settings for your specific distribution.


Advanced Troubleshooting:


If Docker Desktop won't start, check:

  • System requirements (CPU virtualization enabled)
  • Conflicting software (antivirus, VPN)
  • Disk space availability
  • Logs: `~/.docker/logs/`

3. Image Build Failures and Dockerfile Errors


Building Docker images is where many errors surface. A single typo in your Dockerfile can waste hours of debugging time.


Common Causes:


Build failures typically stem from:

  • Syntax errors in Dockerfile
  • Missing files or directories
  • Network issues during package installation
  • Incorrect base image tags
  • Cache-related problems

How to Diagnose:


Docker provides clear feedback about which layer failed. Pay attention to the step number:


docker build --progress=plain --no-cache -t myapp .

The --progress=plain flag shows detailed output for each build step. The --no-cache flag forces a complete rebuild, eliminating cache-related issues.


Common Dockerfile Mistakes:


COPY path issues:


# BAD - Path doesn't exist
COPY ./nonexistent /app

# GOOD - Verify paths exist
COPY ./src /app/src
COPY ./package.json /app/

Package installation failures:


# BAD - No error handling
RUN apt-get update && apt-get install -y package-name

# GOOD - Handle errors and clean up
RUN apt-get update &&     apt-get install -y package-name &&     apt-get clean &&     rm -rf /var/lib/apt/lists/*

Missing continuation characters:


# BAD - Missing backslash
RUN apt-get update
    apt-get install -y package-name

# GOOD - Proper continuation
RUN apt-get update &&     apt-get install -y package-name

How to Fix:


Always structure Dockerfile commands for clarity and debugging:


FROM node:18-alpine

WORKDIR /app

# Copy dependency files first (for better caching)
COPY package*.json ./
RUN npm ci --only=production

# Copy application code
COPY . .

# Set proper permissions
RUN chown -R node:node /app
USER node

# Expose port
EXPOSE 3000

# Use exec form for proper signal handling
CMD ["node", "server.js"]

Pro Tips:

  • Use `.dockerignore` to exclude unnecessary files
  • Leverage layer caching by ordering commands from least to most frequently changing
  • Use multi-stage builds to reduce final image size
  • Pin specific versions instead of using `latest`

4. Volume Mounting Problems


Volume mounting issues cause containers to fail when they can't access expected files or directories. These errors are particularly painful because they often work locally but fail in production.


Common Symptoms:

  • "No such file or directory" errors
  • Permission denied errors
  • Files not appearing in container
  • Changes not persisting

Why This Happens:


Volume mounting issues typically involve:

  • Incorrect path syntax (Windows vs Linux)
  • Permission mismatches
  • SELinux policies (Linux)
  • Path doesn't exist on host

How to Fix:


Path Syntax Issues:


On Linux/macOS:


docker run -v /absolute/path:/container/path image-name

On Windows (using CMD):


docker run -v C:/Users/me/app:/app image-name

On Windows (using PowerShell):


docker run -v C:\Users\me\app:/app image-name

Permission Issues:


Check permissions on host:


ls -la /path/to/mount
chmod 755 /path/to/mount  # If needed

If your container runs as a non-root user, ensure the mounted directory is accessible:


docker run -v /host/path:/container/path:Z image-name

In your Dockerfile, explicitly set the user:


RUN groupadd -r appuser && useradd -r -g appuser appuser
USER appuser

Debugging Volume Mounts:


Verify the volume is correctly mounted:


docker inspect <container-id> | grep -A 10 "Mounts"

Docker Compose Volumes:


In docker-compose.yml, be explicit about volume configuration:


services:
  app:
    volumes:
      - ./data:/app/data:rw
      - named-volume:/app/storage

SELinux Issues (Linux):


If you're on a system with SELinux enabled (like CentOS or RHEL), add the z or Z flag:


docker run -v /host/path:/container/path:Z image-name

5. Network and Port Binding Issues


Network problems manifest as containers that start successfully but can't be accessed, or port binding failures that prevent containers from starting at all.


Common Error Messages:

  • "Bind for 0.0.0.0:3000 failed: port is already allocated"
  • "Cannot connect to container"
  • "Connection refused"

How to Diagnose:


Check if the port is already in use:


# Linux/macOS
lsof -i :3000
netstat -tulpn | grep 3000

# Windows
netstat -ano | findstr :3000

How to Fix:


Port Already in Use:


Either stop the conflicting process or use a different host port:


docker run -p 3001:3000 image-name  # Map host port 3001 to container port 3000

Container-to-Container Communication:


When containers need to communicate, put them on the same network:


docker network create mynetwork
docker run --network mynetwork --name app1 image1
docker run --network mynetwork --name app2 image2
# app2 can now reach app1 using hostname 'app1'

In Docker Compose, this happens automatically:


services:
  app:
    networks:
      - mynetwork
  db:
    networks:
      - mynetwork

networks:
  mynetwork:

Testing Container Networking:


From inside a container, test connectivity:


docker exec -it <container-id> ping <other-container-name>
docker exec -it <container-id> curl http://other-container:3000

Firewall Issues:


Docker modifies iptables rules automatically, but firewalls or security software can interfere:


# Check iptables rules
sudo iptables -L -n

6. Out of Memory (OOM) Errors


Containers killed by the OOM killer are particularly problematic because they often fail silently in production.


How to Identify:


docker inspect <container-id> | grep -i oom
# Look for "OOMKilled": true

Exit code 137 combined with OOMKilled=true confirms memory exhaustion.


Why This Happens:


Your container exceeded its memory limit (if set) or consumed all available host memory. Common causes:

  • Memory leaks in application
  • Insufficient memory limits
  • Too many containers running
  • Application not optimized for container environment

How to Fix:


Monitor Memory Usage:


docker stats
docker stats <container-id>

Set Appropriate Memory Limits:


In docker-compose.yml:


services:
  app:
    deploy:
      resources:
        limits:
          memory: 512M
        reservations:
          memory: 256M

Or with docker run:


docker run -m 512m image-name

Application-Level Fixes:


For Node.js specifically:


// Set Node.js memory limit
node --max-old-space-size=512 server.js

7. Image Pull Errors


Image pull failures prevent containers from starting and often indicate registry issues.


Common Error Messages:

  • "pull access denied"
  • "unauthorized: authentication required"
  • "network timeout"
  • "manifest unknown"

How to Fix:


Authentication Issues:


docker login
docker login registry.example.com

Image Name Typos:


Verify the exact image name:


docker search <image-name>

Network Issues:


If you're behind a corporate proxy, configure Docker to use it:


# Create/edit /etc/docker/daemon.json
{
  "proxies": {
    "http-proxy": "http://proxy.example.com:8080",
    "https-proxy": "http://proxy.example.com:8080"
  }
}

Registry Certificate Issues:


For self-signed certificates:


# Add to /etc/docker/daemon.json
{
  "insecure-registries": ["registry.example.com:5000"]
}

8. Docker Compose Errors


Docker Compose introduces its own set of errors related to orchestrating multiple containers.


Version Compatibility:


Use a supported compose file version:


version: '3.8'  # Check latest supported version

Service Dependencies:


Services failing due to timing issues:


services:
  app:
    depends_on:
      - db
    # Use healthcheck for better dependency management
  db:
    healthcheck:
      test: ["CMD", "pg_isready"]
      interval: 10s
      timeout: 5s
      retries: 5

Common Compose Commands for Troubleshooting:


docker-compose config  # Validate configuration
docker-compose ps      # List running services
docker-compose logs    # View all logs
docker-compose logs app  # View specific service logs
docker-compose exec app sh  # Access service shell

9. Permission and User Issues


Permission errors cause containers to fail when writing files, accessing resources, or performing operations.


Common Symptoms:

  • "Permission denied" errors
  • Files created with wrong ownership
  • Cannot write to mounted volumes

Why This Happens:


Your container runs as a specific user (often root by default), but file permissions don't match. This is especially problematic with:

  • Volume mounts
  • File creation
  • Database operations

How to Fix:


Run Container as Specific User:


docker run --user $(id -u):$(id -g) image-name

Fix Permissions in Dockerfile:


RUN groupadd -r appuser && useradd -r -g appuser appuser
RUN chown -R appuser:appuser /app
USER appuser

Adjust Host Permissions:


chmod -R 755 /host/path
chown -R $USER:$USER /host/path

10. Windows-Specific Issues


Windows introduces unique Docker challenges around line endings, paths, and virtualization.


Line Ending Problems:


Windows uses CRLF (\r\n) while Linux uses LF (\n). Shell scripts with Windows line endings fail in containers:


How to Fix:


Convert line endings before building:


# Use dos2unix or similar tool
dos2unix script.sh

In Git, configure automatic conversion:


git config --global core.autocrlf input

WSL2 Integration:


Ensure Docker Desktop is configured for your WSL2 distribution in Settings → Resources → WSL Integration.


Hyper-V Requirements:


Docker Desktop on Windows requires Hyper-V. Common error:


Hardware assisted virtualization and data execution protection must be enabled

Enable Hyper-V (requires Windows 10 Pro/Enterprise):


Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Hyper-V -All

Or switch to WSL2 backend (works on Windows 10 Home).


Essential Debugging Commands


When troubleshooting Docker issues, these commands are indispensable:


# Container inspection
docker ps -a                    # List all containers
docker logs <container-id>     # View logs
docker inspect <container-id>  # Detailed container info
docker exec -it <container-id> /bin/sh  # Access running container

# Image inspection
docker images                  # List images
docker history <image-name>    # Image build history
docker inspect <image-name>   # Image details

# System information
docker info                    # Docker system info
docker system df              # Disk usage
docker system events          # Real-time events

# Cleanup
docker system prune           # Remove unused resources
docker container prune        # Remove stopped containers
docker image prune            # Remove unused images
docker volume prune           # Remove unused volumes

Preventing Common Docker Issues


Prevention is better than debugging. Follow these practices to avoid common issues:


1. Use Health Checks:


HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
  CMD curl -f http://localhost:3000/health || exit 1

2. Implement Proper Logging:


Configure log rotation:


docker run --log-driver json-file \
  --log-opt max-size=10m \
  --log-opt max-file=3 \
  image-name

3. Set Resource Limits:


services:
  app:
    deploy:
      resources:
        limits:
          cpus: '0.5'
          memory: 512M

4. Use Multi-Stage Builds:


FROM node:18 AS builder
WORKDIR /app
COPY . .
RUN npm run build

FROM node:18-alpine
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY package*.json ./
RUN npm ci --only=production
CMD ["node", "dist/index.js"]

5. Pin Versions:


FROM node:18.17.0-alpine  # Not node:latest

6. Implement Graceful Shutdown:


process.on('SIGTERM', () => {
  console.log('SIGTERM received, shutting down gracefully');
  server.close(() => {
    process.exit(0);
  });
});

When to Use Docker Desktop vs Docker Engine


Understanding when to use Docker Desktop versus Docker Engine directly can prevent configuration issues:


Docker Desktop:

  • Development on macOS/Windows
  • GUI for container management
  • Integrated Kubernetes
  • Automatic updates

Docker Engine (Linux):

  • Production servers
  • CI/CD pipelines
  • More control over configuration
  • Lower resource overhead

Troubleshooting Checklist


When facing Docker issues, work through this systematic checklist:


1. Verify Docker is running:


docker ps

2. Check container status:


docker ps -a

3. Review logs:


docker logs <container-id>
docker logs -f <container-id>  # Follow logs

4. Check exit code:


docker inspect <container-id> | grep ExitCode

5. Monitor resources:


docker stats

6. Test connectivity:


docker exec -it <container-id> ping google.com

7. Verify image:


docker images
docker history <image-name>

8. Check network:


docker network ls
docker network inspect <network-name>

9. Clean up if needed:


docker system prune -a

The Bottom Line


Docker troubleshooting becomes significantly easier once you understand the underlying patterns. Most errors fall into a few categories: configuration issues, resource constraints, permission problems, or network connectivity.


The key to effective troubleshooting is systematic investigation. Don't guess — use logs, inspect commands, and the debugging techniques outlined above to pinpoint the actual problem. Exit codes and error messages provide valuable clues if you know how to interpret them.


Remember that containers are ephemeral by design. They're meant to fail fast and be replaced quickly. Embrace this philosophy by:

  • Building immutable images
  • Using health checks
  • Implementing proper logging
  • Setting resource limits
  • Planning for failure

The best debugging happens when you've structured your containers for observability from the start. Invest time in proper logging, health checks, and error handling — your future self will thank you when issues inevitably arise.


Docker has revolutionized application deployment, but it's not magic. It's a powerful tool that requires understanding and proper configuration. Master these troubleshooting techniques, and you'll spend less time debugging and more time building great applications.


Ready to dive deeper? Start by auditing your current Docker setup using the checklist above. Identify which of these common issues affect your containers, then systematically address them. Your containerized applications will be more reliable, debuggable, and production-ready as a result.

Get In Touch

Connect

Full Stack Software Engineer passionate about building innovative web and mobile applications.

CEO at Appzivo— a product and engineering studio for larger engagements.

© 2026 Saad Minhas. All Rights Reserved.