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
--rmlöscht den Container nach dem Beenden-p 9000:9000ordnet 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.confund benennen Sie sie inprod.confum. - Entfernen der
versionInformationen 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 runvereinfachen. 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.