Export your Docker Hub data before the contract ends
When a renewal, a pricing change or a residency requirement forces images out of Docker Hub, the core content can move. Repositories, tags and image content can be listed and copied over documented APIs and the registry protocol, while account settings, team membership and some metadata must be recreated by hand. Start by inventorying what your namespaces actually hold: list repositories through the namespace-scoped routes of the Docker Hub API reference, then list tags per repository. Organization access tokens only work on those namespace-scoped routes, so an export script built around personal credentials will behave differently from one built around an organization token. Confirm which token type your automation will use before you write it.
The copy itself has two practical paths. Skopeo can copy or sync images, including manifests, layers and signatures, from Docker Hub to another registry or to a local directory, which suits air-gapped transfers and one-off moves. Harbor pull-based replication can do the same from inside your own environment, with name and tag filters and an optional bandwidth limit, and it keeps the target registry in step on a schedule. Pick one path per repository and record which tags were copied, so you can reconcile the target against the source before the contract ends.
The main caveat is pull limits. Every architecture of a multi-architecture image counts as a separate pull, so a bulk export of multi-architecture tags can consume several pulls per tag on an account with a pull limit. Docker's documented limits apply per IP address or subnet for unauthenticated pulls and per account for personal plans, so run exports from an authenticated, well-understood network and check your current plan's allowance in Docker's pull documentation before scheduling a large job. Plan the export window early, and ask your Docker account team to confirm which limits apply to your plan during the transition.
What you can export from Docker Hub and how
This table maps each kind of Docker Hub data to the method that exports it, the output you get and the limits that apply. Read it as a checklist: confirm each row against your own account before starting a bulk export. The main takeaway is that tag listing is API work, while image content moves through the registry API, and multi-architecture tags cost more pulls than their tag count suggests.
| Data type | Export method | Output and limits |
|---|---|---|
| Repository list | Docker Hub API on /v2/namespaces/{namespace}/repositories/, paged with a token | JSON metadata per repository; only namespace-scoped routes work with organization access tokens |
| Tags per repository | Docker Hub API on /v2/namespaces/{namespace}/repositories/{repository}/tags | JSON list of tag names and metadata; confirm pagination limits in the API reference |
| Image manifests and layers | Skopeo copy or sync to a registry or local directory | Layers and manifests copied as OCI content; each pull counts against account limits |
| Multi-architecture indexes | Skopeo copy with all architectures, or sync with the architecture filters you need | Each architecture counts as a separate pull, so a multi-architecture tag uses several pulls |
| Signatures and attestations | Skopeo copy, which carries signatures with the image | Confirm with the destination registry that signatures are stored and verifiable after import |
| Pull limit impact | Plan the export window against per-IP and per-account pull limits | Pulls are counted per architecture, so run exports in batches and check remaining quota first |
| Organization access tokens | Use them only on namespace-scoped API routes | Other routes need a different credential; test each route before scripting the export |
Choosing between Skopeo and Harbor pull replication
Skopeo is a command-line tool that copies images between registries or into a local directory without needing a container runtime or elevated privileges. It fits a bounded export: a list of repositories that someone runs once or a few times, with the output going to a target registry, a file tree or a transfer host. The Skopeo README describes its sync command for mirroring a repository to another registry or to a directory, which covers the air-gapped case where media is carried across a boundary.
- Destination flexibility: Skopeo can write to another registry, including a Harbor project, or to a directory for offline transfer, so it does not require a Harbor instance to exist first.
- Low setup: A shell script, a credentials file and a tag list are enough to start. There is no service to install, patch or back up.
- Manual control of scope: Filters live in your script, so the team must write and review the logic for tag selection and multi-architecture handling.
- No built-in scheduling or audit trail: Retries, bandwidth caps, run history and alerts must come from cron, CI or your own logging.
- Credential handling: Source credentials must be stored and rotated by the team running the script, which matters when the export uses organization access tokens.
Before running a bulk copy, confirm which pull limits apply to your source account, since each architecture of a multi-architecture image counts as a separate pull. Check the copy result for each tag in a test run first.
Harbor replication is configured inside a running Harbor instance. A replication endpoint points at Docker Hub, and a pull-based rule brings matching repositories into a Harbor project. Rules can filter by repository name, tag, label and resource type, and can run manually, on a cron schedule or on push and retag events. This path suits a team that already operates Harbor and wants repeatable, observable transfers with a per-task bandwidth limit. The Harbor replication rules documentation lists the trigger and filter options.
- Built-in scheduling: Cron-based runs repeat the copy until cutover without a separate job runner.
- Bandwidth limit: An optional per-task limit keeps the export from saturating the link shared with production traffic.
- Filters in the UI: Name and tag filters are set in the rule, which reviewers can inspect.
- Requires a running Harbor: Installation, PostgreSQL, storage and upgrades are a prerequisite, so this path carries the operational cost of the registry itself.
- Destination limited to registries: Replication writes to a registry, not to a directory, so an air-gapped transfer still needs Skopeo or a transfer host.
Confirm with your Harbor administrator whether the Docker Hub endpoint credentials are scoped to the namespace being exported and whether the rule's tag filter covers every architecture you need.
The deciding questions are where the copy must end up and who will own the job after it runs. A platform team that already runs Harbor will usually prefer replication because the job, its logs and its filters sit beside the registry. A team without Harbor yet, or one exporting into a directory for an isolated network, will usually start with Skopeo. Both paths read from the same Docker Hub API listing of repositories and tags, so the inventory step is shared.
- Destination is a Harbor instance: Replication is the natural fit when the target project already exists and the team wants recurring syncs.
- Destination is another registry: Skopeo works for any OCI-compatible target, and replication works only if that target is an endpoint Harbor supports.
- Destination is a directory: Skopeo is the practical choice for air-gapped transfer, with the directory carried through an approved transfer host.
- Team skills: Scripting comfort favors Skopeo; comfort operating Harbor's UI and API favors replication.
- One-off versus recurring: A single cutover snapshot can run from a script, while a migration with overlap weeks of dual running benefits from scheduled rules.
Ask your Harbor or platform owner which path their change process accepts, since a scripted export may need the same review as a managed job.
Whichever path you choose, the export is a data movement that touches credentials, pull quotas and supply-chain metadata. Skopeo copies manifests, layers and signatures, so signed images keep their signatures when the copy is made correctly. Harbor replication moves artifacts into a project where access control, audit logs and scanning then apply. Plan the run as a controlled operation with a record of what was copied, from which account and at what time.
- Credential scope: Use tokens limited to the namespaces being read, and revoke them after the export.
- Verification: Compare tag counts and digests between source and destination before closing the job.
- Run history: Replication keeps job records inside Harbor; a script needs its own log file or CI record.
- Upgrade timing: Recent Harbor releases change defaults, such as blocking webhooks to internal addresses by default in v2.15.3, so confirm the target version before scheduling a long job.
- Backup first: Take a Harbor backup before importing a large set, as the v2.15.2 release notes recommend for upgrades.
Ask the implementation partner or your internal owner to document the chosen path, the verification step and the rollback plan in writing before the first run.
What does not export and how to recreate it
The API and replication paths move images, tags and repository listings, but several account-level items sit outside them. Each card below names one item, the workaround, and the point where you should confirm current scope in Docker's documentation before you plan the cutover.
User accounts and team membership
Docker Hub users, teams and organization memberships are account records, not registry content, so a pull or replication job will not copy them. Build an inventory of who holds push, pull and admin rights on each namespace before the export. In the destination, recreate those rights as Harbor projects with role-based access control, and map each Docker Hub team to a Harbor group or OIDC claim where your identity provider supports it. Confirm the current user and team data scope with Docker's documentation before you assume anything is exportable.
Access tokens and credentials
Personal access tokens and organization access tokens are bound to Docker Hub and cannot be transferred. Organization access tokens only work on namespace-scoped API routes, so scripts that depend on them will stop working once you leave. Issue new robot or service accounts in Harbor, store their secrets in your secrets manager, and update CI variables and Kubernetes image pull secrets before cutover. Treat any token that appears in old pipeline logs as compromised and rotate it.
Webhooks and automated build settings
Webhooks, automated builds and their linked source repository settings are Docker Hub configuration, so they do not follow the image data. Export a list of each repository's webhook targets and build rules from the console or the API while your account is still active. Recreate the equivalent in your CI system, or in Harbor webhook policies for push and scan events. Note that Harbor blocks webhooks to internal network addresses by default in v2.15.3, so an internal receiver needs an explicit allowance and a review.
Repository descriptions and README content
Repository short descriptions, full overview text and README markdown are stored as Docker Hub metadata and are not part of the image manifest or its layers. Copy them by hand or script a save of the overview text from the console or API into your source repository. In Harbor, place the text in your Git repository or in a project-level document, because Harbor's project pages do not replace Docker Hub's overview. Images that carry OCI annotations keep their labels, so check those labels before you assume metadata moved.
Billing history and plan records
Invoices, subscription history, payment methods and seat counts are financial records held by Docker, not registry data. Download the invoices and plan documents you need for finance, audit or tax records before you cancel, and note the renewal date so you do not pay for an unused seat. Recreating this history is not possible, so accept the loss of the records inside Docker Hub and keep your own copies. Ask Docker which billing exports are available to your account role before the final invoice closes.
Pull statistics and download counts
Pull counts, download history and usage graphs are analytics data that Docker Hub reports per repository. They do not copy into a new registry, and Harbor records its own pull activity only from the point it starts serving traffic. Record the current totals for any repository your users track, and set up audit logs and metrics in Harbor so future activity is measurable. Accept that the historical series will end at the cutover date.
Run a complete Docker Hub export in order
This sequence produces a complete, verified copy of every repository, tag and architecture you own on Docker Hub, with a digest record that proves the copy matches the source. Work through it once for a full export and again for any final delta before cutover.
Create a scoped read-only access token
Start by creating a Docker Hub access token with read-only permissions for the namespace you are exporting, using an account that owns or administers those repositories. Store the token in your secrets manager, not in shell history or CI variables visible to the whole team. Organization access tokens only work on namespace-scoped API routes, so confirm you are querying the correct organization namespace before you go further. The output is a working token that returns your repository list without errors.
Inventory namespaces and repositories through the API
Call the namespace-scoped repository route in the Docker Hub API reference to list every repository in each namespace in scope, paging through all results. Save the output as a file that lists namespace, repository name, visibility and last-updated date. Ask the account owner whether any repositories are private, archived or owned by other teams, because these often get missed in a manual list. The output is a complete repository inventory that you and the owner have reviewed.
Record tags and architectures for each repository
For each repository in the inventory, call the namespace-scoped tags route and capture every tag name along with its manifest digest. For multi-architecture tags, record each platform entry, such as linux/amd64 and linux/arm64, so you know what the copy must contain. Flag tags that point to the same digest, since copying by digest avoids pulling the same content twice. The output is a tag manifest file that serves as the expected result for verification.
Schedule the bulk copy around pull limits
Docker Hub counts each architecture of a multi-architecture image as a separate pull, so a bulk export of multi-architecture tags consumes several pulls per tag on accounts with a pull limit. Estimate the total pull count from your tag manifest, then confirm the current limits for your account type in the Docker documentation on pull usage. Schedule the copy in batches, run it from a single authenticated host, and pause between batches if you approach the limit. The output is a written batch plan that the operations owner has approved.
Copy each repository with Skopeo or a replication rule
Copy each repository to the destination registry with Skopeo, which carries manifests, layers and signatures from one registry to another, or with a Harbor pull-based replication rule filtered by repository name and tag. Authenticate to Docker Hub with the read-only token and push to the destination with a robot account scoped to the target project. Run one batch at a time and log each copy result. The output is a destination registry populated by batch, with a log entry for every repository and tag.
Record digests from the source and destination
After each batch, list the digest of every tag in the source and in the destination and write both to a comparison file. Digests are content identifiers, so matching digests show the copied manifest is identical to the original, including per-architecture entries. Investigate any tag whose digest differs or is missing, and re-copy it before continuing. The output is a digest comparison file with no unexplained differences.
Verify tags, architectures and signatures
Compare the destination tag list against the manifest from the tag inventory and confirm that every repository, tag and platform entry is present. Pull a sample of images on each architecture from the destination to confirm they start and run as expected. If images were signed, check that the signatures and any attached artifacts also arrived, since Skopeo and Harbor both carry them when they are included in the copy. The output is a signed-off verification report listing any exceptions and how each was resolved.
Run a final delta copy before cutover
Repositories keep changing during a long export, so repeat the inventory and tag steps close to the cutover date and copy only tags whose digests changed. Compare the final digest file again and keep the source read-only or frozen for the duration of the last copy if your process allows it. Keep the verified export, digest files and logs in your records. The output is a final digest match across all in-scope repositories, which is the basis for pointing CI and clusters at the new registry.
How pull limits count against a bulk export
Plan the export around Docker Hub's pull budget before you start it, because a bulk pull can exhaust the limit long before the job finishes. Docker Hub limits unauthenticated pulls to 100 per 6 hours per IPv4 address or IPv6 /64 subnet, and Personal accounts to 200 per 6 hours, according to the Docker Hub pull usage and limits documentation. Every architecture of a multi-architecture image counts as a separate pull, so a tag that ships amd64, arm64 and s390x variants can consume several pulls when you fetch it. An export of a repository with many tags across several platforms can therefore spend the budget in a single run, and the remaining tags fail until the window resets.
The practical controls are authentication and where the job runs. Pulls made with an authenticated account are counted against that account's limit rather than the anonymous per-IP allowance, so run the export with a dedicated account or organization token and confirm the current limit for that account type with Docker before you rely on it. Keep the export on one host or a small, known set of egress addresses, because the limit follows the source IP or subnet and a fleet of CI runners pulling in parallel will share one budget. Estimate the number of pulls by counting tags multiplied by platforms per tag, and split the work into batches that fit the window. Filter out tags you do not need, since every unnecessary pull draws from the same budget.
After the first copy lands in your own environment, avoid repeating the pulls from Docker Hub. If you front Docker Hub with a Harbor proxy cache project, Harbor's documentation says it checks cached images with HEAD requests, and those checks do not trigger the Docker Hub rate limiter, so later runs that revalidate cached content stay within the budget. Confirm this behavior in your own environment with a test pull and a Docker Hub usage check before a production cutover, and record the pull counts for each batch so you can see whether a rerun costs anything.
Verifying the export before you cut over
A bulk export is only finished when the destination matches the source in ways you can prove. The checks below run in parallel where possible and each one should be confirmed against your own repositories, not assumed from a successful copy command.
Match repository and tag counts
Count repositories and tags from the Docker Hub API using namespace-scoped routes, then count the same repositories and tags in Harbor. Run the count per namespace, because organization access tokens only work on those routes. Mismatches usually come from private repositories the export token could not see, or from tags skipped by a name or tag filter in a replication rule. Confirm the counts match for every namespace in scope.
Compare digests per tag and architecture
Counts alone do not prove the content is the same. For each tag, compare the manifest digest at the source with the digest at the destination, and check each platform entry of multi-architecture images separately. A tag that resolves to a different digest after the copy points to a rebuilt or re-tagged image that CI may treat as a new artifact. Record any mismatch with the tag name, platform and digest pair before you move on.
Confirm signatures and referrers
Where images carry signatures, SBOMs or attestations, verify that they arrived and still point at the right image. The OCI Distribution Specification defines a referrers API for this, so check that the destination lists the same referring manifests per digest. Skopeo copies signatures, but confirm that your signing policy still validates against the destination, since an unexpected change can block deployments.
Pull from a clean host
Test the copy the way production will use it. From a host or cluster node with no local image cache and no Docker Hub credentials, pull a sample of images, including one multi-architecture image on each target platform. Use the same registry hostname, pull secret and certificate chain your workloads will use. A pull that works only on the machine that performed the copy does not prove the cutover is ready.
Keep a dated inventory
Write down what was exported, from which namespace, at what time, by which tool and version, and with which digests. Store the inventory outside both registries so it survives a rollback. Keep the record of any excluded repositories and the reason for each exclusion. This inventory is the evidence you will need if a team later asks whether an image existed or changed, and it gives your auditors a starting point for the migration.
Questions buyers ask before exporting from Docker Hub
Can our team export from Docker Hub without outside help?
Yes, most teams with a container platform engineer can run the export themselves, because the tooling is open source and the steps are well documented. The work is mainly inventory, token setup and a repeatable copy job. Effort rises when the estate is large, when images are poorly tagged, or when no one has time to verify the result. Start by listing repositories through the Docker Hub API reference with an organization access token, since those tokens only work on namespace-scoped routes. Then decide whether the team has the time and the on-call coverage to own the copy and its verification.
What makes a Docker Hub export larger or harder?
The main drivers are the number of repositories, the total size of image layers, the number of architectures per image, and how many historical tags you keep. Each architecture of a multi-architecture image is counted as a separate pull by Docker Hub, so a bulk export of multi-architecture tags uses several pulls per tag on accounts with a pull limit. Tag history matters because old tags often point to images nobody uses but that still need copying if policy requires them. Build a spreadsheet of repositories, tag counts and architectures before you estimate effort, and treat untagged or orphaned images as a separate decision.
What do we need in place before the copy starts?
You need four things: a Docker Hub account or organization with read access to the repositories, an access token that can list them, a host that can reach both Docker Hub and your target registry, and a running Harbor instance with projects and credentials set up. The transfer host runs Skopeo or Harbor replication and needs enough disk for staging if you copy through it. Confirm network egress rules, storage capacity on Harbor, and who owns the robot or service accounts used for writes. Check the Skopeo README for the copy commands and the flags your version supports.
How long does a bulk copy take, and what changes the time?
No duration is fixed by the tools, so the honest answer depends on the data. Total image size, the bandwidth between Docker Hub and your transfer host, and the bandwidth between that host and Harbor set the floor. Harbor replication rules can apply a per-task bandwidth limit, which protects other traffic but lengthens the job. Parallelism, retries after transient failures, and the number of architectures also shift the timeline. Ask the implementation partner or your own team to run a pilot on one large repository and one small one, then extrapolate from measured throughput rather than from assumptions.
Do we need a paid Docker plan during the export?
Not always, but pull limits decide the answer. Docker documents that unauthenticated pulls are limited to 100 per 6 hours per IPv4 address or IPv6 /64 subnet, and Personal accounts to 200 per 6 hours. A bulk export from a single host can hit these limits quickly, so authenticate the copy job and spread the work over time if needed. Check the current limits and what your plan includes on Docker's pulls usage page before you schedule the copy. Keep the paid plan until you have verified every tag in Harbor and retired the old pull paths.
Does a Harbor proxy cache avoid pull limits during the export?
A proxy cache helps with ongoing pulls more than with a one-time export. Harbor documents that its proxy cache checks cached images with HEAD requests that do not trigger the Docker Hub rate limiter, but the first fetch of each image still reads from Docker Hub. For the export itself, pulling into Harbor through replication or Skopeo is the direct route. Use the proxy cache afterward for public base images that your clusters pull repeatedly. Confirm the cache behavior against the proxy cache documentation for your Harbor version.
What would an outside implementation partner scope for this export?
DeployOpen plans and implements self-hosted platforms in your own infrastructure, and a Harbor export is a fixed-scope engagement that starts with agreed deliverables and timelines. A typical written scope covers the repository inventory, the copy method for each group of repositories, the verification steps that compare tags, digests and architectures, the Harbor projects and access model, and the cutover plan for CI and cluster pull secrets. Scope also covers backup before any Harbor upgrade and handover documentation. Ask for a written scope with named deliverables, and expect the quote to follow from it rather than from a published price list.
How DeployOpen scopes and delivers a Docker Hub exit
DeployOpen plans and implements self-hosted open-source platforms inside your own cloud accounts, data centers or air-gapped networks. For a Docker Hub export, we start from a written scope that names the namespaces, repositories and credentials involved, then build and document the transfer so your team can verify and keep the copies.
How we scope
- Inventory of namespaces, repositories and tags to export, agreed in writing before work starts
- Decision on who holds organization access tokens and how they are scoped and rotated
- Pull budget estimate for multi-architecture tags, confirmed against your Docker plan and IP addresses
How we build
- Export scripts using the Docker Hub API with access tokens to list repositories and tags
- Skopeo or Harbor pull replication configured to copy every tag and architecture to your registry
- Verification step comparing source and destination tag and digest lists before cutover
How we hand over
- Written runbook covering export steps, retry handling and the pull limit behavior observed during the run
- Documented inventory and digest report delivered with the exported repositories
- Walkthrough with your platform and security teams on storing and retiring the access tokens used
How we support
- Fixed-scope engagements with deliverables and timelines agreed in writing before work starts
- Ongoing support, upgrades and continuous testing available as a retainer after handover
- Follow-up review of the destination registry settings for backup and upgrade planning

