From 665007eeace35053c123f6ba2dc626b48eed0198 Mon Sep 17 00:00:00 2001 From: sarahsanders-docker Date: Mon, 10 Nov 2025 13:40:21 -0500 Subject: [PATCH 1/3] init --- content/manuals/docker-hub/repos/manage/export.md | 2 ++ content/manuals/docker-hub/repos/manage/migrate.md | 3 +++ 2 files changed, 5 insertions(+) create mode 100644 content/manuals/docker-hub/repos/manage/export.md create mode 100644 content/manuals/docker-hub/repos/manage/migrate.md diff --git a/content/manuals/docker-hub/repos/manage/export.md b/content/manuals/docker-hub/repos/manage/export.md new file mode 100644 index 000000000000..f4a28cc20889 --- /dev/null +++ b/content/manuals/docker-hub/repos/manage/export.md @@ -0,0 +1,2 @@ +Export repositories as list view +For: organizations diff --git a/content/manuals/docker-hub/repos/manage/migrate.md b/content/manuals/docker-hub/repos/manage/migrate.md new file mode 100644 index 000000000000..8eb88406a6ff --- /dev/null +++ b/content/manuals/docker-hub/repos/manage/migrate.md @@ -0,0 +1,3 @@ +Migrate repositories +For: organizations +Similar: https://docs.docker.com/docker-hub/repos/manage/hub-images/move/ From 6243644fbe168fc5d83032b97762ea4e4d74c95b Mon Sep 17 00:00:00 2001 From: sarahsanders-docker Date: Tue, 11 Nov 2025 09:49:44 -0500 Subject: [PATCH 2/3] add content --- .../manuals/docker-hub/repos/manage/export.md | 183 ++++++++++++- .../repos/manage/hub-images/bulk-migrate.md | 259 ++++++++++++++++++ .../repos/manage/hub-images/move.md | 10 +- .../docker-hub/repos/manage/migrate.md | 3 - hugo_stats.json | 7 + 5 files changed, 456 insertions(+), 6 deletions(-) create mode 100644 content/manuals/docker-hub/repos/manage/hub-images/bulk-migrate.md delete mode 100644 content/manuals/docker-hub/repos/manage/migrate.md diff --git a/content/manuals/docker-hub/repos/manage/export.md b/content/manuals/docker-hub/repos/manage/export.md index f4a28cc20889..682c0b566545 100644 --- a/content/manuals/docker-hub/repos/manage/export.md +++ b/content/manuals/docker-hub/repos/manage/export.md @@ -1,2 +1,181 @@ -Export repositories as list view -For: organizations +--- +title: Export organization repositories to CSV +linkTitle: Export repositories +description: Learn how to export a complete list of your organization's Docker Hub repositories using the API. +keywords: docker hub, organization, repositories, export, csv, api, access token +--- + +This guide shows you how to export a complete list of repositories from your +Docker Hub organization, including private repositories. You'll use an +Organization Access Token (OAT) to authenticate with the Docker Hub API and +export repository details to a CSV file for reporting or analysis. + +The exported data includes repository name, visibility status, last updated +date, pull count, and star count. + +## Prerequisites + +Before you begin, ensure you have: + +- Administrator access to a Docker Hub organization +- `curl` installed for making API requests +- `jq` installed for JSON parsing +- A spreadsheet application to view the CSV + +## Create an organization access token + +Organization access tokens let you authenticate API requests without +interactive login steps. + +1. Navigate to your organization in Docker Hub and select **Admin Console**. + +2. Select **Access tokens** from the sidebar. + +3. Select **Generate access token**. + +4. Configure the token permissions: + + - Under **Repository permissions**, add every repository you want the + token to access + - Assign at least **Image Pull** (read) access to each repository + - You can add up to 50 repositories per token + +5. Copy the generated token and store it securely. + +> [!IMPORTANT] +> +> If you only enable **Read public repositories**, the API will only return +> public repositories. To include private repositories in your export, you must +> explicitly add them to the token's repository permissions. + +## Authenticate with the Docker Hub API + +Exchange your organization access token for a JWT bearer token that you'll use +for subsequent API requests. + +1. Set your organization name and access token as variables: + + ```bash + ORG="" + OAT="" + ``` + +2. Call the authentication endpoint to get a JWT: + + ```bash + TOKEN=$( + curl -s https://hub.docker.com/v2/users/login \ + -H 'Content-Type: application/json' \ + -d "{\"username\":\"$ORG\",\"password\":\"$OAT\"}" \ + | jq -r '.token' + ) + ``` + +3. Verify the token was retrieved successfully: + + ```console + $ echo "Got JWT: ${#TOKEN} chars" + ``` + +You'll use this JWT as a Bearer token in the `Authorization` header for all +subsequent API calls. + +## Retrieve all repositories + +The Docker Hub API paginates repository lists. This script retrieves all pages +and combines the results. + +1. Set the page size and initial API endpoint: + + ```bash + PAGE_SIZE=100 + URL="https://hub.docker.com/v2/namespaces/$ORG/repositories?page_size=$PAGE_SIZE" + ``` + +2. Paginate through all results: + + ```bash + ALL=$( + while [ -n "$URL" ] && [ "$URL" != "null" ]; do + RESP=$(curl -s "$URL" -H "Authorization: Bearer $TOKEN") + echo "$RESP" | jq -c '.results[]' + URL=$(echo "$RESP" | jq -r '.next') + done | jq -s '.' + ) + ``` + +3. Verify the number of repositories retrieved: + + ```console + $ echo "$ALL" | jq 'length' + ``` + +The script continues requesting the `next` URL from each response until +pagination is complete. + +## Export to CSV + +Generate a CSV file with repository details that you can open in +spreadsheet applications. + +Run the following command to create `repos.csv`: + +```bash +echo "$ALL" | jq -r ' + (["namespace","name","is_private","last_updated","pull_count","star_count"] | @csv), + (.[] | [ + .namespace, .name, .is_private, .last_updated, (.pull_count//0), (.star_count//0) + ] | @csv) +' > repos.csv +``` + +Verify the export completed: + +```console +$ echo "Rows:" $(wc -l < repos.csv) +``` + +Open the `repos.csv` file in your preferred +spreadsheet application to view and analyze your repository data. + +## Troubleshooting + +### Only public repositories appear + +Your organization access token may only have **Read public repositories** +enabled, or it lacks permissions for specific private repositories. + +To fix this: + +1. Navigate to your organization's access tokens in Docker Hub +2. Select the token you created +3. Add private repositories to the token's permissions with at + least **Image Pull** access +4. Regenerate the JWT and retry the export + +### API returns 403 or missing fields + +Ensure you're using the JWT from the `/v2/users/login` endpoint as a +Bearer token in the `Authorization` header, not the organization access +token directly. + +Verify your authentication: + +```console +$ curl -s "https://hub.docker.com/v2/namespaces/$ORG/repositories?page_size=1" \ + -H "Authorization: Bearer $TOKEN" | jq +``` + +If this returns an error, re-run the authentication step to get a fresh JWT. + +### Need access to all repositories + +Organization access tokens are scoped to specific repositories you select +during token creation. To export all repositories, you have two options: + +1. Add all repositories to the organization access token (up to 50 repositories) +2. Use a Personal Access Token (PAT) from an administrator account that has + access across the entire organization + +The choice between these approaches depends on your organization's security +policies. diff --git a/content/manuals/docker-hub/repos/manage/hub-images/bulk-migrate.md b/content/manuals/docker-hub/repos/manage/hub-images/bulk-migrate.md new file mode 100644 index 000000000000..df6a9253459f --- /dev/null +++ b/content/manuals/docker-hub/repos/manage/hub-images/bulk-migrate.md @@ -0,0 +1,259 @@ +--- +title: Bulk migrate Docker images +description: Learn how to migrate multiple Docker images and tags between organizations using scripts and automation. +keywords: docker hub, migration, bulk, images, tags, multi-arch, buildx +--- + +This guide shows you how to migrate Docker images in bulk between Docker Hub +organizations or namespaces. Whether you're consolidating repositories, +changing organization structure, or moving images to a new account, these +techniques help you migrate efficiently while preserving image integrity. + +## Prerequisites + +Before you begin, ensure you have: + +- Docker CLI version 20.10 or later installed +- Docker Buildx (optional but recommended for multi-architecture images) +- Push access to both source and destination organizations +- `jq` installed for JSON parsing in scripts +- `curl` for API calls + +## Authenticate to Docker Hub + +Sign in to Docker Hub to authenticate your session: + +```console +$ docker login +``` + +Enter your credentials when prompted. This authentication persists for your +session and prevents rate limiting issues. + +## Migrate a single image tag + +The basic workflow for migrating a single image tag involves three steps: pull, +tag, and push. + +1. Set your source and destination variables: + + ```bash + SRC_ORG=oldorg + DEST_ORG=neworg + REPO=myapp + TAG=1.2.3 + ``` + +2. Pull the image from the source organization: + + ```console + $ docker pull ${SRC_ORG}/${REPO}:${TAG} + ``` + +3. Tag the image for the destination organization: + + ```console + $ docker tag ${SRC_ORG}/${REPO}:${TAG} ${DEST_ORG}/${REPO}:${TAG} + ``` + +4. Push the image to the destination organization: + + ```console + $ docker push ${DEST_ORG}/${REPO}:${TAG} + ``` + +Repeat these steps for any additional tags you need to migrate, including +`latest` if applicable. + +## Migrate all tags for a repository + +To migrate all tags from a single repository, use this script that queries the +Docker Hub API and processes each tag: + +```bash +#!/usr/bin/env bash +set -euo pipefail + +SRC_ORG="oldorg" +DEST_ORG="neworg" +REPO="myapp" + +# Paginate through tags +TAGS_URL="https://hub.docker.com/v2/repositories/${SRC_ORG}/${REPO}/tags?page_size=100" +while [[ -n "${TAGS_URL}" && "${TAGS_URL}" != "null" ]]; do + RESP=$(curl -fsSL "${TAGS_URL}") + echo "${RESP}" | jq -r '.results[].name' | while read -r TAG; do + echo "==> Migrating ${SRC_ORG}/${REPO}:${TAG} → ${DEST_ORG}/${REPO}:${TAG}" + docker pull "${SRC_ORG}/${REPO}:${TAG}" + docker tag "${SRC_ORG}/${REPO}:${TAG}" "${DEST_ORG}/${REPO}:${TAG}" + docker push "${DEST_ORG}/${REPO}:${TAG}" + done + TAGS_URL=$(echo "${RESP}" | jq -r '.next') +done +``` + +This script automatically handles pagination when a repository has more than +100 tags. + +> [!NOTE] +> +> Docker Hub automatically creates the destination repository on first push if +> your account has the necessary permissions. + +### Migrate private repository tags + +For private repositories, authenticate your API calls with a Docker Hub access +token: + +1. Create a personal access token in your + [Docker Hub account settings](https://hub.docker.com/settings/security). + +2. Set your credentials as variables: + + ```bash + HUB_USER="your-username" + HUB_TOKEN="your-access-token" + ``` + +3. Modify the `curl` command in the script to include authentication: + + ```bash + RESP=$(curl -fsSL -u "${HUB_USER}:${HUB_TOKEN}" "${TAGS_URL}") + ``` + +> [!IMPORTANT] +> +> If you encounter pull rate or throughput limits, keep `docker login` active +> to avoid anonymous pulls. Consider adding throttling or careful parallelization +> if migrating large numbers of images. + +## Migrate multiple repositories + +To migrate multiple repositories at once, create a list of repository names +and process them in a loop. + +1. Create a file named `repos.txt` with one repository name per line: + + ```text + api + web + worker + database + ``` + +2. Save the single-repository script from the previous section as + `migrate-single-repo.sh` and make it executable. + +3. Use this wrapper script to process all repositories: + + ```bash + #!/usr/bin/env bash + set -euo pipefail + + SRC_ORG="oldorg" + DEST_ORG="neworg" + + while read -r REPO; do + [[ -z "${REPO}" ]] && continue + echo "==== Migrating repo: ${REPO}" + export REPO + ./migrate-single-repo.sh + done < repos.txt + ``` + +## Preserve multi-architecture images + +Standard `docker pull` only retrieves the image for your current platform. +For multi-architecture images, this approach loses other platform variants. + +### Use Buildx imagetools (recommended) + +The recommended approach uses Buildx to copy the complete manifest without +pulling images locally: + +```console +$ docker buildx imagetools create \ + -t ${DEST_ORG}/${REPO}:${TAG} \ + ${SRC_ORG}/${REPO}:${TAG} +``` + +This command copies the source manifest with all platforms directly to the +destination tag. + +Verify the migration by inspecting both manifests: + +```console +$ docker buildx imagetools inspect ${SRC_ORG}/${REPO}:${TAG} +$ docker buildx imagetools inspect ${DEST_ORG}/${REPO}:${TAG} +``` + +Compare the platforms and digests in the output to confirm they match. + +### Manual manifest creation + +If you need to use the pull/tag/push workflow for multi-architecture images, +you must pull each platform variant and recreate the manifest using +`docker manifest create` and `docker manifest push`. This approach is slower +and more error-prone than using Buildx imagetools. + +## Verify migration integrity + +After migrating images, verify that they transferred correctly. + +### Single-architecture images + +Compare image digests between source and destination: + +```console +$ docker pull ${SRC_ORG}/${REPO}:${TAG} +$ docker inspect --format='{{index .RepoDigests 0}}' ${SRC_ORG}/${REPO}:${TAG} + +$ docker pull ${DEST_ORG}/${REPO}:${TAG} +$ docker inspect --format='{{index .RepoDigests 0}}' ${DEST_ORG}/${REPO}:${TAG} +``` + +The SHA256 digests should match if the migration succeeded. + +### Multi-architecture images + +For multi-arch images, compare the output from Buildx imagetools: + +```console +$ docker buildx imagetools inspect ${SRC_ORG}/${REPO}:${TAG} +$ docker buildx imagetools inspect ${DEST_ORG}/${REPO}:${TAG} +``` + +Verify that the platforms and manifest digest match between source and +destination. + +## Complete the migration + +After migrating your images, complete these additional steps: + +1. Copy repository metadata in the Docker Hub UI or via API: + + - README content + - Repository description + - Topics and tags + +2. Configure repository settings to match the source: + + - Visibility (public or private) + - Team permissions and access controls + +3. Reconfigure integrations in the destination organization: + + - Webhooks + - Automated builds + - Security scanners + +4. Update image references in your projects: + + - Change `FROM oldorg/repo:tag` to `FROM neworg/repo:tag` in Dockerfiles + - Update deployment configurations + - Update documentation + +5. Deprecate the old location: + - Update the source repository description to point to the new location + - Consider adding a grace period before making the old repository private or + read-only diff --git a/content/manuals/docker-hub/repos/manage/hub-images/move.md b/content/manuals/docker-hub/repos/manage/hub-images/move.md index aa1ebd6273ba..965b2a81214b 100644 --- a/content/manuals/docker-hub/repos/manage/hub-images/move.md +++ b/content/manuals/docker-hub/repos/manage/hub-images/move.md @@ -12,6 +12,11 @@ contributing to an organization. This topic explains how to move images between Docker Hub repositories, ensuring that your content remains accessible and organized under the correct accounts or namespaces. +> [!NOTE] +> +> For bulk migrations, multi-arch images, or scripted workflows, see [Bulk +> migrate Docker images](/manuals/docker-hub/repos/manage/hub-images/bulk-migrate.md). + ## Personal to personal When consolidating personal repositories, you can pull private images from the initial repository and push them into another repository owned by you. To avoid losing your private images, perform the following steps: @@ -29,6 +34,7 @@ When consolidating personal repositories, you can pull private images from the i ```console $ docker tag namespace1/docker101tutorial new_namespace/docker101tutorial ``` + 5. Using `docker login` from the CLI, sign in with your newly created Docker account, and push your newly tagged private images to your new Docker account namespace: ```console @@ -49,15 +55,17 @@ personal account and push them to an organization that's owned by you. ```console $ docker pull namespace1/docker101tutorial ``` + 4. Tag your images with your new organization namespace: ```console $ docker tag namespace1/docker101tutorial /docker101tutorial ``` + 5. Push your newly tagged images to your new org namespace: ```console $ docker push new_org/docker101tutorial ``` -The private images that existed in your user account are now available for your organization. \ No newline at end of file +The private images that existed in your user account are now available for your organization. diff --git a/content/manuals/docker-hub/repos/manage/migrate.md b/content/manuals/docker-hub/repos/manage/migrate.md deleted file mode 100644 index 8eb88406a6ff..000000000000 --- a/content/manuals/docker-hub/repos/manage/migrate.md +++ /dev/null @@ -1,3 +0,0 @@ -Migrate repositories -For: organizations -Similar: https://docs.docker.com/docker-hub/repos/manage/hub-images/move/ diff --git a/hugo_stats.json b/hugo_stats.json index 23fc99e1a492..c5133af1965e 100644 --- a/hugo_stats.json +++ b/hugo_stats.json @@ -37,13 +37,17 @@ "Compliant", "Custom-builder", "DNS-resolution", + "DSOS-Legacy-DVP-programs", + "DVP-program", "Debian", + "Desktop-app", "Diff", "Docker-Build-Cloud", "Docker-Desktop", "Docker-Engine", "Docker-Home", "Docker-Hub", + "Docker-Offload", "Docker-Scout", "Docker-Scout-Dashboard", "Docker-subscription", @@ -112,8 +116,10 @@ "Old-Dockerfile", "Other-providers", "PHP", + "Post-rendering", "PowerShell", "PowerShell-CLI", + "Pre-rendering", "Python", "RHEL-8", "RHEL-9", @@ -134,6 +140,7 @@ "Teams", "Testcontainers-Cloud", "TypeScript", + "Typescript", "Ubuntu", "Ubuntu/Debian", "Unix-pipe", From 1494ec74978701ba4861f930dcc29313b9fe57ab Mon Sep 17 00:00:00 2001 From: sarahsanders-docker Date: Thu, 13 Nov 2025 10:16:43 -0500 Subject: [PATCH 3/3] fix hub/home --- content/manuals/docker-hub/repos/manage/export.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/manuals/docker-hub/repos/manage/export.md b/content/manuals/docker-hub/repos/manage/export.md index 682c0b566545..db1be1eabd36 100644 --- a/content/manuals/docker-hub/repos/manage/export.md +++ b/content/manuals/docker-hub/repos/manage/export.md @@ -27,7 +27,7 @@ Before you begin, ensure you have: Organization access tokens let you authenticate API requests without interactive login steps. -1. Navigate to your organization in Docker Hub and select **Admin Console**. +1. Navigate to your organization in [Docker Home](https://app.docker.com) and select **Admin Console**. 2. Select **Access tokens** from the sidebar.