'cloud build pass secret env to dockerfile

I am using google cloud build to build a docker image and deploy in cloud run. The module has dependencies on Github that are private. In the cloudbuild.yaml file I can access secret keys for example the Github token, but I don't know what is the correct and secure way to pass this token to the Dockerfile.

I was following this official guide but it would only work in the cloudbuild.yaml scope and not in the Dockerfile. Accessing GitHub from a build via SSH keys

cloudbuild.yaml

steps:
  - name: gcr.io/cloud-builders/docker
    args: ["build", "-t", "gcr.io/$PROJECT_ID/$REPO_NAME:$COMMIT_SHA", "."]

  - name: gcr.io/cloud-builders/docker
    args: [ "push", "gcr.io/$PROJECT_ID/$REPO_NAME:$COMMIT_SHA" ]

  - name: gcr.io/google.com/cloudsdktool/cloud-sdk
    entrypoint: gcloud
    args: [
      "run", "deploy", "$REPO_NAME",
      "--image", "gcr.io/$PROJECT_ID/$REPO_NAME:$COMMIT_SHA",
      "--platform", "managed",
      "--region", "us-east1",
      "--allow-unauthenticated",
      "--use-http2",
    ]

images:
  - gcr.io/$PROJECT_ID/$REPO_NAME:$COMMIT_SHA

availableSecrets:
  secretManager:
    - versionName: projects/$PROJECT_ID/secrets/GITHUB_USER/versions/1
      env: "GITHUB_USER"
    - versionName: projects/$PROJECT_ID/secrets/GITHUB_TOKEN/versions/1
      env: "GITHUB_TOKEN"

Dockerfile

# [START cloudrun_grpc_dockerfile]
# [START run_grpc_dockerfile]
FROM golang:buster as builder

# Create and change to the app directory.
WORKDIR /app

# Create /root/.netrc cred github
RUN echo machine github.com >> /root/.netrc
RUN echo login "GITHUB_USER" >> /root/.netrc
RUN echo password "GITHUB_PASSWORD" >> /root/.netrc

# Config Github, this create file /root/.gitconfig
RUN git config --global url."ssh://[email protected]/".insteadOf "https://github.com/"

# GOPRIVATE
RUN go env -w GOPRIVATE=github.com/org/repo

# Do I need to remove the /root/.netrc file? I do not want this information to be propagated and seen by third parties.

# Retrieve application dependencies.
# This allows the container build to reuse cached dependencies.
# Expecting to copy go.mod and if present go.sum.
COPY go.* ./
RUN go mod download

# Copy local code to the container image.
COPY . ./

# Build the binary.
# RUN go build -mod=readonly -v -o server ./cmd/server
RUN go build -mod=readonly -v -o server

# Use the official Debian slim image for a lean production container.
# https://hub.docker.com/_/debian
# https://docs.docker.com/develop/develop-images/multistage-build/#use-multi-stage-builds
FROM debian:buster-slim
RUN set -x && apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y \
    ca-certificates && \
    rm -rf /var/lib/apt/lists/*

# Copy the binary to the production image from the builder stage.
COPY --from=builder /app/server /server

# Run the web service on container startup.
CMD ["/server"]

# [END run_grpc_dockerfile]
# [END cloudrun_grpc_dockerfile]

After trying for 2 days I have not found a solution, the simplest thing I could do was to generate the vendor folder and commit it to the repository and avoid go mod download.



Solution 1:[1]

You have several way to do things.

With Docker, when you run a build, you run it in an isolated environment (it's the principle of isolation). So, you haven't access to your environment variables from inside the build process.

To solve that, you can use build args and put your secret values in that parameter.

But, there is a trap: you have to use bash code and not built in step code in Cloud Build. Let me show you

# Doesn't work
  - name: gcr.io/cloud-builders/docker
    secretEnv: ["GITHUB_USER","GITHUB_TOKEN"]
    args: ["build", "-t", "gcr.io/$PROJECT_ID/$REPO_NAME:$COMMIT_SHA", "--build-args=GITHUB_USER=$GITHUB_USER,GITHUB_TOKEN=$GITHUB_TOKEN","."]

# Working version
  - name: gcr.io/cloud-builders/docker
    secretEnv: ["GITHUB_USER","GITHUB_TOKEN"]
    entrypoint: bash
    args: 
     - -c
     - |
        docker build -t gcr.io/$PROJECT_ID/$REPO_NAME:$COMMIT_SHA --build-args=GITHUB_USER=$$GITHUB_USER,GITHUB_TOKEN=$$GITHUB_TOKEN .

You can also perform the actions outside of the Dockerfile. It's roughly the same thing: load a container, perform operation, load another container and continue.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 guillaume blaquiere