Docker provides the easiest way to deploy the complete Justina platform. This guide covers both single-container deployment and multi-service orchestration with Docker Compose.
Prerequisites
Ensure you have Docker installed:
# Verify Docker installation
docker --version
docker-compose --version
Backend Docker Deployment
Build Backend Image
The backend includes a Dockerfile based on Eclipse Temurin Java 21:
# Base image with Java 21
FROM eclipse-temurin:21-jdk
# Working directory inside container
WORKDIR /app
# Copy project files
COPY . .
# Give permissions to Maven wrapper
RUN chmod +x mvnw
# Build the application
RUN ./mvnw clean package -DskipTests
# Expose port
EXPOSE 8080
# Start command
CMD [ "sh" , "-c" , "java -jar target/*.jar --server.port=${PORT}" ]
Navigate to Backend Directory
Build Docker Image
docker build -t justina-backend:latest .
This process:
Downloads Java 21 base image
Copies source code
Runs Maven build
Creates optimized production image
Run Backend Container
docker run -p 8080:8080 \
-e JWT_SECRET_KEY=your-secret-key \
-e SPRING_DATASOURCE_URL=jdbc:postgresql://host.docker.internal:5432/justina \
-e SPRING_DATASOURCE_USERNAME=postgres \
-e SPRING_DATASOURCE_PASSWORD=password \
justina-backend:latest
Run with H2 Database (Development)
For quick testing without PostgreSQL:
docker run -p 8080:8080 \
-e JWT_SECRET_KEY=dev-secret-key \
justina-backend:latest
H2 database data is lost when the container stops. Only use for development.
Docker Compose Deployment (Recommended)
Docker Compose orchestrates all services together, including the database.
Complete docker-compose.yml
Create docker-compose.yml in your project root:
version : '3.8'
services :
justina-backend :
build : ./backend
ports :
- "8080:8080"
environment :
- PORT=8080
- JWT_SECRET_KEY=your-secret-key-here
- SPRING_DATASOURCE_URL=jdbc:postgresql://postgres:5432/justina
- SPRING_DATASOURCE_USERNAME=postgres
- SPRING_DATASOURCE_PASSWORD=postgres
- SPRING_DATASOURCE_DRIVER_CLASS_NAME=org.postgresql.Driver
- SPRING_JPA_HIBERNATE_DDL_AUTO=update
- SPRING_JPA_PROPERTIES_HIBERNATE_DIALECT=org.hibernate.dialect.PostgreSQLDialect
depends_on :
- postgres
networks :
- justina-network
postgres :
image : postgres:15
environment :
- POSTGRES_DB=justina
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=postgres
volumes :
- postgres-data:/var/lib/postgresql/data
ports :
- "5432:5432"
networks :
- justina-network
volumes :
postgres-data :
networks :
justina-network :
driver : bridge
Deploy with Docker Compose
Start All Services
This command:
Builds backend image if not exists
Pulls PostgreSQL 15 image
Creates network and volumes
Starts all services in detached mode
View Logs
# All services
docker-compose logs -f
# Specific service
docker-compose logs -f justina-backend
Verify Services
# Check running containers
docker-compose ps
# Check backend health
curl http://localhost:8080/swagger-ui/index.html
Management Commands
Start Services
Stop Services
View Information
# Start in foreground
docker-compose up
# Start in background (detached)
docker-compose up -d
# Rebuild and start
docker-compose up --build
Multi-Service Compose with Frontend and AI
Complete deployment including frontend and AI service:
version : '3.8'
services :
justina-backend :
build : ./backend
ports :
- "8080:8080"
environment :
- PORT=8080
- JWT_SECRET_KEY=${JWT_SECRET_KEY}
- SPRING_DATASOURCE_URL=jdbc:postgresql://postgres:5432/justina
- SPRING_DATASOURCE_USERNAME=postgres
- SPRING_DATASOURCE_PASSWORD=${DB_PASSWORD}
- SPRING_DATASOURCE_DRIVER_CLASS_NAME=org.postgresql.Driver
- SPRING_JPA_HIBERNATE_DDL_AUTO=update
- SPRING_JPA_PROPERTIES_HIBERNATE_DIALECT=org.hibernate.dialect.PostgreSQLDialect
depends_on :
- postgres
networks :
- justina-network
justina-frontend :
build : ./frontend
ports :
- "3000:3000"
environment :
- NEXT_PUBLIC_API_URL=http://justina-backend:8080
- NEXT_PUBLIC_WS_URL=ws://justina-backend:8080
depends_on :
- justina-backend
networks :
- justina-network
justina-ai :
build : ./ia
environment :
- BACKEND_URL=http://justina-backend:8080
- IA_USERNAME=ia_justina
- IA_PASSWORD=${IA_PASSWORD}
depends_on :
- justina-backend
networks :
- justina-network
postgres :
image : postgres:15
environment :
- POSTGRES_DB=justina
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=${DB_PASSWORD}
volumes :
- postgres-data:/var/lib/postgresql/data
networks :
- justina-network
volumes :
postgres-data :
networks :
justina-network :
driver : bridge
Create .env file:
JWT_SECRET_KEY = your-secure-secret-key
DB_PASSWORD = your-database-password
IA_PASSWORD = your-ai-password
Deploy:
docker-compose -f docker-compose.full.yml --env-file .env up -d
Production Best Practices
Use Environment Files
Never hardcode secrets in docker-compose.yml: environment :
- JWT_SECRET_KEY=${JWT_SECRET_KEY}
Persist Data with Volumes
Always use named volumes for databases: volumes :
- postgres-data:/var/lib/postgresql/data
Health Checks
Add health checks to ensure services are ready: healthcheck :
test : [ "CMD" , "curl" , "-f" , "http://localhost:8080/actuator/health" ]
interval : 30s
timeout : 10s
retries : 3
Resource Limits
Set memory and CPU limits: deploy :
resources :
limits :
cpus : '2.0'
memory : 2G
Troubleshooting
Check logs for errors: docker-compose logs justina-backend
Common issues:
Port already in use (change port mapping)
Missing environment variables
Database connection failed
Cannot connect to database
Verify network connectivity: docker-compose exec justina-backend ping postgres
Check database is running: docker-compose ps postgres
Clear build cache and rebuild: docker-compose build --no-cache
Clean up unused Docker resources: docker system prune -a
docker volume prune
Next Steps
Configure Environment Variables properly
Set up monitoring and logging
Configure reverse proxy (Nginx/Traefik)
Enable SSL/TLS certificates
Implement automated backups
For manual deployment without Docker, see: