Introduction
Even with the best planning, issues can arise when working with Docker and Docker Compose. This lesson covers common troubleshooting scenarios and essential best practices to ensure your Dockerized applications are efficient, secure, and robust. Understanding how to diagnose problems and follow recommended guidelines will significantly improve your containerization experience.
Key Concepts
Common Troubleshooting Steps
-
Check Logs: Always start by checking container logs.
docker logs [container_id]ordocker compose logs [service_name]often reveal the root cause of an issue. -
Inspect Containers/Services: Use
docker inspect [container_id]ordocker compose inspect [service_name]to view detailed configuration, network settings, and mounted volumes. -
Check Running Processes: Use
docker ps -ato see all containers (running and stopped) and their statuses. For Compose,docker compose ps. -
Resource Usage: Monitor CPU, memory, and disk I/O with
docker statsto identify resource bottlenecks. -
Network Issues: Verify network connectivity. Can containers reach each other? Is port mapping correct? Check
docker network inspect. -
Rebuild/Clean Up: Sometimes, a corrupted image or an old container can cause issues. Try
docker compose down --volumesfollowed bydocker compose up --build -d.
Dockerfile Best Practices
-
Use Specific Base Images: Avoid
latesttag in production (FROM node:18-alpineinstead ofFROM node). -
Multi-stage Builds: Use them to keep final image sizes small.
-
Combine
RUNInstructions: Chain commands with&&and useapt-get cleanto reduce layers and image size. -
.dockerignore: Exclude unnecessary files from the build context (e.g.,.git,node_modulesif installed in a laterRUN). -
Cache Optimization: Place frequently changing instructions (like
COPY . .) later in the Dockerfile. -
Non-Root User: Run containers as a non-root user for security (e.g.,
USER node).
Docker Compose Best Practices
-
Name Your Projects: The directory name typically defines the project name. This helps organize multiple Compose applications.
-
Environment Variables for Configuration: Use environment variables (
.envfile orenvironmentsection) to externalize configuration, making Compose files reusable. -
Named Volumes: Always use named volumes for persistent data rather than bind mounts for production environments.
-
Health Checks: Implement health checks (
healthcheckin Compose) to tell Docker when a service is truly ready, beyond just being started. -
Separate Compose Files: For complex scenarios, use multiple Compose files (e.g.,
docker-compose.ymlfor production,docker-compose.override.ymlfor development) using the-fflag (docker compose -f docker-compose.yml -f docker-compose.override.yml up).
Example/Code
Example Health Check in docker-compose.yml
yamlservices: web: # ... other config ... healthcheck: test: ["CMD-SHELL", "curl -f http://localhost/ || exit 1"] interval: 30s timeout: 10s retries: 3 start_period: 5s
Using an .env file
.env file (in the same directory as docker-compose.yml):
DB_PASSWORD=my_secure_password
docker-compose.yml:
yamlservices: db: image: postgres:14 environment: POSTGRES_PASSWORD: ${DB_PASSWORD} # ... other config ...
Docker Compose will automatically load variables from the .env file.
Summary/Key Takeaways
-
Troubleshooting starts with checking logs, inspecting containers, and verifying network connectivity.
-
Dockerfile best practices include specific base images, multi-stage builds,
.dockerignore, and running as a non-root user. -
Docker Compose best practices involve using environment variables, named volumes, health checks, and potentially separate Compose files for different environments.