

Securely Access Private Git Repositories and Composer Packages in Docker Builds
source link: https://dunglas.fr/2022/08/securely-access-private-git-repositories-and-composer-packages-in-docker-builds/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Securely Access Private Git Repositories and Composer Packages in Docker Builds
When working on enterprise projects, it’s common to have to download private dependencies that require authentication to be installed (usually, internal or paid packages).
In modern setups, you’ll most likely use Docker to package your application (or service) and all its dependencies into a standalone image. Typically, building the Docker image is automated through a continuous deployment system.
Do Not Leak Your Secret Keys!
Most forges, including the popular GitHub and GitLab services, provide at least two ways to access private repositories: using HTTP authentication with personal access tokens or using SSH.
Most package managers, including Composer (the PHP package manager), support authentication by these means.
Composer, for instance, can use the following methods:
- Storing the personal access tokens provided by the forge in a file named
auth.json
- Storing them in an environment variable named
COMPOSER_AUTH
- Relying on SSH authentication
A good security practice is to prevent people who can access your Docker images from also having access to these secrets, and thus to the private repositories they grant access to. This means that the secrets should be used to download dependencies, but should not be accessible to people who have access to the Docker image or to the Git repository containing the source code.
Unfortunately, this is quite difficult to achieve with Docker. For performance reasons, Docker caches the result of each build step in what are called layers.
Anyone with access to an image can access all the layers created during the build process. Exploring the content of layers is very easy with tools like dive
. That means that if you copy your tokens (e.g. the auth.json
file for Composer) to download your private dependencies, then remove them from the image, they will still be accessible to anyone having access to the final image through the layers!
Relying on environment variables or build args is not a better option: their values are also accessible to anyone who has access to the image!
Docker Build Secret Information
Docker 18.09 (2018) and Docker Compose 2.7.0 (2022) have introduced a new feature to solve this common problem: build secrets.
Build secrets allow files containing secrets to be mounted at build time, and guarantee that the content of these files will not be accessible in the final image.
They have also added a new subsystem designed specifically for downloading private dependencies: the ability to use the host system’s SSH access during builds.
This is very convenient because SSH has always been the preferred way to download private Git repositories, and is of course supported out of the box by the popular version control system.
Cloning a Private Git Repository Thanks to SSH Forwarding
Let’s create a Docker image containing a private Git repository but not the credentials needed to download it!
First, make sure that you’re able to download your private repository from your host:
Then, ensure that your private SSH key is added to the SSH agent (Docker will connect to it) by running:
ssh-add
You should now be able to build an image that contains your private repository:
FROM alpine
# OpenSSH client and Git are required dependencies to clone the repository
RUN apk add --no-cache openssh-client git
# Add the SSH public keys of the Git server to the known hosts (here, github.com)
RUN mkdir -p -m 0700 ~/.ssh && ssh-keyscan github.com >> ~/.ssh/known_hosts
# Clone the repository, notice the "--mount=type=ssh" option, which allow this instruction to use SSH forwarding
RUN --mount=type=ssh git clone --depth=1 '[email protected]:dunglas/my-private-repo.git'
Finally, hint Docker that it needs to connect to the default SSH agent of the host:
docker build --ssh default
Tadam! You have cloned a private Git repo without disclosing the secret key!
Downloading Private Composer Packages
Under the hood, Composer uses Git to download private repositories (it can also use other protocols such as HTTP, but this is less practical with Docker and is outside the scope of this article). Applying the same method we’ve seen previously is straightforward.
Here is a composer.json
file referencing a private package stored on GitHub thanks to the repositories
option:
{
"require": {
"dunglas/my-private-package": "dev-main"
},
"repositories": [
{
"type": "vcs",
"url": "[email protected]:dunglas/my-private-package.git"
}
]
}
By the way, if you rely on private packages, consider subscribing to Private Packagist, a nice service created by the Composer team specially dedicated for this use case.
To copy this private repository into the vendor/
directory of the Docker image, use the following Dockerfile
:
FROM php:alpine
RUN apk add --no-cache openssh-client git
RUN mkdir -p -m 0700 ~/.ssh && ssh-keyscan github.com >> ~/.ssh/known_hosts
# Install Composer
COPY --from=composer /usr/bin/composer /usr/bin/composer
# Copy the composer.json and composer.lock file
COPY composer.* .
# Install the dependencies and allow Docker to use the SSH credentials of the host
RUN --mount=type=ssh composer install --no-progress --no-interaction
If you already use the Symfony Docker skeleton or API Platform, you can adapt the provided Dockerfiles: add the required packages, add the SSH keys of your forge, and add `–mount=type=ssh` to the existing RUN
instruction doing a composer install
.
Docker Compose
Docker Compose now natively supports SSH forwarding! Use the new --ssh default
flag to let the builder use the SSH connection of the host:
docker compose build --ssh default
GitHub Actions and GitLab CI
Finally, you’ll probably want to build the Docker image directly into your CD pipeline.
To achieve this, the first step is to create deployment keys for your private Git repositories. Deploy keys are special SSH keys that grant read-only access to Git repositories.
First, generate a pair of public and private keys for each private repository. Then upload the public key on the forge and associate it with the private repository:
After that, store the private key as a CI secret:
Finally, each time you start a job building Docker images, copy the private key from the secret variable to SSH and start an SSH agent. To do so, I strongly recommend using the ssh-agent
GitHub Action, which automates this process:
# .github/workflows/build-image.yml
jobs:
build:
steps:
- uses: actions/checkout@v2
- uses: webfactory/[email protected]
with:
ssh-private-key: ${{ secrets.MY_PRIVATE_DEPLOY_KEY }}
- run: docker compose build --ssh default
You should now be able to safely build Docker images containing private code!
If you need help setting up fast and secure CI/CD pipelines, optimizing your Docker images, or creating platforms on top of Kubernetes, don’t hesitate to contact the great DevOps team at Les-Tilleuls.coop!
If you liked this post, consider sponsoring me on GitHub.
Recommend
-
85
Composer Local Packages for Dummies 2017-12-25 This is the simplest way to start...
-
48
README.md composer-unused Show unused packages by scanning your code
-
21
How to create a private Composer repository with GitLab Package Registry.
-
14
How to use Composer packages directly from GitHub (or other VCS) ...
-
4
How to use your private NPM packages with Docker on CI
-
11
Restore NuGet Packages from a Private Feed when building Docker Containers Posted 2 days ago2021-01-04T00:00:00+01:00 by Wolfgang Ofner
-
2
Composer Packages that Every Laravel Developer Must Have September 13th 2022 new story4
-
10
Access Your Bitbucket Cloud Repositories More Securely With Resource Scoped Access Tokens. November 23, 2022 3 min read
-
5
Accessing Private Git Repositories from Docker Containersby Burkhard Stubert2023/03/202023/03/2...
-
4
Get Composer to suggest dev packages to require-dev Published On2023-08-31
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK