oci-build task
A fork of vito/oci-build-task with
support for authenticating against ECR using an IAM role. See * params
section for variables to set to enable ECR support.
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.
usage
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:
image_resource
First, your task needs to point to the oci-build-task image:
image_resource:
type: registry-image
source:
repository: vito/oci-build-task
params
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 the Dockerfile
to build.
-
$BUILD_ARG_*: params prefixed with BUILD_ARG_ will be provided as build
args. For example BUILD_ARG_foo=bar, will set the foo build arg as bar.
-
$BUILD_ARGS_FILE (default empty): path to a file containing build args in
the form foo=bar, one per line. Empty lines are skipped.
Example file contents:
EMAIL=me@yopmail.com
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.
-
$UNPACK_ROOTFS (default false): unpack the image as Concourse's image
format (rootfs/, metadata.json) for use with the image task step
option.
-
$LOGIN (default empty): if set to ECR the task will attempt to gain ECR
credentials from AWS (using IAM role). The ECR credentials will be written
to ~/.docker/config.json within the config and configured to the default account
repository (eg. https://<account-number>.dkr.ecr.<region>.amazonaws.com). This
behaviour can be changed using the $REGISTRIES and $REGION flags. If set to
PASS the task will use the $PASS field to populate the docker auth.
-
$PASS (default empty): if used with $LOGIN set to PASS this should include
the docker username/password in the form of username:pass - for example passed
in as ((username)):((password)). These will be base64 encoded and used in the
./docker/config.json file.
-
$REG_URL (default "https://index.docker.io/v1/"): if used with $LOGIN set to PASS this specifies
the URL to be used for docker login.
-
$REGISTRIES (default empty): a list of account IDs to use when
creating ECR credentials. Optional use in conjunction with $ECR var.
-
$REGION (default eu-west-1): the region to use when creating ECR credentials.
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 become env 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
outputs
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 with docker 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:
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.
caches
Caching can be enabled by caching the cache path on the task:
caches:
- path: cache
run
Your task should run the build executable:
run:
path: build
migrating from the docker-image resource
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:
- get: 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}
differences from builder task
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, a digest file is provided which can
be tagged with docker tag
- for pushing the image, the repository and tag are configured in the
registry-image
resource
- The
oci-build task has a more efficient caching implementation. By using
buildkit directly we can make use of its local 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!
example
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