Using secrets with GitHub Actions

Table of contents

A build secret is sensitive information, such as a password or API token, consumed as part of the build process. Docker Build supports two forms of secrets:

  • Secret mounts add secrets as files in the build container (under /run/secrets by default).
  • SSH mounts add SSH agent sockets or keys into the build container.

This page shows how to use secrets with GitHub Actions. For an introduction to secrets in general, see Build secrets.

Secret mounts

In the following example uses and exposes the GITHUB_TOKEN secret as provided by GitHub in your workflow.

First, create a Dockerfile that uses the secret:

# syntax=docker/dockerfile:1
FROM alpine
RUN --mount=type=secret,id=github_token \
  cat /run/secrets/github_token

In this example, the secret name is github_token. The following workflow exposes this secret using the secrets input:

name: ci

on:
  push:
    branches:
      - "main"

jobs:
  docker:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v4
      - name: Set up QEMU
        uses: docker/setup-qemu-action@v3
      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3
      - name: Build
        uses: docker/build-push-action@v5
        with:
          context: .
          platforms: linux/amd64,linux/arm64
          tags: user/app:latest
          secrets: |
            "github_token=${{ secrets.GITHUB_TOKEN }}"            

Note

You can also expose a secret file to the build with the secret-files input:

secret-files: |
  "MY_SECRET=./secret.txt"  

If you're using GitHub secrets and need to handle multi-line value, you will need to place the key-value pair between quotes:

secrets: |
  "MYSECRET=${{ secrets.GPG_KEY }}"
  GIT_AUTH_TOKEN=abcdefghi,jklmno=0123456789
  "MYSECRET=aaaaaaaa
  bbbbbbb
  ccccccccc"
  FOO=bar
  "EMPTYLINE=aaaa

  bbbb
  ccc"
  "JSON_SECRET={""key1"":""value1"",""key2"":""value2""}"  
KeyValue
MYSECRET***********************
GIT_AUTH_TOKENabcdefghi,jklmno=0123456789
MYSECRETaaaaaaaa\nbbbbbbb\nccccccccc
FOObar
EMPTYLINEaaaa\n\nbbbb\nccc
JSON_SECRET{"key1":"value1","key2":"value2"}

Note

Double escapes are needed for quote signs.

SSH mounts

SSH mounts let you authenticate with SSH servers. For example to perform a git clone, or to fetch application packages from a private repository.

The following Dockerfile example uses an SSH mount to fetch Go modules from a private GitHub repository.

# syntax=docker/dockerfile:1

ARG GO_VERSION="1.21"

FROM golang:${GO_VERSION}-alpine AS base
ENV CGO_ENABLED=0
ENV GOPRIVATE="github.com/foo/*"
RUN apk add --no-cache file git rsync openssh-client
RUN mkdir -p -m 0700 ~/.ssh && ssh-keyscan github.com >> ~/.ssh/known_hosts
WORKDIR /src

FROM base AS vendor
# this step configure git and checks the ssh key is loaded
RUN --mount=type=ssh <<EOT
  set -e
  echo "Setting Git SSH protocol"
  git config --global url."git@github.com:".insteadOf "https://github.com/"
  (
    set +e
    ssh -T git@github.com
    if [ ! "$?" = "1" ]; then
      echo "No GitHub SSH key loaded exiting..."
      exit 1
    fi
  )
EOT
# this one download go modules
RUN --mount=type=bind,target=. \
    --mount=type=cache,target=/go/pkg/mod \
    --mount=type=ssh \
    go mod download -x

FROM vendor AS build
RUN --mount=type=bind,target=. \
    --mount=type=cache,target=/go/pkg/mod \
    --mount=type=cache,target=/root/.cache \
    go build ...

To build this Dockerfile, you must specify an SSH mount that the builder can use in the steps with --mount=type=ssh.

The following GitHub Action workflow uses the MrSquaare/ssh-setup-action third-party action to bootstrap SSH setup on the GitHub runner. The action creates a private key defined by the GitHub Action secret SSH_GITHUB_PPK and adds it to the SSH agent socket file at SSH_AUTH_SOCK. The SSH mount in the build step assume SSH_AUTH_SOCK by default, so there's no need to specify the ID or path for the SSH agent socket explicitly.


name: ci

on:
  push:
    branches:
      - "main"

jobs:
  docker:
    runs-on: ubuntu-latest
    steps:
      -
        name: Checkout
        uses: actions/checkout@v3
      -
        name: Set up SSH
        uses: MrSquaare/ssh-setup-action@7bfdda6ef6839504e3a5b2625ad971b17461a0db # v3.0.0
        with:
          host: github.com
          private-key: ${{ secrets.SSH_GITHUB_PPK }}
          private-key-name: github-ppk
      -
        name: Build and push
        uses: docker/build-push-action@v5
        with:
          context: .
          ssh: default
          push: true
          tags: user/app:latest
name: ci

on:
  push:
    branches:
      - "main"

jobs:
  docker:
    runs-on: ubuntu-latest
    steps:
      -
        name: Checkout
        uses: actions/checkout@v3
      -
        name: Set up SSH
        uses: MrSquaare/ssh-setup-action@7bfdda6ef6839504e3a5b2625ad971b17461a0db # v3.0.0
        with:
          host: github.com
          private-key: ${{ secrets.SSH_GITHUB_PPK }}
          private-key-name: github-ppk
      -
        name: Build
        uses: docker/bake-action@v4
        with:
          set: |
            *.ssh=default