If you're a European business shipping containers, where you store your private images matters more than most teams realise. A container image is a complete snapshot of your application: source-derived binaries, configuration, credentials baked into layers if you're unlucky, and an audit trail of every version you've ever shipped. Treating that as the equivalent of "code that sits on a CI runner" is missing the point. It's closer to a backup of your production system.
The major container registries — GitHub Container Registry, Docker Hub, Red Hat Quay, Amazon ECR Public, Google Artifact Registry — all run on US-based infrastructure operated by US companies. Under post-Schrems-II law, that creates compliance questions a lot of European teams would rather not have to answer.
This post walks through the actual legal landscape, the major registry options, and where DanubeData's container registry fits in.
The Schrems II problem in one paragraph
In July 2020, the Court of Justice of the European Union invalidated the EU-US Privacy Shield (the legal mechanism that previously authorised most personal-data transfers from the EU to the US). The court's reasoning: US surveillance law (FISA Section 702, Executive Order 12333) doesn't provide European data subjects with rights or remedies that are "essentially equivalent" to those guaranteed by the GDPR. Subsequent guidance from the European Data Protection Board (EDPB) made it explicit: using a US-based service to process EU personal data requires supplementary measures, and in many cases those measures don't exist for cloud services that handle data in cleartext on US soil.
The 2023 EU-US Data Privacy Framework (DPF) was supposed to be the fix. As of writing, it's already under challenge, and many regulators treat it as a temporary patch rather than a settled solution. Several European DPAs (notably French CNIL, German LfDI BW) have issued opinions strongly recommending European data stay on European-operated infrastructure where alternatives exist.
Why container images count
"But we don't put personal data in our Docker images" is the response we hear most. It's not quite right. Even a minimal production image typically contains:
- The compiled binary or runtime bundle that processes personal data. Reverse-engineering it reveals your data model and processing logic, which is itself documentation subject to GDPR Art. 30.
- Configuration files that may include endpoint URLs of EU-located services (e.g., your DB host, your S3 endpoint, your internal API gateway). Those endpoint URLs are operational data the GDPR considers in scope for transfer rules.
- Metadata in the manifest history showing every version you've ever shipped, who pushed it, and when. That's a build-and-deploy audit trail of your business — exactly the kind of thing competitors and threat actors find valuable.
- Accidentally embedded secrets. Search GitHub for
"AWS_SECRET_ACCESS_KEY" filename:dockerfile. People still do this. A registry leak weaponises every one of those secrets.
The EDPB doesn't require that you prove personal data is in the image — it requires you to perform a transfer impact assessment for every transfer of any data that could be subject to foreign access. For a private container registry, the assessment is short: yes, US law enforcement could compel disclosure; yes, there's no EU-equivalent remedy; therefore the transfer needs supplementary measures.
Or, you know, you could just not transfer it.
The major registries and where they live
| Registry | Operator | Primary data location | EU-only option? |
|---|---|---|---|
| Docker Hub | Docker Inc. (US) | US (CloudFront global CDN) | No |
| GitHub Container Registry | GitHub / Microsoft (US) | US (with Azure global CDN) | No |
| Red Hat Quay.io | Red Hat / IBM (US) | US | No (self-hosted Quay yes, hosted no) |
| Google Artifact Registry | Google LLC (US) | Per-region; EU regions available | EU region yes, but US-operated |
| Amazon ECR | Amazon Web Services (US) | Per-region; EU regions available | EU region yes, but US-operated |
| DanubeData | DanubeData (Romania-incorporated, EU) | Germany (Falkenstein) | Yes — only EU operations |
The crucial distinction in that table is between data location and operator jurisdiction. Google Artifact Registry and Amazon ECR both let you pick a Frankfurt or Dublin region — and that gets you data-residency. But the operator is still a US company. Under the CLOUD Act (18 U.S. Code § 2713), a US-based provider can be compelled to disclose customer data regardless of where that data is physically stored. The EDPB has been explicit about this: data location is necessary but not sufficient.
What's sufficient is data hosted by an EU-incorporated operator on EU infrastructure, with no US parent and no US-controlled subsidiaries in the data path. That's the test DanubeData passes.
What changes when you move
The practical effect on engineering is essentially zero. The DanubeData Container Registry is upstream CNCF Distribution with no proprietary extensions. Anything that speaks the OCI Distribution Spec — Docker, podman, buildah, skopeo, crane, Kaniko, Buildpacks, Helm OCI charts — works without modification. The only thing that changes is the hostname.
# Before
FROM ghcr.io/your-org/base-image:v1
# or
FROM docker.io/your-org/base-image:v1
# After
FROM cr.danubedata.ro/your-team/base-image:v1
The authentication flow matches DigitalOcean's: you generate a single token in the dashboard, paste it as the Docker password (any string works for the username), and you're done. No per-CI Docker ID seats, no rate limits beyond your plan, no transatlantic round-trip on every cold pull.
Cost comparison
The other reason European teams have been stuck with US registries is that the EU alternatives have historically been priced for enterprise-only customers. We're trying to change that:
| Provider | Free tier | Cheapest paid | EU jurisdiction? |
|---|---|---|---|
| Docker Hub | 1 private repo + rate-limited public | ~$5/user/mo (Pro) | No |
| GHCR (with GitHub paid plan) | 500 MB private + 1 GB transfer | From ~$4/user/mo (GitHub Pro) | No |
| Quay.io | Public only | $15/mo (5 private repos) | No |
| AWS ECR (EU region) | 500 MB / 12 months | ~$0.10/GB/mo storage + egress | US-operated, EU-stored |
| DanubeData | 500 MB free, no time limit | €3.99/mo (5 GB, 5 repos) | Yes |
The €3.99 Basic plan includes 5 GB and 5 repositories. For a small team mirroring a handful of base images and a few of their own services, that's usually enough. The Professional plan at €14.99 jumps to 100 GB and unlimited repositories, which is plenty for most SaaS-scale teams.
What you're actually getting
Beyond the legal positioning, the registry itself has the production-grade features you'd expect:
- Per-tenant isolation. Your team's repositories live in your team's namespace. Cross-team pulls return 401 at the token service; the
/v2/_catalogendpoint is scoped to your own catalog. - Vault-managed JWT signing. Short-lived (5-minute) bearer tokens signed by an RSA keypair stored in HashiCorp Vault. Rotation is built in and audit-logged.
- Scoped access keys. Per-environment or per-CI keys with push+pull or pull-only scope. Revoke any time; new tokens fail within five minutes.
- Storage encryption. Image data is stored in Ceph in Falkenstein with bucket-level encryption (SSE-KMS via Vault-managed keys).
- Garbage collection. Daily GC reclaims storage from unreferenced blobs. Trigger manually any time from the dashboard.
- Friendly error messages. Hit a storage quota? Docker shows you exactly which limit you're hitting and a link to your subscription page, not a generic "denied".
What we're not pretending to be
Some honesty about scope:
- We don't scan images for vulnerabilities yet. That's on the roadmap. For now, run
trivy image <tag>in your CI. - We don't offer a SLA with financial credits. We run a high-availability setup (two Distribution replicas, replicated Ceph backend), but if uptime guarantees are mandatory for your compliance team, talk to us about a custom plan.
- We don't mirror public registries on demand. If you want a "pull-through cache" that lazily fetches from Docker Hub, that's a separate product (let us know if it's on your wish list).
Migrating in three commands
The minimum viable migration is shorter than booting a build agent:
# 1. Pull from the US-based registry
docker pull ghcr.io/your-org/your-service:v1.2.3
# 2. Retag to point at the European registry
docker tag ghcr.io/your-org/your-service:v1.2.3
cr.danubedata.ro/your-team/your-service:v1.2.3
# 3. Push
echo "$REGISTRY_TOKEN" | docker login cr.danubedata.ro
-u you@example.com --password-stdin
docker push cr.danubedata.ro/your-team/your-service:v1.2.3
Update your deployment manifests / Dockerfiles to reference the new path, and you're done. Your production environment now pulls from a registry under EU law, hosted on a Ceph cluster physically located in Germany, operated by an EU-incorporated company with no US parent.
Try it free
Every DanubeData account starts on the free Starter tier (500 MB, 1 repository). It's enough to mirror one base image or push a small service.
- Create a DanubeData account.
- Open Container Registry → Access Keys → New access key.
- Copy the
cr_…token shown once. - Push your first image.
For background on our broader European-cloud philosophy, see our posts on GDPR-compliant European cloud alternatives and digital sovereignty after Schrems II.
For specifics on the registry, the solution page covers the architecture in more depth.