docker/compose · error

interactive exec is not supported in dry-run mode

Error message

interactive exec is not supported in dry-run mode

What it means

The dry-run client intentionally blocks ExecAttach because an interactive exec session would perform real I/O with the container and cannot be meaningfully simulated. Static exec calls (create/inspect/resize) pass through, but attaching to the session stream is rejected with 'interactive exec is not supported in dry-run mode'.

Source

Thrown at pkg/dryrun/dryrunclient.go:339

func (d *DryRunClient) ConfigRemove(ctx context.Context, id string, options client.ConfigRemoveOptions) (client.ConfigRemoveResult, error) {
	return d.apiClient.ConfigRemove(ctx, id, options)
}

func (d *DryRunClient) ConfigUpdate(ctx context.Context, id string, options client.ConfigUpdateOptions) (client.ConfigUpdateResult, error) {
	return d.apiClient.ConfigUpdate(ctx, id, options)
}

func (d *DryRunClient) ContainerCommit(ctx context.Context, container string, options client.ContainerCommitOptions) (client.ContainerCommitResult, error) {
	return d.apiClient.ContainerCommit(ctx, container, options)
}

func (d *DryRunClient) ContainerDiff(ctx context.Context, container string, options client.ContainerDiffOptions) (client.ContainerDiffResult, error) {
	return d.apiClient.ContainerDiff(ctx, container, options)
}

func (d *DryRunClient) ExecAttach(ctx context.Context, execID string, config client.ExecAttachOptions) (client.ExecAttachResult, error) {
	return client.ExecAttachResult{}, errors.New("interactive exec is not supported in dry-run mode")
}

func (d *DryRunClient) ExecInspect(ctx context.Context, execID string, options client.ExecInspectOptions) (client.ExecInspectResult, error) {
	return d.apiClient.ExecInspect(ctx, execID, options)
}

func (d *DryRunClient) ExecResize(ctx context.Context, execID string, options client.ExecResizeOptions) (client.ExecResizeResult, error) {
	return d.apiClient.ExecResize(ctx, execID, options)
}

func (d *DryRunClient) ContainerExport(ctx context.Context, container string, options client.ContainerExportOptions) (client.ContainerExportResult, error) {
	return d.apiClient.ContainerExport(ctx, container, options)
}

func (d *DryRunClient) ContainerLogs(ctx context.Context, container string, options client.ContainerLogsOptions) (client.ContainerLogsResult, error) {
	return d.apiClient.ContainerLogs(ctx, container, options)
}

View on GitHub (pinned to ddc4b044b6)

Solutions

  1. Run exec commands without --dry-run (they are usually safe to test directly)
  2. Model the check with `docker compose exec -T` outside the dry-run pipeline, keeping only up/create steps in the dry-run pass
  3. Use `docker compose run --rm --dry-run svc cmd` to approximate what the exec would launch

Example fix

# before
docker compose --dry-run exec web cat /etc/hostname
# after
docker compose exec web cat /etc/hostname
Defensive patterns

Strategy: validation

Validate before calling

# in scripts, route exec away from dry-run mode
if [ "$DRY_RUN" = "1" ]; then echo 'skipping exec (unsupported in dry-run)'; else docker compose exec "$@"; fi

Prevention

When it happens

Trigger: `docker compose exec --dry-run <svc> <cmd>` — or any API path reaching ExecAttach — while dry-run mode is enabled.

Common situations: Dry-running a script that mixes `compose exec` steps to verify command sequencing; forgetting that --dry-run applies to the whole invocation including exec subcommands.

Related errors


AI-assisted analysis of docker/compose@ddc4b044b6 (2026-08-15). Data as JSON: /api/errors/fbb9503b3e0102ed. Report an issue: GitHub.