GoogleContainerTools/skaffold · error

docker deployment not supported alongside cluster deployment

Error message

docker deployment not supported alongside cluster deployments

What it means

GetDeployer distinguishes local (docker) deploys from remote (cluster) deploys; if the config requires both it returns this error, because a single apply/deploy cannot push to the local Docker daemon and a cluster at the same time via the deployer mux.

Source

Thrown at pkg/skaffold/runner/deployer.go:214

			if err != nil {
				return nil, err
			}
			if len(deployers) > 0 {
				return nil, fmt.Errorf("kpt deployer mixed in with other deployers not supported yet. Please use only kpt deployer")
			}
			deployers = append(deployers, deployer)
		}
		if d.CloudRunDeploy != nil {
			deployer, err := getCloudRunDeployer(dCtx.RunContext, labeller, runCtx.DeployConfigs(), configName)
			if err != nil {
				return nil, err
			}
			deployers = append(deployers, deployer)
		}
	}

	if localDeploy && remoteDeploy {
		return nil, errors.New("docker deployment not supported alongside cluster deployments")
	}

	return deploy.NewDeployerMux(deployers, runCtx.IterativeStatusCheck()), nil
}

/*
The "default deployer" is used in `skaffold apply`, which uses a `kubectl` deployer to actuate resources
on a cluster regardless of provided deployer configuration in the skaffold.yaml.
The default deployer will honor a select set of deploy configuration from an existing skaffold.yaml:
  - deploy.StatusCheckDeadlineSeconds
  - deploy.Logs.Prefix
  - deploy.Kubectl.Flags
  - deploy.Kubectl.DefaultNamespace

For a multi-config project, we do not currently support resolving conflicts between differing sets of this deploy configuration.
Therefore, in this function we do implicit validation of the provided configuration, and fail if any conflict cannot be resolved.
*/
func getDefaultDeployer(runCtx *runcontext.RunContext, labeller *label.DefaultLabeller, selectors []manifest.GroupKindSelector) (deploy.Deployer, error) {

View on GitHub (pinned to a1189de023)

Solutions

  1. Keep only one deployer type per pipeline — remove either deploy.docker or the cluster deployer from skaffold.yaml
  2. Split into separate projects/profiles and run deploy once per target (local vs cluster)
  3. Move the local-docker workload into the cluster (e.g. a Deployment manifest) so a single cluster deployer suffices

Example fix

// before
deploy:
  docker: {images: [myapp]}
  kustomize: {paths: [k8s]}
// after
deploy:
  kustomize: {paths: [k8s]}  # single (cluster) deploy target
Defensive patterns

Strategy: validation

Validate before calling

hasDocker, hasCluster := false, false
for _, d := range cfg.Deploy { if d.DockerDeploy != nil { hasDocker = true } else { hasCluster = true } }
if hasDocker && hasCluster { return errors.New("skaffold.yaml mixes docker and cluster deployers; keep one target") }

Type guard

func isDockerOnly(d latest.DeployConfig) bool { return d.DockerDeploy != nil && d.KubectlDeploy == nil && d.HelmDeploy == nil && d.KustomizeDeploy == nil }

Try / catch

deployer, err := runner.GetDeployer(ctx, runCtx, labeller, cfg)
if err != nil && strings.Contains(err.Error(), "docker deployment not supported") {
  return fmt.Errorf("split local docker and cluster deploys: %w", err)
}

Prevention

When it happens

Trigger: skaffold.yaml (or merged profiles) contains a docker deploy target together with a cluster deployer (kubectl/helm/kustomize), causing localDeploy && remoteDeploy to both be true.

Common situations: Mixed configs with `deploy.docker` plus `deploy.kubectl`; profiles adding a docker deploy on top of a cluster baseline; teams migrating workloads between local docker and k8s.

Related errors


AI-assisted analysis of GoogleContainerTools/skaffold@a1189de023 (2026-09-05). Data as JSON: /api/errors/86a3c2b7dc7e0ade. Report an issue: GitHub.