Perl on Docker - Dancer2 Hello World Beispiel
Veröffentlicht von Thomas Fahle am (Permalink)
Docker ist eine Freie Software zur Isolierung von Anwendungen mit Hilfe von Containervirtualisierung.
Laut Wikipedia vereinfacht [Docker] die Bereitstellung von Anwendungen, weil sich Container, die alle nötigen Pakete enthalten, leicht als Dateien transportieren und installieren lassen. Container gewährleisten die Trennung und Verwaltung der auf einem Rechner genutzten Ressourcen. Das beinhaltet laut Aussage der Entwickler: Code, Laufzeitmodul, Systemwerkzeuge, Systembibliotheken – alles was auf einem Rechner installiert werden kann..
Dieser Beitrag beschäfitigt sich mit der Containerisierung/Dockerisierung einer sehr einfachen Dancer2 Webapplikation und richtet sich an Dockereinsteiger mit minimalen Dockerkenntnissen.
Schritt für Schritt
In einem eigenen Verzeichnis werden die Datei der Webapplikation hello-world.pl und ein Dockerfile erstellt.
Hello World App
# Shamelessly stolen from https://metacpan.org/pod/Dancer2 use Dancer2; get '/' => sub { "Hello World\n" }; dance;
Dockerfile
FROM ubuntu:focal # https://hub.docker.com/_/ubuntu/ # https://github.com/docker-library/official-images LABEL maintainer="Your Name <YourMail@example.com>" LABEL version="0.10" LABEL description="Just Another Docker Ubuntu Focal Image running Dancer2 hello-world using build-in server" # Upgrade already installed packages # Install Dancer2 # Install File::Slurper # Install Template-Toolkit # Install SQLite3 # Install vim # Autoremove unused packages # Clean local repos # Free disk space to decrease image size ARG DEBIAN_FRONTEND=noninteractive RUN set -ex; \ apt-get update && \ apt-get dist-upgrade -y && \ apt-get -qq -y --no-install-recommends install \ libdancer2-perl \ libfile-slurper-perl \ libtemplate-perl \ sqlite3 libdbd-sqlite3-perl \ vim \ & apt-get -y autoremove & apt-get clean \ ; \ rm -rf /var/lib/apt/lists/* ; \ rm -rf /tmp/* WORKDIR /app COPY ./hello-world.pl /app/ EXPOSE 3000/tcp ENTRYPOINT ["perl", "/app/hello-world.pl"]
Das neue Container-Image basiert auf dem offiziellem Ubuntu Focal Docker Image (FROM ubuntu:focal).
Per LABEL werden diverse Metadaten gesetzt, welche die Verwaltung der Images erleichtern sollen.
Mittels apt-get werden zunächst alle installierten Pakete auf den neuesten Stand gebracht und Dancer2 installiert. Die Umgebungsvariable DEBIAN_FRONTEND wird per ARG temporär – also nur während des Builds – gesetzt. (Bei der Verwendung von ENV werden Umgebungsvariablen dauerhaft (unveränderlich) im Image gesetzt.)
Der Vollständigkeit halber werden die – im Dancer2::Tutorial erwähnten – Module Template-Toolkit, File::Slurper, DBD::SQLite und die Datenbank SQLite installiert, auch wenn sie für das Beispiel nicht benötigt werden.
Danach werden noch alle temporären Dateien und apt-repos gelöscht, um das Image so klein wie möglich zu halten.
Die WORKDIR-Anweisung erzeugt den Ordner /app im Containerimage und setzt diesen als Startpunkt für nachfolgende Befehle, z.B. COPY.
Anschließend wird die Datei hello-world.pl im aktuellen Verzeichis per COPY in das Image kopiert.
Der in Dancer2 eingebaute Miniwebserver nutzt den TCP-Port 3000, der per EXPOSE von aussen zugänglich gemacht wird.
Im letzten Schritt wird mittels ENTRYPOINT die Anwendung gesetzt, die mit dem Start des Containers gestartet werden soll. (Hier könnte man auch CMD verwenden.)
Docker in Aktion
Docker läuft unter Linux mit root-Rechten. Alle Kommandos müssen daher als root-User oder mit sudo-Rechten ausgeführt werden. Die oft in Blogs empfohlene Verwendung der docker-Gruppe öffnet einen Angriffsvektor, den ich allenfalls in Entwicklungsumgebungen toleriere.
In diesem Beitrag wird daher stets folgende Form verwendet:
sudo docker command
Wem das häufige Eintippen des sudo-Befehls zu lästig ist, empfehle ich einen Shell-Alias wie alias docker="sudo docker".
Die nachfolgend aufgeführten Kommandos werden in dem Ordner ausgeführt, in dem sich die beiden o.a. Dateien befinden.
Containerimage bauen
Das Kommando docker build erzeugt eine Containerimagedatei aus den Anweisungen im Dockerfile. Aktuelle Dockerversionen (18.09 oder höher) können BuildKit verwenden - die neue und optimierte build-Version.
sudo DOCKER_BUILDKIT=1 docker build -t dancer-hello-world .
oder ohne BuildKit
sudo docker build -t dancer-hello-world .
Der Parameter -t tagged (benennt) das neu erstellte Image. So können Images in weiteren Kommandos auch über den Namen statt der ID angesprochen werden.
Der Punkt (.) bezieht sich auf das Dockerfile im aktuellen Verzeichnis.
Images listen
Vorhandene Images lassen sich mit docker images anzeigen.
sudo docker images REPOSITORY TAG IMAGE ID CREATED SIZE dancer-hello-world latest 72ba77dc6169 4 hours ago 194MB
Noch mehr Informationen über das Image liefert docker inspect.
sudo docker inspect dancer-hello-world [ { "Id": "sha256:72ba77dc6169d6bc1d08ef56c24b7d5ca74fef84554a9a80ad364c0c3a7a53d1", "RepoTags": [ "dancer-hello-world:latest" ], ... } ]
Container mit App erzeugen und starten
docker run erzeugt aus einem Docker-Image einen Container und startet diesen auch sofort.
sudo docker run -p 3000:3000 -d --name dancer dancer-hello-world 063f9bf4824971fd9fbccf372ea3737d7804d08e37dfcf9975c23b6ce48c7db
Der Parameter -d lässt den Container im Hintergrund (detached) laufen, --name vergibt einen Namen für den Container, -p erzeugt ein Portmapping vom Dockerhost zum Dockercontainer.
Container auflisten
Mit docker ps können vorhandene Container angezeigt werden.
sudo docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 063f9bf48249 dancer-hello-world "perl /app/hello-wor…" 8 minutes ago Up 8 minutes 0.0.0.0:3000->3000/tcp, :::3000->3000/tcp dancer
Der Parameter -a zeigt alle Container an, also auch solche, die bereits beendet sind.
Container Logs
Jetzt noch ein kurzer Blick in die Containerlogs mit docker logs
sudo docker logs dancer >> Dancer2 v0.300000 server 1 listening on http://0.0.0.0:3000
Container Applikation verwenden
Nachdem ausführlich geprüft wurde, ob alles läuft, kann die App ja auch mal verwendet werden:
curl 0.0.0.0:3000 Hello World
Oder http://0.0.0.0:3000 im Browser öffnen.
Shellzugang zu einem laufendem Container
docker exec ermöglicht die Ausführung von Kommandos, z.B. /bin/bash, in einem bereits laufendem Container.
sudo docker exec -it dancer /bin/bash root@063f9bf48249:/app#
Die Parameter -i und -t erzeugen einen interaktiven Zugang per Terminal. Sehr hilfreich zum Debuggen. Docker wechselt in das im Dockerfile angegebene WORKDIR.
Debuggingtipp
Falls die Applikation nicht starten will, kann man den ENTRYPOINT des Dockerfile auf der Kommandozeile überschreiben und sich per Shell in einen neuen Container einloggen.
sudo docker run -p 3000:3000 --name dancer-x --entrypoint='' -it --rm dancer-hello-world /bin/bash root@a753025c55d4:/app# perl -c hello-world.pl hello-world.pl syntax OK root@a753025c55d4:/app# exit
Der Parameter --rm löscht den Container automatisch nach der Verwendung.
Container stoppen
docker stop stoppt (beendet) einen laufenden Container.
sudo docker stop dancer dancer sudo docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 063f9bf48249 dancer-hello-world "perl /app/hello-wor…" 26 minutes ago Exited (137) 11 seconds ago dancer
Gestoppte Container lassen sich mit docker start erneut starten.
Docker Images sichern und verteilen
Nun kann das Image mit docker save als tar-Archiv gesichert und anschließend komprimiert zum Kunden versandt werden.
sudo docker save dancer-hello-world -o myimage.tar sudo gzip myimage.tar
Auf der Empfängerseite wird das Image entkomprimiert und mit docker load geladen.
gunzip myimage.tar.gz sudo docker load -i myimage.tar >>Loaded image: dancer-hello-world:latest
In der Praxis wird allerdings selten auf diesen sehr einfachen Weg zurückgegriffen. Gerade im Unternehmensumfeld bietet sich der Einsatz einer Docker Registry an.
Aufräumarbeiten
Wenn alles getan ist, kann der gestoppte Container per docker rm gelöscht werden.
sudo docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 063f9bf48249 dancer-hello-world "perl /app/hello-wor…" About an hour ago Exited (137) About an hour ago dancer sudo docker rm dancer dancer
Images können mittels docker rmi gelöscht werden, sobald kein Container mehr darauf zugreift.
sudo docker images REPOSITORY TAG IMAGE ID CREATED SIZE dancer-hello-world latest 72ba77dc6169 6 hours ago 194MB sudo docker rmi dancer-hello-world Untagged: dancer-hello-world:latest Deleted: sha256:72ba77dc6169d6bc1d08ef56c24b7d5ca74fef84554a9a80ad364c0c3a7a53d1
Bonus - PSGI
Wer statt des eingebauten Miniwebservers lieber PSGI und plackup verwendet, kann sich folgendes Dockerfile mal anschauen.
FROM ubuntu:focal # https://hub.docker.com/_/ubuntu/ # https://github.com/docker-library/official-images LABEL maintainer="Your Name <YourMail@example.com>" LABEL version="0.10" LABEL description="Just Another Docker Ubuntu Focal Image running Dancer2 hello-world with plackup" # Upgrade already installed packages # Install Dancer2 # Insatll Plackup # Install File::Slurper # Install Template-Toolkit # Install SQLite3 # Install vim # Autoremove unused packages # Clean local repos # Free disk space to decrease image size ARG DEBIAN_FRONTEND=noninteractive RUN set -ex; \ apt-get update && \ apt-get dist-upgrade -y && \ apt-get -qq -y --no-install-recommends install \ libdancer2-perl \ libplack-perl \ libfile-slurper-perl \ libtemplate-perl \ sqlite3 libdbd-sqlite3-perl \ vim \ && apt-get -y autoremove && apt-get clean \ ; \ rm -rf /var/lib/apt/lists/* ; \ rm -rf /tmp/* WORKDIR /app COPY ./hello-world.pl /app/ EXPOSE 5000/tcp ENTRYPOINT ["/usr/bin/plackup", "/app/hello-world.pl"]
That's it.
Siehe auch
- Docker
- Docker Docs
- Build images with BuildKit
- Best practices for writing Dockerfiles
- Official Ubuntu Docker Image
- Dancer2
- Getting started with Perl on Docker
- Distributing a Perl script using Docker container
- Dancer in Docker
- Counter using Dancer2 and Redis in a Docker container
- Hello World with Mojolicious in Docker
- Mojolicious - Bundling application into Docker image
- Musings of dockerizing a Perl application
- Debugging a Perl Docker container
- Containerizing a Perl Script
- A few tips for Perl on Docker and Kubernetes
- Deploying Perl Apps using Docker, Gitlab & Kubernetes (PerlCon Riga 2017)
- Deploying Perl Apps using Docker, Gitlab & Kubernetes (German Perlworkshop 2019)
- Docker for Perl[56] People - A Ridiculously Short Introduction
- Optimierung von Docker-Images
- Docker-Container automatisch starten
- Perl on Docker - Offizielle Perl Docker Images als Grundlage eigener Images
- Perl on Docker - Multi-stage Builds zur Verkürzung von Build-Laufzeiten
- Perl on Docker - Dancer2 und Redis docker-compose Beispiel
- Perl on Docker - Perl commandline Programm als Docker Container erstellen und nutzen
Source-Code der Beispiele im Github Repo perl-howto-code.
Bildnachweis
Photo by Peter Fogden on Unsplash