Artifact Registry: Docker Images, Maven/NPM Packages, and Vulnerability Scanning
A production-focused guide to Artifact Registry: Docker Images, Maven/NPM Packages, and Vulnerability Scanning on Google Cloud Platform..
20+ years shipping production infrastructure and CI/CD at scale. Drawn from code that ran under real load.
- ✓Google Cloud SDK (gcloud) version 400.0.0+, Docker 20.10+, Maven 3.8+, Node.js 18+, a Google Cloud project with billing enabled, and basic familiarity with IAM and CI/CD pipelines.
Artifact Registry: Docker Images, Maven/NPM Packages, and Vulnerability Scanning is like having a specialized tool that handles artifact registry so you don't have to build and manage it yourself — it just works out of the box with Google Cloud's infrastructure.
Your production pipeline just went down because a developer accidentally pushed a Docker image with a critical CVE to a public registry. Or worse, your Maven build broke because someone deleted a dependency from a shared filesystem. These are not hypotheticals—they happen every day. Artifact Registry exists to prevent exactly these scenarios by giving you a secure, auditable, and scalable home for all your build outputs. It's not just storage; it's the backbone of your software supply chain. In this article, we'll cover how to set up Artifact Registry for Docker, Maven, and NPM, integrate vulnerability scanning, and avoid the pitfalls that take down production.
Why Artifact Registry Over a Simple Storage Bucket?
A cloud storage bucket (like GCS or S3) can store files, but it lacks the metadata, access control granularity, and lifecycle management that artifact management demands. Artifact Registry provides immutable versioning, fine-grained IAM (e.g., read-only for CI, write for developers), and native integration with build tools. It also supports vulnerability scanning out of the box, which is critical for compliance. In production, we've seen teams use buckets and then struggle with accidental overwrites, missing audit trails, and manual cleanup. Artifact Registry solves these by enforcing policies like 'keep last 10 versions' or 'block images with critical vulnerabilities'.
Setting Up a Docker Repository with Vulnerability Scanning
Creating a Docker repository is straightforward, but the real value comes from enabling vulnerability scanning. This scans each pushed image against CVE databases (e.g., OS packages, language dependencies). You can configure it to block pushes that contain critical vulnerabilities. In production, we enforce scanning on all images and use a custom policy to reject images with any critical or high CVEs. This prevents vulnerable images from ever reaching production. The scanning is automatic and runs asynchronously, so it doesn't slow down pushes.
Pushing and Pulling Docker Images with Authentication
Authentication is key. Use service accounts with least-privilege roles. For CI, create a dedicated service account with only artifactregistry.reader for pull and artifactregistry.writer for push. Never use user credentials in scripts. Configure Docker to use gcloud auth configure-docker for automatic token refresh. In production, we rotate service account keys every 90 days and use workload identity federation for Kubernetes clusters to avoid storing keys.
Managing Maven Packages with Artifact Registry
Maven repositories in Artifact Registry follow the same pattern. You create a repository with format maven, then configure your pom.xml to use it. The key is to use the google-cloud-maven-plugin for authentication. In production, we use separate repositories for snapshots and releases, with different cleanup policies. Snapshots are kept for 7 days, releases are immutable. This prevents accidental overwrites of release artifacts.
Configuring Maven Authentication
Maven needs credentials to push/pull from Artifact Registry. Use the google-cloud-maven-plugin which reads from Application Default Credentials. In CI, set GOOGLE_APPLICATION_CREDENTIALS to the service account key. For local development, use gcloud auth application-default login. Never store credentials in settings.xml as plaintext. In production, we use a CI-specific service account with only artifactregistry.writer for the snapshot repo and artifactregistry.reader for the release repo.
settings.xml with a service account key. The repo was public, and the key was compromised within hours. We now scan for secrets in commits.Publishing and Consuming NPM Packages
NPM packages in Artifact Registry work similarly. Create a repository with format npm, then configure .npmrc to point to it. Authentication uses npx google-artifactregistry-auth which generates a token. In production, we use scoped packages (e.g., @mycompany/package) to avoid conflicts with public npm. We also enable vulnerability scanning for npm packages, which checks for malicious packages and known vulnerabilities.
Configuring NPM Authentication for CI
For CI, create a .npmrc file that uses the Artifact Registry token. The token can be obtained via npx google-artifactregistry-auth which outputs a token. Store the token as a CI secret. In production, we use a CI service account with artifactregistry.writer for publishing and artifactregistry.reader for installing. We also set registry in .npmrc to the Artifact Registry URL to avoid accidental publishes to public npm.
.npmrc with tokens. Use environment variables and generate the file in CI. We use a template and inject the token at build time..npmrc with a valid token. The token was used to publish malicious packages. We now rotate tokens every 30 days.Vulnerability Scanning for All Artifact Types
Artifact Registry supports vulnerability scanning for Docker, Maven, and NPM. Scanning is automatic and checks against multiple databases (e.g., OSV, NVD). You can view scan results in the console or via API. In production, we use Cloud Build to trigger a webhook on scan completion that fails the build if critical vulnerabilities are found. We also set up alerts for new vulnerabilities in existing artifacts. This is crucial for compliance (e.g., SOC2, PCI-DSS).
Cleanup Policies and Lifecycle Management
Artifact Registry supports cleanup policies to automatically delete old artifacts. You can define rules based on age, version count, or tags. In production, we keep only the last 10 versions of each Docker image, delete Maven snapshots older than 7 days, and keep NPM packages indefinitely but with a maximum of 5 versions. This prevents storage costs from ballooning. We also use --immutable-tags to prevent overwrites. Cleanup policies are evaluated periodically (every few hours).
--dry-run to see what would be deleted before applying. We always run a dry run in a staging environment first.Access Control with IAM and VPC-SC
Fine-grained access control is critical. Use IAM roles like artifactregistry.reader, artifactregistry.writer, and artifactregistry.admin. For production, we use VPC Service Controls to restrict access to the registry from only trusted VPCs. This prevents data exfiltration. We also use private Google Access for on-premises builds. In production, we have a dedicated service account per team with least privilege.
Monitoring and Auditing
Enable audit logs for Artifact Registry to track all operations. Use Cloud Monitoring to set up alerts for failed pushes, high vulnerability counts, or unusual access patterns. In production, we have a dashboard that shows the number of artifacts, vulnerabilities by severity, and storage usage. We also set up alerts for when a critical vulnerability is found in a production image. This is essential for incident response.
Multi-Region Replication and Disaster Recovery
For high availability, use multi-region repositories. Artifact Registry supports us, europe, and asia multi-regions. This replicates data across zones within a region. For disaster recovery, we use a secondary registry in a different region with a Cloud Build trigger to sync critical artifacts. In production, we have a primary in us-central1 and a secondary in europe-west1. If the primary goes down, we switch DNS to the secondary.
On-Demand Scanning in CI/CD: Gate Deployments Before Push
Artifact Registry offers two scanning modes: automatic (after push) and on-demand (before push). On-demand scanning is the key to CI/CD gating. Use 'gcloud artifacts docker images scan' to scan a locally built image before pushing. Evaluate results with a severity policy—zero tolerance for CRITICAL, alert on HIGH above a threshold. Only push to the registry if the scan passes. This prevents vulnerable images from ever reaching the registry. After push, the automatic scan provides continuous monitoring for new CVEs over a 30-day window. For long-lived base images, create a Cloud Scheduler job to re-push monthly to reset the monitoring window. Pair with Binary Authorization for GKE to require a 'passed vulnerability scan' attestation before pods are scheduled, closing the loop from build to deployment.
Language Package Scanning: Beyond Container Images
Artifact Registry's vulnerability scanning isn't just for Docker images. It also scans language packages: Maven (Java), npm (Node.js), Python (PyPI), Go, Ruby, Rust, .NET, and PHP. Scanning runs automatically when packages are pushed, extracting dependency metadata and matching against the GitHub Advisory Database. The scan covers both the package's own dependencies and transitives. For Maven, packages must follow Maven naming conventions. For npm, version matching follows semver. Packages with over 100 files are not scanned. Scanning is enabled per repository (not just per project), so you can disable it for low-risk internal tooling repos while keeping it active on customer-facing packages. Results appear in the Artifact Registry console and are accessible via the Container Analysis API. The cost is $0.26 per scan, with continuous monitoring for 30 days—same as container scanning.
| File | Command / Code | Purpose |
|---|---|---|
| create-repo.sh | gcloud artifacts repositories create my-docker-repo \ | Why Artifact Registry Over a Simple Storage Bucket? |
| enable-scanning.sh | gcloud artifacts repositories update my-docker-repo \ | Setting Up a Docker Repository with Vulnerability Scanning |
| docker-push.sh | gcloud auth configure-docker us-central1-docker.pkg.dev | Pushing and Pulling Docker Images with Authentication |
| pom.xml | Managing Maven Packages with Artifact Registry | |
| settings.xml | Configuring Maven Authentication | |
| npm-publish.sh | npx google-artifactregistry-auth | Publishing and Consuming NPM Packages |
| .npmrc | registry=https://us-central1-npm.pkg.dev/my-project/my-npm-repo/ | Configuring NPM Authentication for CI |
| cloudbuild.yaml | steps: | Vulnerability Scanning for All Artifact Types |
| cleanup-policy.sh | gcloud artifacts repositories set-cleanup-policies my-docker-repo \ | Cleanup Policies and Lifecycle Management |
| iam-policy.sh | gcloud artifacts repositories add-iam-policy-binding my-docker-repo \ | Access Control with IAM and VPC-SC |
| enable-audit-logs.sh | gcloud projects add-iam-policy-binding my-project \ | Monitoring and Auditing |
| create-multi-region.sh | gcloud artifacts repositories create my-docker-repo \ | Multi-Region Replication and Disaster Recovery |
| check_package_vulnerabilities.sh | gcloud artifacts versions describe 1.2.3 \ | Language Package Scanning |
Key takeaways
Common mistakes to avoid
3 patternsIgnoring gcp artifact registry best practices
Over-provisioning without rightsizing analysis
Skipping IAM least-privilege principles
Interview Questions on This Topic
What is Artifact Registry: Docker Images, Maven/NPM Packages, and Vulnerability Scanning and when would you use it in production?
Frequently Asked Questions
20+ years shipping production infrastructure and CI/CD at scale. Drawn from code that ran under real load.
That's Google Cloud. Mark it forged?
4 min read · try the examples if you haven't