Documentation

You are viewing the documentation for the 3.0.5 release. The latest stable release series is 3.0.x.

§Deploying your application

We have seen how to run a Play application in development mode, however the run command should not be used to run an application in production mode. When using run, on each request, Play checks with sbt to see if any files have changed, and this may have significant performance impacts on your application.

There are several ways to deploy a Play application in production mode. Let’s start by using the recommended way, creating a distribution artifact.

§The application secret

Before you run your application in production mode, you need to generate an application secret. To read more about how to do this, see Configuring the application secret. In the examples below, you will see the use of -Dplay.http.secret.key=ad31779d4ee49d5ad5162bf1429c32e2e9933f3b. You must generate your own secret to use when deploying to production.

§Deploying Play with JPA

If you are using JPA, you need to take a look at Deploying Play with JPA.

§Using the dist task

The dist task builds a binary version of your application that you can deploy to a server without any dependency on sbt, the only thing the server needs is a Java installation.

In the Play console, simply type dist:

[my-first-app] $ dist

And will see something like:

$ sbt
[info] Loading global plugins from /Users/play-developer/.sbt/1.0/plugins
[info] Loading project definition from /Users/play-developer/my-first-app/project
[info] Set current project to my-first-app (in build file:/Users/play-developer/my-first-app/)
[my-first-app] $ dist
[info] Packaging /Users/play-developer/my-first-app/target/scala-2.13/my-first-app_2.13-1.0-SNAPSHOT-sources.jar ...
[info] Done packaging.
[info] Wrote /Users/play-developer/my-first-app/target/scala-2.13/my-first-app_2.13-1.0-SNAPSHOT.pom
[info] Main Scala API documentation to /Users/play-developer/my-first-app/target/scala-2.13/api...
[info] Packaging /Users/play-developer/my-first-app/target/scala-2.13/my-first-app_2.13-1.0-SNAPSHOT-web-assets.jar ...
[info] Done packaging.
[info] Packaging /Users/play-developer/my-first-app/target/scala-2.13/my-first-app_2.13-1.0-SNAPSHOT.jar ...
[info] Done packaging.
model contains 21 documentable templates
[info] Main Scala API documentation successful.
[info] Packaging /Users/play-developer/my-first-app/target/scala-2.13/my-first-app_2.13-1.0-SNAPSHOT-javadoc.jar ...
[info] Done packaging.
[info] Packaging /Users/play-developer/my-first-app/target/scala-2.13/my-first-app_2.13-1.0-SNAPSHOT-sans-externalized.jar ...
[info] Done packaging.
[info]
[info] Your package is ready in /Users/play-developer/my-first-app/target/universal/my-first-app-1.0-SNAPSHOT.zip
[info]
[success] Total time: 5 s, completed Feb 6, 2017 2:08:44 PM
[my-first-app] $

This produces a ZIP file containing all JAR files needed to run your application in the target/universal folder of your application.

To run the application, unzip the file on the target server, and then run the script in the bin directory. The name of the script is your application name, and it comes in two versions, a bash shell script, and a windows .bat script.

$ unzip my-first-app-1.0.zip
$ my-first-app-1.0/bin/my-first-app -Dplay.http.secret.key=ad31779d4ee49d5ad5162bf1429c32e2e9933f3b

You can also specify a different configuration file for a production environment, from the command line:

$ my-first-app-1.0/bin/my-first-app -Dconfig.file=/full/path/to/conf/application-prod.conf

For a full description of usage invoke the start script with a -h option.

For Unix users, zip files do not retain Unix file permissions so when the file is expanded the start script will be required to be set as an executable:

$ chmod +x /path/to/bin/<project-name>

Alternatively a tar.gz file can be produced instead. Tar files retain permissions. Invoke the Universal / packageZipTarball task instead of the dist task:

sbt Universal / packageZipTarball

By default, the dist task will include the API documentation in the generated package. If this is not necessary, add these lines in build.sbt:

Compile / doc / sources := Seq.empty

Compile / packageDoc / publishArtifact := false

For builds with sub-projects, the statement above has to be applied to all sub-project definitions.

§The Native Packager

Play uses the sbt Native Packager plugin. The native packager plugin declares the dist task to create a zip file. Invoking the dist task is directly equivalent to invoking the following:

[my-first-app] $ Universal / packageBin

Many other types of archive can be generated including:

Please consult the documentation on the native packager plugin for more information.

§Build a server distribution

The sbt-native-packager plugins provides a number archetypes. The one that Play uses by default is called the Java server archetype, which enables the following features:

More information can be found in the Java Server Application Archetype documentation.

§Minimal Debian settings

Add the following settings to your build:

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

Linux / maintainer := "First Lastname <[email protected]>"

Linux / packageSummary := "My custom package summary"

packageDescription := "My longer package description"

Then build your package with:

[my-first-app] $ Debian / packageBin

§Minimal RPM settings

Add the following settings to your build:

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

Linux / maintainer := "First Lastname <[email protected]>"

Linux / packageSummary := "My custom package summary"

packageDescription := "My longer package description"

rpmRelease := "1"

rpmVendor := "example.com"

rpmUrl := Some("http://github.com/example/server")

rpmLicense := Some("Apache v2")

Then build your package with:

[my-first-app] $ Rpm / packageBin

There will be some error logging. This is because rpm logs to stderr instead of stdout.

§Including additional files in your distribution

Anything included in your project’s dist directory will be included in the distribution built by the native packager. Note that in Play, the dist directory is equivalent to the src/universal directory mentioned in the native packager’s own documentation.

§Play PID Configuration

Play manages its own PID, which is described in the Production configuration.

Since Play uses a separate pidfile, we have to provide it with a proper path, which is packageName.value here. The name of the pid file must be play.pid. In order to tell the startup script where to place the PID file, put a file application.ini inside the dist/conf folder and add the following content:

s"-Dpidfile.path=/var/run/${packageName.value}/play.pid",
# Add all other startup settings here, too

Please see the sbt-native-packager page on Play for more details.

To prevent Play from creating a PID just set the property to /dev/null:

-Dpidfile.path=/dev/null

For a full list of replacements take a closer look at the customize java server documentation and customize java app documentation.

§Publishing to a Maven (or Ivy) repository

You can also publish your application to a Maven repository. This publishes both the JAR file containing your application and the corresponding POM file.

You have to configure the repository you want to publish to, in your build.sbt file:

publishTo := Some(
  "My resolver".at("https://mycompany.com/repo")
)

credentials += Credentials(
  "Repo",
  "https://mycompany.com/repo",
  "admin",
  "admin123"
)

Then in the Play console, use the publish task:

[my-first-app] $ publish

Check the sbt documentation to get more information about the resolvers and credentials definition.

§Running a production server in place

In some circumstances, you may not want to create a full distribution, you may in fact want to run your application from your project’s source directory. This requires an sbt installation on the server, and can be done using the stage task.

$ sbt clean stage

And you will see something like this:

$ sbt
[info] Loading global plugins from /Users/play-developer/.sbt/1.0/plugins
[info] Loading project definition from /Users/play-developer/my-first-app/project
[info] Set current project to my-first-app (in build file:/Users/play-developer/my-first-app/)
[my-first-app] $ stage
[info] Updating {file:/Users/play-developer/my-first-app/}root...
[info] Packaging /Users/play-developer/my-first-app/target/scala-2.13/my-first-app_2.13-1.0-SNAPSHOT-sources.jar ...
[info] Done packaging.
[info] Wrote /Users/play-developer/my-first-app/target/scala-2.13/my-first-app_2.13-1.0-SNAPSHOT.pom
[info] Resolving jline#jline;2.12.2 ...
[info] Done updating.
[info] Main Scala API documentation to /Users/play-developer/my-first-app/target/scala-2.13/api...
[info] Compiling 8 Scala sources and 1 Java source to /Users/play-developer/my-first-app/target/scala-2.13/classes...
[info] Packaging /Users/play-developer/my-first-app/target/scala-2.13/my-first-app_2.13-1.0-SNAPSHOT-web-assets.jar ...
[info] Done packaging.
model contains 21 documentable templates
[info] Main Scala API documentation successful.
[info] Packaging /Users/play-developer/my-first-app/target/scala-2.13/my-first-app_2.13-1.0-SNAPSHOT-javadoc.jar ...
[info] Done packaging.
[info] Packaging /Users/play-developer/my-first-app/target/scala-2.13/my-first-app_2.13-1.0-SNAPSHOT.jar ...
[info] Done packaging.
[info] Packaging /Users/play-developer/my-first-app/target/scala-2.13/my-first-app_2.13-1.0-SNAPSHOT-sans-externalized.jar ...
[info] Done packaging.
[success] Total time: 8 s, completed Feb 6, 2017 2:11:10 PM
[my-first-app] $

This cleans and compiles your application, retrieves the required dependencies and copies them to the target/universal/stage directory. It also creates a bin/<start> script where <start> is the project’s name. The script runs the Play server on Unix style systems and there is also a corresponding bat file for Windows.

For example to start an application of the project my-first-app from the project folder you can:

$ target/universal/stage/bin/my-first-app -Dplay.http.secret.key=ad31779d4ee49d5ad5162bf1429c32e2e9933f3b

You can also specify a different configuration file for a production environment, from the command line:

$ target/universal/stage/bin/my-first-app -Dconfig.file=/full/path/to/conf/application-prod.conf

§Running a test instance

Play provides a convenient utility for running a test application in prod mode.

Note: This is not intended for production usage.

To run an application in prod mode, run runProd:

[my-first-app] $ runProd

§Using the sbt assembly plugin

Though not officially supported, the sbt assembly plugin may be used to package and run Play applications. This will produce one jar as an output artifact, and allow you to execute it directly using the java command.

To use this, add a dependency on the plugin to your project/plugins.sbt file:

addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "2.1.4")

Now add the following configuration to your build.sbt:

assembly / mainClass := Some("play.core.server.ProdServerStart")
assembly / fullClasspath += Attributed.blank(PlayKeys.playPackageAssets.value)

assembly / assemblyMergeStrategy := {
  case manifest if manifest.contains("MANIFEST.MF") =>
    // We don't need manifest files since sbt-assembly will create
    // one with the given settings
    MergeStrategy.discard
  case referenceOverrides if referenceOverrides.contains("reference-overrides.conf") =>
    // Keep the content for all reference-overrides.conf files
    MergeStrategy.concat
  case x =>
    // For all the other files, use the default sbt-assembly merge strategy
    val oldStrategy = (assembly / assemblyMergeStrategy).value
    oldStrategy(x)
}

Now you can build the artifact by running sbt assembly, and run your application by running:

$ java -Dplay.http.secret.key=ad31779d4ee49d5ad5162bf1429c32e2e9933f3b -jar target/scala-2.XX/<yourprojectname>-assembly-<version>.jar

You’ll need to substitute in the right project name, version and scala version, of course.

Next: Production configuration