💡 Practical Experience
Never Use the latest Tag
docker pull nginx is the same as docker pull nginx:latest. Today latest might be 1.25; next month it might become 1.26, and your configuration may no longer be compatible. Always pin the version: nginx:1.25-alpine.
Image Size Is a Hidden Cost
It is easy to think "server disks are cheap, so a larger image does not matter." But image size directly affects deployment speed: CI/CD has to pull and push images on every build. A 1 GB image can be many times slower than a 50 MB image. Use alpine base images when appropriate and build the habit of using multi-stage builds.
Docker Can Eat Your Disk
By default, Docker logs have no size limit. A container that has been running for months can easily produce tens of gigabytes of logs. The first thing to do in production is configure log rotation. Then regularly use docker system df to inspect disk usage and run docker system prune -a only when you understand what will be removed. Do not casually add --volumes, or unused data volumes may be deleted too.
Containers Are Not Virtual Machines
Containers share the host kernel. They do not provide the same isolation boundary as full virtual machines. A root user inside a container can become a serious host risk if the container is misconfigured. Do not relax your security standards just because the app runs in Docker: limit resources, run as a non-root user, and keep privileges tight.
Keep Compose Files Small at First
Splitting a project into too many microservices too early and writing a 200-line Compose file is usually overengineering. For most small projects, 2-3 services are enough: app + db + cache. Move to a more complex platform only when the project actually needs it.