This guide covers deploying the DriveX Backend API using Docker containers, with specific instructions for Railway and other cloud platforms.
Prerequisites
Docker installed (version 20.10+)
Java 17 JDK (for local builds)
Maven 3.9+ (or use included Maven wrapper)
MySQL database (local or cloud-hosted)
Docker Deployment
The application includes a multi-stage Dockerfile optimized for production deployments.
Dockerfile Overview
The Dockerfile uses a two-stage build process:
# Stage 1: Build JAR with Maven
FROM maven:3.9-eclipse-temurin-17-alpine AS build
WORKDIR /app
# Copy pom.xml first for dependency caching
COPY pom.xml .
# Copy source code
COPY src ./src
# Build JAR (skip tests for faster builds)
RUN ./mvnw -DskipTests clean package || mvn -DskipTests clean package
Benefits:
Smaller final image size (build dependencies not included)
Faster deployments
Layer caching for dependencies
Optimized for production use
Building the Docker Image
Build the Image
Build the Docker image from your project root: docker build -t drivex-backend:latest .
The build process may take 3-5 minutes on first run while Maven downloads dependencies.
Verify the Build
Check that the image was created successfully: docker images | grep drivex-backend
You should see output like: drivex-backend latest abc123def456 2 minutes ago 450MB
Test Locally
Run the container locally to test: docker run -p 8080:8080 \
-e SPRING_DATASOURCE_URL=jdbc:mysql://host.docker.internal:3306/DriveX \
-e SPRING_DATASOURCE_USERNAME=root \
-e SPRING_DATASOURCE_PASSWORD=your_password \
drivex-backend:latest
Use host.docker.internal to connect to MySQL running on your host machine from Docker.
Local Deployment
For development and testing without Docker:
Using Maven Wrapper
# Clean and build
./mvnw clean package
# Run the application
./mvnw spring-boot:run
Using Java
# Build JAR
./mvnw clean package -DskipTests
# Run JAR directly
java -jar target/DriveX-0.0.1-SNAPSHOT.jar
With Environment Variables
export SPRING_DATASOURCE_URL = jdbc : mysql :// localhost : 3306 / DriveX
export SPRING_DATASOURCE_USERNAME = root
export SPRING_DATASOURCE_PASSWORD = your_password
export PORT = 8080
./mvnw spring-boot:run
Railway Deployment
Railway provides an optimized platform for Spring Boot applications with built-in MySQL support.
Create Railway Project
Go to Railway
Create a new project
Add a MySQL database service
Note the connection details from the MySQL service
Configure Environment Variables
In your Railway project settings, add the following variables: SPRING_DATASOURCE_URL = jdbc:mysql://mysql.railway.internal:3306/railway
SPRING_DATASOURCE_USERNAME = root
SPRING_DATASOURCE_PASSWORD = ${ MYSQLPASSWORD }
PORT = 8080
Railway automatically provides MYSQLPASSWORD and internal networking via mysql.railway.internal.
Deploy from GitHub
Connect your GitHub repository
Railway auto-detects the Dockerfile
Deploy automatically on every push to main branch
Or deploy manually: # Install Railway CLI
npm install -g @railway/cli
# Login
railway login
# Link project
railway link
# Deploy
railway up
Configure Custom Domain (Optional)
Go to your service settings
Click “Generate Domain” for a Railway subdomain
Or add your custom domain
Railway handles SSL certificates automatically
Railway’s internal networking allows services to communicate without exposing MySQL to the internet. Always use mysql.railway.internal for database connections.
AWS Elastic Beanstalk
Create Dockerrun.aws.json
{
"AWSEBDockerrunVersion" : "1" ,
"Image" : {
"Name" : "your-registry/drivex-backend:latest" ,
"Update" : "true"
},
"Ports" : [
{
"ContainerPort" : 8080 ,
"HostPort" : 8080
}
]
}
Deploy to Elastic Beanstalk
# Initialize EB CLI
eb init -p docker drivex-backend
# Create environment
eb create drivex-production
# Set environment variables
eb setenv SPRING_DATASOURCE_URL=jdbc:mysql://your-rds:3306/drivex \
SPRING_DATASOURCE_USERNAME=admin \
SPRING_DATASOURCE_PASSWORD=password
# Deploy
eb deploy
Google Cloud Run
Build and Push to Container Registry
# Configure Docker for GCR
gcloud auth configure-docker
# Build and tag
docker build -t gcr.io/YOUR_PROJECT_ID/drivex-backend:latest .
# Push to GCR
docker push gcr.io/YOUR_PROJECT_ID/drivex-backend:latest
Deploy to Cloud Run
gcloud run deploy drivex-backend \
--image gcr.io/YOUR_PROJECT_ID/drivex-backend:latest \
--platform managed \
--region us-central1 \
--allow-unauthenticated \
--set-env-vars SPRING_DATASOURCE_URL=jdbc:mysql://10.0.0.1:3306/drivex, \
SPRING_DATASOURCE_USERNAME=root, \
SPRING_DATASOURCE_PASSWORD=secret
Azure App Service
Create App Service
# Create resource group
az group create --name drivex-rg --location eastus
# Create App Service plan
az appservice plan create --name drivex-plan \
--resource-group drivex-rg \
--is-linux --sku B1
# Create web app
az webapp create --name drivex-backend \
--resource-group drivex-rg \
--plan drivex-plan \
--deployment-container-image-name drivex-backend:latest
Configure Environment
az webapp config appsettings set --name drivex-backend \
--resource-group drivex-rg \
--settings \
SPRING_DATASOURCE_URL="jdbc:mysql://your-azure-mysql:3306/drivex" \
SPRING_DATASOURCE_USERNAME="admin@your-server" \
SPRING_DATASOURCE_PASSWORD="password" \
PORT="8080"
Docker Compose for Local Development
Run the entire stack locally with Docker Compose:
version : '3.8'
services :
mysql :
image : mysql:8.0
environment :
MYSQL_DATABASE : DriveX
MYSQL_ROOT_PASSWORD : rootpassword
ports :
- "3306:3306"
volumes :
- mysql_data:/var/lib/mysql
- ./src/main/resources/bs.sql:/docker-entrypoint-initdb.d/init.sql
backend :
build : .
ports :
- "8080:8080"
environment :
SPRING_DATASOURCE_URL : jdbc:mysql://mysql:3306/DriveX
SPRING_DATASOURCE_USERNAME : root
SPRING_DATASOURCE_PASSWORD : rootpassword
SPRING_JPA_HIBERNATE_DDL_AUTO : update
depends_on :
- mysql
volumes :
mysql_data :
Usage:
# Start services
docker-compose up -d
# View logs
docker-compose logs -f backend
# Stop services
docker-compose down
# Stop and remove volumes
docker-compose down -v
Environment Variables
Required environment variables for production:
Variable Required Description Example SPRING_DATASOURCE_URLYes JDBC connection URL jdbc:mysql://host:3306/dbSPRING_DATASOURCE_USERNAMEYes Database username rootSPRING_DATASOURCE_PASSWORDYes Database password secretpasswordPORTNo Server port (default: 8080) 8080SPRING_JPA_HIBERNATE_DDL_AUTONo Schema management validateSPRING_JPA_SHOW_SQLNo SQL logging false
Security Best Practices:
Never commit credentials to version control
Use secret management services (AWS Secrets Manager, GCP Secret Manager, etc.)
Rotate passwords regularly
Use validate or none for ddl-auto in production
Disable SQL logging in production
Health Checks
Spring Boot provides built-in health check endpoints:
# Health check
curl http://localhost:8080/api/actuator/health
# Application info
curl http://localhost:8080/api/actuator/info
Enable Actuator (pom.xml):
< dependency >
< groupId > org.springframework.boot </ groupId >
< artifactId > spring-boot-starter-actuator </ artifactId >
</ dependency >
Configure health endpoints (application.properties):
management.endpoints.web.exposure.include =health,info
management.endpoint.health.show-details =when-authorized
Monitoring and Logging
Application Logs
Docker Logs
Railway Logs
Kubernetes Logs
# Follow logs
docker logs -f < container-i d >
# Last 100 lines
docker logs --tail 100 < container-i d >
Log Configuration
# Log level
logging.level.root =INFO
logging.level.com.DriveX =DEBUG
logging.level.org.springframework.web =INFO
logging.level.org.hibernate =WARN
# Log file
logging.file.name =/var/log/drivex/application.log
logging.file.max-size =10MB
logging.file.max-history =30
JVM Options
Optimize Java runtime for production:
ENTRYPOINT [ "java" , \
"-Xms512m" , \
"-Xmx1024m" , \
"-XX:+UseG1GC" , \
"-XX:MaxGCPauseMillis=200" , \
"-jar" , "app.jar" ]
Connection Pool Tuning
spring.datasource.hikari.maximum-pool-size =20
spring.datasource.hikari.minimum-idle =10
spring.datasource.hikari.connection-timeout =30000
spring.datasource.hikari.idle-timeout =600000
spring.datasource.hikari.max-lifetime =1800000
Troubleshooting
Check logs: docker logs < container-i d >
Common issues:
Database connection errors: Verify SPRING_DATASOURCE_URL
Port already in use: Change PORT environment variable
Out of memory: Increase container memory limits
Database connection timeout
Verify connectivity: # From container
docker exec -it < container-i d > /bin/sh
ping mysql.railway.internal
Check:
Database host is reachable
Credentials are correct
Database service is running
Firewall rules allow connection
Monitor: docker stats < container-i d >
Solutions:
Reduce -Xmx heap size
Decrease connection pool size
Enable JVM garbage collection logging
Profile application for memory leaks
CI/CD Pipeline
GitHub Actions Example
.github/workflows/deploy.yml
name : Deploy to Railway
on :
push :
branches : [ main ]
jobs :
deploy :
runs-on : ubuntu-latest
steps :
- uses : actions/checkout@v3
- name : Set up Java 17
uses : actions/setup-java@v3
with :
java-version : '17'
distribution : 'temurin'
- name : Build with Maven
run : ./mvnw clean package -DskipTests
- name : Build Docker image
run : docker build -t drivex-backend:${{ github.sha }} .
- name : Deploy to Railway
uses : railway/deploy@v1
with :
railway-token : ${{ secrets.RAILWAY_TOKEN }}
Next Steps
Configuration Learn about configuration options and environment variables
Database Setup Set up and manage the MySQL database