Skip to main content

Як push і pull images на Docker Hub?

Push і pull image на Docker Hub це базовий workflow для sharing'у image: тегуєш image зі своїм namespace, логінишся один раз, пушиш, потім тягнеш звідки завгодно.

Теорія

TL;DR

  • Чотири команди покривають 99 відсотків кейсів: docker login, docker tag, docker push, docker pull.
  • Формат імені image: <namespace>/<repo>:<tag>, де <namespace> це твій Docker Hub username або організація. Без префіксу означає «офіційний library namespace», туди ти запушити не можеш.
  • Автентифікація через personal access token (PAT), не пароль акаунту. PAT обмежують scope (read-only / read-write / read-write-delete) і чисто revoke'аються.
  • Credentials лежать у ~/.docker/config.json після docker login. На macOS / Windows за credential helper.
  • Публічні репо: необмежена кількість, безкоштовно. Приватні поза free tier потребують платний план. Анонімні pull rate-лімітовані (100 на 6 годин на IP); автентифіковані вищі.

Швидкий приклад

bash
# 1. Збираємо локальний image $ docker build -t myapp:1.0 . # 2. Тегуємо зі своїм Docker Hub namespace $ docker tag myapp:1.0 youruser/myapp:1.0 # 3. Автентифікуємось (один раз, до logout) $ docker login -u youruser Password: **** # сюди paste PAT, не пароль акаунту Login Succeeded # 4. Push $ docker push youruser/myapp:1.0 The push refers to repository [docker.io/youruser/myapp] adc4d6e8f1c2: Pushed 8a3f2d1c9b8e: Pushed 1.0: digest: sha256:9f8e7d6c... size: 1247 # З іншої машини $ docker pull youruser/myapp:1.0

Ось повний цикл. Build, tag, login, push, потім pull з будь-якого хоста, де встановлений Docker.

Іменування і тегування image

Повна форма для Docker Hub: [docker.io/]<namespace>/<repo>:<tag>.

  • docker.io/ це неявний дефолтний registry. Майже ніколи не пишеш.
  • <namespace> = твій Docker Hub username або організація, до якої ти належиш.
  • <repo> = ім'я репозиторію. Створюється автоматично при першому push.
  • <tag> = мітка цього білду (v1.0, 2026-04-30, pr-1247, latest). Дефолт latest, якщо не вказати.

Приклади:

bash
youruser/myapp:1.0 # особистий namespace, version tag mycompany/api:2026-04-30 # org namespace, date tag mycompany/api # неявно :latest, уникай для проду nginx:1.27 # офіційний library/nginx, library/ неявний

Команда docker tag не рухає байти; вона лише додає ім'я, що вказує на той самий image ID. Один image може мати багато tag.

Автентифікація: PAT, не пароль

Docker Hub підтримує два способи логіну:

bash
# Старий спосіб, пароль акаунту (працює, але погана практика) $ docker login -u youruser Password: <пароль акаунту> # Сучасний спосіб, personal access token $ docker login -u youruser Password: <paste PAT з https://hub.docker.com/settings/security>

PAT дають тобі:

  • Scope токена (read-only / read-write / read-write-delete-public-repo).
  • Revoke без зміни паролю акаунту.
  • Використовувати кілька токенів на машину (CI runner, лептоп, сервер) і ротувати незалежно.

У CI токени тримають як repository secrets. Ніколи не комітимо токен у git, ніколи не вставляємо в Dockerfile.

Де лежать credentials

Після docker login credentials лягають у ~/.docker/config.json:

json
{ "auths": { "https://index.docker.io/v1/": { "auth": "base64(username:PAT)" } } }

На macOS і Windows Docker використовує OS keychain (credsStore: osxkeychain, desktop), файл лише вказує на keychain, не на сирий токен. Linux без credential helper зберігає base64-токен прямо у файлі. chmod 600 ~/.docker/config.json, якщо так робиш.

Типові помилки

Push без префіксу namespace

bash
# НЕПРАВИЛЬНО: намагається запушити в офіційний library/ $ docker push myapp:1.0 requested access to the resource is denied # ПРАВИЛЬНО: включай свій namespace $ docker tag myapp:1.0 youruser/myapp:1.0 $ docker push youruser/myapp:1.0

Повідомлення про помилку безкорисне; причина завжди відсутній namespace.

Логін під паролем акаунту замість PAT

bash
$ docker login -u youruser Password: <пароль акаунту> Login Succeeded

Працює, але якщо твій пароль зливається, зловмисник отримує повний доступ до акаунту. PAT лімітує радіус ураження і revoke'ається окремо.

Запушити :latest і забути запушити версійний tag

bash
# НЕПРАВИЛЬНО: тільки :latest нагорі $ docker tag myapp:1.0 youruser/myapp:latest $ docker push youruser/myapp:latest # ПРАВИЛЬНО: push обидва, щоб люди могли пінитися на конкретну версію $ docker tag myapp:1.0 youruser/myapp:1.0 $ docker tag myapp:1.0 youruser/myapp:latest $ docker push youruser/myapp:1.0 $ docker push youruser/myapp:latest # Або одним махом: docker push --all-tags youruser/myapp

Якщо споживачі можуть тягти тільки :latest, вони не можуть пінитися на конкретну версію, і одного дня твій :latest їх здивує.

Натрапити на rate limit анонімного pull у CI

ERROR: toomanyrequests: You have reached your pull rate limit.

Docker Hub rate-лімітує анонімні IP до 100 pull на 6 годин, а спільний CI IP може спалити це швидко. Автентифікуй CI runner (docker login з токеном) або тягни через registry mirror (Google Artifact Registry, AWS ECR pull-through cache).

Реальне застосування

  • GitHub Actions: docker/login-action@v3 читає username + PAT з secrets, потім docker/build-push-action@v5 будує і пушить в одному кроці. Стандартний патерн у тисячах репо.
  • Локальний лептоп → спільне dev-середовище: запушив свій бранч-image у приватне репо Docker Hub, твій колега робить docker pull і запускає без rebuild.
  • Open-source дистрибуція: інструменти типу tini, dive і багато CLI публікують свої офіційні image на Docker Hub під verified-publisher namespace.
  • CI/CD пайплайни у менших командах: PR-білди, тегнуті як myapp:pr-1247, пушаться у приватне Docker Hub репо, staging-середовище їх тягне, інтеграційні тести бігають.

Питання для поглиблення

Q: Яка різниця між docker push і docker push --all-tags?


A: Звичайний docker push youruser/myapp:1.0 пушить один tag. docker push --all-tags youruser/myapp пушить кожен локальний tag того репозиторію. Корисно, коли ти позначив той самий image і версією, і latest.

Q: Як запушити приватний image?


A: Ті самі команди. Repo створюється при першому push; його visibility ставиш як private з web UI Docker Hub (або через API). Free акаунти Docker Hub включають одне приватне репо; більше потребує платного плану.

Q: Чи можна запушити image для кількох архітектур (amd64 + arm64)?


A: Так, через docker buildx. docker buildx build --platform linux/amd64,linux/arm64 -t youruser/myapp:1.0 --push . будує обидві архітектури і заливає їх як manifest list під одним tag. Споживачі автоматично тягнуть правильну для свого CPU.

Q: Як видалити image з Docker Hub?


A: Видалення tag з web UI або через curl проти Docker Hub API з PAT, що має delete scope. Немає docker delete-tag CLI. Видалення репозиторію теж тільки через web UI.

Q: (Senior) Як уникнути вшивання push-credentials у CI-логи і історію?


A: Використовуй офіційний login action (docker/login-action), що читає з masked secrets і ніколи їх не echo'їть. Для self-hosted CI передавай токен через --password-stdin: echo $DOCKER_TOKEN | docker login -u $DOCKER_USER --password-stdin. Ніколи не використовуй docker login -u user -p $TOKEN, це кладе токен у shell history і process listing (ps aux показав би його під час виклику).

Приклади

Push з GitHub Actions workflow

yaml
name: build-and-push on: push: branches: [main] jobs: publish: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: docker/login-action@v3 with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - uses: docker/build-push-action@v5 with: push: true tags: | youruser/myapp:latest youruser/myapp:${{ github.sha }}

Кожен push у main дає image, тегнутий latest і commit SHA. Прод-деплої пінься на SHA-tag для відтворюваності.

Rate limit'и pull у CI, фікс

bash
# Симптом: build job падає ERROR: toomanyrequests: You have reached your pull rate limit. # Фікс у твоєму CI: логінься перед будь-яким pull - name: Docker login uses: docker/login-action@v3 with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - name: Build run: docker build -t myapp .

Автентифіковані pull мають значно вищий ліміт. Сам login-крок безкоштовний.

Push того самого image у два registry

bash
# Тегуємо раз, пушимо двічі, корисно для надлишковості або міграції $ docker build -t myapp:1.0 . $ docker tag myapp:1.0 youruser/myapp:1.0 $ docker tag myapp:1.0 ghcr.io/youruser/myapp:1.0 $ docker login docker.io $ docker push youruser/myapp:1.0 $ docker login ghcr.io $ docker push ghcr.io/youruser/myapp:1.0

Ті самі байти image, два registry, два namespaces. Споживачі тягнуть звідки хочуть.

Коротка відповідь

Для співбесіди
Premium

Коротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.

Коментарі

Ще немає коментарів