Docker

Des jobs conteneurisés planifiés, sans adopter Kubernetes pour autant.

Si votre équipe utilise Docker mais pas Kubernetes, un job conteneurisé planifié n'a nulle part où aller. Dagu est un binaire unique qui pilote le démon Docker dont vous disposez déjà et ajoute aux conteneurs dépendances, reprises, journaux et interface web.

Ni Kubernetes ni plateforme de conteneurs requis
Les étapes partagent un conteneur, ou chacune apporte son image
Exec dans les conteneurs que votre stack compose fait déjà tourner
Podman fonctionne via la même API compatible Docker
01

L'écart entre docker run et Kubernetes CronJob

Planifier un conteneur est le moment où les bonnes options s'épuisent. Kubernetes CronJob est la réponse mature, à condition d'avoir déjà un cluster. En dessous, la réponse habituelle est un cron qui appelle docker run, et rien d'autre.

  • cron plus docker run n'offre ni reprise, ni dépendance entre jobs, ni historique, ni moyen de voir pourquoi la nuit dernière a échoué
  • Adopter Kubernetes pour planifier un rapport nocturne, c'est beaucoup de plateforme pour peu de job
  • Un orchestrateur généraliste qui traite les conteneurs comme un type d'étape, et non comme la cible de déploiement, occupe exactement cet entre-deux
02

Un seul conteneur pour tout le workflow

Déclarer un conteneur au niveau du workflow fait tourner toutes les étapes dans le même conteneur persistant. Elles partagent le système de fichiers : ce qu'une étape installe reste disponible pour la suivante.

  • Installer les dépendances une fois et les réutiliser entre étapes, sans reconstruire d'image ni réinstaller par tâche
  • Monter des chemins hôte avec volumes et définir les variables d'environnement une fois pour tout le workflow
  • Reprises, dépendances et gestion des échecs restent des champs de workflow ordinaires, indépendamment du conteneur

Dans ce mode les étapes passent par docker exec : l'ENTRYPOINT et le CMD de l'image ne sont pas utilisés pour les commandes d'étape. Mettez la commande dans l'étape.

Un job nocturne entièrement dans une image
# nightly-report.yaml
schedule: "0 3 * * *"
max_active_runs: 1

container:
  image: python:3.12
  volumes:
    - ./data:/data
  env:
    - TZ=Asia/Tokyo

steps:
  - id: install
    run: pip install -r /data/requirements.txt

  - id: build_report
    run: python /data/build_report.py
    depends: install
    retry_policy:
      limit: 2
      interval_sec: 120

  - id: publish
    run: python /data/publish.py
    depends: build_report

mail_on:
  failure: true
03

Faire la maintenance dans les conteneurs déjà en marche

Le mode exec pointe un workflow vers un conteneur déjà en cours d'exécution, par exemple lancé par Docker Compose. Le travail planifié se déroule dans le conteneur applicatif réel, pas dans une copie neuve.

  • Migrations de base, vidage de cache et maintenance de files s'exécutent contre le service réellement en marche
  • Nommer le conteneur sous forme de chaîne constitue toute la configuration
  • Le workflow conserve dépendances et notification d'échec, ce qu'un fichier compose ne sait pas exprimer
Maintenance planifiée sur un service compose en marche
# app-maintenance.yaml
schedule: "0 4 * * *"
max_active_runs: 1

# docker compose で起動済みのコンテナに exec する
container: myapp-web

steps:
  - id: migrate
    run: php artisan migrate --force

  - id: prune_sessions
    run: php artisan session:prune
    depends: migrate

  - id: clear_cache
    run: php artisan cache:clear
    depends: prune_sessions

mail_on:
  failure: true
04

Une image différente par étape

Quand un pipeline traverse plusieurs outils, chaque étape peut apporter son image. Le workflow reste un fichier et un planning, les étapes restent indépendantes.

  • Extraire avec une image cliente de base, transformer avec une image de langage, charger avec un autre client, sans image contenant les trois
  • Un conteneur au niveau étape prime sur celui du workflow, ce qui autorise des exceptions dans un workflow presque uniforme
  • La politique de pull d'image se règle par étape, pour les images figées comme pour celles reconstruites souvent
Un workflow, trois images
# etl-pipeline.yaml
schedule: "0 2 * * *"
max_active_runs: 1

steps:
  - id: extract
    container:
      image: mysql:8
      volumes:
        - ./work:/work
    run: mysqldump --host db.internal -u svc app > /work/dump.sql

  - id: transform
    container:
      image: python:3.12
      volumes:
        - ./work:/work
    run: python /work/transform.py
    depends: extract

  - id: load
    container:
      image: postgres:16
      volumes:
        - ./work:/work
    run: psql -h dw.internal -f /work/out.sql
    depends: transform

handler_on:
  failure:
    run: ./scripts/notify-failure.sh

mail_on:
  failure: true
05

Ce que cela demande à l'hôte

Les étapes conteneurisées dialoguent avec une API compatible Docker. C'est la seule exigence, et aussi la contrainte à connaître avant de planifier un déploiement.

  • Un socket Docker local ou un démon distant via DOCKER_HOST fonctionnent tous deux
  • Podman est pris en charge via son API compatible Docker en définissant DAGU_CONTAINER_RUNTIME=podman
  • Comme Dagu est un binaire unique, l'ordonnanceur lui-même n'exige ni cluster, ni base de métadonnées, ni broker

Les instances gérées de Dagu Cloud tournent avec l'isolation gVisor et n'exposent aucun socket de démon de conteneurs : les étapes conteneurisées n'y sont pas disponibles. Utilisez Dagu auto-hébergé, ou routez le workflow vers un worker auto-hébergé.

06

Là où Kubernetes reste la bonne réponse

Cette page plaide pour un outil plus petit dans une situation précise, pas pour éviter Kubernetes en général.

  • Si vous exploitez déjà un cluster, CronJob est un endroit raisonnable pour des conteneurs planifiés et n'ajoute rien de nouveau
  • Si les jobs exigent un ordonnancement au niveau des pods, de l'autoscaling ou du bin-packing entre nœuds, c'est le travail d'un cluster, pas d'un orchestrateur
  • Pour les workflows qui soumettent du travail à un cluster tout en gardant l'orchestration à l'extérieur, Dagu propose une étape Kubernetes

FAQ

Practical questions before adopting

Faut-il Kubernetes pour exécuter des jobs conteneurisés planifiés ?

Non. Dagu dialogue directement avec un démon compatible Docker : un seul hôte avec Docker suffit. Kubernetes devient utile quand vous avez besoin d'ordonnancement et de mise à l'échelle au niveau du cluster, pas simplement pour lancer un conteneur à 3h.

En quoi est-ce différent de l'opérateur Docker d'Airflow ?

Surtout par le coût d'exploitation. Airflow exige un ordonnanceur, une base de métadonnées et un framework DAG Python avant de lancer un conteneur. Dagu est un binaire unique à état sur fichiers, et les conteneurs sont un champ du workflow ou de l'étape plutôt qu'un opérateur Python.

Les étapes peuvent-elles partager des fichiers ?

Oui. Avec un conteneur au niveau du workflow, les étapes tournent dans le même conteneur et partagent directement son système de fichiers. Avec des images par étape, montez un chemin hôte commun dans chaque étape.

Podman fonctionne-t-il ?

Oui, via l'API compatible Docker de Podman. Définissez DAGU_CONTAINER_RUNTIME=podman sur un déploiement auto-hébergé et les étapes conteneurisées se comportent de la même façon.

Puis-je exécuter une étape dans un conteneur lancé par Docker Compose ?

Oui, c'est le mode exec. Nommez le conteneur en cours d'exécution et les étapes du workflow s'exécutent dedans. Les migrations planifiées et la maintenance de cache sur une stack compose vivante se câblent généralement ainsi.

Next step

Start with one workflow.

Install Dagu, move one script that runs on cron today into YAML, and decide from a real run history.