🐳 Der Polycrate Container¶
Container-Konzept¶
Ein Großteil der Magie von Polycrate passiert innerhalb eines Docker-Containers, der mit jeder Ausführung einer Action auf dem System gestartet wird, auf dem Polycrate ausgeführt wird.
Der Container basiert auf einem von ayedo entwickelten und öffentlich verfügbaren Docker-Image (cargo.ayedo.cloud/library/polycrate), das einen Großteil der best-practice Toolchain für den Einsatz von Infrastructure as Code und cloud-nativen Entwicklungsmethoden beinhaltet.
Der Container gibt Ihnen Zugang zu einer state-of-the-art DevOps runtime. Polycrate exportiert einen Snapshot des Workspaces als YAML-Datei und stellt diese Datei innerhalb des Containers zur Verfügung (Pfad in POLYCRATE_WORKSPACE_SNAPSHOT_YAML), sodass die gesamte Workspace-Konfiguration problemlos von den Tools innerhalb des Containers eingelesen werden kann.
Container Lifecycle¶
sequenceDiagram
participant User
participant CLI as Polycrate CLI
participant Docker
participant Container
participant Tools as Ansible/kubectl/Helm
User->>CLI: polycrate run myblock install
CLI->>CLI: Erstelle Snapshot
CLI->>CLI: Generiere Transaction-ID
alt Custom Dockerfile.poly existiert?
CLI->>Docker: Build Custom Image
Docker->>Docker: FROM polycrate:latest + Custom layers
Docker-->>CLI: Custom Image ready
end
CLI->>Docker: docker run polycrate
Docker->>Container: Start Container
CLI->>Container: Mount Workspace → /workspace
CLI->>Container: Mount SSH Keys
CLI->>Container: Injiziere Environment Variables
CLI->>Container: Injiziere Snapshot (YAML, Pfad in POLYCRATE_WORKSPACE_SNAPSHOT_YAML)
Container->>Container: Setze Working Directory
Container->>Tools: Führe Playbook/Script aus
Tools->>Tools: Lese .snapshot.yml
Tools->>Tools: Greife auf /workspace zu
alt Action erfolgreich
Tools-->>Container: Exit 0
Container-->>Docker: Success
Docker-->>CLI: Container beendet (Exit 0)
CLI->>CLI: Schreibe Artifacts
CLI-->>User: Success
else Action fehlgeschlagen
Tools-->>Container: Exit 1
Container-->>Docker: Failure
Docker-->>CLI: Container beendet (Exit 1)
CLI-->>User: Failure mit Error-Output
end
CLI->>Docker: Cleanup Container
Docker->>Docker: Remove Container Was ist im Container enthalten?¶
Das Polycrate Base-Image (cargo.ayedo.cloud/library/polycrate) basiert auf python:3.12-slim (Debian) und enthält eine umfassende DevOps-Toolchain.
Kubernetes & Container Tools¶
| Tool | Version | Beschreibung |
|---|---|---|
| kubectl | 1.32.1 | Kubernetes CLI |
| helm | 3.18.4 | Kubernetes Package Manager (+ helm-diff Plugin) |
| kustomize | 5.8.0 | Kubernetes Konfiguration |
| cilium | 0.18.5 | Cilium CNI CLI |
| argocd | 3.0.6 | Argo CD CLI für GitOps |
| velero | 1.16.1 | Kubernetes Backup & Migration |
| docker | latest | Docker CLI (from docker:dind) |
| skopeo | system | Container Image Management |
Secrets & Vault Tools¶
| Tool | Version | Beschreibung |
|---|---|---|
| bao | 2.5.1 | OpenBao CLI — Open-Source Vault Fork (API-kompatibel zu HashiCorp Vault) |
Backup & Encryption Tools¶
| Tool | Version | Beschreibung |
|---|---|---|
| restic | 0.18.1 | Backup Tool |
| kopia | 0.22.2 | Backup Tool (Velero Backend) |
| age | 1.2.1 | Moderne Verschlüsselung |
Configuration Management¶
| Tool | Version | Beschreibung |
|---|---|---|
| Ansible | 13.2.0 | Configuration Management und Orchestrierung |
| ansible-core | 2.18.x | Ansible Core Engine |
Utilities¶
| Tool | Beschreibung |
|---|---|
| git | Version Control |
| jq | JSON Processing |
| yq (v4.45.1) | YAML Processing |
| curl / wget | HTTP Clients |
| openssh-client | SSH/SCP Tools |
| sshpass | SSH Password Authentication |
| rsync | File Synchronization |
| envsubst | Environment Variable Substitution |
| htpasswd | HTTP Basic Auth Password Generator |
Database Clients¶
| Tool | Beschreibung |
|---|---|
| mariadb-client | MySQL/MariaDB CLI |
| postgresql-client | PostgreSQL CLI (psql) |
Netzwerk-Tools¶
| Tool | Beschreibung |
|---|---|
| dnsutils | DNS Tools (dig, nslookup) |
| telnet | Telnet Client |
Python Libraries¶
| Library | Beschreibung |
|---|---|
| kubernetes | Kubernetes Python Client |
| openshift | OpenShift Python Client |
| hcloud | Hetzner Cloud Python SDK |
| pynetbox | NetBox API Client |
| pyvmomi | VMware vSphere API Client |
| docker-compose | Docker Compose Python Library |
| cryptography | Cryptographic Primitives |
| passlib | Password Hashing |
Ansible Collections¶
| Collection | Beschreibung |
|---|---|
| community.general | Allgemeine Module |
| community.docker | Docker Module |
| community.vmware | VMware Module |
| netbox.netbox | NetBox Module |
Ansible Roles¶
| Role | Beschreibung |
|---|---|
| geerlingguy.docker | Docker Installation |
| geerlingguy.ntp | NTP Konfiguration |
Cloud Provider CLIs
Cloud Provider CLIs (AWS, Azure, GCloud) sind nicht im Base-Image enthalten. Installieren Sie diese bei Bedarf über ein Dockerfile.poly:
Container-Umgebung¶
Mounts¶
Wenn der Container startet, werden folgende Pfade gemountet:
graph LR
Host[Host-System] --> WS[Workspace-Root]
Host --> SSH[SSH-Keys]
Host --> Docker[Docker Socket optional]
WS -->|mount| CWS[Container: /workspace]
SSH -->|mount| CSSH[Container: ~/.ssh/]
Docker -->|mount| CDocker[Container: /var/run/docker.sock] Host → Container Mappings:
$WORKSPACE_ROOT→/workspace(read/write)$WORKSPACE_ROOT/id_rsa→~/.ssh/id_rsa(read-only)/var/run/docker.sock→/var/run/docker.sock(optional, für Docker-in-Docker)
Environment Variables¶
Polycrate setzt im Container deutlich mehr Variablen als nur die POLYCRATE_*-Namen: dazu gehören Ansible-Defaults (ANSIBLE_*), Kubernetes (KUBECONFIG, K8S_AUTH_KUBECONFIG), ggf. SSH (SSH_AUTH_SOCK, ANSIBLE_SSH_PRIVATE_KEY_FILE) und weitere Laufzeitwerte. Die vollständige Liste steht zur Laufzeit im Workspace-Snapshot unter env: (gleicher Inhalt wie die an den Container übergebenen Variablen).
Auszug: POLYCRATE_* und zentrale Laufzeitvariablen (Stand CLI):
| Variable | Bedeutung |
|---|---|
POLYCRATE_WORKSPACE | Pfad zum Workspace (im Container meist dem Wert von config.containerroot, üblich /workspace) |
POLYCRATE_BLOCK | Name des aktuellen Blocks |
POLYCRATE_BLOCK_WORKDIR | Container-Pfad zum Block-Workdir (wenn konfiguriert) |
POLYCRATE_ACTION | Name der aktuellen Action |
POLYCRATE_WORKFLOW / POLYCRATE_STEP | Bei Workflow-Ausführung |
POLYCRATE_VERSION / POLYCRATE_CLI_VERSION | CLI-Version |
POLYCRATE_IMAGE_REFERENCE / POLYCRATE_IMAGE_VERSION | Konfiguriertes Basis-Image (config.image) |
POLYCRATE_FORCE | Entspricht --force |
POLYCRATE_HOST_UID / POLYCRATE_HOST_GID | UID/GID des Nutzers auf dem Host |
POLYCRATE_WORKSPACE_SNAPSHOT_YAML | Pfad zur temporären Snapshot-Datei (wird in den Container gemountet) |
POLYCRATE_RUNTIME_SCRIPT_PATH | Pfad zum ausführenden Wrapper-Script der Action |
IN_CONTAINER | 1 im Container, 0 bei --local |
IN_CI | Wird von der CLI gesetzt (true) |
Der Workspace-Name steht nicht als POLYCRATE_WORKSPACE_NAME, sondern im Snapshot unter workspace.name. Eine feste Datei POLYCRATE_SNAPSHOT_FILE=/workspace/.snapshot.yml setzt die CLI so nicht; der Pfad liegt unter POLYCRATE_WORKSPACE_SNAPSHOT_YAML (temporärer Pfad, identisch im Container durch Mount).
Zusätzliche Variablen können Sie mit extraenv bzw. -e KEY=value setzen (siehe Container-Konfiguration).
Host User Context (ab 0.29.16)¶
Die Variablen POLYCRATE_HOST_UID und POLYCRATE_HOST_GID enthalten die UID und GID des Users, der polycrate run auf dem Host-System ausführt.
| Variable | Beschreibung |
|---|---|
POLYCRATE_HOST_UID | User ID des ausführenden Host-Users (z.B. "1000") |
POLYCRATE_HOST_GID | Group ID des ausführenden Host-Users (z.B. "1000") |
Anwendungsfall: Permission-Fixing
Da Actions im Container als root ausgeführt werden, gehören neu erstellte Dateien dem Root-User. Mit diesen Variablen können Blocks die Ownership am Ende einer Action korrigieren:
# Am Ende eines Playbooks
- name: Fix ownership for host user
ansible.builtin.file:
path: "{{ workspace.path }}/artifacts"
owner: "{{ lookup('env', 'POLYCRATE_HOST_UID') }}"
group: "{{ lookup('env', 'POLYCRATE_HOST_GID') }}"
recurse: yes
when: lookup('env', 'POLYCRATE_HOST_UID') | default('') != ''
Dies stellt sicher, dass der Host-User nach der Action-Ausführung Schreibzugriff auf die generierten Dateien hat.
Working Directory¶
Das Working Directory wird automatisch auf den Block-Pfad gesetzt:
# Bei lokalem Block
WORKDIR=/workspace/blocks/my-block
# Bei geerbtem Block (from: parent-block)
WORKDIR=/workspace/blocks/parent-block
Siehe Vererbung für Details zum Working Directory bei geerbten Blocks.
Dockerfile.poly¶
Polycrate sucht standardmäßig nach einem Dockerfile im Workspace. Der Dateiname ist in workspace.poly unter config.dockerfile konfigurierbar (Standard in neuen Workspaces: Dockerfile.poly). Alternativ setzen Sie den Pfad per CLI: --dockerfile $FILENAME (gebunden an workspace.config.dockerfile).
Wenn die konfigurierte Datei im Workspace existiert, baut Polycrate daraus ein Image und startet den Container mit diesem Tag statt des unveränderten Referenz-Images.
Das Basis-Image (Pull/Tag) kommt aus config.image im Workspace:
config:
image:
reference: cargo.ayedo.cloud/library/polycrate
version: "0.31.0" # Beispiel: CLI-/Image-Version
dockerfile: Dockerfile.poly
Per CLI: --image-ref und --image-version (siehe CLI-Referenz).
Mit Hilfe dieses Custom-Images können Anpassungen am Workspace, z.B. das Installieren von Packages oder Libraries im Polycrate-Container, persistiert werden.
Per Konvention sollte das Dockerfile.poly auf dem offiziellen Polycrate Image basieren, um existente Funktionalität nicht zu brechen:
Custom Dockerfile.poly Beispiele¶
Beispiel 1: Python Packages installieren¶
FROM cargo.ayedo.cloud/library/polycrate:latest
# Python Packages für Custom Ansible Modules
RUN pip install \
hcloud==1.16.0 \
proxmoxer==2.0.1 \
requests==2.31.0
Beispiel 2: Node.js Tools hinzufügen¶
FROM cargo.ayedo.cloud/library/polycrate:latest
# Node.js und NPM installieren (Ubuntu-basiert!)
RUN apt-get update && apt-get install -y --no-install-recommends \
nodejs npm \
&& rm -rf /var/lib/apt/lists/*
# Global NPM Packages
RUN npm install -g \
cdktf-cli \
serverless
Beispiel 3: Custom CLIs und Tools¶
FROM cargo.ayedo.cloud/library/polycrate:latest
# Tailscale CLI
RUN wget https://pkgs.tailscale.com/stable/tailscale_1.56.1_amd64.tgz && \
tar xzf tailscale_1.56.1_amd64.tgz && \
mv tailscale_1.56.1_amd64/tailscale /usr/local/bin/ && \
rm -rf tailscale_*
# Velero (Kubernetes Backup Tool)
RUN wget https://github.com/vmware-tanzu/velero/releases/download/v1.12.0/velero-v1.12.0-linux-amd64.tar.gz && \
tar xzf velero-v1.12.0-linux-amd64.tar.gz && \
mv velero-v1.12.0-linux-amd64/velero /usr/local/bin/ && \
rm -rf velero-*
Beispiel 4: Ansible Collections hinzufügen¶
FROM cargo.ayedo.cloud/library/polycrate:latest
# Custom Ansible Collections
RUN ansible-galaxy collection install \
community.hashi_vault:4.0.0 \
community.vmware:3.9.0 \
netbox.netbox:3.13.0
Beispiel 5: Multi-Cloud Setup¶
FROM cargo.ayedo.cloud/library/polycrate:latest
# Oracle Cloud CLI
RUN pip install oci-cli
# DigitalOcean CLI
RUN wget -O /usr/local/bin/doctl https://github.com/digitalocean/doctl/releases/download/v1.100.0/doctl-1.100.0-linux-amd64 && \
chmod +x /usr/local/bin/doctl
# Linode CLI
RUN pip install linode-cli
Image Building¶
Wenn ein Dockerfile.poly im Workspace existiert:
# Polycrate buildet das Image automatisch vor jeder Action
polycrate run myblock install
# Das entspricht intern:
docker build -f Dockerfile.poly -t polycrate-workspace:latest .
docker run polycrate-workspace:latest ...
Das Image wird nur neu gebaut, wenn sich das Dockerfile.poly geändert hat.
Container Debugging¶
polycrate debug Command¶
Der einfachste Weg, eine interaktive Debug-Shell im Polycrate-Container zu starten:
# Debug-Container im aktuellen Workspace starten
polycrate debug
# Mit explizitem Workspace-Pfad
polycrate debug -w /path/to/workspace
# Mit zusätzlichen Mounts
polycrate debug -m /local/path:/container/path
# Mit zusätzlichen Environment-Variablen
polycrate debug -e MY_VAR=value
Funktionsweise:
- Der aktuelle Workspace wird geladen (inkl. aller Blöcke)
- Das Workspace-Image wird gepullt (oder gebaut bei
Dockerfile.poly) - Container startet mit allen Mounts, Environment-Variablen und Netzwerk-Konfiguration wie bei einem Action Run
- Interaktive Bash-Shell öffnet sich
Beispiel-Session:
$ polycrate debug
✓ Pulling image cargo.ayedo.cloud/library/polycrate:0.28.0
Starting debug container: polycrate-debug-a1b2c3d4
Workspace: /home/user/my-workspace
Image: cargo.ayedo.cloud/library/polycrate:0.28.0
Type 'exit' to leave the container
root@polycrate:/workspace# ls -la
drwxr-xr-x 5 root root 4096 Dec 15 10:00 blocks
-rw-r--r-- 1 root root 512 Dec 15 10:00 workspace.poly
root@polycrate:/workspace# env | grep POLYCRATE
POLYCRATE_WORKSPACE=/workspace
POLYCRATE_VERSION=0.28.0
root@polycrate:/workspace# exit
$
Use Cases:
- Playbook-Debugging: Ansible-Playbooks manuell ausführen und testen
- Environment-Inspektion: Prüfen welche Variablen im Container gesetzt sind
- Pfad-Validierung: Überprüfen ob Mounts korrekt im Container ankommen
- Tool-Verfügbarkeit: Testen ob benötigte Tools im Image vorhanden sind
- Netzwerk-Debugging: Prüfen ob Netzwerkverbindungen aus dem Container funktionieren
→ Siehe CLI-Referenz für alle Optionen.
Container-Logs anzeigen¶
Polycrate zeigt standardmäßig die gesamte Container-Ausgabe an:
Manuelle interaktive Shell¶
Alternativ können Sie auch manuell eine Shell im Container starten:
# Mit Standard-Image
docker run -it --rm \
-v $(pwd):/workspace \
cargo.ayedo.cloud/library/polycrate:latest \
/bin/bash
# Mit Custom Dockerfile.poly
docker build -f Dockerfile.poly -t polycrate-workspace:latest .
docker run -it --rm \
-v $(pwd):/workspace \
polycrate-workspace:latest \
/bin/bash
Snapshot inspizieren¶
Im Container zeigt POLYCRATE_WORKSPACE_SNAPSHOT_YAML auf die gemountete Snapshot-Datei (temporärer Pfad, oft unter /tmp/). Denselben Inhalt finden Sie im Snapshot unter env:.
# Im Container
SNAP="${POLYCRATE_WORKSPACE_SNAPSHOT_YAML:?}"
cat "$SNAP"
yq eval '.block.config' "$SNAP"
Container-Konfiguration¶
Die CLI unterstützt keine freien docker run-Zusatzargumente (kein config.container.docker_flags). Image, Dockerfile, zusätzliche Umgebungsvariablen und Mounts steuern Sie wie folgt.
Image, Dockerfile und Pfade (config)¶
Auf Workspace-Ebene (in workspace.poly) sind u. a. diese Felder relevant:
name: my-workspace
config:
image:
reference: cargo.ayedo.cloud/library/polycrate
version: "0.31.0"
dockerfile: Dockerfile.poly
# Weitere Pfade: blocksroot, artifactsroot, containerroot, …
Siehe Konfiguration für die vollständige config-Übersicht.
Zusätzliche Umgebungsvariablen und Mounts¶
Auf Workspace-Ebene (nicht unter config):
name: my-workspace
extraenv:
- "MY_CUSTOM_VAR=value"
- "API_KEY=secret-key"
extramounts:
- "/var/run/docker.sock:/var/run/docker.sock"
Entspricht den globalen Flags -e / --env und -m / --mount (siehe CLI-Referenz).
Docker Socket für Docker-CLI im Container¶
Typisches Muster: Docker-Socket vom Host einbinden:
Beispiel-Verwendung:
# Block mit Docker-CLI im Container (Socket gemountet)
actions:
- name: build-and-push
playbook: build-and-push.yml
Docker Native Mode¶
Ab Version 0.28.0 bietet Polycrate einen optionalen Native Docker Mode, der das Docker Go SDK direkt verwendet statt die Docker CLI aufzurufen.
Aktivierung¶
# Via Flag
polycrate --docker-native run myblock install
polycrate -N run myblock install
# Via Umgebungsvariable
export POLYCRATE_DOCKER_NATIVE=true
polycrate run myblock install
# Via Konfigurationsdatei (~/.polycrate/config.yml)
# docker:
# native: true
Vorteile¶
| Aspekt | Docker CLI | Docker Native |
|---|---|---|
| Docker CLI Installation | Erforderlich | Nicht erforderlich |
| Performance | ~50-100ms Overhead pro Aufruf | Direkte API-Aufrufe |
| Fehlerbehandlung | Text-Parsing | Typisierte Errors |
| Output-Streaming | Umständlich | Native Streams |
Spinner-Feedback¶
Im Native Mode zeigt Polycrate animierte Spinner während Docker-Operationen:
⠹ Pulling image cargo.ayedo.cloud/library/polycrate:0.28.0...
✓ Pulling image cargo.ayedo.cloud/library/polycrate:0.28.0
⠼ Building container image my-workspace:0.28.0...
✓ Building container image my-workspace:0.28.0
⠧ Cleaning up containers...
✓ Cleaning up containers
Bei höherem Loglevel (--loglevel 3) werden Spinner deaktiviert und der vollständige Output gestreamt.
Podman-Kompatibilität¶
Der Native Docker Mode ist auch mit Podman kompatibel. Podman kann einen Docker-kompatiblen API-Socket bereitstellen:
# 1. Podman API-Service starten (rootless)
podman system service --time=0 &
# 2. DOCKER_HOST auf Podman-Socket setzen
export DOCKER_HOST=unix:///run/user/$(id -u)/podman/podman.sock
# 3. Polycrate mit Native Backend verwenden
polycrate -N run myblock myaction
polycrate -N debug
Einschränkungen mit Podman
Multi-Arch Builds und Buildx-Features sind mit Podman nicht verfügbar. Für Production-Builds wird weiterhin Docker mit Buildx empfohlen.
Best Practices¶
1. Pinne Image-Versionen¶
# ✅ Gut: Spezifische Version
FROM cargo.ayedo.cloud/library/polycrate:1.2.3
# ❌ Schlecht: Latest (kann brechen)
FROM cargo.ayedo.cloud/library/polycrate:latest
2. Minimiere Layer¶
# ✅ Gut: Kombinierte RUN statements (Ubuntu-basiert!)
FROM cargo.ayedo.cloud/library/polycrate:latest
RUN apt-get update && apt-get install -y --no-install-recommends curl wget && \
pip install --no-cache-dir boto3 requests && \
rm -rf /var/lib/apt/lists/*
# ❌ Schlecht: Viele separate RUN statements
FROM cargo.ayedo.cloud/library/polycrate:latest
RUN apt-get update && apt-get install -y curl
RUN apt-get install -y wget
RUN pip install boto3
RUN pip install requests
3. Cleanup in derselben Layer¶
FROM cargo.ayedo.cloud/library/polycrate:latest
RUN wget https://example.com/tool.tar.gz && \
tar xzf tool.tar.gz && \
mv tool /usr/local/bin/ && \
rm -rf tool* # Cleanup im selben Layer
4. Versioniere dein Dockerfile.poly¶
# Im Workspace
git add Dockerfile.poly
git commit -m "Add custom Python packages to container"
git push
5. Teste Custom Images lokal¶
# Image bauen
docker build -f Dockerfile.poly -t test-polycrate .
# Interaktiv testen
docker run -it --rm test-polycrate /bin/bash
# Tools testen
docker run --rm test-polycrate ansible --version
docker run --rm test-polycrate kubectl version --client
Troubleshooting¶
Image Build schlägt fehl¶
# Prüfen Sie das Dockerfile
cat Dockerfile.poly
# Manuell builden für bessere Fehler-Ausgabe
docker build -f Dockerfile.poly -t polycrate-workspace:latest .
Package Installation schlägt fehl¶
# APT Cache aktualisieren (Ubuntu-basiert!)
FROM cargo.ayedo.cloud/library/polycrate:latest
RUN apt-get update && apt-get install -y --no-install-recommends my-package \
&& rm -rf /var/lib/apt/lists/*
Container startet nicht¶
# Container-Logs prüfen
docker ps -a
docker logs <container-id>
# Image inspizieren
docker images | grep polycrate
docker inspect cargo.ayedo.cloud/library/polycrate:latest
Permission-Probleme mit Mounts¶
Wenn Sie Permission-Probleme mit gemounteten Verzeichnissen haben, gibt es zwei Lösungsansätze:
Option 1: Ownership im Playbook korrigieren (empfohlen)
Nutzen Sie die Environment-Variablen POLYCRATE_HOST_UID und POLYCRATE_HOST_GID um die Ownership am Ende der Action zu korrigieren:
- name: Fix ownership for host user
ansible.builtin.file:
path: "{{ workspace.path }}/dist"
owner: "{{ lookup('env', 'POLYCRATE_HOST_UID') }}"
group: "{{ lookup('env', 'POLYCRATE_HOST_GID') }}"
recurse: yes
when: lookup('env', 'POLYCRATE_HOST_UID') | default('') != ''
Option 2: Eigener User im Container
Die Polycrate-CLI setzt derzeit keinen --user-Override für den Action-Container. Wenn Sie einen Prozess als Non-Root ausführen müssen, starten Sie diesen gezielt im Playbook (z. B. become: false / dediziertes Command) oder nutzen Sie ein angepasstes Image; eine docker_flags-Liste in workspace.poly gibt es nicht.
Zusammenhang mit anderen Konzepten¶
- Snapshot: Wird als YAML-Datei in den Container gemountet (
POLYCRATE_WORKSPACE_SNAPSHOT_YAML) - Actions: Werden im Container ausgeführt
- Workspaces: Werden in den Container gemountet
- Integrationen: Alle Tools laufen im Container
Container-Vorteile
Der Container-basierte Ansatz garantiert: - Reproduzierbarkeit: Gleiche Umgebung auf jedem System - Isolation: Keine Konflikte mit Host-System - Portabilität: Läuft überall wo Docker läuft - Versionierung: Dockerfile.poly im Git versioniert