Docker Guide - jnleyva816/NextMove GitHub Wiki
Docker Guide
This guide covers all aspects of Docker usage in the NextMove project, from development to production deployment.
📦 Container Overview
The NextMove uses a multi-container architecture:
Service | Image | Purpose | Port |
---|---|---|---|
Frontend | jleyva816/nextmove-frontend:latest |
React application | 3000 |
Backend | jleyva816/nextmove-backend:latest |
Spring Boot API | 8080 |
Database | postgres:15 |
PostgreSQL database | 5432 |
Nginx | nginx:alpine |
Reverse proxy (production) | 80/443 |
🏗️ Multi-Stage Builds
Both frontend and backend use optimized multi-stage Docker builds for security and performance.
Backend Dockerfile
# Build stage
FROM openjdk:17-jdk-slim as build
WORKDIR /app
COPY pom.xml .
COPY src ./src
RUN ./mvnw clean package -DskipTests
# Runtime stage
FROM openjdk:17-jre-slim
RUN addgroup --system spring && adduser --system spring --ingroup spring
USER spring:spring
COPY --from=build /app/target/*.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "/app.jar"]
Frontend Dockerfile
# Build stage
FROM node:20-alpine as build
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
RUN npm run build
# Runtime stage
FROM nginx:alpine
COPY --from=build /app/dist /usr/share/nginx/html
COPY nginx.conf /etc/nginx/nginx.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
🔧 Development with Docker Compose
Local Development Setup
# docker-compose.yml
version: '3.8'
services:
postgres:
image: postgres:15
environment:
POSTGRES_DB: nextmove
POSTGRES_USER: postgres
POSTGRES_PASSWORD: password
ports:
- "5432:5432"
volumes:
- postgres_data:/var/lib/postgresql/data
- ./backend/init.sql:/docker-entrypoint-initdb.d/init.sql
backend:
build: ./backend
ports:
- "8080:8080"
environment:
- DB_HOST=postgres
- DB_PORT=5432
- DB_NAME=nextmove
- DB_USER=postgres
- DB_PASSWORD=password
- JWT_SECRET=${JWT_SECRET:-your-secret-key}
depends_on:
- postgres
volumes:
- ./backend:/app
- ~/.m2:/root/.m2
frontend:
build: ./frontend
ports:
- "3000:80"
environment:
- VITE_API_URL=http://localhost:8080
depends_on:
- backend
volumes:
- ./frontend:/app
- /app/node_modules
volumes:
postgres_data:
Development Commands
# Start all services
docker-compose up -d
# View logs
docker-compose logs -f
# Stop services
docker-compose down
# Rebuild and start
docker-compose up --build
# Clean up everything
docker-compose down -v --remove-orphans
🏭 Production Deployment
Production Docker Compose
# docker-compose.prod.yml
version: '3.8'
services:
postgres:
image: postgres:15
environment:
POSTGRES_DB: ${DB_NAME}
POSTGRES_USER: ${DB_USER}
POSTGRES_PASSWORD: ${DB_PASSWORD}
volumes:
- postgres_data:/var/lib/postgresql/data
networks:
- app-network
restart: unless-stopped
backend:
image: jleyva816/nextmove-backend:latest
environment:
- DB_HOST=postgres
- DB_PORT=5432
- DB_NAME=${DB_NAME}
- DB_USER=${DB_USER}
- DB_PASSWORD=${DB_PASSWORD}
- JWT_SECRET=${JWT_SECRET}
- SPRING_PROFILES_ACTIVE=prod
depends_on:
- postgres
networks:
- app-network
restart: unless-stopped
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/actuator/health"]
interval: 30s
timeout: 10s
retries: 3
frontend:
image: jleyva816/nextmove-frontend:latest
depends_on:
- backend
networks:
- app-network
restart: unless-stopped
nginx:
image: nginx:alpine
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
- ./ssl:/etc/nginx/ssl
depends_on:
- frontend
- backend
networks:
- app-network
restart: unless-stopped
volumes:
postgres_data:
networks:
app-network:
driver: bridge
🔨 Building Images
Manual Build Process
# Build backend image
cd backend
docker build -t jleyva816/nextmove-backend:latest .
# Build frontend image
cd frontend
docker build -t jleyva816/nextmove-frontend:latest .
# Tag for different versions
docker tag jleyva816/nextmove-backend:latest jleyva816/nextmove-backend:v1.0.0
docker tag jleyva816/nextmove-frontend:latest jleyva816/nextmove-frontend:v1.0.0
Automated Build (CI/CD)
# .github/workflows/ci-cd.yml (excerpt)
- name: Build and Push Backend Image
run: |
docker build -t jleyva816/nextmove-backend:${{ github.sha }} ./backend
docker tag jleyva816/nextmove-backend:${{ github.sha }} jleyva816/nextmove-backend:latest
docker push jleyva816/nextmove-backend:${{ github.sha }}
docker push jleyva816/nextmove-backend:latest
- name: Build and Push Frontend Image
run: |
docker build -t jleyva816/nextmove-frontend:${{ github.sha }} ./frontend
docker tag jleyva816/nextmove-frontend:${{ github.sha }} jleyva816/nextmove-frontend:latest
docker push jleyva816/nextmove-frontend:${{ github.sha }}
docker push jleyva816/nextmove-frontend:latest
🔐 Security Best Practices
Container Security
- Non-root users: All containers run as non-privileged users
- Distroless images: Minimal attack surface with slim base images
- Secret management: Environment variables for sensitive data
- Read-only filesystems: Where possible
- Network isolation: Private networks for internal communication
Image Scanning
# Scan images for vulnerabilities
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock \
aquasec/trivy:latest image jleyva816/nextmove-backend:latest
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock \
aquasec/trivy:latest image jleyva816/nextmove-frontend:latest
📊 Monitoring & Health Checks
Health Check Configuration
# Backend Dockerfile health check
HEALTHCHECK --interval=30s --timeout=10s --start-period=60s --retries=3 \
CMD curl -f http://localhost:8080/actuator/health || exit 1
Container Monitoring
# Check container resource usage
docker stats
# View container logs
docker logs -f nextmove_backend_1
# Inspect container configuration
docker inspect nextmove_backend_1
🗂️ Volume Management
Data Persistence
volumes:
postgres_data:
driver: local
backend_logs:
driver: local
nginx_logs:
driver: local
Backup Strategies
# Backup database volume
docker run --rm -v nextmove_postgres_data:/data -v $(pwd):/backup \
alpine tar czf /backup/postgres_backup_$(date +%Y%m%d_%H%M%S).tar.gz -C /data .
# Restore database volume
docker run --rm -v nextmove_postgres_data:/data -v $(pwd):/backup \
alpine tar xzf /backup/postgres_backup_20250101_120000.tar.gz -C /data
⚡ Performance Optimization
Resource Limits
services:
backend:
deploy:
resources:
limits:
cpus: '1.0'
memory: 512M
reservations:
cpus: '0.5'
memory: 256M
Build Optimization
# Use .dockerignore to exclude unnecessary files
# .dockerignore
node_modules
npm-debug.log
.git
.gitignore
README.md
.env
coverage
.nyc_output
🚀 Deployment Commands
Development Deployment
# Start development environment
docker-compose up -d
# Scale services
docker-compose up -d --scale backend=2
# Update single service
docker-compose up -d --no-deps backend
Production Deployment
# Deploy to production
docker-compose -f docker-compose.prod.yml up -d
# Rolling update
docker-compose -f docker-compose.prod.yml pull
docker-compose -f docker-compose.prod.yml up -d --no-deps backend
docker-compose -f docker-compose.prod.yml up -d --no-deps frontend
🐛 Troubleshooting
Common Issues
Build failures:
# Clear build cache
docker builder prune
# Build without cache
docker build --no-cache -t jleyva816/nextmove-backend:latest ./backend
Container networking issues:
# Inspect networks
docker network ls
docker network inspect nextmove_default
# Test connectivity
docker exec -it nextmove_backend_1 ping postgres
Permission issues:
# Check container user
docker exec -it nextmove_backend_1 whoami
# Fix file permissions
sudo chown -R $USER:$USER ./data
Debugging Commands
# Enter container shell
docker exec -it nextmove_backend_1 /bin/bash
# View container processes
docker exec -it nextmove_backend_1 ps aux
# Check container environment
docker exec -it nextmove_backend_1 env
📋 Best Practices Checklist
- Use multi-stage builds for optimized images
- Run containers as non-root users
- Implement proper health checks
- Use specific image tags in production
- Configure resource limits
- Implement proper logging
- Use secrets management for sensitive data
- Regular security scanning of images
- Proper backup strategies for persistent data
- Container monitoring and alerting
For more Docker-related questions, check the Troubleshooting Guide or create an issue.