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

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

Дочитали статтю?