ssh-agent: Multiple Deploy Keys in docker build fails

Not exactly a bug, but I found it challenging to find a solution that works with docker build when using multiple deploy keys. The reason seems to be that the build container doesn’t have the ssh and git config necessary to map the right key to the right repo.

For example:

      - name: Setup SSH
        uses: webfactory/ssh-agent@v0.5.0
        with:
          ssh-private-key: |
            ${{ secrets.DEPLOY_KEY_A }}
            ${{ secrets.DEPLOY_KEY_B }}
      - name: Works Well!
        run: |
          git clone github.com/me/private-repo-a
          git clone github.com/me/private-repo-b
      - name: Doesn't work :(
        run: |
          cat > Dockerfile <<EOF
          FROM debian
          RUN --mount=type=ssh git clone github.com/me/private-repo-a
          RUN --mount=type=ssh git clone github.com/me/private-repo-b
          EOF
          docker build --ssh default .

The docker build has access to the keys, but it doesn’t use the right one for each repo, so one of the checkouts will fail.

My solution was to copy the config into the container:

run: |
  mkdir root-config
  cp -r ~/.gitconfig  ~/.ssh root-config/
  docker build ... .

And in my Dockerfile:

COPY root-config /root/
RUN sed 's|/home/runner|/root|g' -i.bak /root/.ssh/config

That works, but it feels pretty hacky. I was just wondering if anyone can come up with a better way/wanted to document a way to make it work.

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Reactions: 4
  • Comments: 16 (6 by maintainers)

Commits related to this issue

Most upvoted comments

I guess the problem is not having the SSH auth socket itself available, but the necessary mapping in .gitconfig and .ssh/config to map keys to repos.

While this is a bit of an older issue, I seemed to have solved this with our build process by doing something like this

Posting here for any other who come across this

    # Setup SSH_AUTH_SOCK to pull from other git repos during the build, using separate sockets via ssh-auth-sock to be able to define them in the docker build section
    - name: Setup SSH_AUTH_SOCK Repo A
      uses: webfactory/ssh-agent@v0.5.4
      with:
        ssh-private-key: ${{ secrets.REPO_A_DEPLOY_KEY }}
        ssh-auth-sock: /tmp/repo-a-${{ github.sha }}.sock

    - name: Setup SSH_AUTH_SOCK Repo B
      uses: webfactory/ssh-agent@v0.5.4
      with:
        ssh-private-key: ${{ secrets.REPO_B_DEPLOY_KEY }}
        ssh-auth-sock: /tmp/repo-b-${{ github.sha }}.sock

    # Sets up buildx to enable docker buildkit features
    - name: Set up Docker Buildx
      id: buildx
      uses: docker/setup-buildx-action@v2
      with:
        install: true

    - name: Build and push
      uses: docker/build-push-action@v3
      with:
        push: true
        tags: myregistry/myrepo:latest
        file: Dockerfile
        ssh: |
          default=${{ env.SSH_AUTH_SOCK }}
          repoa=/tmp/repo-a-${{ github.sha }}.sock
          repob=/tmp/repo-b-${{ github.sha }}.sock

This sets up separate ssh mount IDs you can reference in your build file:

# Note: the id here matches what is defined in the docker build and push step above

# Repo A action
RUN --mount=type=ssh,id=repoa git clone git@github.com:org/repo-a.git .

# Repo B Action
RUN --mount=type=ssh,id=repob yarn install --frozen-lockfile

I didn’t realize the key-* files in ~/.ssh already were just the public keys. So I think that while copying the contents of ~/.ssh into a container is less than ideal, it is at least not disclosing anything meant to be secret and is the best we can do with Docker at the moment.

Thanks for a very helpful action.

@nicolo-kira the solution you suggested is the neated IMO. Including the one in the documentation. Note you can also remove the default=${{ env.SSH_AUTH_SOCK }} line, which is neat because some linters false positively flag this line.

@mpdude Is it possible to add this solution to the documentation? Its safer and easier to implement. I am unsure if there are any downsides to this approach.