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) and Chromium for browser steps | Local development, browser steps, or workflows that need compilers/SDKs baked in |
Only the dev image includes a browser: Playwright's Chromium on amd64 and arm64, in releases newer than v2.17.0. The arm/v7 dev image has no browser.
Chromium keeps its sandbox, which Docker's default seccomp profile blocks. The image carries a profile that lets the sandbox start, and the Compose setup in deploy/docker/browser applies it together with a 1 GB /dev/shm:
mkdir dagu-browser && cd dagu-browser
curl -fsSLO https://raw.githubusercontent.com/dagucloud/dagu/main/deploy/docker/browser/compose.yaml
docker run --rm ghcr.io/dagucloud/dagu:dev cat /usr/share/dagu/seccomp-chromium.json > seccomp-chromium.json
docker compose up -dOpen http://localhost:8080 and create the first admin account. Both examples listen on localhost only, because the first visitor creates the admin account. With docker run, pass the same two options:
docker run -d -p 127.0.0.1:8080:8080 -v dagu-data:/var/lib/dagu \
--security-opt seccomp=./seccomp-chromium.json --shm-size=1g \
ghcr.io/dagucloud/dagu:devThe profile is Docker's default profile plus the clone, setns, and unshare calls the sandbox needs. It applies to every process in the container, not only Chromium, so use it only when you trust the DAG steps in that container. Do not add apparmor=unconfined: on hosts that restrict unprivileged user namespaces, such as Ubuntu 24.04, it stops the sandbox from starting. Without the profile, a browser step fails at launch.
Where the sandbox cannot start, for example in a cluster that does not accept a custom seccomp profile, set DAGU_BROWSER_SANDBOX=false to turn it off; see Browser requirements.
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 .
