Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «Як push і pull images на Docker Hub?». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)**Push і pull на Docker Hub** зводяться до чотирьох команд: `docker login` один раз, `docker tag`, щоб дати image ім'я `username/repo:tag`, `docker push` для завантаження, `docker pull` для скачування. ```bash $ docker login -u youruser # одноразова авторизація $ docker tag myapp:1.0 youruser/myapp:1.0 $ docker push youruser/myapp:1.0 $ docker pull youruser/myapp:1.0 # з іншої машини ``` **Головне:** ім'я image має починатися з твого Docker Hub username (або організації). Використовуй personal access token, не пароль акаунту. Публічні репо безкоштовні; приватні поза free tier потребують платний план.Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)Зображення**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. Споживачі тягнуть звідки хочуть.Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.