My first Docker production deploy went like this:
- Built image locally
- Pushed to registry
- Pulled on server
- App crashed immediately
- Spent 6 hours debugging
Here's everything I learned the hard way.
Lesson 1: Multi-Stage Builds Are Non-Negotiable
# BAD: 1.2GB image with build tools in production
FROM node:18
COPY . .
RUN npm install
RUN npm run build
CMD ["node", "dist/server.js"]
# GOOD: 150MB image, only runtime deps
FROM node:18 AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
FROM node:18-slim
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
CMD ["node", "dist/server.js"]
Result: Image went from 1.2GB to 150MB. Deploys 8x faster.
Lesson 2: Health Checks Save Lives
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD curl -f http://localhost:3000/health || exit 1
Without this, Docker thinks your container is healthy even when the app inside is completely dead.
Lesson 3: Don't Run as Root
RUN addgroup --system app && adduser --system --ingroup app app
USER app
One CVE in your dependency and an attacker has root access to your container.
Lesson 4: .dockerignore Matters
node_modules
.git
.env
*.md
tests/
coverage/
I once accidentally included .env with production database credentials in a public Docker image.
Lesson 5: Log to stdout, Not Files
// BAD
fs.appendFileSync('/var/log/app.log', message);
// GOOD
console.log(JSON.stringify({
timestamp: new Date().toISOString(),
level: 'info',
message: message
}));
Docker captures stdout/stderr automatically.
Lesson 6: Pin Your Base Image Version
# BAD
FROM node:latest
# GOOD
FROM node:18.19.0-slim
My Production Checklist
- [ ] Multi-stage build
- [ ] Non-root user
- [ ] Health check defined
- [ ] .dockerignore configured
- [ ] Base image pinned
- [ ] Logs go to stdout
- [ ] Secrets via env vars, not baked in
Going Deeper
If you're moving to cloud infrastructure:
- CloudSphere Guide ($8.99) - Docker + cloud deployment patterns I use daily
What was your worst Docker production moment?
Top comments (0)