How to Deploy Scala to Docker Without Writing a Dockerfile

M
Miget Team
Writer
January 12, 2026
5 min read

You can containerize any Scala application without writing a Dockerfile using migetpacks. It auto-detects your Scala and sbt versions from build.sbt and project/build.properties, supports Play Framework and sbt-native-packager, and produces an optimized Eclipse Temurin JRE image. One command, zero configuration.


Why Is Writing a Dockerfile for Scala So Complicated?

A production-ready Scala Dockerfile requires:

  • Multi-stage builds to separate sbt from runtime
  • Matching sbt, Scala, and JDK versions
  • Play Framework stage output handling
  • sbt-assembly for fat JARs
  • sbt-native-packager for staged builds
  • Proper sbt memory settings (SBT_OPTS)
  • Coursier and Ivy cache handling

The Scala toolchain with its many version combinations and build plugins makes Docker configuration complex.

How Do I Containerize a Scala App Without a Dockerfile?

Open your terminal, navigate to your Scala project, and run:

cd ~/projects/my-scala-api

docker run --rm \
  -v "$PWD":/workspace/source \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -e OUTPUT_IMAGE=my-scala-api:latest \
  miget/migetpacks:latest

That's it. migetpacks will:

  1. Detect Scala from build.sbt or project/ directory
  2. Read versions from build.sbt and project/build.properties
  3. Detect Play Framework or sbt-native-packager
  4. Run the appropriate build command
  5. Output a slim JRE-based production image

How Are Versions Detected?

Scala Version

SourceExample
.scala-version3.5.2
build.sbt (scalaVersion)scalaVersion := "3.5.2"
project/build.properties (scala.version)scala.version=3.5.2
DefaultLatest stable

sbt Version

SourceExample
project/build.propertiessbt.version=1.10.6
Default1.10.6

Java Version

SourceExample
system.propertiesjava.runtime.version=21
Default21

What Build Command Is Used?

migetpacks detects the application type and adjusts the build:

DetectionBuild CommandOutput
Play Framework (PlayScala/PlayJava in build.sbt)sbt compile stagetarget/universal/stage/
sbt-native-packager (in project/plugins.sbt)sbt compile stagetarget/universal/stage/
Standard sbt projectsbt compile assemblytarget/scala-*/app.jar

What Does the Generated Dockerfile Look Like?

# Build stage
FROM sbtscala/scala-sbt:eclipse-temurin-21.0.6_7_1.11.7_3.5.2 AS builder
WORKDIR /build

ENV JAVA_TOOL_OPTIONS="-Dfile.encoding=UTF-8"
ENV SBT_OPTS="-Xmx2G -XX:MaxMetaspaceSize=512m"

COPY build.sbt ./
COPY project/ project/

RUN sbt update || true

COPY . .

RUN sbt compile assembly \
    && rm -rf src/ project/ build.sbt

# Runtime stage
FROM eclipse-temurin:21-jre
WORKDIR /app
COPY --from=builder --chown=1000:1000 /build /app

You never write or maintain this file - migetpacks handles it automatically.

What Run Command Is Used?

Project TypeDefault Command
Standard (assembly)java -jar target/scala-*/app.jar
Play Frameworktarget/universal/stage/bin/{app-name}
sbt-native-packagertarget/universal/stage/bin/{app-name}

How Do I Build a Play Framework App?

Play Framework works out of the box:

cd ~/projects/my-play-app

docker run --rm \
  -v "$PWD":/workspace/source \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -e OUTPUT_IMAGE=my-play:latest \
  -e RUN_COMMAND="target/universal/stage/bin/myapp -Dhttp.port=5000" \
  miget/migetpacks:latest

How Do I Build Secure Distroless Images?

Enable Docker Hardened Images for minimal containers:

docker run --rm \
  -v "$PWD":/workspace/source \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -e OUTPUT_IMAGE=my-app:latest \
  -e USE_DHI=true \
  miget/migetpacks:latest

Scala uses a hybrid approach: the official sbtscala build image for building, and DHI distroless Eclipse Temurin for runtime.

Next Steps

Stay UpdatedWith Latest Posts

Subscribe to our newsletter and never miss a new blog post, update, or special offer from the Miget team.