Deploy a Scala Play App

Play is a high velocity and productive web framework for Java and Scala. It is based on a lightweight, stateless, web-friendly architecture and features predictable and minimal resource consumption (CPU, memory, threads) for highly-scalable applications thanks to its reactive model, based on Pekko Streams.

This guide covers how to deploy a Scala Play app to Railway in four ways:

  1. One-click deploy from a template.
  2. From a GitHub repository.
  3. Using the CLI.
  4. Using a Dockerfile.

Now, let's create a Play app!

Create a Play App

Note: If you already have a Play app locally or on GitHub, you can skip this step and go straight to the Deploy Play App to Railway.

To create a new Scala Play app, ensure that you have JDK and sbt installed on your machine.

Run the following command in your terminal to create a new Play app:

sbt new

A list of templates will be shown to select from. Select the playframework/play-scala-seed.g8 template.

  • Give it a name, helloworld.
  • Give it an organization name, com.railwayguide
  • Hit Enter for the rest to use the latest versions of play, scala and sbt scaffold.

A new Scala Play app will be provisioned in the helloworld directory.

Modify Scala Play Views and Set Up Database Config

Step 1 : Modify the Index File

Open the project in your editor. Head over to the app/views/index.scala.html file.

Modify it to the following:

@()

@main("Welcome to Play") {
  <h1>Welcome to Play!</h1>
  <h1>Hello World, Railway!</h1>
}

This change adds a new heading, which you'll see when you run the app locally.

Step 2 : Run the App Locally

  • Now, let’s run the app locally to verify our changes. You should see the new headers appear in the browser.

Step 3 : Add PostgreSQL Driver as a Dependency

Play doesn’t provide built-in database drivers, so we need to add the PostgreSQL JDBC driver manually to our project.

In your build.sbt, add the following dependency:

libraryDependencies += "org.postgresql" % "postgresql" % "42.7.4" // Always use the latest stable version

Step 4 : Configure PostgreSQL in application.conf

Next, configure the PostgreSQL database connection in conf/application.conf:

# Default database configuration using PostgreSQL
db.default.driver = org.postgresql.Driver
db.default.url = "jdbc:postgresql://username:[email protected]:5432/scala_play"  # Replace with correct credentials

Make sure to replace username and password with your PostgreSQL credentials.

Step 5 : Update Project Dependencies

To download the PostgreSQL driver and any updated dependencies, run the following:

sbt update

Step 6 : Add Database Migration Tool (Flyway)

Play doesn’t include built-in support for database migrations, so we’ll use Flyway.

  1. Install Flyway Plugin: Open your project/plugin.sbt and add the Flyway plugin:
addSbtPlugin("io.github.davidmweber" % "flyway-sbt" % "7.4.0")
  1. Configure Flyway in build.sbt: Enable Flyway and configure the database connection in your build.sbt:
name := """helloworld"""
organization := "com.railwayguide"
version := "1.0-SNAPSHOT"
executableScriptName := "main"

lazy val root = (project in file(".")).enablePlugins(PlayScala).enablePlugins(FlywayPlugin)

scalaVersion := "2.13.15"

libraryDependencies += guice
libraryDependencies += "org.scalatestplus.play" %% "scalatestplus-play" % "7.0.1" % Test
libraryDependencies += "org.postgresql" % "postgresql" % "42.7.4" // Latest version

flywayUrl := "jdbc:postgresql://127.0.0.1:5432/scala_play?user=<username>"  # Replace with correct credentials
flywayLocations := Seq("filesystem:src/main/resources/db/migration")

Replace username with your database username.

Step 7 : Create the Migration Files

  1. Create Migration Folder: Create the folder structure for your migration files:
src/main/resources/db/migration
  1. Create Migration SQL File: In src/main/resources/db/migration, create a schema migration file called V1_0__create_employees_table.sql with the following content:
CREATE TABLE employee (
  id VARCHAR(20) PRIMARY KEY,
  first_name VARCHAR(30),
  last_name VARCHAR(30),
  email VARCHAR(30),
  admin BOOLEAN
);

Step 8 : Run Database Migrations

Once your migration file is in place, run the Flyway migration with the following command:

sbt flywayMigrate

This will apply the migration and create the employee table in your PostgreSQL database.

Check your database to confirm that the employee table has been successfully created. You can use a database tool like psql or any PostgreSQL client to view the table.

Run the Play App locally

Next, run sbt run in the terminal to build the project, install all the dependencies and start the embedded Pekko HTTP server.

Open your browser and go to http://localhost:9000 to see the app.

Prepare Scala Play App for deployment

  1. Set Application Secret:
    • Open up the application.conf file and add the following to it to set the app's secret.
      play.http.secret.key=${?APPLICATION_SECRET}
  2. Set Database URL:
    • Open up the application.conf file and add the following to it to ensure the DATABASE_URL is read from the environment variable.
      db.default.url="jdbc:${?DATABASE_URL}"
  3. Set Allowed Hosts:
    • By default, Play ships with a list of default Allowed Hosts filter. This is the list of allowed valid hosts = ["localhost", ".local", "127.0.0.1"]. You need to add an option to allow Railway hosts, [".up.railway.app"].
    • Add the following to the application.conf file:
      play.filters.hosts.allowed=[".up.railway.app"]
    Note: Railway provided domains end in .up.railway.app. Once you add your custom domain, please update the allowed hosts to the new URL.
  4. Add sbt-native-packager sbt plugin:
    • Add the sbt-native-packager sbt plugin to project/plugins.sbt
      addSbtPlugin("com.github.sbt" % "sbt-native-packager" % "x.x.x")
    • Enable the JavaAppPackaging plugin in build.sbt and set the executableScriptName to main. Your build.sbt should be looking like this now:
      name := """helloworld"""
      organization := "com.railwayguide"
      
      version := "1.0-SNAPSHOT"
      
      executableScriptName := "main"
      
      lazy val root = (project in file(".")).enablePlugins(PlayScala).enablePlugins(JavaAppPackaging).enablePlugins(FlywayPlugin)
      
      scalaVersion := "2.13.15"
      
      libraryDependencies += guice
      libraryDependencies += "org.scalatestplus.play" %% "scalatestplus-play" % "7.0.1" % Test
      libraryDependencies += "org.postgresql" % "postgresql" % "42.7.4" // Always use the latest stable version
      
      flywayUrl := sys.env.getOrElse("DATABASE_URL", "jdbc:postgresql://127.0.0.1:5432/scala_play?user=username")
      
      flywayLocations := Seq("filesystem:src/main/resources/db/migration")
    • Run sbt update to install the sbt-native-packager and update the dependencies.

Now, we are ready to deploy to Railway!

Deploy the Play App to Railway

Railway offers multiple ways to deploy your Scala app, depending on your setup and preference.

One-Click Deploy from a Template

If you’re looking for the fastest way to get started, the one-click deploy option is ideal.

Click the button below to begin:

Deploy on Railway

We highly recommend that you eject from the template after deployment to create a copy of the repo on your GitHub account.

Note: You can also choose from a variety of Scala app templates created by the community.

Deploy from the CLI

  1. Install the Railway CLI:
  2. Initialize a Railway Project:
    • Run the command below in your Luminus app directory.
      railway init
    • Follow the prompts to name your project.
    • After the project is created, click the provided link to view it in your browser.
  3. Add a Postgres Database Service:
    • Run railway add -d postgres.
    • Hit Enter to add it to your project.
    • A database service will be added to your Railway project.
  4. Add a Service and Environment Variable:
    • Run railway add.
    • Select Empty Service from the list of options.
    • In the Enter a service name prompt, enter app-service.
    • In the Enter a variable prompt, enter APPLICATION_SECRET=<generated-app-secret> where <generated-app-secret> is the secret generated from running playGenerateSecret in your terminal.
    • In the Enter a variable prompt, enter DATABASE_URL=${{Postgres.DATABASE_URL}}.
    Note: Explore the Railway CLI reference for a variety of options.
  5. Deploy the Application:
    • Run railway up to deploy your app.
      • This command will scan, compress and upload your app's files to Railway. You’ll see real-time deployment logs in your terminal.
    • Once the deployment is complete, we can proceed to generate a domain for the app service.
  6. Set Up a Public URL:
    • Run railway domain to generate a public URL for your app.
    • Visit the new URL to see your app live in action!
screenshot of the deployed Scala service

Deploy from a GitHub Repo

To deploy a Scala Play app to Railway directly from GitHub, follow the steps below:

  1. Create a New Project on Railway:

    • Go to Railway to create a new project.
  2. Deploy from GitHub:

    • Select Deploy from GitHub repo and choose your repository.
      • If your Railway account isn’t linked to GitHub yet, you’ll be prompted to do so.
  3. Add Environment Variables and Provision a Database Service:

    • Click Add Variables, but hold off on adding anything just yet. First, proceed with the next step.
    • Right-click on the Railway project canvas or click the Create button, then select Database and choose Add PostgreSQL.
      • This will create and deploy a new PostgreSQL database for your project.
    • Once the database is deployed, you can return to adding the necessary environment variables:
      • DATABASE_URL: Set the value to ${{Postgres.DATABASE_URL}} (this references the URL of your new Postgres database). Learn more about referencing service variables.
      • APPLICATION_SECRET: Set the value to the generated app secret.
  4. Deploy the App Service:

    • Click Deploy on the Railway project canvas to apply your changes.
  5. Verify the Deployment:

    • Once the deployment completes, go to View logs to check if the server is running successfully.

    Note: During the deployment process, Railway will automatically detect that it’s a Scala app.

  6. Set Up a Public URL:

    • Navigate to the Networking section under the Settings tab of your new service.
    • Click Generate Domain to create a public URL for your app.

Use a Dockerfile

  1. Create a Dockerfile in the Play app's root directory.
  2. Add the content below to the Dockerfile:
    # Use the Scala sbt official image
    # https://hub.docker.com/r/sbtscala/scala-sbt/tags
    FROM sbtscala/scala-sbt:eclipse-temurin-21.0.5_11_1.10.5_3.5.2
    
    # Create and change to the app directory.
    WORKDIR /app
    
    # Copy local code to the container image.
    COPY . ./
    
    # Build the app.
    RUN sbt stage
    
    # Run the app
    CMD ["./target/universal/stage/bin/main"]
  3. Either deploy via the CLI or from GitHub.

Railway automatically detects the Dockerfile, and uses it to build and deploy the app.

Note: Railway supports also deployment from public and private Docker images.

This guide covers the main deployment options on Railway. Choose the approach that suits your setup, and start deploying your Scala apps seamlessly!

Next Steps

Explore these resources to learn how you can maximize your experience with Railway:


Edit this file on GitHub