Loading...
Sag Auf Wiedersehen zu Docker Volumes

Sag Auf Wiedersehen zu Docker Volumes

Jonas Scholz - Co-Founder von sliplane.ioJonas Scholz
6 min

Hast du jemals versucht, Docker Volumes für Hot-Reloading in deiner Web-App zu verwenden? Wenn du die gleiche schreckliche Erfahrung wie ich gemacht hast, wirst du das neueste Feature lieben, das Docker gerade veröffentlicht hat: docker-compose watch! Lass mich dir zeigen, wie du dein bestehendes Projekt aufwertest, um ein wunderbares Docker-Dev-Setup zu haben, das dein Team tatsächlich gerne nutzen wird 🤩

TL;DR: Schau dir diese docker-compose Datei und die offizielle Dokumentation an

Lass uns loslegen!

spinning monke

Einführung

Docker hat gerade Docker Compose Watch mit Docker Compose Version 2.22 veröffentlicht. Mit diesem neuen Feature kannst du docker-compose watch anstelle von docker-compose up verwenden und automatisch deinen lokalen Quellcode mit dem Code in deinem Docker-Container synchronisieren, ohne Volumes verwenden zu müssen!

Schauen wir uns an, wie das in einem echten Projekt funktioniert, indem wir ein Projekt verwenden, über das ich zuvor geschrieben habe.

In diesem Projekt habe ich ein Monorepo mit einem Frontend, Backend und einigen zusätzlichen Bibliotheken für die UI und Datenbank.

├── apps
│   ├── api
│   └── web
└── packages
    ├── database
    ├── eslint-config-custom
    ├── tsconfig
    └── ui

Beide Apps (api und web) sind bereits dockerisiert und die Dockerfiles befinden sich im Root des Projekts (1, 2)

Die docker-compose.yml Datei würde so aussehen:

services:
  web:
    build:
      dockerfile: web.Dockerfile
    ports:
      - "3000:3000"
    depends_on:
      - api
  api:
    build:
      dockerfile: api.Dockerfile
    ports:
      - "3001:3000"from within the Docker network

Das ist schon ziemlich gut, aber wie du bereits weißt, ist es nervig, damit während der Entwicklung zu arbeiten. Du musst deine Docker-Images neu bauen, wann immer du deinen Code änderst, obwohl deine Apps wahrscheinlich Hot-Reloading von Haus aus unterstützen (oder mit etwas wie Nodemon, wenn nicht).

Um das zu verbessern, führt Docker Compose Watch ein neues Attribut namens watch ein. Das watch-Attribut enthält eine Liste von sogenannten Regeln, die jeweils einen Pfad enthalten, den sie beobachten, und eine Aktion, die ausgeführt wird, sobald sich eine Datei in dem Pfad ändert.

Sync

Wenn du einen Ordner zwischen deinem Host und deinem Container synchronisiert haben möchtest, würdest du hinzufügen:

services:
  web: # gekürzt der Übersichtlichkeit halber
    build:
      dockerfile: web.Dockerfile
    develop:
      watch:
        - action: sync
          path: ./apps/web
          target: /app/apps/web

Wann immer sich eine Datei auf deinem Host im Pfad ./apps/web/ ändert, wird sie zu deinem Container nach /app/apps/web synchronisiert (kopiert). Das zusätzliche app im Zielpfad ist erforderlich, weil dies unser WORKDIR ist, das im Dockerfile definiert ist. Das ist das Hauptding, das du wahrscheinlich verwenden wirst, wenn du hot-reloadable Apps hast.

Rebuild

Wenn du Apps hast, die kompiliert werden müssen oder Dependencies, die du neu installieren musst, gibt es auch eine Aktion namens rebuild. Anstatt einfach die Dateien zwischen dem Host und dem Container zu kopieren, wird es den Container neu bauen und neustarten. Das ist super hilfreich für deine npm-Dependencies! Lass uns das hinzufügen:

services:
  web: # gekürzt der Übersichtlichkeit halber
    build:
      dockerfile: web.Dockerfile
    develop:
      watch:
        - action: sync
          path: ./apps/web
          target: /app/apps/web
        - action: rebuild
          path: ./package.json
          target: /app/package.json

Wann immer sich unsere package.json ändert, werden wir jetzt unser gesamtes Dockerfile neu bauen, um die neuen Dependencies zu installieren.

Sync+Restart

Neben nur Synchronisieren und Neubauen gibt es auch etwas dazwischen namens sync+restart. Diese Aktion wird zuerst die Verzeichnisse synchronisieren und dann sofort deinen Container neustarten, ohne neu zu bauen. Die meisten Frameworks haben normalerweise Konfigurationsdateien (wie next.config.js), die nicht hot-reloaded werden können (nur sync reicht nicht aus), aber auch keinen langsamen Rebuild benötigen.

Das würde deine compose-Datei zu diesem ändern:

services:
  web: # gekürzt der Übersichtlichkeit halber
    build:
      dockerfile: web.Dockerfile
    develop:
      watch:
        - action: sync
          path: ./apps/web
          target: /app/apps/web
        - action: rebuild
          path: ./package.json
          target: /app/package.json
        - action: sync+restart
          path: ./apps/web/next.config.js
          target: /app/apps/web/next.config.js

Nachteile

Wie immer gibt es kein kostenloses Mittagessen und ein paar Nachteile 😬

Das größte Problem mit dem neuen watch-Attribut ist, dass die Pfade noch sehr grundlegend sind. Die Dokumentation besagt, dass Glob-Muster noch nicht unterstützt werden, was zu einer riesigen Anzahl von Regeln führen kann, wenn du spezifisch sein willst.

Hier sind einige Beispiele, was funktioniert und was nicht:

apps/web Das wird alle Dateien in ./apps/web matchen (z.B. ./apps/web/README.md, aber auch ./apps/web/src/index.tsx)

build/**/!(*.spec|*.bundle|*.min).js Globs werden leider (noch?) nicht unterstützt

~/Downloads Alle Pfade sind relativ zum Projektstamm!

Nächste Schritte

Wenn du immer noch nicht zufrieden mit deinem Docker-Setup bist, gibt es noch viele Möglichkeiten, es zu verbessern!

Zusammenarbeit ist ein großer Teil der Softwareentwicklung und in Silos zu arbeiten kann deinem Team ernsthaft schaden. Langsame Docker-Builds und komplizierte Setups helfen nicht! Um dem entgegenzuwirken und eine Kultur der Zusammenarbeit zu fördern, kannst du Docker-Erweiterungen wie Livecycle verwenden, um deine lokalen docker-compose Apps sofort mit deinen Teamkollegen zu teilen. Da du bereits Docker und docker-compose verwendest, musst du nur die Docker Desktop Extension installieren und auf den Share-Toggle klicken. Deine Apps werden dann ins Internet getunnelt und du kannst deine einzigartige URL mit deinem Team teilen, um Feedback zu bekommen! Ich habe mehr darüber in diesem Post geschrieben, wenn du mehr Anwendungsfälle von Livecycle auschecken willst :)

Stelle wie immer sicher, dass dein Dockerfile Best Practices folgt, besonders bei Multi-Stage-Builds und Caching. Obwohl das das Schreiben des anfänglichen Dockerfiles schwieriger machen könnte, wird es deine Docker-Apps während der Entwicklung viel angenehmer zu verwenden machen.

Eine grundlegende .dockerignore-Datei zu erstellen und die Dependency-Installation vom Code-Building zu trennen, bringt viel!

Fazit

Wie immer hoffe ich, dass du heute etwas Neues gelernt hast! Lass mich wissen, wenn du Hilfe beim Einrichten deines Docker-Projekts brauchst oder wenn du anderes Feedback hast

Cheers, Jonas Co-Founder sliplane.io

Willkommen in der Container-Cloud

Sliplane macht es einfach, Container in der Cloud zu deployen und bei Bedarf zu skalieren. Probier es jetzt aus!