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 runningact --pull=false→ Never pulls; uses local images exclusivelyact --action-offline-mode→ ForcesForcePull=falseand 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 --pulldefaults totrue, ensuring fresh images by default- The flag propagates through
cmd/root.gointo theConfig.ForcePullfield defined inpkg/runner/runner.go RunContextapplies the setting to job containers, service containers, and step containers via calls inpkg/runner/run_context.goandpkg/runner/step_docker.go- The actual Docker client logic in
pkg/container/docker_pull.goevaluatesForcePullto decide whether to skip local caches --action-offline-modeoverrides--pull, forcingForcePulltofalseand 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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →