Pass secrets to Docker build to fetch private Github repositories
Tags: docker, github
Published: 2021-12-28 18:20:17

To fetch private repositories as dependencies in a Docker image build procedure, you must set the Github credentials.

The popular errors while an invalid credential is set:

> fatal: could not read Username for ‘https://github.com': No such device or address

---

## Git URL config
There are lots of posts on the internet to do this by setting your Github personal token in the git URL config, all of them are insecure because actually, they’re suggesting to pass your Github personal token to the Dockerfile as an argument and set it as the username of the Github repositories. remind that every command in Dockerfile, is printed on the build log and is accessible from the build history, so your private token is printed on the logs and ….

## The SSH key method
You can also use an SSH key to download private repositories in the Docker build procedure. for this you need to generate a new SSH key and assign it to your Github account, then store the private key into the repository secrets and write it into a file in the Github action job step, then copy the file from the context directory to the .ssh directory of build container. By using this method, you are not in control of the SSH key scopes, the SSH key is your identity and has access to your whole account.

## Using .netrc file
[The .netrc file contains login and initialization information used by the auto-login process.](https://www.gnu.org/software/inetutils/manual/html_node/The-_002enetrc-file.html)

To use .netrc file, you must generate [a new personal access token](https://github.com/settings/tokens/new) with private repositories related scopes, for example, if your private repositories exist under your account, therepo scope is enough, but if they exist under your organization or team account, theadmin:org scope is required.

Then store the generated personal access token in the repository secrets. Here I saved it with `API_TOKEN_GITHUB` name.

Create a Github action file:
```yaml
name: Docker Image CI

on:
  push:
    branches: [ master ]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - name: Store netrc file
        run: echo 'machine github.com login ${{ secrets.API_TOKEN_GITHUB }} password x-oauth-basic' > .netrc
      - name: Build the Docker image
        run: DOCKER_BUILDKIT=1 docker build --file Dockerfile --tag test-image:$(date +%s) --secret id=github,src=.netrc .
```

In this action, first, we store our secrets into the .netrc file, then pass the file as secret to the Docker build command.
Github action job hides the secrets in the logs, so it’s safe to use secrets in the run command.
After that, you must mount the secret file to root/.netrc in Dockerfile, (in this example we’re running Golang module download command after mounting the secret)

```dockerfile
RUN --mount=type=secret,id=github,dst=/root/.netrc \
    go env -w GOPRIVATE=github.com/YOUR_USERNAME/* \
    && env GIT_TERMINAL_PROMPT=1 go mod download
```

**Notice**: You must run the go mod download or npm install commands right after mounting the secret file, actually in the same Docker Run command.

## Using docker/build-push-action@v2
If you are using a Github action to build or push your image, you should pass the .netrc file like this:

```yaml
# bluh bluh bluh 

- name: Store netrc file
  run: echo 'machine github.com login ${{ secrets.API_TOKEN_GITHUB }} password x-oauth-basic' > .netrc
- name: Push to GitHub Packages
  uses: docker/build-push-action@v2
  with:
    context: .
    push: true
    secret-files: |
      "github=./.netrc"
```

## TL;DR
* Don’t pass your secret to Docker build command as an argument, your secrets are printed in the build logs and history.
* Using SSH key limits your control of the scopes.
* You can store secrets in the .netrc file via the Github action and then pass it as a secret file to the Docker build command. (follow .netrc section)