How to Force Docker Image Pulls Using `act --pull`

Use the act --pull flag to force nektos/act to always fetch Docker images from the registry, even when cached versions already exist locally, ensuring your workflows run with the most recent image layers.

The nektos/act CLI tool emulates GitHub Actions workflows locally using Docker containers. When executing workflow steps that reference container images, act must decide whether to reuse local copies or pull fresh updates from the registry. The act --pull flag controls this behavior explicitly, allowing you to override local caches and guarantee your local CI runs match the latest upstream environments.

Understanding the --pull Flag Behavior

By default, act sets --pull to true, meaning it attempts to pull images even if they exist locally. This ensures you do not inadvertently run stale action environments. When you explicitly use act --pull (or the shorthand -p), you affirm this behavior. Conversely, setting act --pull=false instructs act to skip network requests and use whatever images are currently available on your Docker host.

This flag becomes critical when:

  • You suspect a locally cached image tag (like ubuntu-latest) has drifted from the registry version
  • You need to verify that workflows function with the absolute latest container builds
  • You want to avoid the subtle bugs that outdated base images can introduce

Internal Implementation: How the Flag Propagates

The --pull flag travels through multiple layers of the act architecture, from CLI parsing to Docker daemon execution. Understanding this path helps diagnose pull-related issues.

CLI Flag Definition in cmd/root.go

The flag registers in cmd/root.go using Cobra, binding directly to the input.forcePull boolean:

rootCmd.Flags().BoolVarP(&input.forcePull, "pull", "p", true,
    "pull docker image(s) even if already present")

This establishes the default value of true and allows users to override it via --pull=false.

Configuration Construction

Before execution, cmd/root.go combines the flag value with the --action-offline-mode setting to produce the final ForcePull parameter:

ForcePull: !input.actionOfflineMode && input.forcePull,

This logic ensures that enabling offline mode automatically disables forced pulling, regardless of the --pull flag value.

Runner Configuration Structure

The Config struct defined in pkg/runner/runner.go carries the boolean through the application:

type Config struct {
    // ... other fields ...
    ForcePull bool // force pulling of the image, even if already present
}

Runtime Execution in RunContext

When a job initializes, the RunContext in pkg/runner/run_context.go invokes the pull logic for both service containers and the primary job container:

rc.pullServicesImages(rc.Config.ForcePull)
rc.JobContainer.Pull(rc.Config.ForcePull)

Additionally, each Docker-based step respects the flag through calls in pkg/runner/step_docker.go:

stepContainer.Pull(rc.Config.ForcePull)

Docker Pull Implementation

The actual conditional logic resides in pkg/container/docker_pull.go. The code checks the ForcePull attribute to determine whether to execute a registry fetch or inspect local image caches:

pull := input.ForcePull
if !pull {
    // try to use existing image; if not found, set pull = true
}
if !pull {
    // skip pull entirely
}
// otherwise, execute docker pull

Finally, pkg/container/docker_run.go propagates the flag to the low-level executor:

NewInfoExecutor("%sdocker pull image=%s platform=%s username=%s forcePull=%t",
    logPrefix, cr.input.Image, cr.input.Platform, cr.input.Username, forcePull)

Interaction with --action-offline-mode

The --action-offline-mode flag takes precedence over --pull. When you enable offline mode, act sets ForcePull to false internally, preventing any network requests for Docker images or action metadata.

  • act --pull (default) → Always attempts to pull images before running
  • act --pull=false → Never pulls; uses local images exclusively
  • act --action-offline-mode → Forces ForcePull=false and disables all external network calls

Use offline mode when running in air-gapped environments or when you need guaranteed reproducibility using only your local image cache.

Practical Usage Examples

Force Fresh Image Pulls

Run your workflow while explicitly ensuring all container images are current:

act --pull

Disable Pulling for Cached Runs

Speed up local iterations when you know your images are current:

act --pull=false

Complete Offline Execution

Prevent any network activity while running workflows:

act --action-offline-mode

Complex Workflow with Custom Images

Combine the pull flag with platform specifications and artifact paths:

act --pull \
    --artifact-server-path ./artifacts \
    -j build \
    -P ubuntu-latest=ghcr.io/catthehacker/ubuntu:act-22.04

Summary

  • act --pull defaults to true, ensuring fresh images by default
  • The flag propagates through cmd/root.go into the Config.ForcePull field defined in pkg/runner/runner.go
  • RunContext applies the setting to job containers, service containers, and step containers via calls in pkg/runner/run_context.go and pkg/runner/step_docker.go
  • The actual Docker client logic in pkg/container/docker_pull.go evaluates ForcePull to decide whether to skip local caches
  • --action-offline-mode overrides --pull, forcing ForcePull to false and disabling network requests entirely

Frequently Asked Questions

What is the default value of --pull in act?

According to the source code in cmd/root.go, the default value is true. This means act attempts to pull images even when they exist locally, helping prevent stale environment issues during local testing.

Does --pull affect service containers or just the main job container?

The --pull flag affects all container types. In pkg/runner/run_context.go, the ForcePull configuration is passed to both rc.pullServicesImages() for service containers and rc.JobContainer.Pull() for the primary job container. Additionally, pkg/runner/step_docker.go ensures that individual Docker steps also respect the flag.

How does --action-offline-mode interact with --pull?

The --action-offline-mode flag takes precedence. As implemented in cmd/root.go, the final configuration uses the logic ForcePull: !input.actionOfflineMode && input.forcePull. This means enabling offline mode automatically sets ForcePull to false, preventing any image pulls regardless of the --pull flag value.

Why does act pull images even when I have them locally?

When --pull is true (the default), act executes docker pull to ensure your local image matches the registry's current version for that tag. This prevents "cache drift" where your local ubuntu-latest might be weeks older than the registry's ubuntu-latest. Set --pull=false to skip this behavior and use local images exclusively.

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 →