컨테이너 이미지를 위한 Dependency Proxy
Offering: GitLab.com, GitLab Self-Managed, GitLab Dedicated
GitLab의 컨테이너 이미지용 Dependency Proxy는 자주 접근하는 업스트림 이미지를 위한 로컬 프록시입니다. CI/CD의 경우, Dependency Proxy는 요청을 받아 레지스트리에서 업스트림 이미지를 반환하며, 풀-스루(pull-through) 캐시 역할을 합니다.
GitLab의 컨테이너 이미지용 Dependency Proxy는 자주 접근하는 업스트림 이미지를 위한 로컬 프록시입니다.
CI/CD의 경우, Dependency Proxy는 요청을 받아 레지스트리에서 업스트림 이미지를 반환하며, 풀-스루(pull-through) 캐시 역할을 합니다.
사전 요구 사항#
컨테이너 이미지에 Dependency Proxy를 사용하려면 GitLab 인스턴스에서 활성화되어 있어야 합니다. 기본적으로 활성화되어 있지만, 관리자가 비활성화할 수 있습니다.
지원되는 이미지 및 패키지#
다음 이미지 및 패키지가 지원됩니다.
| 이미지/패키지 | GitLab 버전 |
|---|---|
| Docker | 14.0+ |
계획된 추가 사항 목록은 방향 페이지를 참조하세요.
그룹의 Dependency Proxy 활성화 또는 비활성화#
히스토리
그룹의 Dependency Proxy를 활성화하거나 비활성화하려면:
- 왼쪽 사이드바에서 Settings > Packages and registries를 선택합니다.
- Dependency Proxy 섹션을 확장합니다.
- 프록시를 활성화하려면 Enable Proxy를 켭니다. 비활성화하려면 토글을 끕니다.
이 설정은 그룹의 Dependency Proxy에만 영향을 미칩니다. 전체 GitLab 인스턴스에 대해 Dependency Proxy를 켜거나 끄는 것은 관리자만 할 수 있습니다.
컨테이너 이미지용 Dependency Proxy 보기#
컨테이너 이미지용 Dependency Proxy를 보려면:
- 왼쪽 사이드바에서 Operate > Dependency Proxy를 선택합니다.
Dependency Proxy는 프로젝트에서는 사용할 수 없습니다.
Docker 이미지에 Dependency Proxy 사용#
GitLab을 Docker 이미지의 소스로 사용할 수 있습니다.
사전 요구 사항:
- 이미지가 Docker Hub에 저장되어 있어야 합니다.
컨테이너 이미지용 Dependency Proxy 인증#
히스토리
- GitLab 15.0에서 기능 플래그
dependency_proxy_for_private_groups가 제거되었습니다. - GitLab 16.3에서 그룹 액세스 토큰 지원이 도입되었습니다.
- GitLab 17.11에서
dependency_proxy_read_write_scopes라는 플래그와 함께 배포 토큰 스코프read_virtual_registry및write_virtual_registry가 도입되었습니다. 기본적으로 비활성화되어 있습니다. - GitLab 18.0에서 일반적으로 사용 가능합니다. 기능 플래그
dependency_proxy_read_write_scopes가 제거되었습니다.
컨테이너 이미지용 Dependency Proxy는 그룹과 연관된 공간에 Docker 이미지를 저장하기 때문에 인증해야 합니다.
비공개 레지스트리에서 이미지 사용 지침을 따르되, registry.example.com:5000 대신 포트 없이 GitLab 도메인 gitlab.example.com을 사용합니다.
Admin Mode는 컨테이너 이미지용 Dependency Proxy 인증 중에는 적용되지 않습니다. Admin Mode가 활성화된 관리자가 admin_mode 스코프 없이 개인 액세스 토큰을 만들면, Admin Mode가 활성화되어 있어도 해당 토큰이 작동합니다.
예를 들어, 수동으로 로그인하려면:
echo "$CONTAINER_REGISTRY_PASSWORD" | docker login gitlab.example.com --username my_username --password-stdin
다음을 사용하여 인증할 수 있습니다:
- GitLab 사용자 이름 및 비밀번호.
- GitLab CLI.
- 개인 액세스 토큰.
- 그룹 배포 토큰.
- 그룹의 그룹 액세스 토큰.
토큰 스코프는 다음 중 하나로 설정해야 합니다:
api: 전체 API 액세스 권한 부여.read_registry: 컨테이너 레지스트리에 대한 읽기 전용 액세스 권한 부여.write_registry: 컨테이너 레지스트리에 대한 읽기 및 쓰기 액세스 권한 부여.read_virtual_registry: 그룹 수준 Dependency Proxy를 통한 컨테이너 이미지에 대한 읽기 전용(풀) 액세스 권한 부여. Dependency Proxy가 활성화된 경우에만 사용 가능.write_virtual_registry: 그룹 수준 Dependency Proxy 캐시에 대한 쓰기 액세스(캐시된 이미지 채우기 및 정리 포함) 부여. 해당 캐시를 통한 풀 액세스도 부여함. 프로젝트 컨테이너 레지스트리에 대한 푸시 또는 삭제 액세스는 부여하지 않음. Dependency Proxy가 켜져 있을 때만 사용 가능.
컨테이너 이미지용 Dependency Proxy 인증 시 토큰에는 다음 스코프 조합 중 하나가 포함되어야 합니다:
- 컨테이너 레지스트리 스코프:
read_registry및write_registry. - Dependency Proxy 스코프:
read_virtual_registry및write_virtual_registry. Dependency Proxy를 통해 이미지를 풀하면 GitLab은 그룹 수준 Dependency Proxy 캐시에 데이터를 씁니다.
개인 액세스 토큰 또는 사용자 이름과 비밀번호로 컨테이너 이미지용 Dependency Proxy에 접근하는 사용자는 이미지를 가져오는 그룹에 대해 Guest, Planner, Reporter, Developer, Maintainer 또는 Owner 권한이 있어야 합니다.
컨테이너 이미지용 Dependency Proxy는 Docker v2 토큰 인증 흐름을 따르며, 풀에 사용할 JWT를 클라이언트에 발행합니다. 인증 결과로 발행된 JWT는 일정 시간 후에 만료됩니다. 토큰이 만료되면 대부분의 Docker 클라이언트는 자격 증명을 저장하고 추가 작업 없이 자동으로 새 토큰을 요청합니다.
토큰 만료 시간은 구성 가능한 설정입니다. GitLab.com에서 만료 시간은 15분입니다.
SAML SSO#
SSO 강제 적용이 활성화된 경우, 사용자는 컨테이너 이미지용 Dependency Proxy를 통해 이미지를 풀하기 전에 SSO를 통해 로그인해야 합니다.
SSO 강제 적용은 자동 병합에도 영향을 미칩니다. 자동 병합이 트리거되기 전에 SSO 세션이 만료되면, 병합 파이프라인이 Dependency Proxy를 통해 이미지를 풀하는 데 실패합니다.
CI/CD 내에서 인증#
러너는 컨테이너 이미지용 Dependency Proxy에 자동으로 로그인합니다. Dependency Proxy를 통해 풀하려면 사전 정의된 변수 중 하나를 사용합니다:
CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX: 최상위 그룹을 통해 풀합니다.CI_DEPENDENCY_PROXY_DIRECT_GROUP_IMAGE_PREFIX: 프로젝트가 속한 하위 그룹 또는 직접 그룹을 통해 풀합니다.
최신 alpine 이미지를 풀하는 예시:
# .gitlab-ci.yml
image: ${CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX}/alpine:latest
사용할 수 있는 추가 사전 정의 CI/CD 변수가 있습니다:
CI_DEPENDENCY_PROXY_USER: Dependency Proxy에 로그인하기 위한 CI/CD 사용자.CI_DEPENDENCY_PROXY_PASSWORD: Dependency Proxy에 로그인하기 위한 CI/CD 비밀번호.CI_DEPENDENCY_PROXY_SERVER: Dependency Proxy에 로그인하기 위한 서버.CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX: 최상위 그룹의 Dependency Proxy를 통해 이미지를 풀하기 위한 이미지 프리픽스.CI_DEPENDENCY_PROXY_DIRECT_GROUP_IMAGE_PREFIX: 프로젝트가 속한 직접 그룹 또는 하위 그룹의 Dependency Proxy를 통해 이미지를 풀하기 위한 이미지 프리픽스.
CI_DEPENDENCY_PROXY_SERVER, CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX, CI_DEPENDENCY_PROXY_DIRECT_GROUP_IMAGE_PREFIX에는 서버 포트가 포함됩니다. Dependency Proxy 경로를 명시적으로 포함하는 경우, 포트 없이 Dependency Proxy에 수동으로 로그인하지 않은 한 포트를 포함해야 합니다:
docker pull gitlab.example.com:443/my-group/dependency_proxy/containers/alpine:latest
이미지를 빌드하는 데 Dependency Proxy를 사용하는 예시:
# 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-cli
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 변수를 사용하여 개인 액세스 토큰 또는 배포 토큰을 저장하고 접근할 수도 있습니다.
Docker Hub로 인증#
기본적으로 Dependency Proxy는 Docker Hub에서 이미지를 풀할 때 자격 증명을 사용하지 않습니다. Docker Hub 자격 증명 또는 토큰을 사용하여 Docker Hub 인증을 구성할 수 있습니다.
Docker Hub 인증에 사용할 수 있는 방법:
- Docker Hub 사용자 이름 및 비밀번호.
- 이 방법은 Single Sign-On (SSO)을 강제 적용하는 Docker Hub 조직과는 호환되지 않습니다.
- Docker Hub 개인 액세스 토큰.
- Docker Hub 조직 액세스 토큰.
자격 증명 구성#
그룹의 Dependency Proxy에 Docker Hub 자격 증명을 설정하려면:
-
왼쪽 사이드바에서 Settings > Packages and registries를 선택합니다.
-
Dependency Proxy 섹션을 확장합니다.
-
Enable Proxy를 켭니다.
-
Docker Hub authentication 아래에 자격 증명을 입력합니다:
- Identity는 사용자 이름(비밀번호 또는 개인 액세스 토큰의 경우) 또는 조직 이름(조직 액세스 토큰의 경우)입니다.
- Secret은 비밀번호, 개인 액세스 토큰 또는 조직 액세스 토큰입니다.
두 필드를 모두 작성하거나 모두 비워 두어야 합니다. 두 필드를 모두 비워 두면 Docker Hub 요청이 인증되지 않은 상태로 유지됩니다.
GraphQL API를 사용한 자격 증명 구성#
GraphQL API를 사용하여 Dependency Proxy 설정에서 Docker Hub 자격 증명을 설정하려면:
-
GraphiQL로 이동합니다:
- GitLab.com의 경우 https://gitlab.com/-/graphql-explorer를 사용합니다.
- GitLab Self-Managed의 경우
https://gitlab.example.com/-/graphql-explorer를 사용합니다.
-
GraphiQL에서 다음 뮤테이션을 입력합니다:
mutation { updateDependencyProxySettings(input: { enabled: true, identity: "<identity>", secret: "<secret>", groupPath: "<group path>" }) { dependencyProxySetting { enabled identity } errors } }여기서:
<identity>는 사용자 이름(비밀번호 또는 개인 액세스 토큰의 경우) 또는 조직 이름(조직 액세스 토큰의 경우)입니다.<secret>은 비밀번호, 개인 액세스 토큰 또는 조직 액세스 토큰입니다.<group path>는 Dependency Proxy가 있는 그룹의 경로입니다.
-
Play를 선택합니다.
-
결과 패널에서 오류를 확인합니다.
자격 증명 확인#
Dependency Proxy로 인증한 후 Docker 이미지를 풀하여 Docker Hub 자격 증명을 확인합니다:
docker pull gitlab.example.com/groupname/dependency_proxy/containers/alpine:latest
인증에 성공하면 Docker Hub 사용량 대시보드에서 활동을 볼 수 있습니다.
Dependency Proxy 캐시에 Docker 이미지 저장#
Dependency Proxy 스토리지에 Docker 이미지를 저장하려면:
-
왼쪽 사이드바에서 Operate > Dependency Proxy를 선택합니다.
-
Dependency Proxy image prefix를 복사합니다.
-
다음 명령 중 하나를 사용합니다. 이 예시에서 이미지는
alpine:latest입니다. -
다이제스트로 이미지를 풀하여 정확히 어떤 버전의 이미지를 풀할지 지정할 수도 있습니다.
-
태그로 이미지를 풀하려면
.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 서버에 블롭을 캐시합니다. 다음에 동일한 이미지를 풀할 때 GitLab은 Docker Hub에서 이미지에 대한 최신 정보를 가져오지만, GitLab 서버의 기존 블롭을 제공합니다.
스토리지 사용량 줄이기#
컨테이너 이미지용 Dependency Proxy의 스토리지 사용량을 줄이는 방법에 대한 정보는 Dependency Proxy 스토리지 사용량 줄이기를 참조하세요.
Docker Hub 속도 제한 및 Dependency Proxy#
Dependency Proxy를 사용하여 Docker Hub 속도 제한을 피하는 방법을 시청하세요.
Docker Hub는 풀에 대한 속도 제한을 적용합니다. GitLab CI/CD 구성이 Docker Hub의 이미지를 사용하는 경우, Job이 실행될 때마다 풀로 계산될 수 있습니다. 이 제한을 우회하려면 Dependency Proxy 캐시에서 이미지를 풀하면 됩니다.
이미지를 풀할 때(docker pull과 같은 명령이나 .gitlab-ci.yml 파일에서 image: foo:latest를 사용하여), Docker 클라이언트는 일련의 요청을 만듭니다:
- 이미지 매니페스트가 요청됩니다. 매니페스트에는 이미지를 빌드하는 방법에 대한 정보가 포함되어 있습니다.
- 매니페스트를 사용하여 Docker 클라이언트는 블롭이라고도 하는 레이어 컬렉션을 하나씩 요청합니다.
Docker Hub 속도 제한은 매니페스트에 대한 GET 요청 수를 기반으로 합니다. Dependency Proxy는 주어진 이미지의 매니페스트와 블롭을 모두 캐시하므로, 다시 요청할 때 Docker Hub에 연락하지 않아도 됩니다.
GitLab은 캐시된 태그 이미지가 오래된 것을 어떻게 알 수 있나요?#
alpine:latest와 같은 이미지 태그를 사용하는 경우, 이미지는 시간이 지남에 따라 변경됩니다. 변경될 때마다 매니페스트에는 요청할 블롭에 대한 다른 정보가 포함됩니다. Dependency Proxy는 매니페스트가 변경될 때마다 새 이미지를 풀하지 않으며, 매니페스트가 오래된 경우에만 확인합니다.
Docker는 속도 제한에 대한 이미지 매니페스트의 HEAD 요청을 계산하지 않습니다. alpine:latest에 대한 HEAD 요청을 만들고, 헤더에 반환된 다이제스트(체크섬) 값을 보고 매니페스트가 변경되었는지 확인할 수 있습니다.
Dependency Proxy는 모든 요청을 HEAD 요청으로 시작합니다. 매니페스트가 오래된 경우에만 새 이미지를 풀합니다.
예를 들어, 파이프라인이 5분마다 node:latest를 풀하는 경우, Dependency Proxy는 전체 이미지를 캐시하고 node:latest가 변경된 경우에만 업데이트합니다. 따라서 6시간 동안 이미지에 대한 요청이 360번(Docker Hub 속도 제한을 초과)이 아니라, 해당 시간 동안 매니페스트가 변경되지 않으면 풀이 한 번만 이루어집니다.
Docker Hub 속도 제한 확인#
Docker Hub에 대한 요청 수와 남은 요청 수를 알고 싶다면, 러너에서 또는 CI/CD 스크립트에서도 다음 명령을 실행할 수 있습니다:
# Note, you must have jq installed to run this command
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 Job에서 속도 제한 확인#
이 예시는 jq 및 curl이 설치된 이미지를 사용하는 GitLab CI/CD Job을 보여줍니다:
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 Basic: Access Denied#
Dependency Proxy에 대해 인증할 때 HTTP Basic: Access denied 오류가 발생하면 2단계 인증 문제 해결 가이드를 참조하세요.
Dependency Proxy 연결 실패#
서비스 별칭이 설정되지 않으면 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 Job에서 Dependency Proxy 인증 문제#
GitLab Runner는 Dependency Proxy에 자동으로 인증합니다. 그러나 기본 Docker 엔진은 여전히 권한 부여 확인 프로세스의 영향을 받습니다.
인증 메커니즘의 잘못된 구성으로 인해 HTTP Basic: Access denied 및 403: Access forbidden 오류가 발생할 수 있습니다.
Job 로그를 사용하여 Dependency Proxy에 대해 인증하는 데 사용된 인증 메커니즘을 볼 수 있습니다:
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 오류#
이러한 오류는 Job을 실행하는 사용자가 Dependency Proxy 그룹에 대해 최소한 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와 유사한 경우에서 오류 메시지를 개선하는 작업에 대한 자세한 내용은 이슈 354826을 참조하세요.
Dependency Proxy에서 이미지를 실행할 때 exec format error#
이 문제는 GitLab 16.3에서 해결되었습니다. GitLab 16.2 이하 Self-Managed 인스턴스의 경우 인스턴스를 16.3으로 업데이트하거나 아래에 설명된 해결 방법을 사용할 수 있습니다.
이 오류는 GitLab 16.2 이하에서 ARM 기반 Docker 설치에서 Dependency Proxy를 사용하려고 할 때 발생합니다. Dependency Proxy는 특정 태그로 이미지를 풀할 때 x86_64 아키텍처만 지원합니다.
해결 방법으로, 이미지의 SHA256을 지정하여 Dependency Proxy가 다른 아키텍처를 풀하도록 강제할 수 있습니다:
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/의 내용이 포함되지 않기 때문일 수 있습니다.
이 알려진 문제를 해결하려면 rsync, scp 또는 유사한 도구를 사용하여 영향을 받은 파일이나 전체 gitlab-rails/shared/dependency_proxy/ 폴더 구조를 백업의 소스였던 GitLab 인스턴스에서 복사할 수 있습니다.
데이터가 필요하지 않은 경우 다음을 사용하여 데이터베이스 항목을 삭제할 수 있습니다:
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;"
