Docker build

CustomDockerImage build with self hosted Docker

DockerImage component uses Kaniko to build the Docker images. For cases when Docker BuildKit is preferred, with CustomDockerImage you can connect to a Docker engine.

Here is an example setup with CustomDockerImage component and a self-hosted builder.


DockerInDocker environment

For simplicity you can deploy a Docker in the cluster which will be used for builds. A dockerInDocker and a NetworkPolicy to allow access to it from other k8s namespaces. This can be deployed with Bunnyshell.

kind: Environment
name: dind
type: primary
components:
    -
        kind: KubernetesManifest
        name: network-policy
        runnerImage: 'alpine/k8s:1.29.2'
        deploy:
            - |
                cat << EOF > network-policy.yaml
                    apiVersion: networking.k8s.io/v1
                    kind: NetworkPolicy
                    metadata:
                      name: allow-all-ingress
                    spec:
                      podSelector: {}
                      ingress:
                      - {}
                      policyTypes:
                      - Ingress
                EOF
            - 'kubectl apply -f network-policy.yaml -n {{ env.k8s.namespace }}'
        destroy:
            - 'kubectl delete -f network-policy.yaml -n {{ env.k8s.namespace }}'
    -
        kind: Application
        name: dind
        dockerCompose:
            command:
                - '--host=tcp://0.0.0.0:2375'
            entrypoint: dockerd
            image: 'docker:25-dind'
            privileged: true
            ports:
                - '2375:2375'
            deploy:
                resources:
                    limits:
                        cpus: '1.00'
                        memory: 800M
                    reservations:
                        cpus: '0.50'
                        memory: 500M

Update the deploy resources to your needs.

Note the environment allocated k8s namespace, something like env-abc123


CustomDockerImage

The CustomDockerImage will have the DOCKER_HOST environment variable pointing to dind Service from the DockerInDocker environment, and any docker CLI command will use that Docker engine.

Also in Build Settings configure the build cluster to be the one where the DockerInDocker environment is deployed.

The runnerImage can be anything but it should have docker CLI installed.

kind: Environment
name: 'custom build'
type: primary
components:
    -
        kind: CustomDockerImage
        name: java-image
        gitRepo: 'https://github.com/my-repo.git'
        gitBranch: main
        gitApplicationPath: /
        runnerImage: 'docker:25.0-dind-rootless'
        environment:
            DOCKER_HOST: 'tcp://dind.env-abc123.svc.cluster.local'
            DUMMY_VAR: 'dummy'
        build:
            - 'echo "building ..."'
            - 'echo "FROM eclipse-temurin:17-jdk-alpine" > Dockerfile'
            - |
                cat << EOF > Dockerfile
                    FROM openjdk:17-jdk-alpine

                    ENV DUMMY_VAR={{component.vars.DUMMY_VAR}}
                EOF
            - '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 .'

    -
        kind: Application
        name: java-app
        dockerCompose:
            image: '{{components.java-image.image}}'
            ports:
                - 9000
        hosts:
            -
                hostname: 'java-{{ env.base_domain }}'
                path: /
                servicePort: 9000
        dependsOn:
            - java-image

Note the two essential commands, docker login and docker buildx build. See CustomDockerImage for $BNS_IMAGE_* environment variables.

This example uses simple Dockerfile created at runtime, but the entire gitRepository is cloned in the context.

The example has also an Application component which uses the built image.