Mastering Docker Startup: Practical Command Reference
Unexpected container exit on startup. Log output you never see. Reboot and half the stack doesn’t recover. Anyone working with Docker long enough has hit these issues—the core reason to understand container startup, not just memorize basic commands. Precision here means fewer outages and faster troubleshooting.
Docker Startup: Not Always What It Seems
docker start <container>
Most assume this “just works.” But what’s the process actually doing? Did you use docker run
or docker start
originally—is this a new container, or re-launching a stopped one?
Command | Behavior |
---|---|
docker run | Creates and starts a new container from an image. |
docker start | Starts an existing, previously stopped container. |
docker restart | Stops, then starts an existing container (for config reloads or resets). |
Critical distinction: docker start
will not recreate a container; if your config or image changed, those changes won’t show up.
Real-World Startup Scenarios
1. Detached vs. Attached Mode – Know Your Need
Default startup hides logs and terminal output. For quick restarts:
docker start web_server
But if the container fails immediately, you'll miss the error. For interactive debugging:
docker start -a -i web_server
-a
: Attach STDOUT/STDERR.-i
: Keep STDIN open. Useful for REPLs or shells.
Note: Not all containers are designed for attachment—starting NGINX with -i
gives you nothing useful.
2. Container Stops Instantly? Always Check Logs
Classic mistake: the container process exits, Docker stops it. This often means an ENTRYPOINT or CMD failed, or the command completed successfully and exited.
Check with:
docker logs web_server
Sample error:
Error: database connection refused
Fix the root cause (env var, network, linked service) outside Docker first.
Startup on Reboot: Automating Recovery
Relying on manual starts after OS reboot risks downtime. Set restart policies instead:
docker update --restart=always web_server
or at creation:
docker run --restart=unless-stopped -d --name api_v1 my_api:2.1.0
Policy | Effect |
---|---|
no (default) | Doesn’t restart. |
always | Restarts whenever stopped, including daemon/reboot. |
unless-stopped | Like always, but not if intentionally stopped. |
Multi-Container Startup: Avoid Dependency Hell
Manual sequencing is fragile.
Common pitfall:
docker start backend
docker start frontend
If backend
requires a running database, unpredictability follows.
Workaround for basic setups:
docker start db && sleep 5 && docker start backend
But sleep
is unreliable.
Better: Docker Compose with health checks and depends_on
:
version: '3.8'
services:
db:
image: postgres:15.2
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 5s
timeout: 2s
retries: 6
backend:
image: api:2.1.0
depends_on:
db:
condition: service_healthy
frontend:
image: web:4.1.0
depends_on:
- backend
docker-compose up -d
handles both sequence and health.
Useful Cleanup, Status & Troubleshooting Commands
-
See all containers (including exited):
docker ps -a
-
Inspect a container’s full state (environment, mounts, runtime flags):
docker inspect web_server | less
Look for incorrect ENV or port bindings.
-
Remove exited containers (known docker daemon clutter source):
docker rm $(docker ps -aq -f status=exited)
Gotcha: Environment Variables and Configuration Drift
Restarting with docker start
uses a snapshot state—does not apply new env vars from original docker run
. Any config changes require a new container.
Hidden Edge: Sidecar Debugging
When logs aren’t enough, exec into the running container:
docker exec -it web_server /bin/sh
Not all images include a shell—Alpine usually does (/bin/ash
), but scratch base images won’t.
Wrapping Up
Blindly typing docker start
is a recipe for missed errors and inconsistent behavior. Reliable container startup depends on:
- Picking the right command for the state:
run
vs.start
- Using
-a
/-i
for startup debugging when necessary - Relying on log inspection—not guesswork
- Setting restart policies proactively
- Automating service and dependency order with Compose or orchestrators
One not-so-obvious tip: use Docker Compose’s healthchecks for fragile DB or cache dependencies. Far more robust than manual scripting.
For further practice, deliberately break a startup dependency—e.g., start an app container before your database, observe the failure, then build a Compose file to solve it.
Not perfect, but a solid foundation for production-grade Docker workflows.