Запуск Docker Registry через Traefik с Docker Compose

Частный Docker Registry хранит ваши образы рядом с GitLab Runner и стендом: docker push/pull без Docker Hub. Ниже — registry:2 за Traefik с basic auth (htpasswd).

Нужны рабочий Traefik и сеть traefik_network.

1. Каталог и пароль

mkdir -p registry/{data,auth}
cd registry

Секрет для HTTP API и htpasswd:

# секрет реестра
echo "REGISTRY_HTTP_SECRET=$(openssl rand -hex 32)" > .env

# пользователь registry (нужен apache2-utils / httpd-tools)
htpasswd -Bbn registry '(youpassword)' > auth/htpasswd

2. docker-compose.yml

services:
  registry:
    image: registry:2
    container_name: registry
    restart: always
    volumes:
      - ./data:/var/lib/registry
      - ./auth:/auth
    environment:
      REGISTRY_HTTP_ADDR: 0.0.0.0:5000
      REGISTRY_HTTP_SECRET: ${REGISTRY_HTTP_SECRET}
      REGISTRY_STORAGE_DELETE_ENABLED: "true"
      REGISTRY_AUTH: htpasswd
      REGISTRY_AUTH_HTPASSWD_REALM: Registry Realm
      REGISTRY_AUTH_HTPASSWD_PATH: /auth/htpasswd
      REGISTRY_HTTP_DEBUG_ADDR: 0.0.0.0:5001
    healthcheck:
      test: ["CMD-SHELL", "wget -q --spider http://127.0.0.1:5000/v2/ || exit 1"]
      interval: 30s
      timeout: 5s
      retries: 3
    labels:
      - traefik.enable=true
      - traefik.http.middlewares.registry_https.redirectscheme.scheme=https
      - traefik.http.routers.registry.entrypoints=web
      - traefik.http.routers.registry.middlewares=registry_https@docker
      - traefik.http.routers.registry.rule=Host(`registry.(yourdomain)`)
      - traefik.http.routers.registry_https.entrypoints=websecure
      - traefik.http.routers.registry_https.rule=Host(`registry.(yourdomain)`)
      - traefik.http.routers.registry_https.tls=true
      - traefik.http.routers.registry_https.tls.certresolver=le
      - traefik.http.services.registry.loadbalancer.server.port=5000
    networks:
      - traefik_network

networks:
  traefik_network:
    external: true

⚠️ Замените (yourdomain). Порт 5000 наружу не публикуйте.

3. Запуск и проверка

docker compose up -d
echo '(youpassword)' | docker login registry.(yourdomain) -u registry --password-stdin

Push / pull:

docker tag myimage:latest registry.(yourdomain)/myimage:latest
docker push registry.(yourdomain)/myimage:latest
docker pull registry.(yourdomain)/myimage:latest

Каталог:

curl -u 'registry:(youpassword)' https://registry.(yourdomain)/v2/_catalog

4. GitLab CI

variables:
  REGISTRY_URL: registry.(yourdomain)
  REGISTRY_USER: registry

before_script:
  - echo "$REGISTRY_PASSWORD" | docker login -u "$REGISTRY_USER" --password-stdin "$REGISTRY_URL"

build:
  script:
    - docker build -t "$REGISTRY_URL/myapp:$CI_COMMIT_SHORT_SHA" .
    - docker push "$REGISTRY_URL/myapp:$CI_COMMIT_SHORT_SHA"

REGISTRY_PASSWORD — Masked/Protected variable в CI.

5. Обслуживание

docker exec registry registry garbage-collect /etc/docker/registry/config.yml

Бэкап: ./data + ./auth/htpasswd + .env. Удаление манифестов разрешено (REGISTRY_STORAGE_DELETE_ENABLED).

6. Замечания

  • DNS registry.(yourdomain) должен указывать на Traefik (иначе ACME/x509).
  • Debug API на 5001 наружу не открывайте.
  • Рядом логично держать GitLab Runner и зеркала вроде Pulp/devpi.

Итог: свой HTTPS-registry с htpasswd для CI и локальных образов без зависимости от Docker Hub.