Docker Images
Dagu publishes multiple container images to GitHub Container Registry at ghcr.io/dagucloud/dagu. All images are multi-arch (linux/amd64, linux/arm64, linux/arm/v7) and ship with the same defaults: listen on 8080, run dagu start-all, and honor PUID/PGID/DAGU_* environment variables.
Image overview
| Tag(s) | Base | Package Manager | What's inside | Use when |
|---|---|---|---|---|
latest, <version> | Ubuntu 24.04 | apt | Core runtime + ca-certificates, curl, git, jq, openssh-client, sudo, tini, tzdata, unzip | General deployments; closest to production defaults |
alpine, <version>-alpine | Alpine 3.22 | apk | Musl-based image with bash, sudo, jq, tzdata | Minimal footprint, Alpine-only environments |
dev, <version>-dev | Ubuntu 24.04 | apt | Adds build tools (git, curl/wget, zip/unzip, build-essential, python3/pip, openjdk-17, nodejs/npm, jq, tzdata) | Local development or workflows that need compilers/SDKs baked in |
Prefer pinning to a specific version tag (
ghcr.io/dagucloud/dagu:<version>) for reproducible deployments.
Entrypoint and Process Reaping
Official images start with Tini as PID 1:
/usr/local/bin/tini -g -- /entrypoint.sh dagu start-allKeep that entrypoint unless there is a specific reason to replace it. Tini reaps orphaned child processes and forwards stop signals to Dagu. Without an init process, a workflow step that starts a background subprocess can leave a zombie process in the container.
/entrypoint.sh prepares DAGU_HOME, applies PUID/PGID, runs optional init scripts, and then starts the requested Dagu command.
When changing how the container starts:
- Docker Compose: use
command: ["dagu", "..."]; do not useentrypoint: []orentrypoint: ["dagu", ...]. - Kubernetes: use
args: ["dagu", "..."]; do not usecommand:unless the replacement command keeps an init process. - Docker socket/root mode: if
/entrypoint.shmust be bypassed, keep Tini withentrypoint: ["/usr/local/bin/tini", "-g", "--"].
Examples
Standard image:
docker run -d -p 8525:8080 -v dagu-data:/var/lib/dagu ghcr.io/dagucloud/dagu:latestAlpine image:
docker run -d -p 8525:8080 -v dagu-data:/var/lib/dagu ghcr.io/dagucloud/dagu:alpineDev image with extra tooling:
docker run -d -p 8525:8080 -v dagu-data:/var/lib/dagu ghcr.io/dagucloud/dagu:devFor container steps, use the socket-enabled Docker setup. It preserves Tini while running Dagu with access to the host daemon and explains the resulting host-level privilege.
Custom Images
If your workflows require additional tools (Python, Perl, Ruby, etc.) not included in the standard images, build a custom image based on Dagu:
FROM ghcr.io/dagucloud/dagu:latest
# Install additional packages
RUN apt-get update && apt-get install -y \
python3 \
python3-pip \
perl \
&& rm -rf /var/lib/apt/lists/*
# Install Python packages if needed
RUN pip3 install --break-system-packages requests pandasBuild and run:
docker build -t my-dagu .
docker run -d -p 8080:8080 -v dagu-data:/var/lib/dagu my-daguBuild Arguments
All Dockerfiles accept the following build arguments to customize the container user and data directory:
| Argument | Default | Description |
|---|---|---|
USER | dagu | Username for the in-container user |
USER_UID | 1000 | UID for the in-container user |
USER_GID | $USER_UID | GID for the in-container user |
DAGU_HOME | /var/lib/dagu | Data directory where Dagu stores its state |
Match the container UID/GID to your host user so that bind-mounted files have the correct ownership:
docker build \
--build-arg USER_UID="$(id -u)" \
--build-arg USER_GID="$(id -g)" \
-t my-dagu .
