Docker Patterns
Dockerfile - Java Spring Boot
dockerfile
# Build stage FROM maven:3.9-eclipse-temurin-21 AS build WORKDIR /app COPY pom.xml . RUN mvn dependency:go-offline -B COPY src ./src RUN mvn package -DskipTests -B # Runtime stage FROM eclipse-temurin:21-jre-alpine WORKDIR /app # Security: non-root user RUN addgroup -S appgroup && adduser -S appuser -G appgroup USER appuser COPY --from=build /app/target/*.jar app.jar EXPOSE 8080 HEALTHCHECK --interval=30s --timeout=3s \ CMD wget -q --spider http://localhost:8080/actuator/health || exit 1 ENTRYPOINT ["java", "-jar", "app.jar"]
Dockerfile - Node.js
dockerfile
# Build stage FROM node:20-alpine AS build WORKDIR /app COPY package*.json ./ RUN npm ci COPY . . RUN npm run build # Runtime stage FROM node:20-alpine WORKDIR /app ENV NODE_ENV=production RUN addgroup -S appgroup && adduser -S appuser -G appgroup USER appuser COPY --from=build /app/dist ./dist COPY --from=build /app/node_modules ./node_modules COPY package*.json ./ EXPOSE 3000 HEALTHCHECK --interval=30s --timeout=3s \ CMD wget -q --spider http://localhost:3000/health || exit 1 CMD ["node", "dist/index.js"]
Dockerfile - React (Vite)
dockerfile
# Build stage FROM node:20-alpine AS build WORKDIR /app COPY package*.json ./ RUN npm ci COPY . . RUN npm run build # Runtime stage FROM nginx:alpine COPY --from=build /app/dist /usr/share/nginx/html COPY nginx.conf /etc/nginx/conf.d/default.conf EXPOSE 80 HEALTHCHECK --interval=30s --timeout=3s \ CMD wget -q --spider http://localhost:80 || exit 1
Docker Compose - Full Stack
yaml
version: '3.8'
services:
app:
build:
context: .
dockerfile: Dockerfile
ports:
- "${APP_PORT:-8080}:8080"
environment:
- SPRING_PROFILES_ACTIVE=docker
- DB_HOST=db
- DB_PORT=5432
- DB_NAME=${DB_NAME}
- DB_USER=${DB_USER}
- DB_PASSWORD=${DB_PASSWORD}
- REDIS_HOST=redis
depends_on:
db:
condition: service_healthy
redis:
condition: service_healthy
networks:
- app-network
db:
image: postgres:16-alpine
environment:
POSTGRES_DB: ${DB_NAME}
POSTGRES_USER: ${DB_USER}
POSTGRES_PASSWORD: ${DB_PASSWORD}
volumes:
- postgres_data:/var/lib/postgresql/data
ports:
- "${DB_PORT:-5432}:5432"
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${DB_USER} -d ${DB_NAME}"]
interval: 5s
timeout: 5s
retries: 5
networks:
- app-network
redis:
image: redis:7-alpine
command: redis-server --appendonly yes
volumes:
- redis_data:/data
ports:
- "${REDIS_PORT:-6379}:6379"
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 5s
timeout: 3s
retries: 5
networks:
- app-network
mongo:
image: mongo:7
environment:
MONGO_INITDB_ROOT_USERNAME: ${MONGO_USER}
MONGO_INITDB_ROOT_PASSWORD: ${MONGO_PASSWORD}
volumes:
- mongo_data:/data/db
ports:
- "${MONGO_PORT:-27017}:27017"
healthcheck:
test: ["CMD", "mongosh", "--eval", "db.adminCommand('ping')"]
interval: 10s
timeout: 5s
retries: 5
networks:
- app-network
volumes:
postgres_data:
redis_data:
mongo_data:
networks:
app-network:
driver: bridge
.dockerignore
code
.git .gitignore *.md !README.md .env .env.* target/ node_modules/ dist/ .idea/ *.iml .vscode/ *.log Dockerfile* docker-compose*
.env.example
bash
# Application APP_PORT=8080 # PostgreSQL DB_NAME=myapp DB_USER=postgres DB_PASSWORD=changeme DB_PORT=5432 # Redis REDIS_PORT=6379 # MongoDB MONGO_USER=admin MONGO_PASSWORD=changeme MONGO_PORT=27017
Commands
bash
# Build and start docker compose up -d --build # View logs docker compose logs -f app # Stop all docker compose down # Stop and remove volumes docker compose down -v # Rebuild single service docker compose up -d --build app # Execute command in container docker compose exec app sh # Check health docker compose ps
Best Practices
- •Use multi-stage builds to reduce image size
- •Always use specific image tags, not
latest - •Run as non-root user
- •Include health checks
- •Use
.dockerignoreto exclude unnecessary files - •Use environment variables for configuration
- •Never include secrets in images
- •Use named volumes for persistent data