A Concourse task for building OCI
images. Currently uses
buildkit
for building.
A stretch goal of this is to support running without privileged: true
, though
it currently still requires it.
The task implementation is available as an image on Docker Hub at
vito/oci-build-task
. (This
image is built from Dockerfile
using the oci-build
task
itself.)
This task implementation started as a spike to explore patterns around reusable tasks to hopefully lead to a proper RFC. Until that RFC is written and implemented, configuration is still done by way of providing your own task config as follows:
First, your task needs to point to the oci-build-task
image:
image_resource:
type: registry-image
source:
repository: vito/oci-build-task
Next, any of the following optional parameters may be specified:
-
$CONTEXT
(default.
): the path to the directory to provide as the context for the build. -
$DOCKERFILE
(default$CONTEXT/Dockerfile
): the path to theDockerfile
to build. -
$BUILD_ARG_*
: params prefixed withBUILD_ARG_
will be provided as build args. For exampleBUILD_ARG_foo=bar
, will set thefoo
build arg asbar
. -
$BUILD_ARGS_FILE
(default empty): path to a file containing build args in the formfoo=bar
, one per line. Empty lines are skipped.Example file contents:
[email protected] HOW_MANY_THINGS=1 DO_THING=false
-
$TARGET
(default empty): a target build stage to build. -
$TARGET_FILE
(default empty): path to a file containing the name of the target build stage to build. -
$REGISTRY_MIRRORS
(default empty): registry mirrors to use fordocker.io
. -
$UNPACK_ROOTFS
(defaultfalse
): unpack the image as Concourse's image format (rootfs/
,metadata.json
) for use with theimage
task step option.
Note: this is the main pain point with reusable tasks - env vars are kind of an awkward way to configure a task. Once the RFC lands these will turn into a JSON structure similar to configuring
params
on a resource, and task params will becomeenv
instead.
There are no required inputs - your task should just list each artifact it
needs as an input. Typically this is in close correlation with $CONTEXT
:
params:
CONTEXT: my-image
inputs:
- name: my-image
Should your build be dependent on multiple inputs, you may want to leave
$CONTEXT
as its default (.
) and set an explicit path to the $DOCKERFILE
:
params:
DOCKERFILE: my-repo/Dockerfile
inputs:
- name: my-repo
- name: some-dependency
It might also make sense to place one input under another, like so:
params:
CONTEXT: my-repo
inputs:
- name: my-repo
- name: some-dependency
path: my-repo/some-dependency
Or, to fully rely on the default behavior and use path
to wire up the context
accordingly, you could set your primary context as path: .
and set up any
additional inputs underneath:
inputs:
- name: my-repo
path: .
- name: some-dependency
A single output named image
may be configured:
outputs:
- name: image
The output will contain the following files:
-
image.tar
: the OCI image tarball. This tarball can be uploaded to a registry using the Registry Image resource. -
digest
: the digest of the OCI config. This file can be used to tag the image after it has been loaded withdocker load
, like so:docker load -i image/image.tar docker tag $(cat image/digest) my-name
If $UNPACK_ROOTFS
is configured, the following additional entries will be
created:
-
rootfs/*
: the unpacked contents of the image's filesystem. -
metadata.json
: a JSON file containing the image's env and user configuration.
This is a Concourse-specific format to support using the newly built image for
a subsequent task by pointing the task step's image
option to the output,
like so:
plan:
- task: build-image
output_mapping: {image: my-built-image}
- task: use-image
image: my-built-image
(The output_mapping
here is just for clarity; alternatively you could just
set image: image
.)
Note: at some point Concourse will likely standardize on OCI instead.
Caching can be enabled by caching the cache
path on the task:
caches:
- path: cache
Your task should run the build
executable:
run:
path: build
The docker-image
resource was previously used for building and pushing a
Docker image to a registry in one fell swoop.
The oci-build
task, in contrast, only supports building images - it does not
support pushing or even tagging the image. It can be used to build an image and
use it for a subsequent task image without pushing it to a registry, by
configuring $UNPACK_ROOTFS
.
In order to push the newly built image, you can use a resource like the
registry-image
resource like so:
resources:
- name: my-image-src
type: git
source:
uri: https://github.com/...
- name: my-image
type: registry-image
source:
repository: my-user/my-repo
jobs:
- name: build-and-push
plan:
# fetch repository source (containing Dockerfile)
- get: my-image-src
# build using `oci-build` task
#
# note: this task config could be pushed into `my-image-src` and loaded using
# `file:` instead
- task: build
privileged: true
config:
platform: linux
image_resource:
type: registry-image
source:
repository: vito/oci-build-task
inputs:
- name: my-image-src
path: .
outputs:
- name: image
run:
path: build
# push using `registry-image` resource
- put: my-image
params: {image: image/image.tar}
The builder
task was a stepping
stone that led to the oci-build
task. It is now deprecated. The transition
should be relatively smooth, with the following differences:
- The
oci-build
task does not support configuring$REPOSITORY
or$TAG
.- for running the image with
docker
, adigest
file is provided which can be tagged withdocker tag
- for pushing the image, the repository and tag are configured in the
registry-image
resource
- for running the image with
- The
oci-build
task has a more efficient caching implementation. By usingbuildkit
directly we can make use of itslocal
cache exporter/importer, which doesn't require a separate translation step for saving into the task cache. - This task is written in Go instead of Bash, and has tests!
This repo contains an example.yml
, which builds the image for the task
itself:
fly -t dev execute -c example.yml -o image=. -p
docker load -i image.tar
That -p
at the end is not a typo; it runs the task with elevated privileges.