Backend & DevOps2026-08-16 24 min read

Optimizing Docker Images for Production Microservices

Creating lightweight and secure Docker containers using multi-stage builds and optimal layer caching configurations.

ED
EropaDev Tech Team
DevOps Lead
#Docker #Docker Compose #Infrastructure #DevOps

Containerization with Docker transformed software deployment workflows. It guarantees that the application runs on production servers exactly as it does on local developer machines. However, unoptimized Docker images lead to slow CI/CD pipeline builds, high storage costs, and unnecessary security vulnerabilities.

The first rule of image optimization is using multi-stage builds. This approach allows using heavy build tools in temporary layers and copying only compiled assets into the final production image. For Nuxt 4, we build the application in a Node.js image, but copy only the compiled .output directory to the runner, shrinking the container from 1GB to 150MB.

Here is an optimized multi-stage Dockerfile for Nuxt 4:

Stage 1: Build FROM node:20-alpine AS builder WORKDIR /app COPY package*.json ./ RUN npm ci COPY . . RUN npm run build

Stage 2: Runner FROM node:20-alpine AS runner WORKDIR /app COPY --from=builder /app/.output ./.output EXPOSE 3000 CMD ["node", ".output/server/index.mjs"]

For PHP/Laravel configurations, we segregate PHP-FPM and Nginx web servers into isolated containers. The PHP container includes only required extensions (opcache, pdo_pgsql, redis) on top of lightweight Alpine Linux distributions. In production, we disable OPcache timestamp validation since container source files are immutable during runtime.

Production OPcache config settings (opcache.ini):
opcache.enable=1
opcache.validate_timestamps=0
opcache.memory_consumption=256
opcache.max_accelerated_files=20000

Container security dictates running processes under non-privileged users instead of root. For Node.js, we assign the default node user; for PHP-FPM, we assign the www-data user. This defends the host node if an attacker manages to break out of the containerized process.

Optimize Docker layer caching by structuring instructions correctly. Copy dependency files (package.json or composer.json) and run installations first, then copy the rest of your application code. Docker caches these installation layers, which cuts build times in your CI/CD pipeline significantly.

Adhering to these container design patterns accelerates your code deployments, secures your infrastructure topologies, and minimizes virtual machine operational costs.

Published by EropaDev Engineering Team