5 Dockerfile Misconfigurations You Should Avoid
When I started learning Docker and optimizing my containers, I realized that most of my issues weren’t about missing tools they were about how I wrote my Dockerfiles. Over time, I identified a few mistakes I repeatedly made, and I want to share them so others can avoid the same pitfalls.
0️⃣ Don’t Forget to Open Docker Desktop
When I started building images locally, I got stuck for almost a day without realizing the problem: I hadn’t opened Docker Desktop! 😅
If you’re building locally, always make sure Docker is running before you start it can save you hours of frustration.
1️⃣ Running Containers as Root
When I first ran containers, I didn’t think much about users. By default, Docker runs as root which felt convenient but was risky.
✅ What I learned:
Always create and use a non-root user inside your container.
FROM python:3.12-slim
RUN useradd -m appuser
USER appuser
WORKDIR /app
COPY . .
CMD ["python", "app.py"]
It’s a small change, but it adds a huge layer of security.
2️⃣ Using Untagged or Heavy Base Images
Early on, I would just use python:latest or big base images for convenience. The result? Bloated, unpredictable containers.
✅ What I learned:
Use versioned tags and multistage builds to keep images clean and stable.
# Build Stage
FROM maven:3.9.6-eclipse-temurin-21 AS builder
WORKDIR /app
COPY . .
RUN mvn clean package
# Runtime Stage
FROM eclipse-temurin:21-jre-alpine
WORKDIR /app
COPY --from=builder /app/target/app.jar /app/
CMD ["java", "-jar", "app.jar"]
This approach keeps your final image smaller and more predictable.
3️⃣ Using COPY . . Without Thinking
I used COPY . . in almost every Dockerfile at first. It was easy until I realized I was dragging in build artifacts, configs, and secrets by mistake.
✅ What I learned:
Be explicit about what you copy.
COPY target/app.jar /app/
A little extra effort here avoids heavier and riskier images later.
4️⃣ Splitting Updates and Installs into Separate Layers
I once ran apt-get update and apt-get install in separate RUN commands. It worked… until the cache broke during updates.
✅ What I learned:
Combine updates, installs, and cleanup in a single layer.
RUN apt-get update &&
apt-get install -y curl vim &&
rm -rf /var/lib/apt/lists/*
Fewer layers = cleaner cache = smaller images.
5️⃣ Installing Extra Dependencies
I used to install packages with all the extras, thinking it wouldn’t matter. It did images grew larger and the attack surface increased.
✅ What I learned:
Install only what’s necessary and clean up after.
RUN apt-get update &&
apt-get install -y --no-install-recommends curl &&
rm -rf /var/lib/apt/lists/*
Less clutter, more control.
🧭 Takeaways From My Docker Journey
Building Dockerfiles the right way is all about:
- Least privilege (non-root user)
- Minimal base images
- Explicit COPY instructions
- Single-layer installs
- Trimmed dependencies
After applying these lessons, my containers became smaller, safer, and more predictable exactly how modern DevOps should be.