Heroku-ish Apphosting via Dokku
Dokku ist eine Software mit deren Hilfe man schnell von Code zu einer laufenden Webanwendung kommt.
Benutzung (Admins)
Man kann generell auf zwei Arten mit Dokku interagieren. Via SSH und lokal via sudo. Manche Befehle lassen sich aus Sicherheitsgründen nur lokal ausführen. Desweiteren wird über das Plugin dokku-acl eingeschränkt, wer welche Befehle via SSH ausführen kann (siehe ACLs). Für das Ausführen von Befehlen via SSH wird folgendes Hilfs-Alias verwendet:
alias dokku='ssh dokku@dokku.informatik.uni-bremen.de --'
Über die lokale Gruppe dokku wird gesteuert, wer sich mit seinem UNIX-Account auf dem Server anmelden und lokal dokku via sudo ausführen darf.
Im Folgenden werden die wichtigsten Aktionen kurz erklärt:
Account anlegen
- Ausführbarkeit: lokal
Für die Erstellung eines Benutzer-Accounts wird ein Accountname und ein SSH-Public-Key benötigt.
ssh dokku echo "$PUB_KEY" | sudo dokku ssh-keys:add $USER
Anwendung anlegen
- Ausführbarkeit: lokal, SSH (nur Super-User)
dokku apps:create $APP
Anderen Benutzern Rechte auf eine Anwendung geben
- Ausführbarkeit: lokal
ssh dokku sudo dokku acl:add $APP $USER
Datenbank anlegen (Optional)
- Ausführbarkeit: lokal, SSH (nur Super-User)
Dokku hat ein Konzept von Diensten, i.d.R. Datenbanken, die persistente Daten für Anwendungen aufbewahren. Dienste werden separat angelegt und müssen danach mit der jeweiligen Anwendung verlinkt werden. Wenn eine Anwendung keine Datenbank benötigt kann dieser Schritt übersprungen werden.
Derzeit ist nur ein Dienst-Plugin für PostgreSQL installiert. Siehe die Liste von Plugins in der Dokku-Dokumentation für weitere Optionen.
dokku postgres:create $DB dokku postgres:link $DB $APP
Zugriff auf gelinkte Postgres-Datenbanken
Siehe link the postgres service to the app und promote service as DATABASE_URL in in der Dokumentation des Postgres-Plugins.
Anderen Benutzern Rechte auf eine Datenbank geben
- Ausführbarkeit: lokal
ssh dokku sudo dokku acl:add-service postgres $DB $USER
Persistente Daten
- Ausführbarkeit: lokal, SSH (nur Super-User)
Dokku verpackt Anwendungen in Docker-Container, welche keine persistenten Verzeichnisse haben. Das bedeutet, dass Dateien die von einer Anwendung im lokalen Dateisystem gespeichert werden nach einem Neustart der Anwendung verfallen. Falls persistente lokale Dateien benötigt werden, können Verzeichnisse des Host-Systems in die Container gemountet werden.
dokku storage:ensure-directory $DIRNAME dokku storage:mount $APP /var/lib/dokku/data/storage/$DIRNAME:$MOUNTPATH
Dabei ist /var/lib/dokku/data/storage/$DIRNAME der lokale Pfad auf dem dokku-Server und $MOUNTPATH der Mountpoint innerhalb des Containers.
Ein Beispiel hierfür, um ein Verzeichnis aus dem NFS in den Container zu mounten kann folgendermaßen aussehen:
dokku storage:ensure-directory $DIRNAME dokku storage:mount $APP /home/dml.uni-bremen.de/docroot/apps/$DIRNAME:/app/storage
Im Container ist dann in /storage das Verzeichnis aus dem NFS gemountet. /app/ stellt im Container selbst die root-Ebene / dar. Das gemountete NFS-Verzeichnis muss die erforderlichen Berechtigungen haben, damit dokku hier auch lesen und schreiben darf. Da Dokku im NFS jedoch nicht bekannt ist, müssen hier die Rechte für andere User angepasst werden. Es empfiehlt sich zwei Unterverzeichnisse anzulegen. Ein Verzeichnis bspw. /data, um persistente Daten dem Container zur Verfügung zu stellen, mit den Rechten 775 und ein weiteres Verzeichnis bspw. /export, mit den Rechten 773, in das Dokku schreiben darf.
Persistente Daten exportieren
Persistente Daten können von Accounts mit Rechten auf die jeweilige Anwendung als tgz-Archiv exportiert werden.
- Ausführbarkeit: lokal, SSH
dokku storage:export $APP > /path/to/archive.tgz
Benutzung (Endbenutzer)
Wie auch Admins, können Endbenutzer via SSH Dokku-Befehle ausführen, für die sie die entsprechenden Rechte haben (siehe ACLs). Das oben gelistete Hilfs-Alias ist also auch hier Voraussetzung, um die folgenden Kommandos ausführen zu können. Das Hilfsalias wird nicht von allen Shells unterstützt. Unter Windows eignet sich die Git-Shell. Der Alias gilt nur für die Laufzeit der Shell und muss nach Beendigung dieser erneut eingerichtet werden.
alias dokku='ssh dokku@dokku.informatik.uni-bremen.de --'
App aus Git-Repository installieren
Nachdem eine Person Zugang zu einer Anwendung bekommen hat, kann diese mit ihrem SSH-Public-Key ihren Code direkt via git auf den Dokku-Server pushen. Bei jedem Push wird die Anwendung mit dem aktualisierten Code neu gebaut. Falls dies nicht gewünscht ist, kann eine Anwendung via dokku apps:lock $APP bzw. dokku apps:unlock $APP ge- und entsperrt werden.
git remote add dokku dokku@dokku:$APP git push dokku main
Anforderungen an den Code
Der Build-Prozess von Dokku erkennt automatisch die verwendete Programmiersprache und baut ein Docker-Image aus dem Code in das alle Abhängigkeiten installiert werden.
Zusätzlich muss eine Datei mit Namen Procfile in das Wurzelverzeichnis des Quelltextes abgelegt werden, das den Heroku-Procfile Spezifikationen entspricht. Kurz zusammengefasst definiert das Procfile wie die Anwendung zu starten ist. Für eine Streamlit-Anwendung könnte Procfile z.B. wie folgt aussehen:
web: streamlit run --server.port $PORT --server.address 0.0.0.0 --browser.serverAddress appnane.apps.informatik.uni-bremen.de --server.runOnSave=false --server.allowRunOnSave=false --server.fileWatcherType=none --browser.gatherUsageStats=false --global.developmentMode=false app.py
Wichtig ist, dass die Anwendung auf dem Port lauscht, der in der Umgebungsvariable $PORT definiert ist (i.d.R. 5000) und nicht nur auf localhost.
Domain(s)
Die Standard-Domain einer Anwendung ist $APP.apps.informatik.uni-bremen.de. Es werden automatisch via Letsencrypt TLS-Zertifikate bezogen.
Die Domain einer Anwendung kann via dokku domains:* Befehle geändert werden. Voraussetzung dafür ist, dass der jeweilige Domainname auf den Dokku-Server zeigt.
Die aktuellen URLs, unter der eine Anwendung erreichbar ist, können via dokku urls $APP angezeigt werden.
Starten, Stoppen, Neustarten, Neubauen einer Anwendung
Mit den Befehlen unter dokku ps:* kann mit dem laufenden Container einer Anwendung interagiert werden. Diese Befehle können via SSH von jedem Account mit Zugriffsrechten auf die jeweilige Anwendung ausgeführt werden.
ps:rebuild $APP ps:restart $APP ps:start $APP ps:stop $APP
Ausrollen von Anwendungen via Gitlab-CI
Wenn man eine Anwendung in Gitlab verwalten und dessen CI/CD-Funktion nutzen möchte, um Änderungen an Dokku zu übertragen, geht das wie folgt:
Im Gitlab-Projekt unter Settings -> General -> Visibility, project features, permissions sicherstellen, dass der Punkt CI/CD aktiviert ist.
Unter Settings -> CI/CD -> Runners -> Shared runners die Option Enable shared runners for this project aktivieren.
Unter Settings -> CI/CD -> Variables über den Button Add variable eine Variable mit dem Namen SSH_PRIVATE_KEY anlegen, die den Wert des zu benutzenden SSH-Private-Key hat (hier sollte ein separater Key verwendet werden, der nur für die jeweilige Dokku-Anwendung genutzt wird und sonst nichts).
Im Git-Repository eine Datei mit dem Namen .gitlab-ci.yml anlegen, die folgenden Inhalt hat (dabei "$APP" mit dem Namen der Dokku-Anwendung ersetzen und ggf. den Branch-Namen "main" anpassen):
--- image: dokku/ci-docker-image stages: - deploy variables: GIT_DEPTH: 0 deploy: stage: deploy only: - main variables: BRANCH: main GIT_REMOTE_URL: ssh://dokku@dokku.informatik.uni-bremen.de:22/$APP script: - dokku-deploy after_script: - dokku-unlock
ACLs
Siehe ~dokku/.dokkurc/acl für die tatsächliche Liste der ACLs.
Das ACL-Plugin staffelt Berechtigungen wie folgt:
- Super-User die alles dürfen.
Befehle die alle Benutzer immer ausführen dürfen. (DOKKU_ACL_USER_COMMANDS)
Befehle die von Benutzern mit Rechten auf eine Anwendung ausführen dürfen (via dokku acl:add $APP $USER). (DOKKU_ACL_PER_APP_COMMANDS)
Befehle die von Benutzern mit Rechten auf einen Dienst ausführen dürfen (via dokku acl:add-service postgres $DB $USER). (DOKKU_ACL_PER_SERVICE_COMMANDS)
Befehle die von Benutzern mit Rechten auf eine Anwendung und verlinkten Dienst ausführen dürfen. (DOKKU_ACL_LINK_COMMANDS)
Derzeit gelten die folgenden ACLs:
- DOKKU_ACL_USER_COMMANDS
- help
- version
- apps:exists
- apps
- apps:list
- DOKKU_ACL_PER_APP_COMMANDS
- logs
- urls
- ps:rebuild
- ps:restart
- ps:stop
- ps:start
- git-upload-pack
- git-upload-archive
- git-receive-pack
- git-hook
- apps:lock
- apps:locked
- apps:unlock
- apps:report
- apps:destroy
- config
- config:bundle
- config:clear
- config:export
- config:get
- config:keys
- config:show
- config:set
- config:unset
- cron:list
- cron:report
- cron:run
- DOKKU_ACL_PER_SERVICE_COMMANDS
- postgres:export
- postgres:import
- postgres:app-links
- postgres:info
- postgres:logs
- postgres:restart
- postgres:enter
- postgres:promote