Es gibt verschiedene Ansätze, um Play-Anwendungen in ein Docker-Image zu packen. Sie können eine Dockerfile-Datei von Hand erstellen, eine bereits vorhandene Datei anpassen oder einfach ein Tool verwenden, um sie zu generieren. Da Play mit einer großartigen Paketierungsanwendung – sbt-native-packager – geliefert wird, werden wir die letzte Option verwenden.
Docker Image
In build.sbt
müssen wir hinzufügen:
import com.typesafe.sbt.packager.docker._
dockerChmodType := DockerChmodType.UserGroupWriteExecute
dockerPermissionStrategy := DockerPermissionStrategy.CopyChown
Dadurch werden die richtigen Dateiberechtigungen in unserem Docker-Image festgelegt.
Der nächste Schritt besteht darin, zum Projektverzeichnis zu navigieren, eine sbt-Shell zu öffnen und Folgendes auszuführen
docker:publishLocal
Mit diesem Befehl wird unser lokales Docker-Abbild erstellt.
Um zu überprüfen, ob das Image erstellt wurde, müssen wir ein Terminal öffnen und docker images [APP_NAME]
ausführen, wobei [APP_NAME] der Name Ihrer Play-Anwendung ist. Es sollte ein Datensatz vorhanden sein, der unser Abbild mit einer TAG-Nummer darstellt, die der Anwendungsversion entspricht, die in application.conf
.
Danach müssen wir das Bild mit dem Befehl ausführen:
docker run --rm -p 9000:9000 APP_NAME:TAG
--rm
löscht den Container nach dem Beenden-p 9000:9000
ordnet Port 9000 dem Container-Port 9000 zu
Mit dieser Einstellung wird Ihre Play-Anwendung mit derselben Konfigurationsdatei wie Ihre lokale Version ausgeführt. In den meisten Fällen werden Sie eine separate Konfiguration für Ihre Produktionsumgebung und für Ihre lokale Entwicklung benötigen. Um dies zu erreichen, werden wir:
- Kopieren Sie die Datei
application.conf
und benennen Sie sie inprod.conf
um. - Entfernen der
version
Informationen aus der Produktionskonfigurationsdatei - Fügen Sie
include "application.conf"
der Produktionsdatei hinzu
Dies ermöglicht es uns, einige Einstellungen in der Produktionsumgebung zu überschreiben, indem wir prod.conf
bearbeiten.
Um unsere Play-Anwendung mit der neuen Konfigurationsdatei auszuführen, müssen wir das Docker-Image neu erstellen und den Container mit einem neuen Image und einem weiteren Parameter erneut starten: -Dconfig.file=/opt/docker/conf/prod.conf
.Der vollständige Befehl sollte in etwa so aussehen:
docker run -p 9000:9000 APP_NAME:TAG -Dconfig.file=/opt/docker/conf/prod.conf
Volumes
Um Änderungen an einer Produktionskonfigurationsdatei vorzunehmen, müssen Sie diese in Ihrer lokalen Version des Quellcodes bearbeiten, das Image neu erstellen und den Container erneut starten. Das funktioniert zwar, ist aber ziemlich mühsam. Ein besserer Weg wäre, ein Docker-Volume einzurichten. Dazu müssen wir das conf
Verzeichnis von Ihrem Projekt in die Produktion kopieren und Ihr Image mit einem zusätzlichen Argument ausführen:
docker run
-p 9000:9000
-v /full/path/to/conf/directory:/opt/docker/conf APP_NAME:TAG
-Dconfig.file=/opt/docker/conf/prod.conf
Mit der Option -v /full/path/to/conf/directory:/opt/docker/conf
wird ein Docker-Volume erstellt, das es uns ermöglicht, Dateien zwischen dem Host-System und dem Docker-Container auszutauschen. Wenn Sie nun Änderungen an Ihren Produktionskonfigurationsdateien vornehmen, müssen Sie nur den Docker-Container neu starten.
Da wir nun die Produktionskonfiguration von unserer Entwicklungskonfiguration trennen können, können wir den docker run
vereinfachen. Wir können eine application.ini
Datei in unserer Produktionsumgebung erstellen und – -Dconfig.file=/opt/docker/conf/prod.conf
und andere Startparameter darin einfügen. Danach können wir unser Image mit diesem Befehl starten:
docker run
-p 9000:9000
-v /full/path/to/conf/directory:/opt/docker/conf
APP_NAME:TAG
Files
Die meisten Serveranwendungen müssen Datei-Uploads verarbeiten. Um das Speichern von Dateien aus der Play-Anwendung zu ermöglichen, müssen wir ein Verzeichnis erstellen. Dazu müssen wir den folgenden Code zubuild.sbt
hinzufügen.
dockerCommands ++= Seq(
ExecCmd("RUN", "mkdir",
s"${(defaultLinuxInstallLocation in Docker).value}/APP_NAME_files"),
)
Dies fügt dem generierten Dockerfile einen Befehl hinzu, der das Verzeichnis APP_NAME_files
im Container erstellt.
Bei jedem Neustart wird der Docker-Container neu aufgebaut, was bedeutet, dass alle Dateien, die sich nicht in Volumes befinden, verworfen werden, einschließlich Dateien aus einem zuvor erstellten Verzeichnis. Um dies zu verhindern, müssen wir dem Befehl docker run
ein weiteres Volume hinzufügen. Wenn wir schon dabei sind, können wir ein weiteres Volume für Protokolldateien hinzufügen.
docker run
-p 9000:9000
-v /full/path/to//conf:/opt/docker/conf
-v /full/path/to/files:/opt/docker/APP_NAME_files
-v /full/path/to/logs:/opt/docker/YOUR_LOG_DIR
APP_NAME:TAG
Tipps und Tricks
Durch Hinzufügen von dockerUpdateLatest := true
zu Ihrer build.sbt
haben Sie immer Zugriff auf die neueste Version Ihres Images buy TAG latest
Wenn Sie Ihre Datenbank auf demselben Rechner wie Ihren Docker-Container hosten, können Sie vom Container aus über host.docker.internal
oder über die öffentliche IP Ihres Rechners darauf zugreifen.