Custom Docker Image

Build component for Docker images

Introduction

Custom Docker Image Components are useful when you don't have your images already built (by a pipeline) and also they require a custom setup, more than DockerImage component can offer. Defining such a component will enable Bunnyshell to build your images for you to use in other components.

This is a combination between GenericComponent and DockerImage, you can declare any build steps, what is important in the end, the image $BNS_IMAGE_FULL_NAME should exists in the registry.

Custom Docker Image components are not displayed in the main user interface. They can be defined and edited only within the bunnyshell.yaml file, where they have their own kind, named CustomDockerImage.


Usecases


Example

-
    kind: CustomDockerImage
    name: my-app-image
    gitRepo: 'https://gitlab.com/example/my-app.git'
    gitBranch: master
    gitApplicationPath: /
    runnerImage: openjdk:17-jdk-alpine
    environment:
        ENV: bunnyshell
    build:
        - 'echo "building $BNS_IMAGE_FULL_NAME ..."'
        - './gradlew :jib --image="$BNS_IMAGE_FULL_NAME" -Djib.to.auth.username="$BNS_IMAGE_REGISTRY_USERNAME" -Djib.to.auth.password="$BNS_IMAGE_REGISTRY_PASSWORD" --debug'
    

Component attributes

CustomDockerImage Components have the following attributes:

  • runnerImage: the Docker image in which the build commands will run. This field is mandatory.
  • runnerImageAuth: credentials for pulling the runnerImage. See below examples foreach supported image registry.
  • environment: a key-value map of component-level variables. The SECRET[] method can be used to mark a secret value (e.g. - VAR_NAME: SECRET['secret value']).
  • build: a list of commands that will be ran in order to build the Docker image. This field is mandatory.
  • name: the name
  • gitRepo: the URL of the Git repository where the Dockerfile is located. This field is mandatory.
  • gitBranch: the branch where the Dockerfile is located. This attribute is relative to the gitRepo. This field is mandatory.
  • gitApplicationPath: the path to the application folder, relative to the branch. This field is mandatory.

🚧

Note

If the gitRepo, gitBranch or gitApplicationPath are not provided, Bunnyshell will return an error when trying to validate your environment.

Bunnyshell must have access to the git repository through an existing Git integration (i.e. a Git account that was already connected to Bunnyshell). See the Git Providers page for more information.

The repository will be cloned entirely, not just the specified gitApplicationPath.

 

runnerImage

The image must be specified in it's full form <registry>/<repository>:<tag> except it's an image hosted on dockerhub and then it can have only <repository>:<tag>. If the tag is not present the latest tag will be assumed.

If the image you want to use is built by Bunnyshell, you have two possibilities to obtain the image full name:

  • use interpolation {{ components.my-runner-image.image }} if you have in the same environment another DockerImage or CustomDockerImage component named my-runner-image, which should build before this component
  • copy the image full name from previous pipeline logs if the DockerImage or CustomDockerImage that built the image is part of another environment. Go to pipeline logs, click on a Build job, then in the logs box below, check for either:
    • "create builder pod" > "pushing into: registry "<REGISTRY>" repository "<REPOSITORY>" tag "<TAG>""
    • "check image already built" > "image found <REGISTRY>/<NAME>:<TAG>"

If the runnerImage is not public and the image registry where it's stored is not yet connected to Bunnyshell (see Image Registries) you must provide runnerImageAuth object with the credentials to pull the image.

📘

Note

Images stored in the Bunnyshell Managed Registry cannot be used cross Organizations.


runnerImageAuth

If the runnerImage is not public and the image registry is not connected to Bunnyshell (see Image Registries) you must provide the pull credentials.

Both username and password allow interpolation expression, so you can interpolate environmentVariables or even Project variables.

See below explanations and examples for each supported image registry type.

AWS private ECR

runnerImage: <AWSAccountID>.dkr.ecr.<AWSRegion>.amazonaws.com/my-image:my-tag
runnerImageAuth:
  provider: aws
  username: "AWS Access Key ID"
  password: "AWS Secret Access Key"

Both username and password are required, and we will extract AWS Account ID and AWS Region from the runnerImage.


AWS public ECR

runnerImage: public.ecr.aws/123abc/my-image:my-tag
runnerImageAuth:
  provider: aws_public
  username: "AWS Access Key ID"
  password: "AWS Secret Access Key"

Sometimes is useful to provide credentials even for AWS public ECR to bypass any pull rate limit.

Both username and password are required.


Azure Container Registry

runnerImageAuth:
  provider: azure
  username: "Azure SP application ID / Token name"
  password: "Azure SP password / Token secret"

Both username and password are required.


Docker Hub

runnerImageAuth:
  provider: docker_hub
  username: "DockerHub username"
  password: "DockerHub password / Access Token"

Both username and password are required.


Google Container Registry

runnerImageAuth:
  provider: gcp
  password: "Google Service Account Key (JSON)"

Only password is required.


GitHub Container Registry

runnerImageAuth:
  provider: github
  username: "GitHub Username / Organization"
  password: "GitHub Access Token"

Both username and password are required.


GitLab Container Registry

runnerImageAuth:
  provider: gitlab
  username: "GitLab Username"
  password: "GitLab Access Token"

Both username and password are required.


Harbor

runnerImageAuth:
  provider: harbor
  username: "Harbor Username / Robot Account name"
  password: "Harbor Password / Robot Account password"

Both username and password are required.


JFrog Artifactory

runnerImageAuth:
  provider: jfrog
  username: "JFrog Artifactory Username"
  password: "JFrog Artifactory API Key"

Both username and password are required.


environment

Key value map with component level environment variables. They will be injected in the build scripts context. They allow interpolation expressions just like all the other environment variables in bunnyshell.yaml.

📘

Note

One thing different from GenericComponent (or Helm, Kubernets and Terraform) which have environment too, the environment variables injected in the build context consists only from the variables defined at component level, no environmentVariable or Project variable will be injected. They are treated more like “some build arguments”, so that’s why we keep it sandboxed, like we have on DockerImage.args, StaticApplication.buildArguments and Application.dockerCompose.build.args


build

Build scripts will run on a Pod with runnerImage in the root folder of the specified gitRepository. The cluster where the Pod runs, the k8s resources and the maximum allowed time for the scripts to run are configured in Build Settings.

The goal of the build scripts is to push the $BNS_IMAGE_FULL_NAME in the registry. If at the end the image is not there the build job will be considered failed.

To know where to push the image and what are the push credentials Bunnyshell automatically injects the following environment variables (with example values):

BNS_IMAGE_REGISTRY=904643107945.dkr.ecr.eu-west-1.amazonaws.com
BNS_IMAGE_NAME=bns-abc123_1-1-765674709-e16cb4d98d554e20133d6b459a5cb6e6
BNS_IMAGE_TAG=d0c51431f847b8b4bd69f7b8249d86d28e5152e0
BNS_IMAGE_FULL_NAME=904643107945.dkr.ecr.eu-west-1.amazonaws.com/bns-abc123_1-1-765674709-e16cb4d98d554e20133d6b459a5cb6e6:d0c51431f847b8b4bd69f7b8249d86d28e5152e0
BNS_IMAGE_REGISTRY_USERNAME=AWS
BNS_IMAGE_REGISTRY_PASSWORD=abcd1234

so you can use them like:

build:
  - 'echo "$BNS_IMAGE_REGISTRY_PASSWORD" | docker login --username "$BNS_IMAGE_REGISTRY_USERNAME" --password-stdin $BNS_IMAGE_REGISTRY'
  - 'docker buildx build -t $BNS_IMAGE_FULL_NAME --push .'
build:
  - './gradlew :jib --image="$BNS_IMAGE_FULL_NAME" -Djib.to.auth.username="$BNS_IMAGE_REGISTRY_USERNAME" -Djib.to.auth.password="$BNS_IMAGE_REGISTRY_PASSWORD"'

Value Interpolation

The built images can be used in other components using the following interpolations:

  • {{ components.NAME.image }}: contains full image name, including the tag.
    Example: nginx:latest
  • {{ components.dev_test_image.imageName }}: contains only the image name.
    Example: nginx
  • {{ components.dev_test_image.imageTag }}: contains only the image tag.
    Example: latest

The runnerImage, runnerImageAuth, environment and build allows interpolation expressions.

 

Resources

The CustomDockerImage component does not produce any deployed runnable resources, just the container images.

Still, the Pod itself that will build the image, will run in the cluster and with the k8s resources specified in the Build Settings.