Managing multi-container applications requires precise control over their lifecycle. The three fundamental commands—up, down, and restart—form the backbone of daily operations with Docker Compose. This guide explores these commands in depth, from basic usage to advanced scenarios.
The docker compose up Command
The up command is your primary tool for launching applications. It reads your configuration file and brings your entire application stack to life.
Basic Usage
The simplest form of the command starts all services defined in your docker-compose.yml file:
docker compose up
This command performs several operations in sequence:
- Creates any networks specified in your configuration
- Creates volumes if they don't already exist
- Builds images if they're not available locally
- Creates and starts containers for each service
- Attaches to container output streams, displaying logs in your terminal
When you run this command, you'll see colorized output from all your containers streaming to your terminal, each prefixed with the service name.
Detached Mode
Running containers in the foreground ties up your terminal. For most production and development scenarios, you'll want detached mode:
docker compose up -d
The -d or --detach flag runs containers in the background. Your terminal becomes available immediately after the containers start. The command outputs container names and IDs, then returns control to you.
Detached mode is essential for:
- Production deployments
- Long-running development sessions
- Automated deployment scripts
- CI/CD pipelines
Selective Service Startup
You don't always need to start every service. Specify individual services to launch only what you need:
docker compose up web
This starts the web service and any services it depends on. Dependency resolution happens automatically based on depends_on directives in your configuration.
Starting multiple specific services:
docker compose up web database cache
This pattern is invaluable during development when you're working on specific components and don't need the entire stack running.
Forcing Recreation
Sometimes containers need a fresh start. The --force-recreate flag destroys and recreates containers even when their configuration hasn't changed:
docker compose up --force-recreate
Use this when:
- Containers are in an inconsistent state
- You've made manual changes inside containers that need reverting
- Debugging mysterious issues
- You want a completely clean slate
Selective Recreation
More surgical than --force-recreate, the --no-recreate flag prevents recreation of existing containers:
docker compose up --no-recreate
This starts only stopped containers without touching running ones. It's useful when you've added new services to your configuration but want to leave existing services undisturbed.
Rebuilding Images
When you've changed your application code or dependencies, you need fresh images:
docker compose up --build
This rebuilds images before starting containers. The command respects Docker's layer caching, so only changed layers rebuild.
For a complete rebuild ignoring all cache:
docker compose up --build --no-cache
The --no-cache option is heavier but ensures absolute freshness. Use it when:
- Debugging build issues
- Dependencies have updated but layer cache is stale
- You suspect cache corruption
Timeout Control
Container shutdown during restart or recreation uses a default timeout. Adjust this with the --timeout flag:
docker compose up --timeout 30
This gives containers 30 seconds to shut down gracefully before forceful termination. Longer timeouts help services that need time to:
- Flush buffers to disk
- Complete in-flight requests
- Close database connections cleanly
- Send shutdown signals to child processes
Removing Orphan Containers
When you remove services from your configuration, their containers become orphans. Clean them up automatically:
docker compose up --remove-orphans
This identifies containers created by previous configurations and removes them before starting your current stack.
Startup Behavior Control
The --abort-on-container-exit flag changes how up behaves in attached mode:
docker compose up --abort-on-container-exit
When any container exits, all containers stop. This is particularly useful for:
- Test suites where one container runs tests and others provide services
- Batch processing pipelines
- Scenarios where one service failure should halt everything
Combine with --exit-code-from to propagate a specific container's exit code:
docker compose up --abort-on-container-exit --exit-code-from tests
This runs your stack, waits for the tests service to complete, then stops everything and exits with the test container's exit code. Perfect for CI/CD integration.
Always Recreate Specific Services
The --always-recreate-deps flag recreates dependent services even when the primary service hasn't changed:
docker compose up --always-recreate-deps web
When starting the web service, all its dependencies recreate regardless of whether they need to.
Quiet Mode
Suppress the build output with --quiet-pull:
docker compose up --quiet-pull
This pulls images without showing progress bars, keeping your terminal output clean. Useful in scripts where you want minimal noise.
Parallel Operations
By default, Compose starts services in parallel for speed. Control this behavior with --no-parallel:
docker compose up --no-parallel
This starts services sequentially, one after another. Use it when:
- Debugging startup issues
- You need predictable ordering
- Parallel startup causes resource contention
The docker compose down Command
The down command stops and removes containers, networks, and optionally volumes and images. It's the clean shutdown mechanism for your application stack.
Basic Usage
The simplest invocation stops containers and removes containers and networks:
docker compose down
This command:
- Stops all running containers gracefully
- Removes stopped containers
- Removes networks created by Compose
- Leaves volumes and images intact
Removing Volumes
Volumes persist data across container lifecycles. To remove them during shutdown:
docker compose down --volumes
The --volumes flag (or shorter -v) deletes all volumes defined in your configuration. Use this carefully—it destroys all persisted data including databases, uploaded files, and application state.
This is appropriate for:
- Development environment resets
- Test cleanup
- Situations where you want a completely fresh start
Never use it in production unless you're absolutely certain you want to delete all data.
Removing Images
Images consume disk space. Clean them up with:
docker compose down --rmi all
This removes all images used by services. Alternatively, remove only locally built images:
docker compose down --rmi local
The local option removes only images that were built from your configuration, leaving pulled images intact. This is safer and faster when you're sharing images across multiple projects.
Complete Cleanup
For a total teardown removing everything:
docker compose down --volumes --rmi all
This leaves no trace of your application stack. It's the nuclear option for cleanup.
Timeout Control
Like up, down respects timeout values for graceful shutdown:
docker compose down --timeout 45
Longer timeouts give applications time to shut down properly. This is critical for:
- Databases flushing transactions
- Message queues processing remaining messages
- Applications completing active requests
- Services deregistering from service discovery
Removing Orphans
Clean up containers from removed services:
docker compose down --remove-orphans
This finds containers that were part of your stack but are no longer in your configuration and removes them.
The docker compose restart Command
The restart command stops and starts containers without removing them. It's faster than down followed by up because it reuses existing containers.
Basic Usage
Restart all services:
docker compose restart
This stops and starts all containers in your stack. The containers themselves persist—only the processes inside restart.
Restarting Specific Services
Target individual services:
docker compose restart web
This restarts only the web service, leaving others running. Multiple services can be specified:
docker compose restart web worker
Timeout Control
Control how long to wait for graceful shutdown:
docker compose restart --timeout 60
This gives each container 60 seconds to shut down before forceful termination. The timeout applies to the stop phase only; startup proceeds immediately after.
When to Use Restart
Use restart when:
- You've changed application code but not configuration
- You need to reload application state without destroying containers
- You want the fastest possible turnaround time
- Container configuration hasn't changed
Don't use restart when:
- You've modified the Compose configuration
- You need to rebuild images
- You've changed environment variables
- You need to recreate networks or volumes
In these cases, use down followed by up instead.
Command Combinations and Workflows
Development Workflow
A typical development cycle looks like:
# Initial startup with fresh build docker compose up --build -d # Make code changes... # Quick restart to reload code docker compose restart web # Configuration change requires recreation docker compose up -d # End of day cleanup docker compose down
Testing Workflow
For automated testing:
# Start stack and run tests docker compose up --abort-on-container-exit --exit-code-from tests # Clean up including test data docker compose down --volumes
Production Deployment
A production deployment might use:
# Pull latest images docker compose pull # Recreate containers with new images docker compose up -d --force-recreate # Verify everything is running docker compose ps
Emergency Procedures
When things go wrong:
# Hard stop everything docker compose down --timeout 5 # Start fresh docker compose up -d --force-recreate --remove-orphans
Troubleshooting Common Issues
Containers Won't Stop
If down hangs, containers may be unresponsive. Force removal:
docker compose down --timeout 0
Zero timeout immediately kills containers without waiting for graceful shutdown.
Stale Containers After Configuration Changes
When services disappear from your configuration but containers remain:
docker compose up -d --remove-orphans
Followed by:
docker compose down --remove-orphans
Port Conflicts
If up fails with port binding errors, existing containers may be holding ports. Clean up:
docker compose down
Then check for conflicts:
docker ps -a
Network Issues
When containers can't communicate after changes:
docker compose down docker compose up -d
This recreates networks with fresh configuration.
Disk Space Exhaustion
When repeated up and down cycles fill your disk:
docker compose down --rmi local --volumes
Remove unused images and volumes manually:
docker system prune -a --volumes
Performance Considerations
Startup Time Optimization
Reduce startup time by:
- Using --no-deps when starting single services that don't need dependencies
- Leveraging build cache effectively with --build
- Pre-pulling images before running up
- Starting only necessary services during development
Resource Usage
Monitor resource consumption:
- Detached mode (-d) frees terminal resources
- Selective service startup reduces memory and CPU usage
- Proper timeout values prevent hanging processes
Parallel Execution
Compose parallelizes operations by default. For systems with limited resources, use --no-parallel to reduce concurrent load during startup.
Exit Codes and Automation
The up command returns meaningful exit codes for automation:
- 0: Successful execution
- 1: Generic error
- 124: Timeout waiting for containers
Capture and handle these in scripts:
docker compose up -d
if [ $? -eq 0 ]; then
echo "Stack started successfully"
else
echo "Failed to start stack"
exit 1
fi
Signal Handling
When running in attached mode, Compose handles signals:
- CTRL+C (SIGINT): Stops containers gracefully
- Second CTRL+C: Immediately kills containers
- SIGTERM: Graceful shutdown
These signals respect timeout values and allow proper cleanup.
Command Aliases and Shortcuts
While not official, many developers create shell aliases:
alias dcup='docker compose up -d' alias dcdown='docker compose down' alias dcrestart='docker compose restart'
These speed up daily workflows significantly.
Best Practices
Development
- Always use detached mode during active development
- Restart specific services rather than the entire stack
- Use --build when dependencies change
- Clean up regularly with down --volumes to prevent data buildup
Production
- Always specify timeout values explicitly
- Use --force-recreate during deployments to ensure fresh state
- Never use --volumes flag with down in production
- Monitor exit codes in automation scripts
- Implement health checks and wait for readiness before declaring success
General
- Use --remove-orphans regularly to prevent container accumulation
- Combine flags to optimize workflows
- Understand the difference between restart and recreation
- Document your specific workflow patterns for team members
Integration with CI/CD
These commands integrate seamlessly into pipelines:
# Pre-deployment docker compose down docker compose pull # Deployment docker compose up -d --force-recreate --timeout 120 # Verification step would follow
The deterministic behavior and clear exit codes make these commands ideal for automation.
Resource Cleanup Strategies
Develop a cleanup strategy appropriate for your use case:
Conservative Cleanup
docker compose down
Removes containers and networks only.
Moderate Cleanup
docker compose down --rmi local
Also removes locally built images.
Aggressive Cleanup
docker compose down --volumes --rmi all
Complete removal including data.
Choose based on your disk space constraints and data persistence requirements.
Mastering up, down, and restart provides complete control over your application lifecycle. These commands, with their various flags and options, handle everything from quick development iterations to complex production deployments. Understanding their nuances and knowing which flags to combine for specific scenarios makes you proficient in managing containerized applications.