Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «Як передати образ між хостами без реєстру?». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)**Бери `docker save` + `docker load`**, щоб шиппити image як tar-файл. Registry не потрібен. ```bash # Вихідний host docker save myapp:1.0 -o myapp.tar # (або pipe напряму: docker save myapp:1.0 | gzip > myapp.tar.gz) # Трансфер (scp, rsync, USB, що завгодно) scp myapp.tar user@dest:/tmp/ # Цільовий host docker load -i /tmp/myapp.tar # Loaded image: myapp:1.0 ``` **Головне:** `save` для image, `export` для container (вони різні). Для автоматизованих pipeline бери registry, save/load для ad-hoc, air-gapped або offline сценаріїв.Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)Зображення**Передача Docker image без registry** це відповідь, коли image на host A потрібно на host B, а ти не можеш або не хочеш пушити у registry. Пара `docker save`/`load` це канонічне рішення. ## Теорія ### TL;DR - **`docker save`** = експортує IMAGE (з усіма шарами + метаданими) у tar-файл або stdout. - **`docker load`** = імпортує image-tar назад в інший daemon. - Відрізняється від **`docker export`/`import`**, що працюють на **container** і дають flattened single-layer image без метаданих. - Use cases: air-gapped середовища, USB-трансфер між dev-машинами, image-promotion між безпечними мережами, offline-демо. - Для рутинного cross-host трансферу registry значно кращий (дедуплікація, auth, pull-by-digest). ### Швидкий приклад ```bash # Вихідний host: пакуємо image $ docker save myapp:1.0 -o myapp.tar $ ls -lh myapp.tar -rw------- 1 me me 256M ... myapp.tar # Стискаємо для швидшого трансферу $ docker save myapp:1.0 | gzip > myapp.tar.gz # Трансфер (як завгодно) $ scp myapp.tar.gz user@dest:/tmp/ # Цільовий host: load $ docker load -i /tmp/myapp.tar # АБО $ gunzip -c /tmp/myapp.tar.gz | docker load Loaded image: myapp:1.0 $ docker run --rm myapp:1.0 ``` Image тепер на цільовому host, ніби pull з registry, з тим самим іменем, tag і шарами. ### One-liner через SSH Без проміжного файлу: ```bash $ docker save myapp:1.0 | gzip | ssh user@dest 'gunzip | docker load' ``` Stream через провід, без temp-файлу. Чудово для одноразових трансферів. ### `save` vs `export` Це людей плутає. | | `docker save` | `docker export` | |---|---|---| | Оперує на | image | container | | Шари | збережено (кожен шар у tar) | flattened у один шар | | Image-метадані | збережено (CMD, ENV, history тощо) | втрачено | | Зворотній | `docker load` | `docker import` | | Use case | sharing image | snapshot filesystem only | ```bash # IMAGE save → load (рекомендовано) docker save myimg -o image.tar docker load -i image.tar # CONTAINER export → import (тільки filesystem) docker export <container> -o fs.tar docker import fs.tar imported:1.0 # створює новий image без метаданих ``` 99% часу хочеш `save`/`load`. `export`/`import` для legacy або специфічних кейсів (перебудова image filesystem з нуля). ### Кілька image у одному tar ```bash docker save myapp:1.0 myapp:1.1 nginx:1.27 -o multi.tar docker load -i multi.tar ``` Корисно для шиппінгу цілого стеку у air-gapped середовище одним файлом. ### Типові помилки **Плутати save з export** ```bash # НЕПРАВИЛЬНО: container export, втрачає CMD/ENV/etc. $ docker export api > api.tar $ docker import api.tar api:fresh $ docker run api:fresh # error: no command specified # ПРАВИЛЬНО: image save, зберігає усе $ docker save myimg:1.0 > myimg.tar $ docker load < myimg.tar $ docker run myimg:1.0 # працює як було ``` **Save у stdout без редиректу** ```bash # НЕПРАВИЛЬНО: tar-бінар корумпує термінал $ docker save myimg # (термінал пішов у розноc) # ПРАВИЛЬНО $ docker save myimg -o myimg.tar # АБО $ docker save myimg > myimg.tar ``` Завжди `-o file` або `> file`. Дефолт це stdout, безпечно при редиректі, terminal-breaking без. **Забути, що tar величезний** Save-tar приблизно розміру image (multi-stage з 25MB фіналом → 25MB tar; 1GB image → 1GB tar). Стискай для трансферу: ```bash docker save myimg | zstd > myimg.tar.zst # zstd швидший за gzip docker save myimg | xz > myimg.tar.xz # xz менший, повільніший ``` **Ім'я image не зберігається при `import`** ```bash # `docker import` НЕ зберігає імен $ docker export api > fs.tar $ docker import fs.tar sha256:abc123... # untagged # Треба тегувати руками ``` `docker load` зберігає імена; `docker import` ні. Ще одна причина брати `save`/`load`. ### Коли використовувати save/load (а коли ні) **Бери save/load коли:** - Air-gapped або offline-трансфер (без мережі між host). - Одноразовий трансфер між двома відомими машинами. - Маленька команда, що ще не налаштувала registry. - Бекап/архів конкретних версій image. - Initial bootstrap registry (load image спочатку, потім push). **Бери registry натомість коли:** - Кілька споживачів потребують image (кожен робить `docker pull`). - Хочеш pull-by-digest, signing, vulnerability scan, RBAC. - Трансфер це частина CI/CD-pipeline. - Дбаєш про дедуплікацію між версіями (registry зберігає шари раз). ### Реальне застосування - **Air-gapped enterprise:** усі image течуть як save-tar між security-зонами. - **Customer-on-premise деплой:** ship застосунку як tar, що `docker load`'ить клієнт у своїй мережі. - **Disaster recovery:** save критичних image у backup-storage як tar; load, якщо registry втрачено. - **Embedded / edge devices:** preload image через `docker load` з USB-stick під час виробництва. - **Image-promotion через security-межі:** save у dev, scan offline, load у прод через one-way diode. ### Питання для поглиблення **Q:** Яка різниця між `save` і `pull`? **A:** `pull` тягне image з registry (HTTP). `save` експортує локальний image у tar. Протилежні напрямки руху image з різними storage-носіями. **Q:** Чи зберігається історія image? **A:** З `docker save`/`load` так, повна image-історія, включно з усіма шарами і метаданими. З `docker export`/`import` ні, flattened у один шар. **Q:** Чи цільовий host потребує тієї самої Docker-версії? **A:** OCI-сумісні tarball'и interoperable між сучасними Docker-версіями. Дуже старі daemon можуть мати формат-проблеми, але для будь-якого Docker за останні кілька років працює. **Q:** Що насправді у tar? **A:** Директорія на шар (кожна з tar його filesystem-змін), `manifest.json`, config blob і tag-інфо. Tar це zip-bundled OCI image. **Q:** (Senior) Як заскриптувати multi-image трансфер для air-gapped деплою? **A:** Збери manifest потрібних image (`grep image: compose.yaml | awk ...`), pull кожен на connected-стороні, save усі у один tar (`docker save img1 img2 img3 -o stack.tar`), zstd-стискай для трансферу, шипни через зазор, load на air-gapped стороні. Додай digest-верифікацію на отримуючій стороні: `docker images --digests | tee received.txt` порівняно з digest-списком source, щоб ловити tampered або часткові трансфери. ## Приклади ### Air-gapped деплой Compose-стеку ```bash # На connected build-машині $ docker compose -f compose.yaml pull # переконатися, що всі image present $ images=$(grep image: compose.yaml | awk '{print $2}') $ docker save $images -o stack-2026-04-30.tar.gz # усі image в одному файлі # 1.2 GB ... трансфер через дозволений канал # На air-gapped target $ docker load -i stack-2026-04-30.tar.gz Loaded image: nginx:1.27-alpine Loaded image: postgres:16 Loaded image: myorg/api:1.2.3 $ docker compose up -d ``` Один tar, один load, увесь стек крутиться offline. ### Stream через SSH ```bash $ docker save myapp:1.0 | ssh user@destination 'docker load' Loaded image: myapp:1.0 ``` Без temp-файлу. Корисно, коли disk-space тісний на будь-якій стороні. ### Порівняння з registry-підходом ```bash # save/load: просто, без setup, повільно для повторних трансферів docker save myapp:1.0 | ssh dest 'docker load' # 30 секунд, повний image передано # Registry: dedup, швидше на повторних трансферах docker push myreg.example.com/myapp:1.0 # На dest: docker pull myreg.example.com/myapp:1.0 # 5 секунд, лише змінені шари передано ``` Для щоденних workflow registry перемагає по швидкості і tooling. Для одноразових трансферів save/load перемагає по простоті.Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.