[Accessing Private Google Artifact Registry With Poetry: Local and Docker Setup]
Analyze with AI
Get AI-powered insights from this Mad Devs tech article:
Before you start
The setup described here uses Poetry >= 1.7.1, keyring >= 24.0.0, and keyrings.google-artifactregistry-auth >= 1.0.0. A few updates worth noting:
keyrings.google-artifactregistry-authhas been superseded by google-auth-based credential helpers in newer Poetry versions. If you encounter authentication issues with the keyring approach on Python 3.12+, try runningpython -m keyrings.google_artifactregistry_authexplicitly to verify the keyring backend is correctly registered.- Docker BuildKit is now enabled by default in Docker Desktop 4.x+ and Docker Engine 23+. The
--mount=type=secretsyntax used in this guide requires BuildKit and will work out of the box without settingDOCKER_BUILDKIT=1explicitly. - In January 2025, Google patched the ImageRunner vulnerability in Cloud Run, which allowed unauthenticated access to private Artifact Registry images under certain IAM conditions. If your GAR repository was accessible via Cloud Run before January 28 2025, it is worth auditing your IAM bindings to confirm no unintended access was granted.
Accessing a private Google Artifact Registry locally: Python and Docker
When building Python applications with Poetry in a Docker container, we sometimes encounter issues accessing private packages stored in the Google Artifact Registry (GAR). Locally, this challenge arises because docker build cannot directly handle the Google Cloud credentials in the same way as our CI/CD pipeline, where we leverage service accounts and the Kaniko action for secure builds.
To resolve this, we'll cover two approaches: keyring-based authentication for local Python development using keyrings.google-artifactregistry-auth, and Docker Compose build secrets for containerised builds – both without exposing GCP credentials in the image.
Non-containerized
This approach uses keyrings.google-artifactregistry-auth to allow Poetry to authenticate with your private GAR Python repository automatically via application default credentials — no manual token passing required.
Pre-requirements
- Python ^3.12
- Poetry ^1.7.1
- Google Cloud SDK ^489.0.0
- Keyring ^24.0.0
- keyrings.google-artifactregistry-auth ^1.0.0
- Read access to your GAR Python repository
- Logged into GCP (gcloud auth application-default login)
Setup
1. Keyring setup
Install keyring support for Google Artifact Registry:
pip install keyring
pip install keyrings.google-artifactregistry-auth2. Connect Poetry to your GAR repo
Access to the private repository in the Google Artifact Registry can be managed through Poetry. First, configure a custom source in Poetry for the GAR repository by running:
poetry source add --priority=explicit <PACKAGE_NAME> https://<REGION>-python.pkg.dev/<PROJECT>/<REGISTRY>/simpleNote: Be sure to append /simple to the repository URL for compatibility.
Now you can install packages from your private repo:
poetry add --source <PACKAGE_NAME> [email protected]Notes
In some cases, accessing the repository may require setting an explicit OAuth token for authentication in Poetry. Use the following command to configure this globally in Poetry:
poetry config http-basic.<PACKAGE_NAME> oauth2accesstoken $(gcloud auth print-access-token)Containerized
Pre-requirements
- Docker ^20.10
- Docker Compose ^2.0
- Google Cloud SDK ^489.0.0
- Read access to your GAR Python repository
- Logged into GCP (
gcloud auth application-default login)
Setup
1. Secrets configuration
First, define a secret in docker-compose.yaml using the local path to your credentials file:
secrets:
gcloud_credentials:
file: ~/.config/gcloud/application_default_credentials.json- We define
gcloud_credentials.fileas a consistent path for Unix-like environments indocker-compose.yaml: - This configuration uses Docker Compose build secrets to securely pass the
application_default_credentials.jsonfile from your local machine to the build context – credentials never end up in the image layers or the build cache.
2. Dockerfile adjustments
In the Dockerfile, we handle credentials with the following setup:
ARG GOOGLE_APPLICATION_CREDENTIALS
ENV GOOGLE_APPLICATION_CREDENTIALS=${GOOGLE_APPLICATION_CREDENTIALS}
RUN --mount=type=secret,id=gcloud_credentials \
mkdir -p $(dirname ${GOOGLE_APPLICATION_CREDENTIALS}) && \
cp /run/secrets/gcloud_credentials ${GOOGLE_APPLICATION_CREDENTIALS}--mount=type=secret,id=gcloud_credentials: Securely mounts the credentials during the build process.GOOGLE_APPLICATION_CREDENTIALS: Specifies the credential file's path within the container.
3. Service configurations
Here, gcloud_credentials is the secret mounted at build time, as specified in the secrets configuration.
some-service:
build:
context: .
dockerfile: ./Dockerfile.local
args:
GOOGLE_APPLICATION_CREDENTIALS: /tmp/application_default_credentials.json
secrets:
- gcloud_credentialsUsage
Just run:
docker-compose up --buildConclusion
This approach allows local Docker builds to access private GAR resources securely, ensuring that credentials are handled appropriately and remain protected.
