This project uses Docker to containerize each major component — Frontend, Backend, and gRPC service — providing isolated, reproducible environments optimized for development and production deployment. The Docker setup leverages multi-stage builds to produce minimal, secure images by separating build-time dependencies from runtime.
Overview
- Frontend Service: A React/Vite frontend built inside a Node.js Alpine container, then served via an optimized Nginx Alpine container configured with SPA fallback routing, caching headers, security headers, and health checks.
- Backend Service: A Kotlin Spring Boot application containerized with JDK 21 on Alpine Linux. Multi-stage build compiles the application into a bootable JAR with Gradle, then runs it under a non-root user with appropriate health checks.
- gRPC Service: A Go-based gRPC server built in a Golang Alpine container, producing a statically linked Linux binary. The runtime image is Alpine with minimal dependencies and a gRPC health probe for container readiness.
Key Features
Multi-stage Builds
Each Dockerfile uses multi-stage builds to separate the build environment from the final runtime container. This approach minimizes the final image size and attack surface by excluding build tools and caches from the runtime image.
Security Best Practices
- Containers run as a non-root user (
appuser
) inside a dedicated group (appgroup
) to improve security.
- Minimal base images like
alpine
and official lightweight images are used to reduce vulnerabilities.
- Health checks are defined to enable container orchestration platforms (e.g., Kubernetes, Docker Compose) to monitor container health and restart if necessary.
- Sensitive or unnecessary files (e.g.,
.env
, build caches, IDE configs) are excluded via .dockerignore
to keep images clean.
Health Checks
- Backend and frontend containers expose HTTP health endpoints checked regularly via
curl
.
- The gRPC container uses the official
grpc_health_probe
binary to verify server readiness.
Development vs. Production