How Dewy's Pull-Based Deployment Works: A Complete Technical Guide

Dewy's pull-based deployment fetches Docker images from registries using Dewy.RunContainer, validates slot metadata, authenticates with the registry, and executes zero-downtime blue/green rollouts through Docker or Podman runtimes.

Dewy is an open-source deployment tool written in Go that implements a pull-based model for containerized applications. Unlike push-based systems that require external triggers, Dewy actively queries registries for new artifacts and pulls them to the target host, ensuring the latest version is always running.

The Pull-Based Deployment Workflow

The deployment process orchestrated by Dewy.RunContainer in dewy.go follows a strict sequence to ensure reliable container updates.

Step 1: Fetching Artifact Metadata from the Registry

Dewy begins by contacting the configured registry (OCI, S3, GitHub Releases, etc.) via registry.New(...).Current. The response contains the image URL, tag, digest, and optional slot (blue/green) information.

In registry/registry.go (lines 29-45), the Current method retrieves this metadata, which serves as the source of truth for the deployment.

Step 2: Slot Filtering for Blue/Green Deployments

If the user supplied a --slot flag, Dewy checks the artifact's Slot field and aborts the deployment when it does not match. This logic in dewy.go (lines 85-92) ensures that only artifacts built for the specific environment (e.g., "blue" or "green") are deployed.

Step 3: Resolving the Image Reference

The URL returned by the registry has the form img://registry/repo:tag. Dewy strips the img:// prefix in dewy.go (lines 94-96) to obtain a Docker-compatible image reference that can be passed to the container runtime.

Step 4: Creating the OCI Artifact Object

artifact.New selects the appropriate implementation based on the URL scheme. For OCI images, it returns an OCI struct as defined in artifact/artifact.go (lines 31-38). This abstraction allows Dewy to handle different artifact types uniformly.

Step 5: Pulling the Image with Docker or Podman

OCI.Download executes docker pull (or podman pull via the runtime) to fetch the image into the local daemon's store. The implementation in artifact/oci.go (lines 36-44) first verifies that the Docker binary exists, then executes the pull command and logs the result.

Step 6: Executing Pre-Deploy Hooks and Notifications

After a successful pull, Dewy sends a "pull notification" and runs any user-specified before-deploy hook. This occurs in dewy.go (lines 43-55), allowing users to perform health checks or database migrations before the new container goes live.

Step 7: Deploying the Container with Runtime Abstraction

Dewy.deployContainer, called from RunContainer in dewy.go (lines 56-64), uses the selected runtime (Docker or Podman). The runtime first checks whether the image already exists locally, then proceeds with the deployment.

Step 8: Blue/Green Rollout Strategy

If a slot is defined, the new container starts with a temporary alias while the old one remains running. The alias switches atomically to complete the zero-downtime deployment. This logic resides in deployContainerInternal within the runtime implementations, specifically in container/docker.go (lines 340-460).

Step 9: Reporting Deployment Status

After the rollout completes, Dewy calls registry.Report to inform the upstream registry about the deployment outcome. This final step in dewy.go (lines 79-87) closes the feedback loop, allowing registries to track which versions are running in production.

Key Implementation Details in the Dewy Source Code

The pull-based deployment relies on several critical components within the linyows/dewy repository:

  • dewy.go: Contains the main orchestration logic including RunContainer, slot validation, and the deployment sequence.
  • registry/registry.go: Defines the Registry interface and implementations for OCI, S3, and GitHub Releases, providing the Current method for metadata retrieval.
  • artifact/oci.go: Implements the OCI artifact type with the Download method that triggers the actual docker pull command.
  • container/docker.go: Provides the Docker runtime implementation with robust pull logic including authentication retry and blue/green deployment in deployContainerInternal.
  • container/podman.go: Offers equivalent functionality for Podman users, maintaining the same pull-based deployment interface.

Practical Examples of Pull-Based Deployment

CLI Deployment with Slot Specification

Deploy the latest image for the "myapp" container using the green slot for zero-downtime rollout:

dewy \
  --registry img://ghcr.io/example/myapp \
  --name myapp \
  --slot green \
  server
  • --registry points to an OCI image using the img:// scheme.
  • --slot ensures the deployment only proceeds when the artifact's build metadata matches "green", enabling blue/green deployment strategies.

Programmatic Deployment in Go

Trigger the same pull-based deployment flow programmatically using Dewy's Go API:

package main

import (
	"context"
	"log"

	"github.com/linyows/dewy"
	"github.com/linyows/dewy/config"
)

func main() {
	// Configure the deployment
	cfg := &config.Config{
		Registry:   "img://ghcr.io/example/myapp",
		Command:    config.Server,
		Container:  config.ContainerConfig{Name: "myapp"},
		Slot:       "green",
		Notifier:   "null://",
		BeforeDeployHook: "",
		AfterDeployHook:  "",
	}

	// Initialize Dewy
	d, err := dewy.New(cfg)
	if err != nil {
		log.Fatalf("init: %v", err)
	}

	// Execute the pull-based container deployment
	if err := d.RunContainer(); err != nil {
		log.Fatalf("deploy failed: %v", err)
	}
}

The RunContainer method orchestrates the complete workflow: fetching registry metadata, pulling the image, executing hooks, and performing the blue/green container swap.

Docker Runtime Pull Logic with Retry Mechanism

The Docker runtime implements robust pull logic with authentication retry and fallback to local images. This excerpt from container/docker.go demonstrates the key steps:

func (d *Docker) Pull(ctx context.Context, imageRef string) error {
	// Check local cache first
	if _, err := d.execCommandOutput(ctx, "image", "inspect", imageRef); err == nil {
		d.logger.Info("Image already exists locally, pulling to check for updates")
	}

	// Attempt registry login if not already authenticated
	reg := extractRegistry(imageRef)
	if !d.loggedInRegistries[reg] {
		_ = d.Login(ctx, reg) // Continue even if login fails
	}

	// Pull the image
	output, err := d.pullImage(ctx, imageRef)

	// Retry on authentication errors
	if err != nil && isAuthError(output) {
		delete(d.loggedInRegistries, reg)
		if loginErr := d.Login(ctx, reg); loginErr == nil {
			_, err = d.pullImage(ctx, imageRef)
		}
	}

	// Fallback to local image if pull fails but local copy exists
	if err != nil && localErr == nil {
		d.logger.Warn("Failed to pull image, but local image exists – using local version")
		return nil
	}
	return err
}

See the full implementation at Docker.Pull.

Summary

  • Pull-based architecture: Dewy actively queries registries via registry.New(...).Current and pulls images using OCI.Download, ensuring the target host always runs the latest artifact.
  • Registry abstraction: Supports OCI, S3, and GitHub Releases through a unified interface in registry/registry.go.
  • Slot-based filtering: The --slot flag enables blue/green deployments by validating artifact metadata before deployment in dewy.go.
  • Robust runtime handling: Both Docker and Podman implementations include authentication retry logic, local image fallback, and zero-downtime container swapping in deployContainerInternal.
  • Hook integration: Supports BeforeDeployHook and AfterDeployHook for custom automation during the deployment lifecycle.

Frequently Asked Questions

What makes Dewy's deployment model "pull-based"?

Dewy uses a pull-based model where the deployment agent on the target host actively queries the configured registry for new artifacts using registry.New(...).Current, rather than waiting for external push notifications. The agent then pulls the Docker image locally using docker pull or podman pull before starting the container, ensuring the host always has the latest version without requiring external orchestrators to push updates.

How does Dewy handle authentication failures during image pulls?

The Docker runtime in container/docker.go implements a resilient authentication retry mechanism. When Docker.Pull encounters an authentication error, it attempts to re-login to the registry and retries the pull operation. If the pull continues to fail but a local copy of the image exists, Dewy logs a warning and falls back to the local image, allowing deployments to proceed even during temporary registry connectivity issues.

Can Dewy deploy containers using Podman instead of Docker?

Yes, Dewy supports both Docker and Podman as container runtimes. The container/podman.go file provides equivalent functionality to container/docker.go, implementing the same pull-based deployment interface including image pulling, authentication handling, and blue/green rollout strategies. Users can configure their preferred runtime through Dewy's configuration options.

What is the purpose of the slot flag in Dewy deployments?

The --slot flag enables blue/green deployment strategies by allowing users to specify which deployment environment (e.g., "blue" or "green") should receive the update. Before deploying, Dewy checks the artifact's Slot field retrieved from the registry in dewy.go (lines 85-92). If the slot doesn't match the flag value, the deployment aborts, preventing accidental deployments to the wrong environment and enabling safe zero-downtime rollouts.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →