# Архивация образов и Хранилище образов (hub)

<span style="color: rgb(224, 62, 45);">**Первый в /projects\_ogrinizer/compose-files второй в /projects\_ogrinizer/compose-files/Dockerhub**</span>

**Терминология**

**реестр (registry или hub)** – сервис, отвечающий за хранение и распространение образов.  
**репозиторий (repository)** – набор взаимосвязанных образов, обычно различные версии приложения  
**тег (tag)** – алфавитно-цифровой идентификатор, присваиваемый образам внутри репозитория (например, 14.04 или stable). Тегов может быть много.  
**Пространства имен:**

- начинающиеся с текстовой строки и слеша (/), такие как amouat/revealjs В репозитории Docker Hub это образы, выгруженные конкретным пользователем.
- имена без префиксов и слешей, принадлежат пространству имен «root», управляемому компанией Docker Inc.
- имена с префиксами в виде имени хоста или IP-адреса представляют образы, хранящиеся в сторонних реестрах (не в Docker Hub). Например, localhost:5000/wordpress

Docker сохраняет аутентификационную информацию в файле .dockercfg, расположенном в вашем домашнем каталоге.

**Создание архива образа из существующего образа**

Создаем Dockerfile

```
FROM alpine:latest
ARG NODE_ENV=production2
ENV NODE_ENV=${NODE_ENV}
RUN mkdir /var/www
RUN echo $NODE_ENV > /var/www/first.txt
CMD ["cat", "/var/www/first.txt"]
```

Собираем образ

```
docker build -t bobrobot:1.0 .
```

 Сохраняем образ, копируем и устанавливаем на нужной системе, и запускаем

```
docker save bobrobot:1.0 > bobrobot:1.0.tar
docker load -i bobrobot\:1.0.tar
docker run bobrobot:1.0
```

**Команды**

<table border="1" id="bkmrk-%D0%9A%D0%BE%D0%BC%D0%B0%D0%BD%D0%B4%D0%B0-%D0%94%D0%BE%D0%BF.-%D0%BF%D0%B0%D1%80.-%D0%9E%D0%BF" style="border-collapse: collapse; width: 100%;"><colgroup><col style="width: 25.1474%;"></col><col style="width: 12.3973%;"></col><col style="width: 62.4553%;"></col></colgroup><thead><tr><td class="align-center">Команда</td><td class="align-center">Доп. пар.</td><td class="align-center">Описание</td></tr></thead><tbody><tr><td>**docker login**</td><td>  
</td><td>Регистрация/вход на сервер реестра. По умолчанию Docker Hub. ```
docker login https://hub.bobrobotirk.ru
```

</td></tr><tr><td>**docker logout**</td><td>  
</td><td>Выход из реестра Docker. По умолчанию Docker Hub.</td></tr><tr><td>**docker pull**</td><td>  
</td><td>Загружает заданный образ из реестра. Реестр определяется по имени образа, по умолчанию принимается Docker Hub.</td></tr><tr><td>**docker push**</td><td>  
</td><td>Выгружает образ или репозиторий в заданный реестр. При отсутствии тега выгружаются все образы указанного репозитория в заданный реестр. ```
docker push hub.bobrobotirk.ru/testimage
```

</td></tr><tr><td>**docker search**</td><td>  
</td><td>Выводит список общедоступных репозиториев из реестра Docker Hub</td></tr><tr><td>**docker build .**</td><td>  
</td><td>  
</td></tr><tr><td>  
</td><td>-t</td><td>Определение имени репозитория и тега</td></tr><tr><td>**docker tag &lt;current&gt; &lt;in hub&gt;**</td><td>  
</td><td>Устанавливается соответствие имени с образом, который ссылается на образ в репозитории Docker Hub. ```
docker tag testimage hub.bobrobotirk.ru/testimage
```

</td></tr></tbody></table>

**Локальный hub (теория из разных источников, кое-что устаревшее)**

[Пример](https://www.dmosk.ru/miniinstruktions.php?mini=docker-local-repo)

На серверной стороне:

```bash
mkdir dockertest_certs
openssl req -newkey rsa:4096 -nodes -sha256 -subj "/CN=dockertest" -addext "subjectAltName = DNS:dockertest" -keyout dockertest_certs/domain.key -x509 -days 365 -out dockertest_certs/domain.crt
docker run -d -p 5000:5000 -v $(pwd)/dockertest_certs:/certs -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt -e REGISTRY_HTTP_TLS_KEY=/certs/domain.key --restart=always --name registry registry
docker run --entrypoint htpasswd httpd:2 -Bbn testuser testpassword >> auth/htpasswd #добавить пользователя
```

На клиентской стороне (из-под root):

```bash
mkdir -p /etc/docker/certs.d/dockertest:5000
#добавить в /etc/hosts запись о сервере dockertest
scp sergey@dockertest:/home/sergey/dockertest_certs/domain.crt /etc/docker/certs.d/dockertest:5000/ca.crt
service docker restart
```

Перелинковать на клиенте образ на новый хаб и загрузить его

```bash
docker tag amouat/identidock:0.1 dockertest:5000/identidock:0.1
docker push dockertest:5000/identidock:0.1
```

Пример docker-compose.yml для запуска локального реестра

```yaml
services:
 registry:
  restart: always
  image: registry
  ports:
   - "5000:5000"
  environment:
   REGISTRY_HTTP_TLS_CERTIFICATE: /certs/domain.crt
   REGISTRY_HTTP_TLS_KEY: /certs/domain.key
   REGISTRY_AUTH: htpasswd
   REGISTRY_AUTH_HTPASSWD_PATH: /auth/htpasswd
   REGISTRY_AUTH_HTPASSWD_REALM: Registry Realm
  volumes:
   - ./dockertest_certs:/certs
   - ./auth:/auth
```

**Практический запуск регистра**

Поскольку это пока что тестовый хаб, решил сделать [сертификат LetsEncrypt](http://bobrobotirk.ru/books/linux/page/sertifikat-ot-letsencrypt "Сертификат от LetsEncrypt"). На dns сервере сделал запись сайта hub.bobrobotirk.ru. Прокинул порты 443 и 8090 до виртуальной машины. Создал папки

```
mkdir data
mkdir auth
mkdir certs
```

В папку certs скопировал сертификат и ключ. Для создания пользователей установил утилиту

```
sudo apt-get install apache2-utils
```

Создал пользователя testuser с паролем StrongPassword

```
htpasswd -Bbn testuser StrongPassword > auth/htpasswd
```

Для добавления пользователей:

```
htpasswd -Bb auth/htpasswd user2 password2
```

Создал docker-compose.yaml

```yaml
services:
  registry-server:
    image: registry:2.8.2
    container_name: registry-server
    restart: always
    ports:
      - "443:5000" # Перенаправление HTTPS-трафика
    environment:
      REGISTRY_HTTP_HEADERS_Access-Control-Allow-Origin: '["https://hub.bobrobotirk.ru"]'
      REGISTRY_HTTP_HEADERS_Access-Control-Allow-Methods: '["HEAD", "GET", "OPTIONS", "DELETE"]'
      REGISTRY_HTTP_HEADERS_Access-Control-Allow-Credentials: '["true"]'
      REGISTRY_HTTP_HEADERS_Access-Control-Allow-Headers: '["Authorization", "Accept", "Cache-Control"]'
      REGISTRY_HTTP_HEADERS_Access-Control-Expose-Headers: '["Docker-Content-Digest"]'
      REGISTRY_AUTH: htpasswd
      REGISTRY_AUTH_HTPASSWD_REALM: Registry Realm
      REGISTRY_AUTH_HTPASSWD_PATH: /auth/htpasswd
      REGISTRY_HTTP_TLS_CERTIFICATE: /certs/cert.crt
      REGISTRY_HTTP_TLS_KEY: /certs/key.key
      REGISTRY_STORAGE_DELETE_ENABLED: "true"
    volumes:
      - ./data:/var/lib/registry # Для сохранения данных реестра
      - ./auth:/auth                     # Для файла htpasswd
      - ./certs:/certs                  # Для SSL сертификатов

  registry-ui:
    image: joxit/docker-registry-ui:main
    container_name: registry-ui
    restart: always
    ports:
      - "8090:80" # Интерфейс доступен по порту 8090
    environment:
      SINGLE_REGISTRY: "true"
      REGISTRY_TITLE: "BobRobotIRK Docker Registry"
      DELETE_IMAGES: "true"
      SHOW_CONTENT_DIGEST: "true"
      NGINX_PROXY_PASS_URL: "https://hub.bobrobotirk.ru" # URL реестра
      SHOW_CATALOG_NB_TAGS: "true"
      CATALOG_MIN_BRANCHES: "1"
      CATALOG_MAX_BRANCHES: "1"
      TAGLIST_PAGE_SIZE: "100"
      REGISTRY_SECURED: "true" # Реестр защищен авторизацией
      CATALOG_ELEMENTS_LIMIT: "1000"
    depends_on:
      - registry-server
```

И по адресу [http://hub.bobrobotirk.ru:8090/](http://hub.bobrobotirk.ru:8090/) появился web интерфейс с авторизацией.

Авторизовался с другого сервера

```
docker login https://hub.bobrobotirk.ru
```

Создал Dockerfile

```
FROM alpine:latest
ARG NODE_ENV=production2
ENV NODE_ENV=${NODE_ENV}
RUN mkdir /var/www
RUN echo $NODE_ENV > /var/www/first.txt
CMD ["cat", "/var/www/first.txt"]
```

Собрал образ (пора переходить на buildx)

```
docker build -t testimage .
```

Точка обозначает расположение Dockerfile)

Он появился в списке образов

```
docker images
REPOSITORY   TAG       IMAGE ID       CREATED         SIZE
testimage    latest    1f3755f48bea   3 minutes ago   7.83MB
```

Добавил тег образу

```
docker tag testimage hub.bobrobotirk.ru/testimage
```

Загрузил образ на hub

```
docker push hub.bobrobotirk.ru/testimage
```

Да, образ отобразился в списке. Теперь на третьем сервере авторизовался на hub.bobrobotirk.ru и попробовал запустить контейнер из образа

```
services:
  testapp:
    image: hub.bobrobotirk.ru/testimage
```

Образ скачался и контейнер запустился. Повторить это все просто, а в первый раз потратил на это один день.

P.s. Второй вариант, в случае наличия внешнего nginx reverse proxy + https termination

```yaml
services:
  http-registry-server:
    image: registry:2.8.2
    container_name: http-registry-server
    restart: no
    ports:
      - "${HUB_BACKEND_PORT}:5000" # Перенаправление HTTP-трафика
    environment:
      REGISTRY_AUTH: htpasswd
      REGISTRY_AUTH_HTPASSWD_REALM: Registry Realm
      REGISTRY_AUTH_HTPASSWD_PATH: /auth/htpasswd
      REGISTRY_STORAGE_DELETE_ENABLED: "true"
      REGISTRY_HTTP_ADDR: 0.0.0.0:5000
      REGISTRY_HTTP_NET: "tcp"  # Явно указываем протокол
      REGISTRY_HTTP_HEADERS_Access-Control-Allow-Origin: '["*"]'
      REGISTRY_HTTP_HEADERS_Access-Control-Allow-Methods: '["HEAD", "GET", "OPTIONS", "DELETE"]'
      REGISTRY_HTTP_HEADERS_Access-Control-Allow-Credentials: '["true"]'
      REGISTRY_HTTP_HEADERS_Access-Control-Allow-Headers: '["Authorization", "Accept", "Cache-Control"]'
      REGISTRY_HTTP_HEADERS_Access-Control-Expose-Headers: '["Docker-Content-Digest"]'
    volumes:
      - ./data:/var/lib/registry # Для сохранения данных реестра
      - ./auth:/auth                     # Для файла htpasswd

  http-registry-ui:
    image: joxit/docker-registry-ui:main
    container_name: http-registry-ui
    restart: no
    ports:
      - "${HUB_BACKEND_WEB_PORT}:80"
    environment:
      NGINX_PROXY_PASS_URL: "http://${HUB_BACKEND_IP}:${HUB_BACKEND_PORT}"
      SINGLE_REGISTRY: "true"
      REGISTRY_TITLE: "${WEB_TITLE}"
      DELETE_IMAGES: "true"
      SHOW_CONTENT_DIGEST: "true"
      SHOW_CATALOG_NB_TAGS: "true"
      CATALOG_MIN_BRANCHES: "1"
      CATALOG_MAX_BRANCHES: "1"
      TAGLIST_PAGE_SIZE: "100"
      REGISTRY_SECURED: "true" # Реестр защищен авторизацией
      CATALOG_ELEMENTS_LIMIT: "1000"
    depends_on:
      - http-registry-server
```

**Примеры**

Загрузка образа с тегом latest в репозиторий amouat/revealjs из реестра Docker Hub.

```bash
docker pull amouat/revealjs:latest 
```

Загрузка образа из неофициального реестра.

```bash
docker pull gcr.io/google-containers/git-sync:v3.1.5
```

Определение имени репозитория identidock и тега 0.1 для образа, собранного из локального dockerfile.

```bash
docker build -t "identidock:0.1" .
```

Устанавливается соответствие имени amouat/identidock с образом, который ссылается на имя пользователя amouat в репозитории Docker Hub.

```bash
docker tag "identidock:0.1" "amouat/identidock:0.1"
```

**Ссылки**

[Настройка локального hub](https://www.dmosk.ru/miniinstruktions.php?mini=docker-local-repo)