Polycrate API für Teams: Zentrales Monitoring und Remote-Triggering
TL;DR Die Polycrate API macht aus einzelnen Workspaces eine Team-Plattform: alle Workspaces, Action …
Diese Serie zeigt Schritt für Schritt, wie Ansible mit Polycrate zu einer strukturierten, teilbaren und compliance-fähigen Automatisierungsplattform wird – von den Grundlagen bis zu Enterprise-Szenarien.
block.poly für Konfiguration, docker-compose.yml.j2 als Template, Ansible-Playbook als Action – alles sauber strukturiert und teamfähig; der Block folgt derselben Registry-Konvention wie im Beitrag Nginx und Let’s Encrypt als wiederverwendbarer Polycrate-Block (registry.acme-corp.com/infra/…, Version per from: …:0.1.0 im Workspace, Veröffentlichung mit polycrate blocks push …).docker-compose.yml und nicht in der lesbaren workspace.poly, sondern in secrets.poly im gleichen YAML-Format wie workspace.poly (Merge zur Laufzeit); die Datei wird im Rahmen der Workspace-Verschlüsselung geschützt – im Template referenzieren Sie block.config.db_password nach dem Merge.community.docker.docker_compose, Health-Checks und Polycrate-Actions reproduzierbar und für Kolleg:innen einfach ausführbar.Nicht jedes Team braucht sofort Kubernetes. Viele System-Admins betreiben heute:
Für solche Szenarien ist Docker-Compose oft genau richtig:
docker-compose up -d kennen viele Admins bereits.docker logs, Volumes im Filesystem.Die Probleme kommen an anderer Stelle:
docker-compose.yml, .env-Dateien oder im Wiki.Genau hier setzt Polycrate an: Ansible läuft vollständig im Container, die Automatisierung wird als Block strukturiert, Geheimnisse werden verschlüsselt, und alles ist als wiederverwendbare Einheit teilbar.
Eine gute Übersicht zur Ansible-Integration in Polycrate finden Sie in der offiziellen Dokumentation.
Wir bauen ein Beispiel-Setup für die fiktive Firma acme-corp.com. Zielgruppe: Linux-Admins, die einen Docker-Compose-Stack (z. B. App + Postgres) auf mehreren Ubuntu-Servern verwalten.
Zuerst definieren wir unseren Workspace:
# workspace.poly
name: acme-corp-automation
organization: acme
blocks:
- name: acme-app-stack
from: registry.acme-corp.com/infra/docker-stack:0.1.0
config:
stack_name: acme-app
docker_host_group: docker_hosts
host_port: 80
app_port: 8080
image_app: "ghcr.io/acme/app:1.2.3"
db_image: "postgres:15-alpine"
db_name: "acmeapp"
db_user: "acmeapp"
backup_host: "backup01.acme-corp.com"
backup_path: "/data/backups/acme-app"Wichtig:
registry.acme-corp.com. In from: ist die Version explizit gepinnt (:0.1.0) – Best Practice für reproduzierbare Builds (siehe Registry-Dokumentation). Beim ersten Zugriff lädt Polycrate den Block nach blocks/registry.acme-corp.com/infra/docker-stack/ (Pfad spiegelt den Registry-Namen).config abgelegt und werden später im Template und im Playbook verwendet.docker_hosts, die wir im Inventory definieren.Polycrate verwendet ein YAML-Inventory im Workspace-Root:
# inventory.yml
all:
hosts:
docker01.acme-corp.com:
ansible_user: ubuntu
docker02.acme-corp.com:
ansible_user: ubuntu
children:
docker_hosts:
hosts:
docker01.acme-corp.com:
docker02.acme-corp.com:ANSIBLE_INVENTORY automatisch auf diese Datei.all.hosts; Child-Gruppen listen nur die Hostnamen (ohne erneute Variablen) – so passt das Inventory zur SSH-Integration (polycrate ssh).hosts: "{{ block.config.docker_host_group }}" verwenden.Jetzt modellieren wir den Docker-Compose-Stack als Block. Dieser Block enthält:
block.poly mit Actions (deploy, backup, remove) und Block-Konfiguration,docker-compose.yml.j2,deploy.yml, backup.yml und remove.yml,secrets.poly für sensible Konfigurationswerte (gleiches Format wie workspace.poly, siehe unten).# blocks/registry.acme-corp.com/infra/docker-stack/block.poly
name: registry.acme-corp.com/infra/docker-stack
version: 0.1.0
kind: generic
config:
stack_name: acme-app
docker_host_group: docker_hosts
host_port: 80
app_port: 8080
image_app: "ghcr.io/acme/app:1.2.3"
db_image: "postgres:15-alpine"
db_name: "acmeapp"
db_user: "acmeapp"
db_container_name: "acme-app-db"
backup_host: "backup01.acme-corp.com"
backup_path: "/data/backups/acme-app"
actions:
- name: deploy
playbook: deploy.yml
description: "Deploy oder Update des Docker-Compose-Stacks mit Rolling Update"
- name: backup
playbook: backup.yml
description: "Backup der Postgres-Datenbank aus dem Docker-Container"
- name: remove
playbook: remove.yml
description: "Stack vollständig entfernen (Container, Volumes, Projektverzeichnis)"Damit haben wir:
from: mit Tag nutzbar; optional zusätzlich über PolyHub auffindbar.polycrate blocks push)Voraussetzungen und Namensmodell (vollständiger OCI-name ohne Tag in der block.poly, Version im Feld version:) sind im Beitrag Nginx und Let’s Encrypt als wiederverwendbarer Polycrate-Block erklärt. Kurz zum Einprägen des Block-Sharings:
polycrate blocks push registry.acme-corp.com/infra/docker-stackDamit landet registry.acme-corp.com/infra/docker-stack:0.1.0 in der Registry – Kolleg:innen nutzen exakt diese Referenz in workspace.poly (from: mit Tag), ohne Playbooks manuell zu kopieren.
Der Aufruf ist für das Team immer gleich:
polycrate run acme-app-stack deploy
polycrate run acme-app-stack backup
polycrate run acme-app-stack removeKein Ansible-CLI-Wirrwarr mehr – Polycrate-Actions bieten eine einfache UX, auch für Kolleg:innen, die nicht täglich mit Ansible arbeiten.
Statt eine feste docker-compose.yml zu committen, nutzen wir ein Jinja2-Template. So kommen Ports, Images und Volumes dynamisch aus block.config (inkl. per Merge aus secrets.poly übernommene Geheimnisse wie db_password).
# blocks/registry.acme-corp.com/infra/docker-stack/docker-compose.yml.j2
version: "3.9"
services:
app:
image: "{{ block.config.image_app }}"
container_name: "{{ block.config.stack_name }}-app"
restart: unless-stopped
depends_on:
- db
environment:
DATABASE_URL: "postgresql://{{ block.config.db_user }}:{{ block.config.db_password }}@db:5432/{{ block.config.db_name }}"
ports:
- "{{ block.config.host_port }}:{{ block.config.app_port }}"
volumes:
- "{{ block.config.stack_name }}-app-data:/var/www/data"
healthcheck:
test: ["CMD-SHELL", "curl -f http://localhost:{{ block.config.app_port }}/health || exit 1"]
interval: 10s
timeout: 3s
retries: 10
db:
image: "{{ block.config.db_image }}"
container_name: "{{ block.config.db_container_name }}"
restart: unless-stopped
environment:
POSTGRES_DB: "{{ block.config.db_name }}"
POSTGRES_USER: "{{ block.config.db_user }}"
POSTGRES_PASSWORD: "{{ block.config.db_password }}"
volumes:
- "{{ block.config.stack_name }}-db-data:/var/lib/postgresql/data"
volumes:
{{ block.config.stack_name }}-app-data: {}
{{ block.config.stack_name }}-db-data: {}Wichtig:
db_password kommt nach dem Merge von workspace.poly und secrets.poly in block.config an und steht im Template als block.config.db_password zur Verfügung.workspace.poly bleibt ohne Geheimnisse lesbar.secrets.poly im gleichen Format wie workspace.polyPasswörter gehören nicht in .env oder in die docker-compose.yml. In Polycrate legen Sie sensible Werte in secrets.poly im Workspace-Root ab – mit demselben YAML-Schema wie workspace.poly, damit Polycrate die Dateien zur Laufzeit merged (Reihenfolge der Überlagerung: block.poly, dann workspace.poly, dann secrets.poly). So bleibt workspace.poly lesbar und frei von Geheimnissen; secrets.poly wird im Rahmen der Workspace-Verschlüsselung geschützt (Klartext typischerweise nur lokal, verschlüsselte .age-Artefakte im Git). Ausführlich: Konfiguration und Workspace-Verschlüsselung.
# secrets.poly (Workspace-Root, neben workspace.poly)
blocks:
- name: acme-app-stack
config:
db_password: "hier-steht-das-echte-Postgres-Passwort"Der Block-Instanzname acme-app-stack entspricht dem Eintrag unter blocks: in workspace.poly. Nach dem Merge steht db_password in Ansible/Templates wie gewohnt unter block.config.db_password zur Verfügung.
Vorteile:
.env-Lecks.block.config.db_password (siehe docker-compose.yml.j2 oben).Das Herzstück ist das Ansible-Playbook, das Polycrate im Container ausführt. Wichtig: Das Playbook läuft im Polycrate-Container, aber steuert per SSH die Linux-Server aus dem Inventory (hosts: docker_hosts). Wir installieren nichts im Container selbst außer den notwendigen Tools.
# blocks/registry.acme-corp.com/infra/docker-stack/deploy.yml
- name: Deploy Docker-Compose-Stack mit Rolling Update
hosts: "{{ block.config.docker_host_group }}"
become: true
serial: 1
vars:
project_name: "{{ block.config.stack_name }}"
project_dir: "/opt/{{ project_name }}"
tasks:
- name: Zielverzeichnis für den Stack anlegen
ansible.builtin.file:
path: "{{ project_dir }}"
state: directory
owner: root
group: root
mode: "0750"
- name: docker-compose.yml aus Template rendern
ansible.builtin.template:
src: "docker-compose.yml.j2"
dest: "{{ project_dir }}/docker-compose.yml"
owner: root
group: root
mode: "0640"
- name: Neueste Images ziehen
community.docker.docker_compose:
project_src: "{{ project_dir }}"
files:
- "docker-compose.yml"
pull: yes
state: present
- name: Stack aktualisieren (Rolling Update pro Host)
community.docker.docker_compose:
project_src: "{{ project_dir }}"
files:
- "docker-compose.yml"
state: present
remove_orphans: true
register: compose_result
- name: Auf gesunden Zustand des App-Containers warten
ansible.builtin.uri:
url: "http://{{ inventory_hostname }}:{{ block.config.host_port }}/health"
status_code: 200
timeout: 5
validate_certs: false
register: healthcheck
retries: 30
delay: 2
until: healthcheck.status == 200Die remove-Action fährt den Stack auf den Ziel-Hosts kontrolliert herunter, entfernt Container und benannte Volumes und löscht das Projektverzeichnis – destruktiv für die Postgres-Daten im Volume, wenn Sie remove_volumes: true nutzen.
# blocks/registry.acme-corp.com/infra/docker-stack/remove.yml
- name: Docker-Compose-Stack vollständig entfernen
hosts: "{{ block.config.docker_host_group }}"
become: true
serial: 1
vars:
project_name: "{{ block.config.stack_name }}"
project_dir: "/opt/{{ project_name }}"
tasks:
- name: Compose-Projekt stoppen und entfernen (inkl. Volumes)
community.docker.docker_compose:
project_src: "{{ project_dir }}"
files:
- "docker-compose.yml"
state: absent
remove_volumes: true
- name: Projektverzeichnis auf dem Host löschen
ansible.builtin.file:
path: "{{ project_dir }}"
state: absentEin paar Punkte dazu:
serial: 1 sorgt für ein Rolling Update über die Hosts in docker_hosts.
docker01 wird aktualisiert und der Healthcheck abgewartet.docker02 usw.community.docker.docker_compose das “Updaten ohne alles abzureißen”:
state: present mit dem selben Projekt führt im Hintergrund das Äquivalent zu docker-compose pull + docker-compose up -d aus.uri-Task minimieren Downtime:
Mehr Details zur Nutzung von Ansible mit Polycrate finden Sie im Abschnitt Ansible-Integration der Dokumentation.
Ausführen ist jetzt trivial:
polycrate run acme-app-stack deploy
polycrate run acme-app-stack removePolycrate:
community.docker,secrets.poly) bereit,deploy.yml bzw. remove.yml für den Block acme-app-stack aus.Kein lokales Ansible, kein Python-Versions-Chaos, kein Frickeln an ansible.cfg. Das ist die Lösung des klassischen Dependency-Problems.
Backups sind oft das, was im Alltag “später” automatisiert wird – bis es zu spät ist. Die gute Nachricht: Im selben Block können Sie eine backup-Action definieren, die regelmäßig oder ad hoc läuft.
# blocks/registry.acme-corp.com/infra/docker-stack/backup.yml
- name: Backup der Postgres-Datenbank aus dem Docker-Container
hosts: "{{ block.config.docker_host_group }}"
become: true
vars:
project_name: "{{ block.config.stack_name }}"
backup_dir: "/var/backups/{{ project_name }}"
timestamp: "{{ ansible_date_time.iso8601_basic }}"
backup_file: "{{ backup_dir }}/{{ block.config.db_name }}-{{ timestamp }}.sql.gz"
tasks:
- name: Backup-Verzeichnis auf dem Host anlegen
ansible.builtin.file:
path: "{{ backup_dir }}"
state: directory
owner: root
group: root
mode: "0750"
- name: pg_dump im Container ausführen und komprimieren
ansible.builtin.shell: >
docker exec {{ block.config.db_container_name }}
pg_dump -U {{ block.config.db_user }} {{ block.config.db_name }}
| gzip > {{ backup_file }}
args:
executable: /bin/bash
- name: Backup auf Backup-Server synchronisieren
ansible.builtin.shell: >
rsync -az {{ backup_dir }}/
backup@{{ block.config.backup_host }}:{{ block.config.backup_path }}/
args:
executable: /bin/bashHier nutzen wir bewusst klassische Admin-Tools:
docker exec für pg_dump des Datenbank-Containers.gzip zur Komprimierung.rsync für die Übertragung auf einen Backup-Server.Auch das läuft natürlich komplett aus dem Polycrate-Container heraus auf den Ziel-Hosts. Starten:
polycrate run acme-app-stack backupSie können diese Action in einen Polycrate-Workflow einbinden, z. B. “backup und danach aufräumen”. Mehr dazu in der Dokumentation zu Workflows.
Wie sähe das gleiche Setup mit “plain Ansible” typischerweise aus?
community.docker-Collection, eventuell docker-Python-Bindings.ansible-vault wird für Secrets genutzt, aber nicht jeder kommt gut damit zurecht.Mit Polycrate:
secrets.poly (gleiches Format wie workspace.poly) und werden über die Workspace-Verschlüsselung geschützt.deploy, backup, remove), die Sie auch Kolleg:innen anvertrauen können, die sonst wenig mit Ansible zu tun haben.Der Block ist – wie oben – bereits als Artefakt in registry.acme-corp.com gedacht; polycrate blocks push registry.acme-corp.com/infra/docker-stack ist der wiederkehrende Schritt bei neuen Versionen. Ergänzend: PolyHub und die Polycrate-Best-Practices.
Docker-Compose und Kubernetes sind Werkzeuge mit unterschiedlichen Stärken. Aus Admin-Sicht hilft folgende Daumenregel:
Docker-Compose ist oft die bessere Wahl, wenn:
Kubernetes wird interessanter, wenn:
Mit Polycrate sind Sie in beiden Welten zuhause:
Der Punkt ist: Sie müssen Kubernetes nicht einführen, um saubere, reproduzierbare Automatisierung zu bekommen. Polycrate bringt Ordnung, Sharability und Sicherheit auch in bestehende Docker-Compose-Setups.
Docker selbst installieren Sie (falls noch nicht vorhanden) klassisch über Ihr Betriebssystem – z. B. apt auf Ubuntu. Das ist bewusst nicht Teil des Playbooks oben, um die Zuständigkeiten klar zu halten.
Die Ansible-Collection community.docker wird im Polycrate-Container bereitgestellt. Sie müssen sie nicht auf den Ziel-Hosts installieren – nur der Docker-Daemon und das docker-CLI müssen dort vorhanden sein. Polycrate kümmert sich darum, dass Ansible im Container die passende Collection-Version zur Verfügung hat, ohne Ihr lokales System zu verändern.
Alternativ können Sie einen eigenen Block (z. B. mit apt/dnf und dem offiziellen Docker-Repo) bauen, der Docker auf den Ziel-Hosts installiert – und diesen vor dem App-Stack-Block ausführen. Das bleibt hier bewusst eine Hausaufgabe für den Leser; dieser Beitrag fokussiert den Compose-Stack.
Die sensiblen Werte aus secrets.poly werden verschlüsselt abgelegt; die verschlüsselten Artefakte können im Git-Repository landen. workspace.poly bleibt ohne Passwörter lesbar – Geheimnisse stehen nur in secrets.poly (bzw. in der verschlüsselten Form in Git).
Solange Sie die Workspace-Verschlüsselung nutzen (siehe Workspace-Verschlüsselung), stehen keine Klartext-Geheimnisse in Git. Nur wer den Workspace-Schlüssel hat, kann entschlüsseln; in Playbooks/Templates verwenden Sie die gemergten Werte wie block.config.db_password.
Ja. Genau das ist eine der Stärken des Block-Modells. Typischer Ansatz:
acme-corp-automation-staging, acme-corp-automation-prod).config-Werte im jeweiligen workspace.poly (z. B. andere Images, Ports, Hostgroups).So bleibt die Automatisierung identisch, aber die Umgebungsparameter sind sauber getrennt und bleiben trotzdem nachvollziehbar.
Weitere Fragen? Siehe unsere FAQ
In diesem Beitrag haben Sie gesehen, wie Sie einen bestehenden Docker-Compose-Stack auf Linux-Servern in einen strukturierten Polycrate-Block überführen:
block.poly, docker-compose.yml.j2, deploy.yml, backup.yml, remove.yml sowie secrets.poly im Workspace so kombiniert, dass Deployments, Backups und Aufräumen reproduzierbar, sicher und teamfähig sind.community.docker.docker_compose, Idempotenz, Rolling Updates) – ohne sich um lokale Python- oder Collection-Versionen kümmern zu müssen.Genau das ist der Ansatz, den wir bei ayedo verfolgen: Wir helfen Teams, vorhandene Infrastruktur – ob klassischer Linux-Server mit Docker-Compose oder später Kubernetes – in robuste, teilbare Automatisierung zu überführen. Polycrate ist dabei das Werkzeug, mit dem Sie als System-Admin Schritt für Schritt mehr Struktur, Sicherheit und Wiederverwendbarkeit etablieren können, ohne Ihren Stack über Nacht zu wechseln.
Wenn Sie Ihre eigenen Docker-Compose-Stacks in ähnliche Blöcke überführen oder eine bestehende Ansible-Landschaft in Polycrate migrieren möchten, unterstützen wir Sie gern – von ersten Workshop-Sessions bis zu maßgeschneiderten Plattform-Lösungen.
Starten Sie mit einer unverbindlichen Docker-Automatisierung Demo
TL;DR Die Polycrate API macht aus einzelnen Workspaces eine Team-Plattform: alle Workspaces, Action …
TL;DR Polycrate protokolliert nicht nur Action Runs (Ansible-Playbooks), sondern auch SSH-Sessions, …
TL;DR Das Model Context Protocol (MCP) ist ein offener Standard: KI-Clients sprechen per JSON-RPC …