Skip to main content

Chapter 4: Cloud Deployment

Introduction​

Your application is ready, Docker configured, CI/CD in place. It's time to go live! This chapter covers the main cloud deployment options.


🎯 Chapter Objectives​

By the end of this chapter, you will know how to:

  1. ✅ Deploy on Railway
  2. ✅ Deploy on Heroku
  3. ✅ Understand AWS options
  4. ✅ Configure a managed database
  5. ✅ Choose the right platform

1. Platform Comparison​

PlatformDifficultyCostIdeal for
Railway⭐ EasyFree → $5/monthPersonal projects, startups
Heroku⭐ Easy$7/monthSimple apps
Render⭐ EasyFree → $7/monthHeroku alternative
AWS ECS⭐⭐⭐ ComplexVariableEnterprise
Kubernetes⭐⭐⭐⭐ AdvancedVariableMicroservices

Why Railway?​

  • ✅ Simple interface
  • ✅ Deployment from GitHub
  • ✅ Integrated PostgreSQL
  • ✅ Free to start
  • ✅ Supports Docker

Deployment​

Option 1: From GitHub

  1. Go to railway.app
  2. "New Project" → "Deploy from GitHub repo"
  3. Select your repository
  4. Railway automatically detects Spring Boot

Option 2: With Docker

# Install Railway CLI
npm i -g @railway/cli

# Login
railway login

# Create a project
railway init

# Deploy
railway up

Configuration​

# Environment variables (in Railway Dashboard)
SPRING_PROFILES_ACTIVE=prod
DATABASE_URL=${{Postgres.DATABASE_URL}}

Add PostgreSQL​

  1. In the Railway project: "New" → "Database" → "PostgreSQL"
  2. Variables are automatically injected

railway.json​

{
"$schema": "https://railway.app/railway.schema.json",
"build": {
"builder": "DOCKERFILE",
"dockerfilePath": "Dockerfile"
},
"deploy": {
"startCommand": "java -jar app.jar",
"healthcheckPath": "/actuator/health",
"restartPolicyType": "ON_FAILURE"
}
}

3. Heroku​

Preparation​

Procfile (at the root):

web: java -Dserver.port=$PORT -jar target/*.jar

system.properties:

java.runtime.version=17

Deployment​

# Install Heroku CLI
# https://devcenter.heroku.com/articles/heroku-cli

# Login
heroku login

# Create the app
heroku create my-spring-app

# Add PostgreSQL
heroku addons:create heroku-postgresql:mini

# Deploy
git push heroku main

# View logs
heroku logs --tail

Environment Variables​

heroku config:set SPRING_PROFILES_ACTIVE=prod
heroku config:set JWT_SECRET=your-secret-key

# View all variables
heroku config

With Docker​

# Login to Heroku registry
heroku container:login

# Build and push
heroku container:push web

# Deploy
heroku container:release web

4. Render​

Deployment​

  1. Go to render.com
  2. "New" → "Web Service"
  3. Connect GitHub
  4. Configure:
    • Build Command: mvn clean package -DskipTests
    • Start Command: java -jar target/*.jar

render.yaml​

services:
- type: web
name: my-spring-app
env: docker
dockerfilePath: ./Dockerfile
envVars:
- key: SPRING_PROFILES_ACTIVE
value: prod
- key: DATABASE_URL
fromDatabase:
name: mydb
property: connectionString

databases:
- name: mydb
plan: free

5. AWS (Options)​

Elastic Beanstalk (Simple)​

# Install EB CLI
pip install awsebcli

# Initialize
eb init

# Create the environment
eb create production

# Deploy
eb deploy

ECS with Fargate (Docker)​

# Create a cluster
aws ecs create-cluster --cluster-name my-cluster

# Create a task definition (JSON)
aws ecs register-task-definition --cli-input-json file://task-definition.json

# Create a service
aws ecs create-service \
--cluster my-cluster \
--service-name my-service \
--task-definition my-task \
--desired-count 2

task-definition.json​

{
"family": "my-spring-app",
"containerDefinitions": [
{
"name": "app",
"image": "myuser/myapp:latest",
"portMappings": [
{
"containerPort": 8080,
"hostPort": 8080
}
],
"environment": [
{
"name": "SPRING_PROFILES_ACTIVE",
"value": "prod"
}
],
"logConfiguration": {
"logDriver": "awslogs",
"options": {
"awslogs-group": "/ecs/my-app",
"awslogs-region": "us-east-1"
}
}
}
],
"requiresCompatibilities": ["FARGATE"],
"cpu": "256",
"memory": "512"
}

6. Managed Database​

Railway PostgreSQL​

# Automatically configured
spring.datasource.url=${DATABASE_URL}

Heroku Postgres​

# Heroku provides DATABASE_URL automatically
spring.datasource.url=${DATABASE_URL}

AWS RDS​

spring.datasource.url=jdbc:postgresql://mydb.xxx.us-east-1.rds.amazonaws.com:5432/mydb
spring.datasource.username=${DB_USERNAME}
spring.datasource.password=${DB_PASSWORD}

Parse DATABASE_URL​

Some platforms provide a URL in the format:

postgres://user:password@host:5432/dbname

Spring configuration to parse:

@Configuration
public class DatabaseConfig {

@Bean
@Profile("prod")
public DataSource dataSource() {
String databaseUrl = System.getenv("DATABASE_URL");

if (databaseUrl != null && databaseUrl.startsWith("postgres://")) {
// Parse Heroku/Railway format
URI uri = URI.create(databaseUrl);
String username = uri.getUserInfo().split(":")[0];
String password = uri.getUserInfo().split(":")[1];
String jdbcUrl = "jdbc:postgresql://" + uri.getHost() + ":" + uri.getPort() + uri.getPath();

HikariDataSource ds = new HikariDataSource();
ds.setJdbcUrl(jdbcUrl);
ds.setUsername(username);
ds.setPassword(password);
return ds;
}

// Fallback
return DataSourceBuilder.create().build();
}
}

7. Deployment Checklist​

Before Deployment​

□ Tests pass locally
□ Production profile configured
□ Secrets externalized
□ Dockerfile tested
□ Health check configured
□ Logs configured

Environment Variables​

# Essential
SPRING_PROFILES_ACTIVE=prod
DATABASE_URL=...
JWT_SECRET=...

# Optional
SERVER_PORT=8080
JAVA_OPTS="-Xmx512m"

Post-Deployment​

□ Application accessible
□ Health check OK
□ Logs visible
□ Database connected
□ Monitoring in place

8. Monitoring in Production​

Actuator​

management.endpoints.web.exposure.include=health,info,prometheus
management.endpoint.health.show-details=when_authorized

Cloud Logging​

# JSON logs for cloud
logging.pattern.console={"timestamp":"%d","level":"%p","logger":"%c","message":"%m"}%n

Monitoring Services​

  • Railway: Integrated metrics
  • Heroku: Heroku Metrics
  • AWS: CloudWatch
  • External: Datadog, New Relic

9. Summary​

Recommendations by Use Case​

Personal project / POC:
→ Railway (free, simple)

Startup / MVP:
→ Railway or Render ($5-20/month)

SME / Production:
→ Heroku or AWS Elastic Beanstalk

Enterprise / Scale:
→ AWS ECS / Kubernetes

Quick Deployment (Railway)​

# 1. Have a Dockerfile
# 2. Push to GitHub
# 3. On railway.app:
# - New Project → GitHub
# - Add PostgreSQL
# - Configure variables
# 4. Done! 🚀

🎯 Next Step​

Time for practice! Let's Dockerize and deploy an application.

➡️ TP12.1: Complete Dockerization


⬅️ Back to Module 12