Частный Docker Registry хранит ваши образы рядом с GitLab Runner и стендом: docker push/pull без Docker Hub. Ниже — registry:2 за Traefik с basic auth (htpasswd).
Нужны рабочий Traefik и сеть traefik_network.
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
docker-compose.ymlservices:
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наружу не публикуйте.
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
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.
docker exec registry registry garbage-collect /etc/docker/registry/config.yml
Бэкап: ./data + ./auth/htpasswd + .env. Удаление манифестов разрешено (REGISTRY_STORAGE_DELETE_ENABLED).
registry.(yourdomain) должен указывать на Traefik (иначе ACME/x509).5001 наружу не открывайте.Итог: свой HTTPS-registry с htpasswd для CI и локальных образов без зависимости от Docker Hub.