Skip to main content
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

1

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.
2

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
3

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.
1

Create Railway Project

  1. Go to Railway
  2. Create a new project
  3. Add a MySQL database service
  4. Note the connection details from the MySQL service
2

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.
3

Deploy from GitHub

  1. Connect your GitHub repository
  2. Railway auto-detects the Dockerfile
  3. 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
4

Configure Custom Domain (Optional)

  1. Go to your service settings
  2. Click “Generate Domain” for a Railway subdomain
  3. Or add your custom domain
  4. 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.

Cloud Platform Deployment

AWS Elastic Beanstalk

1

Package Application

./mvnw clean package
2

Create Dockerrun.aws.json

{
  "AWSEBDockerrunVersion": "1",
  "Image": {
    "Name": "your-registry/drivex-backend:latest",
    "Update": "true"
  },
  "Ports": [
    {
      "ContainerPort": 8080,
      "HostPort": 8080
    }
  ]
}
3

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

1

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
2

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

1

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
2

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:
docker-compose.yml
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:
VariableRequiredDescriptionExample
SPRING_DATASOURCE_URLYesJDBC connection URLjdbc:mysql://host:3306/db
SPRING_DATASOURCE_USERNAMEYesDatabase usernameroot
SPRING_DATASOURCE_PASSWORDYesDatabase passwordsecretpassword
PORTNoServer port (default: 8080)8080
SPRING_JPA_HIBERNATE_DDL_AUTONoSchema managementvalidate
SPRING_JPA_SHOW_SQLNoSQL loggingfalse
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

# Follow logs
docker logs -f <container-id>

# Last 100 lines
docker logs --tail 100 <container-id>

Log Configuration

application.properties
# 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

Performance Optimization

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-id>
Common issues:
  • Database connection errors: Verify SPRING_DATASOURCE_URL
  • Port already in use: Change PORT environment variable
  • Out of memory: Increase container memory limits
Verify connectivity:
# From container
docker exec -it <container-id> /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-id>
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

Build docs developers (and LLMs) love