diff --git a/public-site/docs/src/guides/build-secrets/index.md b/public-site/docs/src/guides/build-secrets/index.md index 9aae155b..9e453cec 100644 --- a/public-site/docs/src/guides/build-secrets/index.md +++ b/public-site/docs/src/guides/build-secrets/index.md @@ -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 @@ -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. \ No newline at end of file diff --git a/public-site/docs/src/references/reference-radix-config/index.md b/public-site/docs/src/references/reference-radix-config/index.md index c9fa3642..1ff7d5a1 100644 --- a/public-site/docs/src/references/reference-radix-config/index.md +++ b/public-site/docs/src/references/reference-radix-config/index.md @@ -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`