Your container starts, immediately dies, restarts, dies again. The docker ps output shows “Restarting (1) 2 seconds ago” and you’re watching it cycle endlessly. Here’s how to break the loop and find the actual problem.

Step 1: Check the Exit Code

First, figure out how it’s dying:

1
docker inspect --format='{{.State.ExitCode}}' container_name

Common exit codes:

  • 0 — Clean exit (shouldn’t restart unless you have restart: always)
  • 1 — Application error (check logs)
  • 137 — Killed by OOM (out of memory)
  • 139 — Segmentation fault
  • 143 — SIGTERM received (graceful shutdown request)

Step 2: Read the Logs (Before They Disappear)

Containers in restart loops lose logs on each restart. Catch them quick:

1
2
3
4
5
6
7
8
# Follow logs in real-time
docker logs -f container_name

# Get last 100 lines
docker logs --tail 100 container_name

# Include timestamps
docker logs -t container_name

If logs are empty, the container is crashing before your app even starts — likely a Docker-level issue, not application code.

Step 3: Common Causes and Fixes

Port Already in Use

The most common cause I see. Another process (or another container) already has the port:

1
2
3
4
# Find what's using port 8080
lsof -i :8080
# or
netstat -tlnp | grep 8080

Fix: Stop the conflicting process, or change your container’s port mapping:

1
2
3
# docker-compose.yml
ports:
  - "8081:8080"  # Map to different host port

Missing Environment Variables

Your app expects DATABASE_URL but it’s not set:

1
2
# Check what env vars the container sees
docker exec container_name env

Fix: Add the missing variables:

1
2
environment:
  - DATABASE_URL=postgres://localhost/mydb

Volume Mount Doesn’t Exist

Container expects a config file at /app/config.yml but the host path doesn’t exist:

1
2
# Verify the host path exists
ls -la /path/on/host/config.yml

Fix: Create the file, or make it optional in your app.

Network Issues (Container Can’t Reach Dependencies)

Your app needs to connect to another container (database, redis) but can’t reach it:

1
2
3
# Test connectivity from inside the container
docker exec container_name ping db_container
docker exec container_name nc -zv db_container 5432

Fix: Ensure both containers are on the same Docker network:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
services:
  app:
    networks:
      - backend
  db:
    networks:
      - backend

networks:
  backend:

Out of Memory (Exit Code 137)

Docker killed your container for using too much RAM:

1
2
# Check container memory stats
docker stats container_name

Fix: Increase memory limit or fix the memory leak:

1
2
3
4
deploy:
  resources:
    limits:
      memory: 1G

Step 4: Stop the Restart Loop to Debug

You can’t debug a container that keeps restarting. Temporarily disable the restart policy:

1
2
3
4
5
6
7
# Stop the loop
docker update --restart=no container_name
docker stop container_name

# Now start it manually to see what happens
docker start container_name
docker logs container_name

Or override the entrypoint to keep it alive:

1
2
docker run -it --entrypoint /bin/sh your_image
# Now you're inside — poke around

Step 5: The Nuclear Option

When you just need it running and will debug later:

1
2
3
# Remove and recreate
docker rm -f container_name
docker compose up -d container_name

For persistent issues, sometimes a fresh pull helps:

1
2
docker compose pull
docker compose up -d --force-recreate

Real Example: What Bit Me Last Week

Had a dashboard container in a restart loop after a server reboot. Exit code 1, logs showed connection refused to the API.

Root cause: The dashboard container started before the API container. It tried to connect, failed, crashed, restarted, failed again.

Fix: Added a health check and dependency:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
services:
  dashboard:
    depends_on:
      api:
        condition: service_healthy
  api:
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
      interval: 5s
      timeout: 3s
      retries: 5

Now the dashboard waits until the API is actually ready, not just “started.”

Quick Diagnostic Checklist

  1. docker inspect --format='{{.State.ExitCode}}' container — How is it dying?
  2. docker logs container — What does it say before death?
  3. lsof -i :PORT — Is the port taken?
  4. docker exec container env — Are env vars set?
  5. docker stats container — Is it running out of memory?
  6. docker network inspect — Can it reach its dependencies?

Most restart loops are environment issues, not code bugs. Check the boring stuff first.