Skaffold’s superpower in CI isn’t about building images; it’s about orchestrating the entire development and deployment loop across your cluster and local machine, making CI feel like a seamless extension of your dev environment.

Let’s see Skaffold in action within a GitLab CI pipeline. Imagine you’ve pushed a change to your main branch.

# .gitlab-ci.yml
stages:
  - build_and_deploy

variables:
  # Replace with your actual image registry details
  IMAGE_REGISTRY: registry.gitlab.com/your-group/your-project
  IMAGE_TAG: ${CI_COMMIT_SHA:0:8}

build_and_deploy_app:
  stage: build_and_deploy
  image: google/cloud-sdk:latest # Or an image with kubectl and Skaffold installed
  script:
    - echo "Authenticating to Kubernetes cluster..."
    # Assuming you have a Kubernetes context configured (e.g., via secrets/variables)
    # For GKE, you might use: gcloud container clusters get-credentials <cluster-name> --zone <zone> --project <project-id>
    - kubectl config use-context my-gke-cluster

    - echo "Running Skaffold..."
    # This command will build, tag, and push the image, then deploy it to Kubernetes
    - skaffold run --default-repository ${IMAGE_REGISTRY} --tag ${IMAGE_TAG} --file=./skaffold.yaml
  only:
    - main # Only run this job for the main branch

Here’s a corresponding skaffold.yaml that defines the build and deploy process:

# skaffold.yaml
apiVersion: skaffold.dev/v2beta20
kind: Config
build:
  local:
    # Use Docker for building images locally in CI
    useDockerCLI: true
    push: true
  artifacts:
    - image: my-app
      context: ./app # Directory containing your Dockerfile
      docker:
        dockerfile: Dockerfile
deploy:
  kubectl:
    manifests:
      - k8s/deployment.yaml
      - k8s/service.yaml

When skaffold run executes in this GitLab CI job, it performs several key steps:

  1. Build: It looks at the build section of skaffold.yaml. Since useDockerCLI: true and push: true are set, it invokes docker build in the ./app directory, tags the resulting image with your specified registry and tag (e.g., registry.gitlab.com/your-group/your-project:abcdef12), and then pushes this image to your configured container registry.
  2. Tagging: Skaffold automatically applies the tag you provided in the CI job (${CI_COMMIT_SHA:0:8}) to the built image.
  3. Deploy: It then moves to the deploy section. For kubectl deployments, Skaffold reads your k8s/deployment.yaml and k8s/service.yaml files. It substitutes the placeholder image name (often my-app as defined in skaffold.yaml) with the fully qualified, tagged image it just built and pushed. Finally, it applies these manifests to your Kubernetes cluster using kubectl apply.

This entire process, from building your container to updating your Kubernetes deployment, is handled by a single skaffold run command. The CI pipeline simply provides the environment and triggers this command.

The problem Skaffold solves in CI is the disjointed nature of traditional CI/CD for Kubernetes. Usually, you’d have separate steps for building an image, pushing it, then running kubectl apply with manual image tag substitutions. Skaffold unifies this. It understands your application’s build dependencies (like Dockerfiles) and your deployment configuration (Kubernetes manifests), and it intelligently orchestrates them. When you push an image, Skaffold knows which Kubernetes resources to update with that new image tag.

The skaffold.yaml is your central source of truth for how your application is built and deployed. Skaffold reads this configuration and translates it into concrete actions. The build section defines how your container images are created, and the deploy section specifies how those images are rolled out to your cluster. Skaffold handles the coordination between these two.

A common pattern, especially with GitOps workflows, is to use Skaffold in conjunction with tools like Argo CD or Flux CD. In this setup, your CI pipeline might not directly deploy to production. Instead, Skaffold would build and push the image, and then perhaps update a Git repository with a new tag in a deployment manifest. The GitOps tool then picks up this change from Git and performs the actual rollout. This decouples the build/push from the deployment itself, offering greater control and auditability.

What most people miss is how Skaffold’s dev mode capabilities can be mimicked in CI for faster feedback loops. While skaffold dev is for local development, you can achieve a similar "build-deploy-test" cycle in CI by using skaffold render followed by kubectl apply with a specific image tag, and then running your integration tests against the deployed application. Skaffold’s ability to manage image tagging and manifest rendering is key here, allowing you to automate these rapid feedback cycles.

The next hurdle you’ll face is managing multiple microservices and their dependencies within a single CI pipeline.

Want structured learning?

Take the full Skaffold course →