Automatisches Erstellen des Images mit Docker

Corin Corvus

Lieutenant
Registriert
Dez. 2010
Beiträge
831
Moin,

ich habe mir gestern auf meinem Containerserver Watchtower installiert um meine Container zu aktualisieren.
Der Server ist ein Linux Debian Server mit Docker installiert. Als Oberfläche nutze ich Portainer. Dort habe ich Stacks eingerichtet, was nichts anderes ist als eine Compose Datei.

Auf dem Containerserver sind 2 Wordpress Container für unterschiedliche Webseiten.
Beide brauchen LDAP und ich kann daher nicht einfach das originale verwenden, muss dafür das hier durchführen beim Erstellen des images: https://github.com/dalareo/docker-wordpress-ldap-support

Meine Compose sieht so aus:
version: '3.1' volumes: wordpress: db: services: wordpress: image: wordpress-ldap:latest restart: always stdin_open: true tty: true ports: - 12006:80 environment: WORDPRESS_DB_HOST: db WORDPRESS_DB_USER: WORDPRESS_DB_PASSWORD: WORDPRESS_DB_NAME: wordpress volumes: - /opt/ct/wordpress_w1/data:/var/www/html labels: - "com.centurylinklabs.watchtower.enable=true" db: image: mariadb:latest restart: always environment: MYSQL_DATABASE: wordpress MYSQL_USER: MYSQL_PASSWORD: MYSQL_ROOT_PASSWORD: volumes: - db:/var/lib/mysql labels: - "com.centurylinklabs.watchtower.enable=true"

Mein Problem ist nun, dass Watchtower natürlich nicht das Image findet und nicht aktualisieren kann.
Ich habe dann rumgeforscht und mehrere dinge versucht, dass das Image beim Deploy automatisch erstellt wird.
Dazu sollte ich laut Doku ein Dockerfile erstellen und aus der Compose den "image:" part rausnehmen.

habe dann den Ordner /opt/images erstellt und ein "dockerfile" erstellt mit dem inhalt von oben.


Sieht dann so aus:
services: wordpress: build: context: /opt/images restart: always

Das funktionierte gar nicht. Ständig findet er den Pfad nicht, mache ich das manuell als root mit docker build -t /opt/images/ geht es.

Habe das dann mit "inline" versucht:
services: wordpress: build: context: . dockerfile_inline: FROM wordpress RUN set -x \ && apt-get update \ && apt-get install -y libldap2-dev \ && rm -rf /var/lib/apt/lists/* \ && docker-php-ext-configure ldap --with-libdir=lib/x86_64-linux-gnu/ \ && docker-php-ext-install ldap \ && apt-get purge -y --auto-remove libldap2-dev

Ging auch nicht. Hier kommt dann ein anderer Fehler:
Build dockerfile_inline failed to deploy a stack: failed to solve: rpc error: code = Unknown desc = failed to solve with frontend dockerfile.v0: failed to read dockerfile: open /var/lib/docker/tmp/buildkit-mount3183161608/Dockerfile: no such file or directory


Bin langsam etwas ratlos.

Jemand eine Idee?
Hoffe ich bin hier nicht im falschen Bereich.

Danke
 
Watchtower kannte ich noch nicht. Schaue ich mir mal an, sieht ganz interessant aus.

Mein Vorschlag geht daher in ne andere Richtung: hast du dein Zeug nicht eh in nem SCM? Ich erledige solch Aufgaben mit GitLab Pipelines (bzw. GitHub Actions, Jenkins oder was auch immer man hat). Da hat man alle Freiheiten und kann auf Änderungen am Dockerfile bzw. der docker-compose.yml gleich beim Commit reagieren. Planen kann man Pipeline-Läufe auch, z. B. für nightlies oder eben zyklische Aktualisierung der base images.
Ergänzung ()

Corin Corvus schrieb:
habe dann den Ordner /opt/images erstellt und ein "dockerfile" erstellt mit dem inhalt von oben.
Heißt die Datei wirklich exakt so? Per Standard heißt das Dockerfile eben genau so: Dockerfile (case sensitive), außer du schreibst es so, was aber in diesem Fall eher Quark is:
Code:
build:
  context: /opt/images
  dockerfile: dockerfile
 
Zuletzt bearbeitet:
  • Gefällt mir
Reaktionen: Corin Corvus
ChromeRonin schrieb:
Watchtower kannte ich noch nicht. Schaue ich mir mal an, sieht ganz interessant aus.
Watchtower guckt halt in regelmäßigen Abständen für die laufenden Container, ob es für deren zugrundeliegenden Images neue Versionen gibt. Dann holt Watchtower die Images selbstständig und startet den Container damit neu.
 
  • Gefällt mir
Reaktionen: Corin Corvus
ChromeRonin schrieb:
Was ist ein SCM?

Über Github mache ich da noch gar nichts. Jenkins habe ich bislang auch noch nie verwendet.

Ich hatte es mit "dockerfile" und "Dockerfile" versucht. beides wollte nicht. Er hat wohl generell Probleme den Pfad zu finden.
 
Zuletzt bearbeitet von einem Moderator:
Corin Corvus schrieb:
Mein Problem ist nun, dass Watchtower natürlich nicht das Image findet und nicht aktualisieren kann.
Ich habe dann rumgeforscht und mehrere dinge versucht, dass das Image beim Deploy automatisch erstellt wird.
Dazu sollte ich laut Doku ein Dockerfile erstellen und aus der Compose den "image:" part rausnehmen.

habe dann den Ordner /opt/images erstellt und ein "dockerfile" erstellt mit dem inhalt von oben.
Ein Dockerfile sieht doch ziemlich anders aus als ein docker-compose vom Inhalt her. Ich kenne Watchtower nicht, aber ich vermute mal der sucht nach dem Image namen im angegebenen Repository - wenn nichts angegeben ist, eben localhost. Da dein Dockerfile wohl fehlerhaft ist, wird Docker als kein Image bauen und es auch nicht in deinem Repository ablegen, somit findet Watchtower das nicht.
Ein docker image list --all sollte dir ja anzeigen ob ein Image mit dem richtigen Namen existiert oder nicht.
 
Corin Corvus schrieb:
Source-Control-Management, also Quelltextverwaltung/Versionsverwaltung wie git, CVS, Subversion. Dass kann man dann auch ins automatische Deployment integrieren, so dass Änderungen am Quellcode oder bei neuen Versionen entsprechend ein neuer Build (und ein neues Docker-Image erstellt) wird und das dann auch direkt ausgeliefert wird.

Mit einem Commit bei bspw. Git kann man dann quasi den ganzen Automatismus triggern, der dafür sorgt, dass bei Docker der Container mit einem neuen Image neu gestartet wird.
 
  • Gefällt mir
Reaktionen: Corin Corvus
Falc410 schrieb:
Ein Dockerfile sieht doch ziemlich anders aus als ein docker-compose vom Inhalt her. Ich kenne Watchtower nicht, aber ich vermute mal der sucht nach dem Image namen im angegebenen Repository - wenn nichts angegeben ist, eben localhost. Da dein Dockerfile wohl fehlerhaft ist, wird Docker als kein Image bauen und es auch nicht in deinem Repository ablegen, somit findet Watchtower das nicht.
Ein docker image list --all sollte dir ja anzeigen ob ein Image mit dem richtigen Namen existiert oder nicht.
geht ja in dem Fall nicht speziell um Watchtower, sondern darum, dass ich das Erstellen des images automatisieren will.
Watchtower schaut, wenn ein Image angegeben ist, in der Registry docker.io. Da findet er selbst erstelle images nicht.
Daher muss ich es irgendwie so umsetzen, dass er während des pullens erstellt. Das soll laut docker doku irgendwie auch mit einer compose gehen.
https://docs.docker.com/compose/compose-file/build/

Ich scheitere aber daran, dass er in dem Fall das Dockerfile nicht findet und damit nichts erstellt (manuell beim Deployen der Compose.
Ergänzung ()

mibbio schrieb:
Source-Control-Management, also Quelltextverwaltung/Versionsverwaltung wie git, CVS, Subversion. Dass kann man dann auch ins automatische Deployment integrieren, so dass Änderungen am Quellcode oder bei neuen Versionen entsprechend ein neuer Build (und ein neues Docker-Image erstellt) wird und das dann auch direkt ausgeliefert wird.

Mit einem Commit bei bspw. Git kann man dann quasi den ganzen Automatismus triggern, der dafür sorgt, dass bei Docker der Container mit einem neuen Image neu gestartet wird.
Wäre also grundlegend empfehlenswert, sich mal sowas wie gitlab aufzubauen und damit dann solche Änderungen zu verwalten?
 
Ungetestet, sollte aber funktionieren:

docker-compose.yml:

Code:
version: "3"
services:
  wordpress:
    image: wordpress:latest
    restart: on-failure:1
    depends_on: db
    stdin_open: true
    tty: true
    ports:
      - 80:80
    environment:
      - WORDPRESS_DB_HOST=db
      - WORDPRESS_DB_USER=wordpress
      - WORDPRESS_DB_PASSWORD=wordpress
      - WORDPRESS_DB_NAME=wordpress
    labels:
      - "com.centurylinklabs.watchtower.enable=true"
  db:
    image: mariadb:latest
    restart: on-failure:1
    environment:
      - MYSQL_ROOT_PASSWORD=somewordpress
      - MYSQL_DATABASE=wordpress
      - MYSQL_USER=wordpress
      - MYSQL_PASSWORD=wordpress
    expose:
      - 3306
      - 33060
    volumes:
      - db_data
    labels:
      - "com.centurylinklabs.watchtower.enable=true"
volumes:
    db_data:

docker compose down
docker compose up -d

have fun
 
Oh je, dann hast du Pech gehabt.
 
Es gibt hunderte Wege die Katze zu häuten (sagt man das so? 😅).

Ich hab mir die Watchtower-Doku nochmal angesehen und es ist eher der falsche Hammer für deinen Nagel. Nach dem, was ich gelesen hab, brauchst du:

1. Eine Registry (Docker Hub oder self-hosted)
2. Einen Automatismus dein Image zyklisch zu bauen und auf die Registry zu pushen

Letzteres könnte auch ein stumpfes Shellscript sein, das per Cron gestartet wird (docker build (…) / docker-push (…) 2-3 Zeiler). Docker Hub kann auch automatische Builds, aber leider nicht in der kostenlosen Version.

Zum SCM: Bist du privat oder beruflich unterwegs? Eigentlich aber auch nicht so wichtig, heutzutage gehört für mich alles, was irgendwie nach Code riecht (oder eben auch Infrastructure as code) in Git-Repos. Spätestens nach dem ersten "verdammt, was genau hab ich letzte Woche geändert?"-Moment sieht man den Mehrwert.
GitLab kann man selbst hosten und es bringt auch gleich ne Container Registry mit, hat aber natürlich wie alle ne gewisse Lernkurve.

Generell der Tipp: keep it simple. Man hat bei sowas oft das "Not Enterprise enough"-Syndrom erhöht mit GUIs, Middleware und Automatisierungen nur unnötig die Komplexität der Sache.
 
  • Gefällt mir
Reaktionen: Corin Corvus
ChromeRonin schrieb:
Ist halt die Frage, ob 1 Image mit immer der gleichen Änderung eine Registry mit Gitlab und so wert ist.
Was Änderungen angeht (abseits von Code, eher mit Hinweisen und Links) nutze ich Obsidian. Da logge ich so gesehen jede Änderung mit inkl. Verweis.

Ich bin Privat, als auch beruflich unterwegs in dem Bereich, allerdings in beiden Feldern eher als Hoster, weniger als "ich baue mir komplett selbst container und code rum". Daher kam die Notwendigkeit einer Registry nie auf.
 
Zuletzt bearbeitet von einem Moderator:
Um eine Registry, wo du deine erstellten Images reinschiebst, wirst du halt nicht wirklich drumrum kommen, wenn du das Image nicht nur auf dem Rechner nutzen willst, auf dem es erstellt wurde.
Du kannst naturlich das Image auch erst auf dem Server bauen, auf dem dann der Container ausgeführt wird., aber dann musst du halt immer das geänderte Dockerfile auf den Server bekommen.
Außerdem weiß ich nicht, ob dann Watchtower auch funktioniert, weil das ja glaube nur in den hinterlegten Registries nach neuen Images guckt und nicht in den lokalen Images.
 
Es wurde ja nicht auf meinem Rechner erstellt, sondern auf dem Server, wo es verwendet werden soll. Nutze dort Portainer oder halt die CLI und erstelle das Image.
Wenn ich da nun manuell die Compose starte mit dem Imagenamen, geht das.
Heißt: Das Image ist lokal vorhanden und wird von Docker erkannt.
Nur Watchtower checkt das halt nicht. Das mit dem Rebuild und Cron wäre möglich, das Image würde sich also erneuern.
Aber wenn Watchtower das nicht checkt und den Container nicht aktualisiert, ist es wie gehüpft oder gesprungen, ich muss dann immer wieder manuell ran. Genau das wollte ich ja nicht mehr.


Ich glaube du hast mir gerade die Lösung mit der richtigen Frage in einer Suchmaschine bereitet: https://github.com/containrrr/watchtower/issues/416#issuecomment-1436688710

Ich probier das mal.
 
Die Registry kannst auch ohne GitLab aufsetzen, den Server hast ja schon. Wenn du keine Authentifizierung brauchst ist das nicht mehr als ein

docker run -d -p 127.0.0.1:5000:5000 -v /opt/docker/registry:/var/lib/registry --restart=always --name registry registry:2

oder per Docker Compose:

Code:
registry:
  restart: always
  image: registry:2
  ports:
    - "127.0.0.1:5000:5000"
  volumes:
    - /opt/docker/registry:/var/lib/registry

Wenn du in die docker-compose.yml deines Projekts image aufnimmst, kannst dein Image mit docker compose build bauen und mit docker compose push auf die eigene Registry schieben:

Code:
…
  build:
    context: …
  image: localhost:5000/wordpress-ldap:1.0.0
Ergänzung ()

Corin Corvus schrieb:
Ich glaube du hast mir gerade die Lösung mit der richtigen Frage in einer Suchmaschine bereitet: https://github.com/containrrr/watchtower/issues/416#issuecomment-1436688710

Ich probier das mal.
Ah! Nen Versuch ists wert 👍
 
Zuletzt bearbeitet:
  • Gefällt mir
Reaktionen: Corin Corvus
ChromeRonin schrieb:
Wenn du keine Authentifizierung brauchst ist das nicht mehr als ein
Der Server mit der Registry, oder zumindest der Port, sollte dann aber nicht öffentlich aus dem Internet erreichbar sein. Denn ohne Authentifizierung kann dir ja jeder Fremde dort gigabyteweise Images hochladen und damit den Speicherplatz vom Server vollmüllen.
 
Das sowieso nicht. Müsste ich ja so oder so in der Firewall überhaupt erst freischalten, was nicht passieren wird.

Fahre aber meist nur 1 Woche ohne Authentifizierung zu Testzwecken. Habe da immer direkt Kalendertermine, damit ich das nicht vergesse umzustellen.
 
mibbio schrieb:
Der Server mit der Registry, oder zumindest der Port, sollte dann aber nicht öffentlich aus dem Internet erreichbar sein. Denn ohne Authentifizierung kann dir ja jeder Fremde dort gigabyteweise Images hochladen und damit den Speicherplatz vom Server vollmüllen.
Korrekt, kann man auch ordentlich binden. Edit im Codeblock oben (- "127.0.0.1:5000:5000")
 
Zurück
Oben