Dependency Proxy

Tier: Free, Premium, Ultimate Offering: GitLab.com, Self-Managed, GitLab Dedicated

GitLab의 Dependency Proxy는 자주 액세스하는 상위 이미지에 대해 사용할 수 있는 로컬 프록시입니다.

CI/CD의 경우 의존성 프록시는 요청을 수신하고 레지스트리에서 상위 이미지를 반환하여 풀 스루 캐시로 작동합니다.

Prerequisites

의존성 프록시를 사용하려면 GitLab 인스턴스에 대해 활성화되어 있어야 합니다. 기본적으로 활성화되어 있지만 관리자가 비활성화할 수 있습니다.

지원되는 이미지 및 패키지

다음 이미지 및 패키지가 지원됩니다.

이미지/패키지 GitLab 버전
Docker 14.0+

계획된 추가 사항의 목록은 방향 페이지를 참조하세요.

그룹을 위한 의존성 프록시 활성화 또는 비활성화

그룹에서 의존성 프록시를 활성화하거나 비활성화하려면:

  1. 왼쪽 사이드바에서 검색 또는 이동을 선택하고 그룹을 찾습니다.
  2. 설정 > 패키지 및 레지스트리를 선택합니다.
  3. 의존성 프록시 섹션을 확장합니다.
  4. 프록시를 활성화하려면 프록시 활성화를 켭니다. 꺼내려면 토글을 끕니다.

이 설정은 그룹을 위한 의존성 프록시에만 영향을 미칩니다. 전체 GitLab 인스턴스의 의존성 프록시를 관리자만 켜거나 끌 수 있습니다.

의존성 프록시 보기

의존성 프록시를 보려면:

  1. 왼쪽 사이드바에서 검색 또는 이동을 선택하고 그룹을 찾습니다.
  2. 운영 > 의존성 프록시를 선택합니다.

의존성 프록시는 프로젝트에서 사용할 수 없습니다.

Docker 이미지에 대한 의존성 프록시 사용

GitLab을 Docker 이미지의 원본으로 사용할 수 있습니다.

사전 요구 사항:

  • 귀하의 이미지는 Docker Hub에 저장되어 있어야 합니다.

의존성 프록시와의 인증

의존성 프록시가 Docker 이미지를 그룹과 연관된 공간에 저장하기 때문에 의존성 프록시에 대해 인증해야 합니다.

개인 레지스트리에서 이미지 사용 지침을 따르되, 포트 없이 GitLab 도메인을 사용하세요.

참고: 관리자 모드는 의존성 프록시와의 인증 중에 적용되지 않습니다. 관리자가 관리자 모드를 사용하고 admin_mode 범위가없는 개인 액세스 토큰을 만들면 관리자 모드가 활성화되어 있어도 해당 토큰이 작동합니다.

예를 들어, 수동으로 로그인:

echo "$CONTAINER_REGISTRY_PASSWORD" | docker login gitlab.example.com --username my_username --password-stdin

다음을 사용하여 인증할 수 있습니다:

개인 액세스 토큰이나 사용자 이름과 암호를 사용하여 의존성 프록시에 액세스하는 사용자는 해당 그룹의 게스트 역할 이상이어야 합니다.

의존성 프록시는 Docker v2 토큰 인증 플로를 준수하여 클라이언트에게 풀 요청에 사용할 JWT를 발급합니다. 인증을 위해 클라이언트에게 발급된 JWT는 시간이 지난 후 만료됩니다. 토큰이 만료되면 대부분의 Docker 클라이언트는 자격 증명을 저장하고 자동으로 새로운 토큰을 요청합니다.

토큰 만료 시간은 구성 가능한 설정입니다. GitLab.com에서의 만료 시간은 15분입니다.

SAML SSO

SSO 강제 적용이 활성화되어 있을 때, 사용자는 의존성 프록시를 통해 이미지를 가져오기 전에 SSO를 통해 로그인해야 합니다.

SSO 강제 적용은 자동 병합에도 영향을 미칩니다. SSO 세션이 자동 병합이 트리거되기 전에 만료되면 병합 파이프라인은 이미지를 가져오지 못하고 실패합니다.

CI/CD 내에서 인증

런너는 의존성 프록시에 자동으로 로그인합니다. 의존성 프록시를 통해 가져오려면 사전 정의된 변수 중 하나를 사용합니다.

  • CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX는 최상위 그룹을 통해 가져옵니다.
  • CI_DEPENDENCY_PROXY_DIRECT_GROUP_IMAGE_PREFIX는 하위 그룹 또는 프로젝트가 있는 직접적인 그룹을 통해 가져옵니다.

최신 알파인 이미지를 가져오는 예:

# .gitlab-ci.yml
image: ${CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX}/alpine:latest

또한 사용할 수 있는 다른 사전 정의 CI/CD 변수가 있습니다.

  • CI_DEPENDENCY_PROXY_USER: 의존성 프록시에 로그인하는 CI/CD 사용자.
  • CI_DEPENDENCY_PROXY_PASSWORD: 의존성 프록시에 로그인하는 CI/CD 암호.
  • CI_DEPENDENCY_PROXY_SERVER: 의존성 프록시에 로그인하는 서버.
  • CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX: 의존성 프록시를 통해 이미지를 가져오는 데 사용되는 이미지 접두어를 나타냅니다.
  • CI_DEPENDENCY_PROXY_DIRECT_GROUP_IMAGE_PREFIX: 의존성 프록시를 통해 이미지를 가져오는 데 사용되는 이미지 접두어를 나타낸느데 사용됩니다.

CI_DEPENDENCY_PROXY_SERVER, CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX, CI_DEPENDENCY_PROXY_DIRECT_GROUP_IMAGE_PREFIX에는 서버 포트가 포함됩니다. 의존성 프록시 경로를 명시적으로 포함하는 경우 포트를 포함해야 합니다. 수동으로 의존성 프록시에 로그인할 때 포트가 포함되지 않았다면:

docker pull gitlab.example.com:443/my-group/dependency_proxy/containers/alpine:latest

이미지를 빌드할 때 의존성 프록시를 사용하는 예:

# Dockerfile
FROM gitlab.example.com:443/my-group/dependency_proxy/containers/alpine:latest
# .gitlab-ci.yml
image: docker:20.10.16

variables:
  DOCKER_HOST: tcp://docker:2375
  DOCKER_TLS_CERTDIR: ""

services:
  - docker:20.10.16-dind

build:
  image: docker:20.10.16
  before_script:
    - echo "$CI_DEPENDENCY_PROXY_PASSWORD" | docker login $CI_DEPENDENCY_PROXY_SERVER -u $CI_DEPENDENCY_PROXY_USER --password-stdin
  script:
    - docker build -t test .

또한 사용자 정의 CI/CD 변수를 사용하여 개인 액세스 토큰 또는 배포 토큰을 저장하고 액세스할 수 있습니다.

Dependency Proxy 캐시에 Docker 이미지 저장

Dependency Proxy 저장소에 Docker 이미지를 저장하려면:

  1. 왼쪽 사이드바에서 검색 또는 이동을 선택하고 그룹을 찾습니다.
  2. 운영 > Dependency Proxy를 선택합니다.
  3. Dependency Proxy 이미지 접두어를 복사합니다.
  4. 다음 명령 중 하나를 사용하십시오. 이 예시에서 이미지는 alpine:latest입니다.
  5. 이미지를 명확히 지정하려면 다이제스트로 이미지를 끌어올 수도 있습니다.

    • 이미지를 태그별로 끌어오려면 이미지를 .gitlab-ci.yml 파일에 추가합니다.
    image: gitlab.example.com/groupname/dependency_proxy/containers/alpine:latest
    
    • 이미지를 다이제스트로 끌어오려면 이미지를 .gitlab-ci.yml 파일에 추가합니다.
    image: ${CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX}/alpine@sha256:c9375e662992791e3f39e919b26f510e5254b42792519c180aad254e6b38f4dc
    
    • Docker 이미지를 수동으로 끌어옵니다.
    docker pull gitlab.example.com/groupname/dependency_proxy/containers/alpine:latest
    
    • Dockerfile에 URL을 추가합니다.
    FROM gitlab.example.com/groupname/dependency_proxy/containers/alpine:latest
    

GitLab은 Docker Hub에서 Docker 이미지를 끌어와서 블롭을 GitLab 서버에 캐시합니다. 동일한 이미지를 다음에 다시 끌어올 때는 Docker Hub에서 이미지의 최신 정보를 가져오지만 기존의 블롭은 GitLab 서버에서 제공합니다.

저장 공간 사용량 줄이기

Dependency Proxy에서 저장 공간 사용량을 줄이는 정보는 Dependency Proxy 저장 공간 사용량 줄이기를 참조하세요.

Docker Hub 속도 제한과 Dependency Proxy

Dependency Proxy를 사용하여 Docker Hub 속도 제한을 피하는 방법은 여기에서 확인할 수 있습니다.

2020년 11월, Docker는 Docker Hub에서의 풀 요청 속도 제한을 도입했습니다. GitLab CI/CD 구성이 Docker Hub에서 이미지를 사용하는 경우, 작업을 실행할 때마다 요청이 풀 요청으로 계산될 수 있습니다. 이 한도를 피하기 위해 Dependency Proxy 캐시에서 이미지를 끌어올 수 있습니다.

이미지를 끌어올 때(Docker pull 명령어 또는 .gitlab-ci.yml 파일에서 image: foo:latest를 사용하여), Docker 클라이언트는 일련의 요청을 수행합니다. 1. 이미지 매니페스트를 요청합니다. 매니페스트에는 이미지를 빌드하는 방법에 대한 정보가 포함되어 있습니다. 1. 매니페스트를 사용하여 Docker 클라이언트는 한 번에 하나씩 알려진 레이어 모음 또는 블롭을 요청합니다.

Docker Hub 속도 제한은 매니페스트의 GET 요청 수에 기반합니다. Dependency Proxy는 주어진 이미지의 매니페스트와 블롭을 캐시하기 때문에 다시 요청할 때 Docker Hub에 연락할 필요가 없습니다.

캐시된 태그별 이미지가 오래된지 GitLab은 어떻게 알까요?

alpine:latest와 같은 이미지 태그를 사용하면 시간이 지남에 따라 이미지가 변경됩니다. 각 변경 때마다 매니페스트에는 요청할 블롭에 대한 다른 정보가 포함됩니다. Dependency Proxy는 매니페스트가 오래된지만 확인하므로 매니페스트가 오랫동안 변경되지 않습니다.

Docker는 이미지 매니페스트에 대한 HEAD 요청을 속도 제한으로 계산하지 않습니다. HEAD 요청으로 alpine:latest에 대한 요청을 할 수 있고, 헤더에 반환된 다이제스트(체크섬) 값을 확인하여 매니페스트가 변경되었는지 확인할 수 있습니다.

Dependency Proxy는 모든 요청을 HEAD 요청으로 시작합니다. 매니페스트가 오래된 경우에만 새 이미지가 끌어옵니다.

예를 들어, 파이프라인이 5분마다 node:latest를 끌어오는 경우, Dependency Proxy는 전체 이미지를 캐시하고 node:latest가 변경될 때만 업데이트합니다. 따라서 6시간 동안 이미지에 360회의 요청(이를 넘어선 Docker Hub 속도 제한)이 아닌 한 번의 풀 요청만 있게 됩니다. 그 시간 동안 매니페스트가 변경되지 않았다면요, 단 한 번의 풀 요청만이 있습니다.

Docker Hub 속도 제한 확인

Docker Hub에 대한 요청 수와 남은 횟수를 알고 싶다면, 다음 명령어를 실행할 수 있습니다.

# 참고: 이 명령어를 실행하려면 jq가 설치되어 있어야 합니다
TOKEN=$(curl "https://auth.docker.io/token?service=registry.docker.io&scope=repository:ratelimitpreview/test:pull" | jq --raw-output .token) && curl --head --header "Authorization: Bearer $TOKEN" "https://registry-1.docker.io/v2/ratelimitpreview/test/manifests/latest" 2>&1 | grep --ignore-case RateLimit
...

출력 예시:

RateLimit-Limit: 100;w=21600
RateLimit-Remaining: 98;w=21600

이 예시는 6시간 동안 100번의 풀 요청 한도가 있고, 98번의 풀 요청이 남아 있는 것을 보여줍니다.

CI/CD 작업에서 속도 제한 확인

다음은 jqcurl이 설치된 GitLab CI/CD 작업을 보여줍니다.

hub_docker_quota_check:
    stage: build
    image: alpine:latest
    tags:
        - <optional_runner_tag>
    before_script: apk add curl jq
    script:
      - |
        TOKEN=$(curl "https://auth.docker.io/token?service=registry.docker.io&scope=repository:ratelimitpreview/test:pull" | jq --raw-output .token) && curl --head --header "Authorization: Bearer $TOKEN" "https://registry-1.docker.io/v2/ratelimitpreview/test/manifests/latest" 2>&1

문제 해결

인증 오류: “HTTP 기본: 액세스 거부”

Dependency Proxy로 인증하는 동안 ‘HTTP 기본: 액세스 거부’ 오류가 발생하면, 이중 인증 해결 가이드를 참조하십시오.

Dependency Proxy Connection Failure

서비스 별칭이 설정되어 있지 않으면 docker:20.10.16 이미지는 dind 서비스를 찾지 못하고 다음과 같은 오류가 발생합니다:

error during connect: Get http://docker:2376/v1.39/info: dial tcp: lookup docker on 192.168.0.1:53: no such host

Docker 서비스를 위해 서비스 별칭을 설정하여 이를 해결할 수 있습니다:

services:
    - name: ${CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX}/docker:18.09.7-dind
      alias: docker

CI/CD 작업에서 종속성 프록시로 인증하는 중 문제점

GitLab 러너는 자동으로 종속성 프록시에 대해 인증합니다. 그러나 내부 Docker 엔진은 여전히 권한 해결 프로세스의 영향을 받습니다.

인증 메커니즘의 구성 오류는 HTTP Basic: Access denied403: Access forbidden과 같은 오류를 일으킬 수 있습니다.

작업 로그를 사용하여 종속성 프록시에 대해 인증하는 데 사용된 인증 메커니즘을 확인할 수 있습니다:

Authenticating with credentials from $DOCKER_AUTH_CONFIG
Authenticating with credentials from /root/.docker/config.json
Authenticating with credentials from job payload (GitLab Registry)

예상한 인증 메커니즘을 사용 중인지 확인하세요.

이미지를 가져올 때 Not Found 또는 404 오류

이러한 오류는 작업을 실행하는 사용자가 종속성 프록시 그룹에 대한 최소한의 Guest 역할을 가지고 있지 않을 수 있음을 나타낼 수 있습니다:

  • ERROR: gitlab.example.com:443/group1/dependency_proxy/containers/alpine:latest: not found
    
    failed to solve with frontend dockerfile.v0: failed to create LLB definition: gitlab.example.com:443/group1/dependency_proxy/containers/alpine:latest: not found
    
  • ERROR: Job failed: failed to pull image "gitlab.example.com:443/group1/dependency_proxy/containers/alpine:latest" with specified policies [always]:
    Error response from daemon: error parsing HTTP 404 response body: unexpected end of JSON input: "" (manager.go:237:1s)
    

유사한 경우에 Access denied로 오류 메시지를 향상시키는 데 사용된 작업에 대한 자세한 정보는 issue 354826를 참조하세요.

종속성 프록시에서 이미지를 실행할 때 exec format error

참고: 이 문제는 GitLab 16.3에서 해결되었습니다. 16.2 이전의 직접 관리되는 인스턴스의 경우 인스턴스를 16.3으로 업데이트하거나 아래에 문서화된 해결방법을 사용할 수 있습니다.

16.2 이전의 GitLab에서 ARM 기반 Docker 설치에서 종속성 프록시를 사용하려고 하면 이 오류가 발생합니다. 종속성 프록시는 특정 태그로 이미지를 가져올 때 x86_64 아키텍처만 지원합니다.

해결책으로 종속성 프록시가 다른 아키텍처 이미지를 가져오도록 이미지의 SHA256를 명시할 수 있습니다:

docker pull ${CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX}/library/docker:20.10.3@sha256:bc9dcf5c8e5908845acc6d34ab8824bca496d6d47d1b08af3baf4b3adb1bd8fe

이 예에서 bc9dcf5c8e5908845acc6d34ab8824bca496d6d47d1b08af3baf4b3adb1bd8fe는 ARM 기반 이미지의 SHA256입니다.

백업을 복원한 후 MissingFile 오류

MissingFile 또는 Cannot read file 오류가 발생하는 경우 백업 아카이브gitlab-rails/shared/dependency_proxy/의 내용이 포함되지 않아서 발생할 수 있습니다.

알려진 문제를 해결하려면 백업 원본인 GitLab 인스턴스로부터 영향을 받는 파일 또는 전체 gitlab-rails/shared/dependency_proxy/ 폴더 구조를 복사하는 데 rsync, scp 또는 유사한 도구를 사용할 수 있습니다.

데이터가 필요하지 않은 경우 다음과 같이 데이터베이스 항목을 삭제할 수 있습니다:

gitlab-psql -c "DELETE FROM dependency_proxy_blobs; DELETE FROM dependency_proxy_blob_states; DELETE FROM dependency_proxy_manifest_states; DELETE FROM dependency_proxy_manifests;"