posts projects about

Собственное зеркало Docker Hub

30 мая 2024 г. server

Сегодня Docker заблокировал доступ к своему репозиторию контейнеров hub.docker.com для пользователей из России. Поэтому я поднял себе уютное приватное прокси-зеркало в странах не столь отдаленных. Покажу как это быстро сделать.

UPD. 04.06.24. hub.docker.com уже снова доступен в России

Проблема

Ошибка выглядит как 403 в ответ на docker pull любого образа (веб-морда hub.docker.com тоже недоступна):

#docker pull nginx:latest
Error response from daemon: pull access denied for nginx, repository does not exist or may require 'docker login': denied: <html><body><h1>403 Forbidden</h1>
Since Docker is a US company, we must comply with US export control regulations. In an effort to comply with these, we now block all IP addresses that are located in Cuba, Iran, North Korea, Republic of Crimea, Sudan, and Syria. If you are not in one of these cities, countries, or regions and are blocked, please reach out to https://hub.docker.com/support/contact/
</body></html>

Быстрофикс

Я перепробовал кучу зеркал из интернета, вот это единственное, которое вызывает доверие и работает надежно - https://dockerhub.timeweb.cloud. Если не хочется заморачиваться со своим, то можно использовать его. Для этого в файл /etc/docker/daemon.json (на десктопе - в настройки docker engine - см.скриншот ниже) надо добавить:

"registry-mirrors": [ "https://dockerhub.timeweb.cloud"]

Вот так выглядит мой полный daemon.json:

{
  "registry-mirrors": ["https://dockerhub.timeweb.cloud"],
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "100m",
    "max-file": "3"
  }
}

И перезапустить докер: service docker restart. После этого можно пуллить образы.

Решение

Чтобы организовать свое приватное зеркало поднадобится виртуалка за границей. Сегодня уже многие российские VPC-провайдеры предоставляют возможность поднимать виртуалки в соседних странах, что очень удобно для обхода блокировок.

На созданной виртуалке я использовал Docker Registry от самого докера. Сейчас он называется Distribution — это программа, которая позволяет создать свой приватный container registry. В ней есть функция проксирования+кэш внешних репозиториев. Она и понадобится.

Создаю папки:

#mkdir /opt/registry
#mkdir /opt/registry/data

Создаю docker-compose.yml:

version: '3.3'

services:
  registry:
    image: registry:2
    ports:
      - "0.0.0.0:5000:5000"
    volumes:
      - "/opt/registry/config.yml:/etc/docker/registry/config.yml"
      - "/opt/registry/data:/var/lib/registry"
    restart: always

И создаю конфиг /opt/registry/config.yml:

version: 0.1
storage:
  filesystem:
    rootdirectory: /var/lib/registry
  delete:
    enabled: true
http:
  addr: 0.0.0.0:5000
proxy:
  remoteurl: https://registry-1.docker.io
  ttl: 1d

Что важно:

  • проксирование в registry-1.docker.io
  • ttl для кэша в 1 день
  • если delete:true, то будет очищать данные кэша старше 1-го дня, чтобы много места не съедало. Тут можно тюнить, если место на диске позволяет.

Теперь в папке /opt/registry выполняю:

#docker-compose up -d

Запускается container registry, который уже можно прописывать себе в настройки докер демона /etc/docker/daemon.json (чтобы демон подхватил настройки придётся его перезапустить):

"registry-mirrors": [
    "http://my-private-registry.example.com:5000"
]

И в настройки docker на десктопе: registry-mirrors в MacOS

Опционально

Для секурности можно спрятать это за nginx:

server {
    server_name my-private-registry.example.com;

    location / {
        proxy_pass http://127.0.0.1:5000;
    }

    listen 80; 
}

Попросить certbot выдать сертификат с редиректом, и получить красивый секурный конфиг:

server {
    server_name my-private-registry.example.com;

    location / {
        proxy_pass http://127.0.0.1:5000;
    }

    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/my-private-registry.example.com/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/my-private-registry.example.com/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot

}server {
    if ($host = my-private-registry.example.com) {
        return 301 https://$host$request_uri;
    } # managed by Certbot

    listen 80;
    server_name my-private-registry.example.com;
    return 404; # managed by Certbot
}

И теперь в настройки докера добавить:

"registry-mirrors": [
    "https://my-private-registry.example.com"
]

P.S. И не забыть заменить 0.0.0.0 на 127.0.0.1 в docker-compose.yml