Skip to content

dargstack/dargstack

Repository files navigation

dargstack

Docker Swarm, made simple. Dev-first deployments, production overlays, built-in audit trail.

dargstack is a CLI tool and project structure specification that reduces Docker Swarm complexity to a minimal command set. Define your development setup as the base, express production as incremental changes on top.

dargstack does not replace docker stack. You can interact with docker stack on the same stack that you manage with dargstack.


The following projects successfully employ dargstack in production:


Migrating from v3? See MIGRATION.md. Contributing? See CONTRIBUTING.md.


Table of Contents


Why dargstack?

Deploying the same app to development and production with Docker Swarm usually means maintaining two nearly identical compose files. Change one thing? Manually copy, edit, hope nothing breaks.

dargstack inverts this: define development as the source of truth, then express production as changes on top. One deploy command. One audit trail. Done.

dargstack docker stack
βœ… A single resource and diff specification ❌ Two compose files for dev and prod – risk of configuration drift
βœ… Clear file separation by service ❌ Monolithic compose file – hard to maintain if big
βœ… Snapshot for every deploy; easy inspect and diff ❌ Volatile audit trail – live console tracing only
βœ… Safer secret management with auto-generation and templating ❌ Manual secret management – tedious, often insecure defaults
βœ… Development certificates auto-generated ❌ No TLS certificates – out of scope, traffic unencrypted
βœ… Zero downtime service update motivation ❌ Stop-first update order by default – unreliable availability in production

Install

Recommended β€” From GitHub Releases

ARCHIVE="dargstack_$(uname -s | tr '[:upper:]' '[:lower:]')_$(uname -m | sed -e 's/x86_64/amd64/' -e 's/aarch64/arm64/').tar.gz"
curl -sfL -o "$ARCHIVE" "https://github.com/dargstack/dargstack/releases/latest/download/$ARCHIVE"
curl -sfL https://github.com/dargstack/dargstack/releases/latest/download/checksums.txt | sha256sum -c - --ignore-missing
tar xzf "$ARCHIVE" && rm "$ARCHIVE"
sudo mv dargstack /usr/local/bin/

Alternative β€” From Source

Prerequisite – Go installed, see go.dev: Download and install.

go install github.com/dargstack/dargstack/v4/cmd/dargstack@latest

Package integrity is enforced by the Go module proxy and the module's go.sum lockfile. Pin to a specific version (e.g., @v4.1.0) for a reproducible, auditable install.

Quick Start

Prerequisite – Docker installed, see docs.docker.com: Install Docker Engine.

  1. Initialize a new dargstack project:

    dargstack initialize
  2. Fill in your service configuration according to the docker.com: Compose file reference.

  3. Deploy:

    cd <project_name>
    dargstack deploy

Done! πŸŽ‰ Your stack is live.

Core Concepts

Suppose you have an api service as part of an example project:

example/
β”œβ”€β”€ api/                                # The service's source code
β”‚   β”œβ”€β”€ Dockerfile                      # Dockerfile for the api service
β”‚   └── ...
β”œβ”€β”€ stack/
β”‚   β”œβ”€β”€ artifacts/                      # Generated files
β”‚   β”‚   β”œβ”€β”€ audit-log/                  # Deployment snapshots (gitignored)
β”‚   β”‚   β”œβ”€β”€ certificates/               # Local TLS certificates (gitignored)
β”‚   β”‚   β”œβ”€β”€ docs/
β”‚   β”‚   β”‚   └── README.md               # Generated stack documentation
β”‚   β”‚   β”œβ”€β”€ .gitignore
β”‚   β”‚   └── README.md                   # Explains artifacts folder contents
β”‚   β”œβ”€β”€ src/
β”‚   β”‚   β”œβ”€β”€ development/
β”‚   β”‚   β”‚   β”œβ”€β”€ api/
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ compose.yaml        # Full Docker Compose document
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ configuration.toml  # File-based volume mount
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ key.secret          # Secret used by the service
β”‚   β”‚   β”‚   β”‚   └── ...
β”‚   β”‚   β”‚   └── .env                    # Environment variables
β”‚   β”‚   └── production/
β”‚   β”‚       β”œβ”€β”€ api/
β”‚   β”‚       β”‚   β”œβ”€β”€ compose.yaml        # YAML deep-merge override
β”‚   β”‚       β”‚   β”œβ”€β”€ configuration.toml  # File-based override
β”‚   β”‚       β”‚   └── ...
β”‚   β”‚       └── .env                    # Key-based override
β”‚   └── dargstack.yaml                  # Project configuration
└── ...

Service Files

Each service file is a full Docker Compose document β€” files are deep-merged by spruce. See github.com: What are all the Spruce operators? for special keywords controlling merge behavior.

# src/development/api/compose.yaml
services:
  api:
    image: api:latest
    ports:
      - "3000:3000"
    secrets:
      - api-key
    deploy:
      labels:
        - (( append ))
        - dargstack.development.build=../../../../api
        - traefik.http.routers.api.rule=Host(`api.${STACK_DOMAIN}`)
        - traefik.http.routers.api.tls=true
        - traefik.http.services.api.loadbalancer.server.port=8080
        - some.label=for-development # dargstack:dev-only
    user: (( prune ))

secrets:
  api-key:
    file: ./key.secret

x-dargstack:
  secrets:
    api-key:
      length: 32
      special_characters: false

Key rules:

  • Each service file has a services: top-level key
  • Secrets, volumes, networks, and configs are declared in the same file as the service that uses them
  • Production files contain only differences from development:
# src/production/api/compose.yaml
services:
  api:
    image: ghcr.io/myorg/api:v1.0.0
    deploy:
      replicas: 3
      update_config:
        parallelism: 1
        order: start-first # Zero-downtime (use stop-first for stateful services)

Git Cloning

The dargstack.development.git.ssh and dargstack.development.git.https labels instruct dargstack to clone a git repository before building a service's Docker image. The repository is cloned to a sibling directory of the stack, named after the repository:

services:
  webapp:
    deploy:
      labels:
        dargstack.development.git.ssh: "git@github.com:mystack/webapp.git"
    image: mystack/webapp:development

This clones webapp.git to a webapp/ directory next to the stack directory, and automatically sets the build context to that directory. You can override the build context with dargstack.development.build to point to a subdirectory:

services:
  webapp:
    deploy:
      labels:
        dargstack.development.git.ssh: "git@github.com:mystack/webapp.git"
        dargstack.development.git.https: "https://github.com/mystack/webapp.git"
        dargstack.development.build: "../../../../repository/packages/frontend"
    image: mystack/webapp:development

The SSH URL is used as the primary clone URL, with the HTTPS URL as a fallback. Providing both ensures cloning works regardless of network restrictions. The repository is cloned once (on first deploy) and left untouched on subsequent deploys.

Configuration: dargstack.yaml

metadata:
  compatibility: ">=4.0.0 <5.0.0" # required, string (semver range)
  name: my-stack # optional, defaults to parent directory name
  source: # optional
    name: my-repo
    url: https://github.com/org/repo
  external_services: # optional
    status:
      description: Service status dashboard

runtime:
  sudo: auto # optional, `auto` | `always` | `never`
  build:
    mode: always # optional, `always` | `missing`
  deploy:
    volumes:
      prompt: true # optional, prompt to remove volumes on first deploy

environment:
  development:
    domain: app.localhost # optional, defaults to "app.localhost"
    certificate:
      include: [] # optional, domains added to TLS cert
      exclude: [] # optional, domains removed from TLS cert
  production:
    branch: main # optional, defaults to "main"
    domain: app.localhost # optional, defaults to "app.localhost"
    tag: latest # optional, `latest` | string

Profiles & Performance

Deploy named groups of services to save resources:

# src/development/adminer/compose.yaml
services:
  adminer:
    image: adminer
    deploy:
      labels:
        dargstack.profiles: db # Only deployed with --profiles db

Multiple profiles: dargstack.profiles: "db,monitoring" (comma-separated).

Profiles can also be activated via the COMPOSE_PROFILES environment variable (comma-separated). The --profiles flag takes precedence over COMPOSE_PROFILES.

If no profile selection is made and any service declares default, only services with dargstack.profiles: default are deployed; unlabeled services are excluded. If no profile selection is made and no service declares default, all services (including unlabeled) are deployed.

When one or more profiles are explicitly activated with --profiles, only services whose dargstack.profiles intersect the active profile set are deployed. Services without a dargstack.profiles label are deployed only if the special unlabeled profile is explicitly activated (for example: --profiles unlabeled or --profiles db --profiles unlabeled).

Secret Templating

Define secrets with generation settings and template resolution:

x-dargstack:
  secrets:
    postgres-password:
      type: random_string
      length: 32
      special_characters: true
    jwt-signing-key.secret:
      type: private_key
      key_type: ed25519
    external-api-token:
      type: third_party
      hint: "Get yours at https://example.com/settings/tokens"
    dev-only-secret:
      type: insecure_default
      insecure_default: "CHANGE_ME"
    api-db_url:
      type: template
      template: "postgresql://postgres:{{secret:postgres-password}}@postgres:5432/app"

type controls secret behavior. Supported values: random_string, wordlist_word, private_key, third_party, insecure_default, template. If omitted, the type is inferred from the fields provided:

  • private_key if key_type or key_size is set
  • third_party if third_party is set
  • template if template is set
  • insecure_default if insecure_default is set
  • random_string if length or special_characters is set

random_string properties:

  • length β€” Random string length (default: 32)
  • special_characters β€” Include special characters (default: true; set false to opt out)

private_key properties:

  • key_type β€” Key algorithm: ed25519 (default), rsa, ecdsa
  • key_size β€” Key size: RSA default 2048; ECDSA 256 (P-256), 384 (P-384), 521 (P-521)

third_party properties:

  • hint β€” Human-readable hint for expected value (shown when the secret is unset)

insecure_default properties:

  • insecure_default β€” Default value used for the secret

template properties:

  • template β€” Template string, supporting the following tokens:
    • {{secret:<name>}} (or legacy {{<name>}}) β€” Reference another secret
    • {{random_string}}, {{random_string:<length>}}, {{random_string:<length>:<special>}} β€” Inline random generation
    • {{wordlist_word}} β€” Inline word generation
    • {{private_key}} β€” Inline private key generation

Environment Files

.env files use KEY=VALUE format. During deploy, missing values are prompted. Production blocks on missing values.

Platform Overrides

dargstack is linux-first. When running on macOS, some compose configurations are invalid or undesirable: volume mounts referencing Linux-only paths (/dev/disk/by-id/, /dev/kmsg), privileged: true where not needed, or services like cadvisor that depend on Linux kernel features.

Platform overrides live under x-dargstack.platform.<os> and use spruce operators to modify the base configuration. Supported platforms: darwin, linux, windows.

services:
  cadvisor:
    image: gcr.io/cadvisor/cadvisor:v0.50.0
    volumes:
      - /:/rootfs:ro
      - /var/run:/var/run:ro
      - /sys:/sys:ro
      - /var/lib/docker/:/var/lib/docker:ro
      - /dev/disk/by-id/:/dev/disk/by-id:ro
    devices:
      - /dev/kmsg
    privileged: true

x-dargstack:
  platform:
    darwin:
      services:
        cadvisor:
          volumes:
            - (( prune ))
            - /:/rootfs:ro
            - /var/run:/var/run:ro
            - /sys:/sys:ro
          devices:
            - (( prune ))
          privileged: false

Multiple platforms can coexist in one file. The active platform is auto-detected via runtime.GOOS, or overridden with --platform darwin.

Commands

Command Description
dargstack audit View deployment audit log
dargstack build Build development Dockerfiles
dargstack certify Generate TLS certificates
dargstack clone Clone an existing dargstack project
dargstack deploy Deploy the stack
dargstack document Generate the stack documentation
dargstack initialize Bootstrap a new dargstack project
dargstack profiles List discovered deploy profiles
dargstack remove Remove the deployed stack
dargstack secret Manage stack secrets
dargstack update Update dargstack to the latest version
dargstack validate Validate stack resources

See docs/dargstack.md for global flags and detailed command documentation.


Licensed under GPLv3.

Releases

Sponsor this project

Packages

Used by

Contributors

Languages