Builders

This page discusses how to set up Skaffold to use the tool of your choice to build Docker images.

Skaffold supports the following tools to build your image:

The build section in the Skaffold configuration file, skaffold.yaml, controls how artifacts are built. To use a specific tool for building artifacts, add the value representing the tool and options for using that tool to the build section.

For a detailed discussion on Skaffold configuration, see Skaffold Concepts and skaffold.yaml References.

Dockerfile locally with Docker

If you have Docker Desktop installed, Skaffold can be configured to build artifacts with the local Docker daemon.

By default, Skaffold connects to the local Docker daemon using Docker Engine APIs. Skaffold can, however, be asked to use the command-line interface instead. Additionally, Skaffold offers the option to build artifacts with BuildKit.

After the artifacts are successfully built, Docker images will be pushed to the remote registry. You can choose to skip this step.

Configuration

To use the local Docker daemon, add build type local to the build section of skaffold.yaml. The following options can optionally be configured:

Option Description Default
push should images be pushed to a registry. If not specified, images are pushed only if the current Kubernetes context connects to a remote cluster.
useDockerCLI use docker command-line interface instead of Docker Engine APIs. false
useBuildkit use BuildKit to build Docker images. false

Example

The following build section instructs Skaffold to build a Docker image gcr.io/k8s-skaffold/example with the local Docker daemon:

build:
  artifacts:
  - image: gcr.io/k8s-skaffold/example
  local: {}

Which is equivalent to:

build:
  artifacts:
  - image: gcr.io/k8s-skaffold/example
  local:
    useDockerCLI: false
    useBuildkit: false

Dockerfile remotely with Google Cloud Build

Google Cloud Build is a Google Cloud Platform service that executes your builds using Google infrastructure. To get started with Google Build, see Cloud Build Quickstart.

Skaffold can automatically connect to Cloud Build, and run your builds with it. After Cloud Build finishes building your artifacts, they will be saved to the specified remote registry, such as Google Container Registry.

Skaffold Google Cloud Build process differs from the gcloud command gcloud builds submit. Skaffold will create a list of dependent files and submit a tar file to GCB. It will then generate a single step cloudbuild.yaml and will start the building process. Skaffold does not honor .gitignore or .gcloudignore exclusions. If you need to ignore files use .dockerignore. Any cloudbuild.yaml found will not be used in the build process.

Configuration

To use Cloud Build, add build type googleCloudBuild to the build section of skaffold.yaml. The following options can optionally be configured:

Option Description Default
projectId ID of your Cloud Platform Project. If it is not provided, Skaffold will guess it from the image name. For example, given the artifact image name gcr.io/myproject/image, Skaffold will use the myproject GCP project.
diskSizeGb disk size of the VM that runs the build. See Cloud Build Reference.
machineType type of the VM that runs the build. See Cloud Build Reference.
timeout amount of time (in seconds) that this build should be allowed to run. See Cloud Build Reference.
dockerImage image that runs a Docker build. See Cloud Builders. gcr.io/cloud-builders/docker
kanikoImage image that runs a Kaniko build. See Cloud Builders. gcr.io/kaniko-project/executor
mavenImage image that runs a Maven build. See Cloud Builders. gcr.io/cloud-builders/mvn
gradleImage image that runs a Gradle build. See Cloud Builders. gcr.io/cloud-builders/gradle
concurrency how many artifacts can be built concurrently. 0 means “no-limit” Defaults to 0.

Example

The following build section, instructs Skaffold to build a Docker image gcr.io/k8s-skaffold/example with Google Cloud Build:

build:
  artifacts:
  - image: gcr.io/k8s-skaffold/example
  googleCloudBuild:
    projectId: YOUR-GCP-PROJECT

Dockerfile in-cluster with Kaniko

Kaniko is a Google-developed open-source tool for building images from a Dockerfile inside a container or Kubernetes cluster. Kaniko enables building container images in environments that cannot easily or securely run a Docker daemon.

Skaffold can help build artifacts in a Kubernetes cluster using the Kaniko image; after the artifacts are built, kaniko must push them to a registry.

Configuration

To use Kaniko, add build type kaniko to the build section of skaffold.yaml. The following options can optionally be configured:

Option Description Default
flags additional flags to be passed to Kaniko command line. See Kaniko Additional Flags. Deprecated - instead the named, unique fields should be used, e.g. buildArgs, cache, target. []
dockerfile locates the Dockerfile relative to workspace. Dockerfile
target Dockerfile target name to build.
buildArgs arguments passed to the docker build. It also accepts environment variables via the go template syntax. {}
buildContext where the build context for this artifact resides.
image Docker image used by the Kaniko pod. Defaults to the latest released version of gcr.io/kaniko-project/executor.
cache configures Kaniko caching. If a cache is specified, Kaniko will use a remote cache which will speed up builds.
reproducible used to strip timestamps out of the built image. false
skipTLS skips TLS verification when pulling and pushing the image. false

The buildContext can be either:

Option Description
gcsBucket GCS bucket to which sources are uploaded. Kaniko will need access to that bucket to download the sources.
localDir configures how Kaniko mounts sources directly via an emptyDir volume.

Since Kaniko must push images to a registry, it is required to set up cluster credentials. These credentials are configured in the cluster section with the following options:

Option Description Default
HTTP_PROXY for kaniko pod.
HTTPS_PROXY for kaniko pod.
pullSecret path to the Google Cloud service account secret key file.
pullSecretName name of the Kubernetes secret for pulling the files from the build context and pushing the final image. If given, the secret needs to contain the Google Cloud service account secret key under the key kaniko-secret. kaniko-secret
pullSecretMountPath path the pull secret will be mounted at within the running container.
namespace Kubernetes namespace. Defaults to current namespace in Kubernetes configuration.
timeout amount of time (in seconds) that this build is allowed to run. Defaults to 20 minutes (20m).
dockerConfig describes how to mount the local Docker configuration into a pod.
resources define the resource requirements for the kaniko pod.
concurrency how many artifacts can be built concurrently. 0 means “no-limit” Defaults to 0.

To set up the credentials for kaniko have a look at the kaniko docs. The recommended way is to store the pull secret in Kubernetes and configure pullSecretName. Alternatively, the path to a credentials file can be set with the pullSecret option:

build:
  cluster:
    pullSecretName: pull-secret-in-kubernetes
    # OR
    pullSecret: path-to-service-account-key-file

Similarly, when pushing to a docker registry:

build:
  cluster:
    dockerConfig:
      path: ~/.docker/config.json
      # OR
      secretName: docker-config-secret-in-kubernetes

Note that the kubernetes secret must not be of type kubernetes.io/dockerconfigjson which stores the config json under the key ".dockerconfigjson", but an opaque secret with the key "config.json".

Example

The following build section, instructs Skaffold to build a Docker image gcr.io/k8s-skaffold/example with Kaniko:

build:
  artifacts:
    - image: gcr.io/k8s-skaffold/example
      kaniko:
        buildContext:
          gcsBucket: YOUR-BUCKET
  cluster:
    pullSecretName: YOUR-PULL-SECRET-NAME

Jib Maven and Gradle locally

Jib is a set of plugins for Maven and Gradle for building optimized Docker and OCI images for Java applications without a Docker daemon.

Skaffold can help build artifacts using Jib; Jib builds the container images and then pushes them to the local Docker daemon or to remote registries as instructed by Skaffold.

Skaffold requires using Jib v1.4.0 or later.

Configuration

To use Jib, add a jib field to each artifact you specify in the artifacts part of the build section. context should be a path to your Maven or Gradle project.

The jib type offers the following options:

Option Description Default
project selects which sub-project to build for multi-module builds.
args additional build flags passed to the builder. []

Skaffold’s jib support chooses the underlying builder (Maven or Gradle) based on the presence of standard build files in the artifact’s context directory:

  • Maven: pom.xml, or .mvn directory.
  • Gradle: build.gradle, gradle.properties, settings.gradle, or the Gradle wrapper script (gradlew, gradlew.bat, or gradlew.cmd).

Example

See the Skaffold-Jib demo project for an example.

Multi-Module Projects

Skaffold can be configured for multi-module projects too. A multi-module project has several modules (Maven terminology) or sub-projects (Gradle terminology) that each produce a separate container image.

Maven

To build a Maven multi-module project, first identify the sub-projects (also called modules in Maven) that should produce a container image. Then for each such sub-project:

  • Create a Skaffold artifact in the skaffold.yaml.
  • Set the artifact’s context field to the root project location.
  • Add a jib element and set its project field to the sub-project’s :artifactId, groupId:artifactId, or the relative path to the sub-project within the project.

Gradle

To build a multi-module project with Gradle, first identify the sub-projects that should produce a container image. Then for each such sub-project:

  • Create a Skaffold artifact in the skaffold.yaml.
  • Set the artifact’s context field to the root project location.
  • Add a jib element and set its project field to the sub-project’s name (the directory, by default).

Jib Maven and Gradle remotely with Google Cloud Build

//TODO(#1299)

Bazel locally

Bazel is a fast, scalable, multi-language, and extensible build system.

Skaffold can help build artifacts using Bazel; after Bazel finishes building container images, they will be loaded into the local Docker daemon.

Configuration

To use Bazel, bazel field to each artifact you specify in the artifacts part of the build section, and use the build type local. context should be a path containing the bazel files (WORKSPACE and BUILD). The following options can optionally be configured:

Option Description Default
target Required bazel build target to run.
args additional args to pass to bazel build. []

Example

The following build section instructs Skaffold to build a Docker image gcr.io/k8s-skaffold/example with Bazel:

build:
  artifacts:
  - image: gcr.io/k8s-skaffold/example
    bazel:
      target: //:example.tar

Custom Build Script Run Locally

Custom build scripts allow skaffold users the flexibility to build artifacts with any builder they desire. Users can write a custom build script which must abide by the following contract for skaffold to work as expected:

Contract between Skaffold and Custom Build Script

Skaffold will pass in the following environment variables to the custom build script:

Environment Variable Description Expectation
$IMAGES An array of fully qualified image names, separated by spaces. For example, “gcr.io/image1 gcr.io/image2” The custom build script is expected to build an image and tag it with each image name in $IMAGES. Each image should also be pushed if $PUSH_IMAGE=true.
$PUSH_IMAGE Set to true if each image in $IMAGES is expected to exist in a remote registry. Set to false if each image in $IMAGES is expected to exist locally. The custom build script will push each image in $IMAGES if $PUSH_IMAGE=true
$BUILD_CONTEXT An absolute path to the directory this artifact is meant to be built from. Specified by artifact context in the skaffold.yaml. None.
Local environment variables The current state of the local environment (e.g. $HOST, $PATH). Determined by the golang os.Environ function. None.

As described above, the custom build script is expected to:

  1. Build and tag each image in $IMAGES
  2. Push each image in $IMAGES if $PUSH_IMAGE=true

Once the build script has finished executing, skaffold will try to obtain the digest of the newly built image from a remote registry (if $PUSH_IMAGE=true) or the local daemon (if $PUSH_IMAGE=false). If skaffold fails to obtain the digest, it will error out.

Additional Environment Variables

Skaffold will pass in the following additional environment variables for the following builders:

Local builder
Environment Variable Description Expectation
Docker daemon environment variables Inform the custom builder of which docker daemon endpoint we are using. Allows custom build scripts to work with tools like Minikube. For Minikube, this is the output of minikube docker-env. None.
Cluster Builder
Environment Variable Description Expectation
$KUBECONTEXT The expected kubecontext in which the image will be built. None.
$NAMESPACE The expected namespace in which the image will be built. None.
$PULL_SECRET_NAME The name of the secret with authentication required to pull a base image/push the final image built on cluster. None.
$DOCKER_CONFIG_SECRET_NAME The secret containing any required docker authentication for custom builds on cluster. None.
$TIMEOUT The amount of time an on cluster build is allowed to run. None.

Configuration

To use a custom build script, add a custom field to each corresponding artifact in the build section of the skaffold.yaml. Currently, this only works with the local and cluster build types. Supported schema for custom includes:

Option Description
buildCommand command executed to build the image.
dependencies file dependencies that skaffold should watch for both rebuilding and file syncing for this artifact.

buildCommand is required and points skaffold to the custom build script which will be executed to build the artifact.

Dependencies for a Custom Artifact

dependencies tells the skaffold file watcher which files should be watched to trigger rebuilds and file syncs. Supported schema for dependencies includes:

Option Description Default
dockerfile should be set if the artifact is built from a Dockerfile, from which skaffold can determine dependencies.
command represents a custom command that skaffold executes to obtain dependencies. The output of this command must be a valid JSON array.
paths should be set to the file dependencies for this artifact, so that the skaffold file watcher knows when to rebuild and perform file synchronization. []
ignore specifies the paths that should be ignored by skaffold’s file watcher. If a file exists in both paths and in ignore, it will be ignored, and will be excluded from both rebuilds and file synchronization. Will only work in conjunction with paths. []
Paths and Ignore

Paths and Ignore are arrays used to list dependencies. Any paths in Ignore will be ignored by the skaffold file watcher, even if they are also specified in Paths. Ignore will only work in conjunction with Paths, and with none of the other custom artifact dependency types.

custom:
  buildCommand: ./build.sh
  dependencies:
    paths:
    - pkg/**
    - src/*.go
    ignore:
    - vendor/**
Dockerfile

Skaffold can calculate dependencies from a Dockerfile for a custom artifact. Passing in the path to the Dockerfile and any build args, if necessary, will allow skaffold to do dependency calculation.

Option Description Default
path locates the Dockerfile relative to workspace.
buildArgs arguments passed to the docker build. It also accepts environment variables via the go template syntax. {}
custom:
  buildCommand: ./build.sh
  dependencies:
    dockerfile:
      path: path/to/Dockerfile
      buildArgs:
        file: foo
Getting dependencies from a command

Sometimes you might have a builder that can provide the dependencies for a given artifact. For example bazel has the bazel query deps command. Custom artifact builders can ask Skaffold to execute a custom command, which Skaffold can use to get the dependencies for the artifact for file watching.

The command must return dependencies as a JSON array, otherwise skaffold will error out.

For example, the following configuration is valid, as executing the dependency command returns a valid JSON array.

custom:
  buildCommand: ./build.sh
  dependencies:
    command: echo ["file1","file2","file3"]

Custom Build Scripts and File Sync

Syncable files must be included in both the paths section of dependencies, so that the skaffold file watcher knows to watch them, and the sync section, so that skaffold knows to sync them.

Custom Build Scripts and Logging

STDOUT and STDERR from the custom build script will be redirected and displayed within skaffold logs.

Example

The following build section instructs Skaffold to build an image gcr.io/k8s-skaffold/example with a custom build script build.sh:

build:
  artifacts:
    - image: gcr.io/k8s-skaffold/example
      custom:
        buildCommand: ./build.sh
        dependencies:
          paths:
            - .
          ignore:
            - README*

A sample build.sh file, which builds an image with bazel and docker:

#!/bin/bash

bazel build //:skaffold_example.tar
TAR_PATH=$(bazel info bazel-bin)
docker load -i $TAR_PATH/skaffold_example.tar


images=$(echo $IMAGES | tr " " "\n")

for image in $images
do
    docker tag bazel:skaffold_example $image

    if $PUSH_IMAGE
    then
        docker push $image
    fi

done