Skip to content

Commit

Permalink
Added description of useBildKit option (#240)
Browse files Browse the repository at this point in the history
  • Loading branch information
satr authored Sep 1, 2023
1 parent fb74074 commit 08a207a
Show file tree
Hide file tree
Showing 2 changed files with 90 additions and 9 deletions.
83 changes: 78 additions & 5 deletions public-site/docs/src/guides/build-secrets/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,12 @@ title: Docker Build secrets
---

# Build secrets
* [With an option `useBuildKit: false`](./#build-secrets-without-buildkit)
* [With an option `useBuildKit: true`](./#build-secrets-with-buildkit)

[Build secrets](../../references/reference-radix-config/#secrets) are passed base-64 encoded, they need to be decoded before use and it should be done in same `RUN` as a command, which uses this secret

## Build secrets without BuildKit
With an option `spec.build.useBuildKit: false`, to ensure that multiline build secrets are handled correct by the build, **all** [Build secrets](../../references/reference-radix-config/#secrets) are passed as `ARG`-s during container build, base-64 encoded (they need to be decoded before use).

```dockerfile
FROM alpine
Expand All @@ -31,17 +35,86 @@ docker build . --build-arg SECRET1=$(echo "some-build-arg"|base64) --progress=pl
```dockerfile
# Use SDK image (first stage)
FROM mcr.microsoft.com/dotnet/sdk:5.0 AS build-env

#an argument, passed to `docker build` with `--build-arg` option
ARG SECRET1

#.....

# Build runtime image (second stage)
FROM mcr.microsoft.com/dotnet/aspnet:5.0

#repeate the argument, passed to `docker build` with `--build-arg` option
ARG SECRET1

#.....
```
## Build secrets with BuildKit
With an option `spec.build.useBuildKit: true`, build secrets are not available as `ARG`-s during container build. [Build secrets](../../references/reference-radix-config/#secrets) can be mounted as files within the `RUN` directive. BuildKit is an improved backend to replace the legacy builder. Read [more](https://docs.docker.com/build/buildkit/).

:::tip
Docker build workflow has some differences for the command `docker build`, for example how [ARG](https://docs.docker.com/engine/reference/builder/#understand-how-arg-and-from-interact) with BuildKit [persists across build stages](https://github.com/moby/buildkit/issues/1977).
:::

Mount a secret with secret name as `id:SECRET1` argument and assign its to `BUILD_ARG`, reading it from the file in the folder `/run/secrets`, where it is mounted with a file name same as the secret's name

Syntax: `RUN --mount=type=secret,id=SECRET_NAME,dst=DESTINATION_PATH COMMAND`, where:
- `SECRET_NAME` is a name of a build secret, defined in the radixconfig.yaml `spec.build.secrets` option.
- `COMMAND` is a single or multiple commands (separated by &&, semicolon or space), which can use the file with a secret.
- `DESTINATION_PATH` is an optional path to a folder, where file with a secret will be created. Default is `/run/secrets`, if not specified.
```dockerfile
FROM alpine

#one secret in the specified destination file and folder /abc/my-secrets/secret-1.txt
RUN --mount=type=secret,id=SECRET1,dst=/abc/my-secrets/secret-1.txt export BUILD_ARG=$(cat /abc/my-secrets/secret-1.txt) && \
echo $BUILD_ARG

#one secret in the default destination file and folder /run/secrets and a file with a name, the same as the secret name
RUN --mount=type=secret,id=SECRET1 export BUILD_ARG=$(cat /run/secrets/SECRET1) && \
echo $BUILD_ARG
```

### Development and troubleshooting
For verification that secrets are used as expected, Docker image can be built and run locally. Environment variable `DOCKER_BUILDKIT=1` is set for the command in case if the build ToolKit is not set [by default](https://docs.docker.com/build/buildkit/#getting-started) for the local Docker engine:
* Create a `Dockerfile`, which uses a secret (see an example above)
* Create a local file, containing a secret: `/some-path/secret1.txt`
* Build a Docker image with an option `--secret`, referring to this file path and the secret name, used in the Dockerfile
```bash
DOCKER_BUILDKIT=1 docker build . --secret id=SECRET1,src=/some-path/secret1.txt -t some-image-name
```
* To see full build log and avoid cached layers, add options `--progress=plain --no-cache`
* To easy run the built image, add a target image name `-t some-image-name`
```bash
DOCKER_BUILDKIT=1 docker build . --secret id=SECRET1,src=/some-path/secret1.txt -t some-image-name --progress=plain --no-cache
```
* Optionally, run the built image to verify that secrets used as expected
```bash
docker run -it some-image-name
```
* Multiple build secrets can be added as multiple `RUN --mount` options (and `docker build` options `--secrets`). Different `dst` files can be used
```dockerfile
FROM alpine

#one secret in the specified destination file and folder /abc/my-secrets/secret-1.txt
RUN --mount=type=secret,id=SECRET1,dst=/abc/my-secrets/secret-1.txt \
--mount=type=secret,id=DB_PASSWORD,dst=/config/db-pass.txt \
export BUILD_ARG=$(cat /abc/my-secrets/secret-1.txt) && \
export DB_PASS=$(cat /config/db-pass.txt) && \
echo $BUILD_ARG && \
echo $DB_PASS
```
Run it locally
```bash
DOCKER_BUILDKIT=1 docker build . --secret id=SECRET1,src=/some-path/secret1.txt --secret id=DB_PASSWORD,src=/maybe-another-path/db_password.txt -t some-image-name --progress=plain --no-cache
```
* Files, created by a `RUN --mount` options are available only for commands, executed in that particular `RUN`, not in following `RUN` commands or within Docker container, running with this image.
* If a file, specified in the `dst` option already exists, it will be overridden in the `RUN`, where the `--mount` option use it, but it will have original content in further layers
```dockerfile
FROM alpine
#put some original text to a file /abc/db_server.txt
RUN mkdir -p /abc && echo "default-server-name">/abc/db_server.txt
#verify the file contents a text "default-server-name"
RUN cat /abc/db_server.txt
#get secret value to the same file and veryfy it contains a value from the secret, overriding the original text
RUN --mount=type=secret,id=SECRET1,dst=/abc/db_server.txt cat /abc/db_server.txt
#verify the file again contents text "default-server-name"
RUN cat /abc/db_server.txt
```
* Secrets can contain multi-line text, for example - configuration files
* With an option `spec.build.useBuildKit: true` components are built not in the Azure ACR task, but within the Radix Kubernetes cluster. Such pipeline job can encounter some performance difference, which will be monitored and tuned.
16 changes: 12 additions & 4 deletions public-site/docs/src/references/reference-radix-config/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,21 +41,29 @@ spec:
```yaml
spec:
build:
useBuildKit: true
secrets:
- SECRET_1
- SECRET_2
variables:
VAR1: val1
CONNECTION_STRING: "Provider=MySQLProv;Data Source=mydb;"
CONNECTION_STRING: "Provider=MySQLProv;Data Source=mydb;"
```

The `build` section of the spec contains configuration needed during build (CI part) of the components. In this section you can specify build secrets, which is needed when pulling from locked registries, or cloning from locked repositories.

`secret` - add secrets to Radix config `radixconfig.yaml` in the branch defined as `Config Branch` for your application. This will trigger a new build. This build will fail as no specified build secret has been set. You will now be able to set the secret **values** in the configuration section of your app in the Radix Web Console. These secrets also can be used in the [sub-pipelines](../../guides/sub-pipeline).
`useBuildKit` - (optional, default `false`) build a component with Docker BuildKit. Read [more](../../guides/build-secrets/#build-secrets-with-buildkit) in the guide.

`variables` - environment variable names and values (currently available only in [sub-pipelines](../../guides/sub-pipeline)), provided for all build Radix environments in [sub-pipelines](../../guides/sub-pipeline). These common environment variables are overridden by environment-specific environment variables with the same names.
`secret` - (optional) add secrets to Radix config `radixconfig.yaml` in the branch defined as `Config Branch` for your application. This will trigger a new build. This build will fail as no specified build secret has been set. You will now be able to set the secret **values** in the configuration section of your app in the Radix Web Console. These secrets also can be used in the [sub-pipelines](../../guides/sub-pipeline).

To ensure that multiline build secrets are handled correct by the build, **all** build secrets are passed base-64 encoded, they need to be decoded before use. The [build secrets](../../guides/build-secrets/) guide describes how to use these arguments in a Dockerfile.
`variables` - (optional) environment variable names and values (currently available only in [sub-pipelines](../../guides/sub-pipeline)), provided for all build Radix environments in [sub-pipelines](../../guides/sub-pipeline). These common environment variables are overridden by environment-specific environment variables with the same names.

:::tip
* When an option `useBuildKit: false`, to ensure that multiline build secrets are handled correct by the build, **all** build secrets are passed as `ARG`-s during container build, base-64 encoded (they need to be decoded before use).
* When an option `useBuildKit: true`, build secrets are not available as `ARG`-s during container build, but they can be mounted as files. Secret values are not base-64 encoded in these files.

Read the [build secrets](../../guides/build-secrets/) guide to see how to use build secrets in a Dockerfile.
:::

## `environments`

Expand Down

0 comments on commit 08a207a

Please sign in to comment.