DigitalOcean Container Registry Guide 2026 — Store Docker Images
บริการเก็บ Docker image ส่วนตัวของ DigitalOcean ที่เชื่อมต่อโดยตรงกับ Kubernetes และ App Platform โดยไม่ต้องตั้ง credential เพิ่มเอง
DigitalOcean Container Registry is a private Docker image storage service managed entirely by DigitalOcean. It integrates with standard Docker CLI and connects directly to DigitalOcean Kubernetes and App Platform. This guide walks you through pricing tiers, how to push and pull images using doctl, and long-term Registry maintenance with practical commands you can use right away.
Contents
What Is Container Registry
DigitalOcean Container Registry (DOCR) is a private Docker image storage service fully managed by DigitalOcean. You don't need to set up your own Registry server, manage storage, or patch security systems yourself. The Registry fully supports the OCI (Open Container Initiative) standard, so it works seamlessly with Docker, Buildx, Podman, or any CI/CD tool that speaks Docker Registry API v2 without requiring major workflow changes. For development teams deploying apps via containers—whether on Droplets, DigitalOcean Kubernetes (DOKS), or App Platform—Container Registry is the central hub for storing finished images before deployment, replacing the need for Docker Hub public repos (which expose your images to everyone unless you pay for private repos) or running your own Registry on a Droplet (which requires you to manage SSL, disk space, and backups yourself). Image URLs in DOCR follow the format registry.digitalocean.com/<registry-name>/<image-name>:<tag>, for example registry.digitalocean.com/my-registry/my-app:v1.2. One DigitalOcean account creates one Registry (a single namespace), but you can create multiple repositories within it depending on your plan's repository limit. What sets DOCR apart from self-hosted Registry is its seamless integration with other DigitalOcean services without requiring manual credential setup. DOKS pulls images from DOCR without needing to create imagePullSecrets by hand, and App Platform uses DOCR as its image source for instant auto-deploy when new image tags are pushed. One important limitation to be aware of: Container Registry is not available in every DigitalOcean region. It currently lacks service in Richmond (ric1) and Kansas City (mkc1), unlike Droplets, Kubernetes, Load Balancers, and VPCs which cover all 15 datacenters. Before architecting a setup that ties Registry to clusters or Droplets in those regions, always check regional availability first.
- Private registry supporting OCI standard; works directly with Docker/Buildx/Podman
- URL format: registry.digitalocean.com/
/ : - Connects to DOKS and App Platform with no manual credential setup required
- One account = one Registry namespace, but you can create multiple repositories
Pricing Plans: Starter/Basic/Professional
Based on real-world use, digitalOcean Container Registry offers three tiers based on usage scale: Starter, Basic, and Professional. The main differences are the number of repositories you can create, included storage space, and overage charges if you exceed your quota (prices as of July 2026—check DigitalOcean's website for current rates before deciding). The Starter plan costs $0/month, lets you create 1 repository, and includes 500 MiB of storage. It's ideal for experimenting, small personal projects, or teams with a single uncomplicated image. This free tier has no overage fees because usage is capped. The Basic plan costs $5/month, supports up to 5 repositories, includes 5 GiB of storage, and charges $0.02 per additional GiB if you exceed quota. It suits small-to-medium teams with multiple services or microservices that need separate images. The Professional plan costs $20/month, allows unlimited repositories, includes 100 GiB of storage, and applies the same $0.02/GiB overage rate. It works for teams with many images, multiple tags per image for rollback scenarios, or CI/CD that builds images frequently and consumes storage quickly. Choosing a plan should reflect your team's actual behavior, not just how many services exist, because every image layer accumulates when you push a new tag. If you never delete old images or set up garbage collection, you'll hit your quota faster than expected. Create a Registry with a specific plan using doctl registry create my-registry --subscription-tier basic --region sgp1 and check your current plan and storage consumption with doctl registry get, which displays Registry name, endpoint, active plan, and storage usage versus quota. Upgrade plans anytime via doctl registry update-subscription --subscription-tier professional without recreating the Registry or migrating existing images.
- Starter: free, 1 repository, 500 MiB storage, no overage charges
- Basic: $5/month, 5 repositories, 5 GiB storage, $0.02/GiB overage
- Professional: $20/month, unlimited repositories, 100 GiB storage, $0.02/GiB overage
- Upgrade plans anytime with doctl registry update-subscription; no image migration needed
Push/Pull Docker Images with doctl
Using Container Registry starts with installing doctl, DigitalOcean's official CLI (github.com/digitalocean/doctl). Install it via Homebrew on macOS with brew install doctl, via snap on Linux with sudo snap install doctl, or download the binary directly from GitHub releases. After installation, authenticate with a Personal Access Token from cloud.digitalocean.com/account/api/tokens using doctl auth init, then paste your token when prompted. Once authenticated, log in to Registry with doctl registry login. This command calls Docker's credential helper automatically, letting your local Docker CLI push/pull from registry.digitalocean.com without needing a separate docker login or password management (the token expires on schedule and requires re-login periodically). To push an image, first build it normally with docker build -t my-app ., then tag it to point at your Registry using docker tag my-app registry.digitalocean.com/my-registry/my-app:v1, and finally push with docker push registry.digitalocean.com/my-registry/my-app:v1. When deploying on the other end—whether Droplet, Kubernetes, or App Platform—pull the image back with docker pull registry.digitalocean.com/my-registry/my-app:v1. doctl also provides commands to manage repositories and tags directly without relying on Docker CLI every time: doctl registry repository list shows all repositories in your Registry, doctl registry repository list-tags my-app displays every tag of that repository with file size and push date, and doctl registry repository delete-tag my-app v1 removes tags you no longer need before running garbage collection to reclaim storage. For teams using CI/CD pipelines like GitHub Actions, insert doctl registry login and docker push steps into your workflow YAML, store your Personal Access Token as a GitHub Secret, and call it during the build. This ensures new images are pushed to Registry automatically every time you merge code into your main branch.
- Install doctl: brew (macOS) / snap (Linux) / binary from GitHub releases
- doctl auth init binds your Personal Access Token before each use session
- doctl registry login sets up Docker credential helper automatically
Connect to DigitalOcean Kubernetes
DigitalOcean Kubernetes (DOKS) integrates natively with Container Registry—no need to manually create Kubernetes Secrets to pull images, a step normally required for private registries from other providers. Usually, when a cluster needs to pull from a private registry, you must create an imagePullSecrets object storing credentials, then reference it in every pod spec. But DOCR binds to the cluster in a single command. Connect them using doctl kubernetes cluster registry add my-cluster. This command automatically creates and distributes the necessary Secrets into the cluster's namespace, letting pods pull from registry.digitalocean.com right away without requiring admins to base64-encode credentials by hand or run kubectl create secret docker-registry. To disconnect, use doctl kubernetes cluster registry remove my-cluster. After connecting, reference images in your Deployment manifests normally—for instance, set image: registry.digitalocean.com/my-registry/my-app:v1 in your container spec—without adding imagePullSecrets to individual pods, since the cluster binds permissions at the service account level by default. Cost-wise, DOKS keeps control plane free but charges for node pools starting at $12/month per node (using standard Droplet pricing). Container Registry pricing is separate based on your chosen tier (Starter/Basic/Professional). Tying Registry to a cluster carries no additional fee beyond these two services. Note that Registry and Kubernetes don't need to be in the same region to connect (linking happens via API, not a private network within a single region), but pulling images across regions frequently can slow deployments, especially for large images. Consider placing Registry close to your cluster's actual region to reduce pull latency.
- doctl kubernetes cluster registry add automatically binds Secrets to the cluster; no manual imagePullSecrets needed
- Disconnect with doctl kubernetes cluster registry remove
- Deployment manifests reference images directly once cluster is connected
- DOKS control plane is free; node pools start $12/month; Registry pricing separate per plan
- Registry and cluster can be in different regions, but should be geographically close to minimize pull latency
Connect to App Platform for CI/CD
App Platform is DigitalOcean's PaaS service that deploys from container images directly, not just from source code in GitHub/GitLab. When you create a new App and select DigitalOcean Container Registry as the image source, the system lets you pick any repository and tag from your Registry in the same account—no separate credentials needed because App Platform and Registry share one account. The key advantage for CI/CD workflows is App Platform's auto-deploy feature: whenever a new image tag is pushed to your linked repository, App Platform automatically triggers a deployment without requiring you to call the DigitalOcean API separately from your CI pipeline. This creates a clean CI flow: build image, push to DOCR with a defined tag (such as latest or commit SHA), then App Platform detects the tag and deploys automatically. Configure this through the Control Panel when creating or editing your App, or via app spec (YAML) file by setting image.registry_type: DOCR, image.repository, and image.tag, then deploy using doctl apps create --spec app.yaml or doctl apps update <app-id> --spec app.yaml for updates. On cost, App Platform offers a free tier for static sites only (maximum 3 apps, 1 GiB transfer per app). Deploying from container images requires a paid plan starting at the Shared tier with 1vCPU/512MiB RAM/50GiB transfer for $5/month, scaling up with larger instance sizes (DigitalOcean discontinued old tier names like Basic/Professional in mid-2026 and shifted to letting you select container instance size directly). One important constraint: you can only reference images from Registry in the same DigitalOcean account. You cannot pull images from another account's Registry or from Docker Hub public via this auto-deploy mechanism—you must mirror images into your own DOCR first.
- Choose DOCR as image source when creating App; no separate credentials required
- Enable auto-deploy to trigger when new tags are pushed to your linked repository
- Configure via app spec YAML (image.registry_type: DOCR) and deploy with doctl apps create/update
Maintain Your Registry: Garbage Collection and Deleting Old Images
After running Registry for a while and pushing images frequently without deleting old tags, your storage quota fills up faster than expected because every image layer (even if parts overlap with previous tags) stays on disk until explicitly removed. DigitalOcean Container Registry includes garbage collection to reclaim space from layers and manifests no longer referenced by any tag. The standard process is: first delete the tags you don't want anymore using doctl registry repository delete-tag my-app v0.9, or delete an entire repository with doctl registry repository delete my-old-app --force if you no longer use it. Deleting tags alone does not instantly free storage because underlying layers remain until you run garbage collection. Start garbage collection with doctl registry garbage-collection start my-registry. The system scans for manifests and layers with no tag references, then removes them. During garbage collection, avoid pushing new images to the same Registry because operations may collide with the scanning process. Check if garbage collection is running using doctl registry garbage-collection get-active my-registry and view past runs with doctl registry garbage-collection list my-registry. Teams pushing images frequently from CI/CD should run garbage collection as a scheduled routine: for example, set a policy to keep only the last N tags per repository (like 10 recent tags for rollback capability), delete tags older than that using a script that calls doctl registry repository list-tags to compare dates before batch-deleting, then run garbage collection on a schedule like weekly. This approach prevents unnecessary plan upgrades when storage grows only because old images are never removed, not because actual usage increased.
- Delete old tags with doctl registry repository delete-tag before running garbage collection
- Start garbage collection using doctl registry garbage-collection start
- Do not push new images while garbage collection is running
- Check status with get-active and review history with list
- Set a policy to keep only the most recent N tags per repository; this reduces storage bloat without plan upgrades
Common Mistakes and How to Fix Them
The most common mistake when using Container Registry continuously is forgetting to run garbage collection regularly. Deleting tags with doctl registry repository delete-tag alone does not reclaim storage space immediately—layers with no tag references linger until you run doctl registry garbage-collection start. Teams whose CI/CD pushes images on every commit but never run garbage collection often see overage bills of $0.02 per GiB climbing steadily even though only a handful of images are in active use. The rest of the storage holds orphaned layers accumulating in the background. A close second is sloppy tagging, especially using only the latest tag in production and overwriting it each deploy. This makes rollback impossible because latest always points to the newest image; older versions, even if not deleted, have no tag to pull them back. The fix is to tag every build with identifying information like commit SHA or version numbers alongside latest, so you can always roll back. The third common issue specific to CI/CD teams is Personal Access Token expiration. The token that doctl registry login uses may expire or be revoked from cloud.digitalocean.com/account/api/tokens without you updating the CI secret, causing doctl registry login to suddenly fail partway through a pipeline that used to work. Teams should either calendar token expiry checks or use a dedicated service account token for CI/CD separate from developers' personal tokens; this way, revoking individual tokens doesn't break the pipeline. A final common mistake in multi-project teams is pushing to the wrong repository or account, especially when switching context between multiple DigitalOcean teams without verifying which account doctl currently targets, or tagging with an incorrect registry name. Docker CLI creates the repository automatically if it doesn't exist, so no error flags the mistake—the image lands in the wrong place silently. This can hit your plan's repository quota (Basic plan limits 5 repositories) without obvious cause. Always double-check your doctl context and tag names before pushing in production.
- Forgetting garbage collection causes overage bills even though active images are few; orphaned layers accumulate silently
- Using only the latest tag in production prevents rollback—always tag with commit SHA or version alongside latest
- Personal Access Token expiration breaks CI/CD pipelines partway through; use dedicated service tokens separate from personal ones
Best Practices
A solid tagging strategy is the foundation of sustainable Container Registry management. Most development teams use semantic versioning alongside commit SHA, for example docker tag my-app registry.digitalocean.com/my-registry/my-app:v1.4.2 paired with docker tag my-app registry.digitalocean.com/my-registry/my-app:$(git rev-parse --short HEAD) so you can trace each image back to its commit. The latest tag still works for test environments, but should not be your only tag for production deployments because rollback becomes impossible. A recommended CI/CD pattern is "build once, promote everywhere": build the image once, then move the same image through each environment (build once, promote everywhere) instead of rebuilding for staging then again for production. This reduces the risk that image contents differ between environments due to dependency version shifts between builds. Do this by pushing a single build with a commit-specific tag, then have each environment pull that exact same tag rather than relying on latest. Reducing image size helps both push/pull speed and storage consumption in every plan. The basic approach uses multi-stage builds: separate the compile/build step in one image containing your full toolchain from the final image used to run the app, then copy only the binary or necessary files into a smaller base image like alpine or distroless. Pair this with a .dockerignore file to prevent copying unnecessary files like old node_modules, .git, or log files into the build context from the start. Smaller images lower garbage collection overhead and reduce overage costs proportionally. For multi-person or multi-team setups, manage Registry access through DigitalOcean Teams instead of sharing one Personal Access Token across everyone. Split tokens by role: one token for CI/CD pipelines with minimal required permissions, separate from tokens individual developers use on their own machines. If someone leaves or a token leaks, you can revoke just that token without breaking pipelines or other developers. Also verify Registry is bound to the correct Project within DigitalOcean Teams, ensuring dev/staging/production environments are clearly separated.
- Tag with semantic version + commit SHA together; don't use latest as your only production tag
- Build once, promote everywhere: build once, then push the same tag through every environment
- Multi-stage build + small base images (alpine/distroless) + .dockerignore reduce size and lower overage cost
- Split Personal Access Tokens by role via DigitalOcean Teams (CI/CD vs. personal developer tokens)
- Bind Registry to the correct Project within Teams to clearly separate dev/staging/production