Scalafmt with Docker
Ian Hellström | 4 March 2020 | 2 min read
Scalafmt is a popular formatter for Scala. The formatting it produces is not always identical across versions, even with the same configuration file. To ensure all developers on a team format the code in the same way, I’ll show you how to roll your own Scalafmt action container with Docker.
All of my Scala projects have a
.scalafmt.conf file in the root to ensure consistent formatting:
style = "IntelliJ" version = "2.4.2" maxColumn = 100 newlines.alwaysBeforeTopLevelStatements = true newlines.penalizeSingleSelectMultiArgList = false rewrite.rules = [ "RedundantBraces" "RedundantParens" "SortImports" "PreferCurlyFors" ] rewrite.redundantBraces.stringInterpolation = truene danglingParentheses = false spaces.afterTripleEquals = true align.openParenDefnSite = true align.openParenCallSite = false literals.long = Upper literals.float = Lower literals.double = Upper
Although it lists a specific
version, I have noticed that different Scalafmt versions can produce different results;
version is as of this writing not used anywhere.
There is now an
edition option, but that has not always been there.
So, let’s build a Docker image instead.
The following Docker configuration can be used to create an action container for the
FROM alpine:3.11.3 RUN apk --no-cache add curl openjdk11-jre-headless WORKDIR /scripts RUN curl -Lo coursier https://git.io/coursier-cli && chmod +x /scripts/coursier RUN /scripts/coursier bootstrap org.scalameta:scalafmt-cli_2.12:2.4.2 \ -r sonatype:snapshots \ -o /usr/local/bin/scalafmt \ --standalone \ --main org.scalafmt.cli.Cli RUN rm -f /scripts/coursier ENTRYPOINT ["scalafmt"]
It uses a small Linux base image and follows the installation instructions.
The headless JRE is installed because
scalafmt is a command-line tool, so it does not need any graphical components.
There is no need to grab the JDK either.
To build the image, execute
docker build -t scalafmt:2.4.2 $(pwd).
Please note that the tag matches the Scalafmt version.
For development on your own machine, I recommend an alias:
alias scalafmt='docker run --rm -w $(pwd) -v $(pwd):$(pwd) scalafmt:2.4.2 --exclude target'
That way, you can run
scalafmt from a project’s root, as if you had Scalafmt installed locally.
It automatically excludes the
If, however, you want to exclude more or different directories, add those to the alias itself or leave off
--exclude target altogether.
Whenever the team decides to upgrade to a newer Scalafmt version, you can
- Rebuild the image;
- Push it to a container registry;
- Have everyone update their aliases.
That way, everyone is guaranteed to produce the same formatting.
You may wonder why I do not suggest the native image instead. Unfortunately, it does not yet work on Windows, so it’s not portable. More importantly, I never got it to work on my machine. Docker (almost) always works.