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 includingRunContainer, slot validation, and the deployment sequence.registry/registry.go: Defines theRegistryinterface and implementations for OCI, S3, and GitHub Releases, providing theCurrentmethod for metadata retrieval.artifact/oci.go: Implements theOCIartifact type with theDownloadmethod that triggers the actualdocker pullcommand.container/docker.go: Provides the Docker runtime implementation with robust pull logic including authentication retry and blue/green deployment indeployContainerInternal.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
--registrypoints to an OCI image using theimg://scheme.--slotensures 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(...).Currentand pulls images usingOCI.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
--slotflag enables blue/green deployments by validating artifact metadata before deployment indewy.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
BeforeDeployHookandAfterDeployHookfor 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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →