Home > Mobile >  Docker BuildKit returning '/run/secrets/<secret-id>: No such file or directory' when
Docker BuildKit returning '/run/secrets/<secret-id>: No such file or directory' when

Time:12-21

I am still fairly new to docker and DevOps. I am trying to pass a secret to my Docker container to be used in the build. I read that using BuildKit allows for more security as the secrets are not baked into the container. I am running into issues after following steps from the bottom comment of this post here https://stackoverflow.com/a/70309396 which seemed to solve my issue perfectly and appeared really straight forward and simple, however I am not sure what is wrong? I am able to pass other envs into the build using --build-arg (I have not included them in the yaml code snippet), but this method seems to be breaking for me on the Dockerfile stage (I think).

My build pipeline has the value stored as a secret, and when I echo the secret into the file $(Pipeline.Workspace)/direct_line_secret.txt and cat it as seen below, I get *** hidden value returned in the pipeline build as expected (second line from the bottom).

Starting: Store direct line secret
==============================================================================
Task         : Bash
Description  : Run a Bash script on macOS, Linux, or Windows
Version      : 3.195.0
Author       : Microsoft Corporation
Help         : https://docs.microsoft.com/azure/devops/pipelines/tasks/utility/bash
==============================================================================
Generating script.
========================== Starting Command Output ===========================
/usr/bin/bash /home/vsts/work/_temp/070f6401-2a4d-4656-b674-4fadcce142ea.sh
***
Finishing: Store direct line secret

This is my yaml file for creating this script and the docker build task.

trigger:
- main

resources:
- repo: self

variables:
  dockerfilePath: '$(Build.SourcesDirectory)/Dockerfile'
  tag: '$(Build.BuildId)'
  DOCKER_BUILDKIT: 1

  # Agent VM image name
  vmImageName: 'ubuntu-latest'

stages:
- stage: Build
  displayName: Build and push stage
  jobs:
  - job: Build
    displayName: Build
    pool:
      vmImage: $(vmImageName)
    variables:
      DOCKER_BUILDKIT: 1
    steps:
    - bash: |
        echo ${DIRECT_LINE_SECRET} > $SECRET
        cat $SECRET
      displayName: Store direct line secret
      env:
        DIRECT_LINE_SECRET: $(nextPublicDirectLineSecret)
        SECRET: $(Pipeline.Workspace)/direct_line_secret.txt

    - task: Docker@2
      displayName: Build image
      inputs:
        command: build
        repository: $(imageRepository)
        dockerfile: $(dockerfilePath)
        containerRegistry: $(dockerRegistryServiceConnection)
        arguments: --secret id=dl_secret,src=$(Pipeline.Workspace)/direct_line_secret.txt --build-arg [...]
        tags: |
          $(tag)

[...]

and this is my Dockerfile


# Build target base #
#####################
FROM node:lts-alpine AS base
WORKDIR /app
ARG NODE_ENV=production \
    API_BASE \
    SIGNALR_BASE \
    DIRECT_LINE_SECRET
ENV PATH=/app/node_modules/.bin:$PATH \
    NODE_ENV="$NODE_ENV" \
    NEXT_PUBLIC_API_BASE_URL=$API_BASE \
    NEXT_PUBLIC_SIGNALR_BASE_URL=$SIGNALR_BASE
RUN apk --no-cache add curl
COPY package.json yarn.lock /app/
EXPOSE 3000

# Build target dependencies #
#############################
FROM base AS dependencies
# Install prod dependencies
RUN yarn install --production && \
    # Cache prod dependencies
    cp -R node_modules /prod_node_modules && \
    # Install dev dependencies
    yarn install --production=false

# Build target development #
############################
FROM dependencies AS development
COPY . /app
CMD [ "yarn", "dev" ]

# Build target builder #
########################
FROM base AS builder
COPY --from=dependencies /app/node_modules /app/node_modules
COPY . /app
RUN --mount=type=secret,id=dl_secret 
RUN export NEXT_PUBLIC_DIRECT_LINE_SECRET=$(cat /run/secrets/dl_secret)
RUN yarn build && \
    rm -rf node_modules

# Build target production #
###########################
FROM base AS production
COPY --from=builder /app/public /app/public
COPY --from=builder /app/.next /app/.next
COPY --from=builder /app/next.config.js /app/next.config.js
COPY --from=dependencies /prod_node_modules /app/node_modules
CMD [ "yarn", "start" ]

HEALTHCHECK --interval=5s --timeout=5s --retries=3 \
    CMD curl --fail http://localhost:3000 || exit 1

I originally had these two lines just under the top RUN line but thought maybe they were being called too early? Still I get the same issue when moved lower...

RUN --mount=type=secret,id=dl_secret 
RUN export NEXT_PUBLIC_DIRECT_LINE_SECRET=$(cat /run/secrets/dl_secret)

This is the error I am getting in the build pipeline on the docker build task

[...]

#12 [builder 3/5] RUN --mount=type=secret,id=dl_secret
#12 sha256:8a1115368ff855c4abf1043ef21d89bc00cfaa8759ba13fc73644e5df74a668b
#12 DONE 0.3s

#13 [builder 4/5] RUN export NEXT_PUBLIC_DIRECT_LINE_SECRET=$(cat /run/secrets/dl_secret)
#13 sha256:0e752980cf8a0ad0065c0ecc815a4f42a9c06aff4dc6de47eef68b9f01805e96
#13 0.306 cat: can't open '/run/secrets/dl_secret': No such file or directory
#13 DONE 0.3s

[...]

When reading the documentation on BuildKit, it says to run docker build like this DOCKER_BUILDKIT=1 docker build, or to have the variable set, as was seen in the post I linked above which I have done (I even set it twice to make sure it wasn't in the wrong place) but this is what my docker command looks like when looking through these pipeline build logs /usr/bin/docker build -f /home/vsts/work/1/s/Dockerfile --label com.azure.dev.image.system.teamfoundationcollectionuri=https://dev.azure.com/[...] whether its supposed to have the DOCKER_BUILDKIT=1 in front of the build command I don't know, could this be the reason its not working?

I am not sure what is wrong with the build, whether it is a case of the file not being created, or just that I have set it up wrong? I have spent hours trying to research the problem and not found much applicable info and have made 100s of edits to no avail. Maybe it is something rather simple, but I am really in a rush to have this sorted this weekend and I am not sure what to try next. I'm not sure how to browse the files on DevOps to see if any files are there.

Any help would be greatly appreciated!

CodePudding user response:

The --mount command must be used in the same layer that you wish to consume your secret. You are currently specifying the --mount in a one RUN command and then attempting to cat the mounted secret in another RUN command.

If you change your Dockerfile to use a single RUN command, the mounted secret will be available:

RUN --mount=type=secret,id=dl_secret \
  export NEXT_PUBLIC_DIRECT_LINE_SECRET=$(cat /run/secrets/dl_secret)

The current syntax for Dockerfile frontends can be found here: https://github.com/moby/buildkit/blob/master/frontend/dockerfile/docs/syntax.md#run---mounttypesecret

  • Related