컨테이너 가상 레지스트리
GitLab v19.2Offering: GitLab.com, GitLab Self-Managed
이 기능의 사용 가능 여부는 기능 플래그에 의해 제어됩니다. GitLab 컨테이너 가상 레지스트리는 업스트림 레지스트리에서 컨테이너 이미지를 캐시하는 데 사용할 수 있는 로컬 프록시입니다. 컨테이너 가상 레지스트리를 사용하기 전에:
히스토리
- GitLab 18.5에서
container_virtual_registries라는 기능 플래그와 함께 도입. 기본적으로 비활성화됨. - GitLab 18.9에서 실험에서 베타로 변경.
- GitLab 18.10에서 GitLab.com, GitLab Self-Managed, GitLab Dedicated에서 활성화.
이 기능의 사용 가능 여부는 기능 플래그에 의해 제어됩니다. 자세한 내용은 기록을 참조하세요.
GitLab 컨테이너 가상 레지스트리는 업스트림 레지스트리에서 컨테이너 이미지를 캐시하는 데 사용할 수 있는 로컬 프록시입니다. 풀스루 캐시로 작동하여 자주 접근하는 이미지를 로컬에 저장하여 대역폭 사용량을 줄이고 빌드 성능을 향상시킵니다.
사전 요건#
컨테이너 가상 레지스트리를 사용하기 전에:
-
가상 레지스트리를 사용하기 위한 사전 요건을 검토합니다.
-
가상 레지스트리에 대한 인증을 구성합니다. 자세한 내용은 가상 레지스트리에 인증을 참조하세요.
컨테이너 가상 레지스트리를 사용할 때 다음 제한 사항을 기억하세요:
-
최상위 그룹당 최대
5개의 컨테이너 가상 레지스트리를 만들 수 있습니다. -
지정된 컨테이너 가상 레지스트리에
5개의 업스트림만 설정할 수 있습니다. -
Geo 지원은 구현되지 않았습니다.
가상 레지스트리 관리#
히스토리
그룹의 컨테이너 가상 레지스트리를 관리합니다.
API를 사용할 수도 있습니다.
컨테이너 가상 레지스트리 만들기#
컨테이너 가상 레지스트리를 만들려면:
-
상단 바에서 Search or go to를 선택하고 그룹을 찾습니다. 이 그룹은 최상위 레벨이어야 합니다.
-
Deploy > Virtual registry를 선택합니다.
-
다음을 수행합니다:
-
기존 레지스트리가 있는 경우 Create registry를 선택합니다. 드롭다운 목록에서 Container를 선택합니다.
-
기존 레지스트리가 없는 경우 드롭다운 목록에서 Container를 선택합니다. 그런 다음 Create registry를 선택합니다.
-
-
Name과 선택적 Description을 입력합니다.
-
Create registry를 선택합니다.
업스트림 레지스트리 관리#
가상 레지스트리에서 업스트림 컨테이너 레지스트리를 관리합니다.
컨테이너 업스트림 레지스트리 만들기#
가상 레지스트리에 연결할 컨테이너 업스트림 레지스트리를 만듭니다.
사전 요건:
- 컨테이너 가상 레지스트리가 있어야 합니다. 자세한 내용은 가상 레지스트리 만들기를 참조하세요.
컨테이너 업스트림 레지스트리를 만들려면:
-
상단 바에서 Search or go to를 선택하고 그룹을 찾습니다. 이 그룹은 최상위 레벨이어야 합니다.
-
Deploy > Virtual registry를 선택합니다.
-
Registry types 아래에서 View registries를 선택합니다.
-
Registries 탭 아래에서 레지스트리를 선택합니다.
-
Add upstream을 선택합니다. 가상 레지스트리에 기존 업스트림이 있는 경우 드롭다운 목록에서 다음 중 하나를 선택합니다:
-
업스트림을 구성하려면 Create new upstream을 선택합니다.
-
Link existing upstream > Select existing upstream을 선택합니다.
드롭다운 목록에서 업스트림을 선택합니다.
-
선택 사항. 만들기 전에 업스트림 연결을 테스트하려면 Test upstream을 선택합니다.
-
Add upstream을 선택합니다.
-
-
필드를 입력합니다.
username과 password를 모두 포함하거나 둘 다 포함하지 않습니다. 설정하지 않으면 업스트림에 액세스할 때 공개(익명) 요청이 사용됩니다.
-
Docker 강화 이미지에 업스트림을 연결하려면 다음을 Upstream URL로 사용합니다:
https://dhi.io
- Docker Hub에 업스트림을 연결하려면 다음을 Upstream URL로 사용합니다:
https://registry-1.docker.io
Docker Hub 레지스트리 API는 docker.io가 아닌 registry-1.docker.io에서 호스팅됩니다.
대부분의 컨테이너 도구는 docker.io를 자동으로 재작성하지만, 가상 레지스트리는
제공한 URL로 프록시를 합니다.
https://docker.io를 사용하면 레지스트리가 OCI 응답 대신 HTML을 반환합니다.
-
Artifact caching period는 기본적으로 24시간입니다. 캐시 항목 검사를 비활성화하려면
0으로 설정합니다. -
만들기 전에 업스트림 연결을 테스트하려면 Test upstream을 선택합니다.
-
Create upstream을 선택합니다.
캐시 유효성 설정에 대한 자세한 내용은 캐시 유효 기간 설정을 참조하세요.
컨테이너 가상 레지스트리 인증#
컨테이너 가상 레지스트리는 최상위 그룹과 연결된 레지스트리에 컨테이너 이미지를 저장하고 연결합니다. 컨테이너 이미지에 액세스하려면 그룹의 컨테이너 가상 레지스트리로 인증해야 합니다.
수동으로 인증하려면 다음 명령을 실행합니다:
echo "$CONTAINER_REGISTRY_PASSWORD" | docker login gitlab.example.com/virtual_registries/container/1 --username <your_username> --password-stdin
또는 가상 레지스트리 인증에 설명된 방법 중 하나로 인증을 구성합니다.
컨테이너 가상 레지스트리는 Docker v2 토큰 인증 플로우를 따릅니다:
-
클라이언트 인증 후 클라이언트에 발급된 JWT 토큰이 컨테이너 이미지 풀을 승인합니다.
-
토큰은 만료 시간에 따라 만료됩니다.
-
토큰이 만료되면 대부분의 Docker 클라이언트는 사용자 자격 증명을 저장하고 추가 작업 없이 새 토큰을 자동으로 요청합니다.
가상 레지스트리에서 컨테이너 이미지 풀#
가상 레지스트리를 통해 컨테이너 이미지를 풀하려면:
-
가상 레지스트리에 인증합니다.
-
가상 레지스트리 URL 형식을 사용하여 이미지를 풀합니다:
gitlab.example.com/virtual_registries/container/<registry_id>/<image_path>:<tag>
예시:
- 태그로 이미지 풀:
docker pull gitlab.example.com/virtual_registries/container/1/library/alpine:latest
- 다이제스트로 이미지 풀:
docker pull gitlab.example.com/virtual_registries/container/1/library/alpine@sha256:c9375e662992791e3f39e919b26f510e5254b42792519c180aad254e6b38f4dc
Dockerfile에서 이미지 풀:
FROM gitlab.example.com/virtual_registries/container/1/library/alpine:latest
.gitlab-ci.yml파일에서 이미지 풀:
image: gitlab.example.com/virtual_registries/container/1/library/alpine:latest
이미지를 풀할 때 가상 레지스트리는:
-
이미지가 이미 캐시되어 있는지 확인합니다.
이미지가 캐시되어 있고 업스트림의
cache_validity_hours설정에 따라 여전히 유효하면 캐시에서 이미지를 제공합니다. -
이미지가 캐시되지 않았거나 캐시가 무효화된 경우 구성된 업스트림 레지스트리에서 이미지를 가져와 캐시합니다.
-
Docker 클라이언트에 이미지를 제공합니다.
이미지에 대한 가상 레지스트리 캐시 유효성 검사#
alpine:latest와 같은 이미지 태그는 항상 최신 버전의 이미지를 풀합니다. 새 버전에는 업데이트된 이미지 매니페스트가 포함됩니다. 컨테이너 가상 레지스트리는 매니페스트가 변경될 때 새 이미지를 풀하지 않습니다.
대신 컨테이너 가상 레지스트리는:
-
업스트림의
cache_validity_hours설정을 확인하여 이미지 매니페스트가 무효화되는 시점을 결정합니다. -
업스트림에 HEAD 요청을 보냅니다. 매니페스트가 무효화되면 새 이미지를 풀합니다.
예를 들어, 파이프라인이 node:latest를 풀하고 cache_validity_period를 24시간으로 설정한 경우 가상 레지스트리는 캐시가 만료되거나 업스트림에서 node:latest가 변경될 때 이미지를 캐시하고 업데이트합니다.
문제 해결#
인증 오류: HTTP Basic: Access Denied#
가상 레지스트리에 인증할 때 HTTP Basic: Access denied 오류가 발생하면
2단계 인증 문제 해결을 참조하세요.
가상 레지스트리 연결 실패#
서비스 별칭이 설정되지 않은 경우 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: docker:20.10.16-dind
alias: docker
CI/CD job에서 가상 레지스트리 인증 문제#
GitLab Runner는 CI/CD job 토큰을 사용하여 자동으로 인증합니다. 그러나 기반이 되는 Docker 엔진은 여전히 인증 확인 프로세스를 따릅니다.
인증 메커니즘의 잘못된 구성으로 인해 HTTP Basic: Access denied 및 403: Access forbidden 오류가 발생할 수 있습니다.
job 로그를 사용하여 가상 레지스트리에 인증하는 데 사용된 인증 메커니즘을 확인할 수 있습니다:
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을 실행하는 사용자가 가상 레지스트리를 소유하는 그룹에 대해 Guest, Planner, Reporter, Developer, Maintainer 또는 Owner 권한이 없거나,
read_virtual_registry권한을 가진 최소 액세스 커스텀 역할이 없습니다. -
URL의 가상 레지스트리 ID가 잘못되었습니다.
-
업스트림 레지스트리에 요청한 이미지가 없습니다.
-
가상 레지스트리에 구성된 업스트림이 없습니다.
오류 메시지 예시:
ERROR: gitlab.example.com/virtual_registries/container/1/library/alpine:latest: not found
ERROR: Job failed: failed to pull image "gitlab.example.com/virtual_registries/container/1/library/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)
이러한 오류를 해결하려면:
-
그룹에 대해 Guest, Planner, Reporter, Developer, Maintainer 또는 Owner 권한이 있거나
read_virtual_registry권한을 가진 최소 액세스 커스텀 역할이 있는지 확인합니다. -
가상 레지스트리 ID가 올바른지 확인합니다.
-
가상 레지스트리에 하나 이상의 업스트림이 구성되어 있는지 확인합니다.
-
업스트림 레지스트리에 이미지가 있는지 확인합니다.
S3 버킷에 Object Lock이 활성화된 경우 오류: unexpected EOF#
Dependency Proxy의 객체 스토리지 버킷에 S3 Object Lock이
활성화되어 있으면 컨테이너 이미지 풀이 레이어 중간에
unexpected EOF로 실패할 수 있습니다.
Docker 클라이언트의 오류 예시:
sha256:9db411d588e2: Downloading [==================================================>] 12.18MB/12.18MB
unexpected EOF
GitLab Workhorse 로그에는 업스트림 S3 PutObject 호출에서 400 응답이 표시됩니다:
operation error S3: PutObject, https response error StatusCode: 400, ...
InvalidRequest: Content-MD5 OR x-amz-checksum- HTTP header is required for
Put Object requests with Object Lock parameters
버킷에 Object Lock이 구성된 경우 S3는 모든 PutObject 요청에 무결성 헤더를 포함하도록 요구합니다. 기본적으로 Workhorse에서 사용하는 AWS SDK는 이러한 헤더를 전송하지 않습니다. 업로드가 실패하면 Workhorse가 Docker 클라이언트로 스트리밍하는 응답이 잘립니다.
원인을 확인하려면:
- Dependency Proxy 버킷에 Object Lock이 활성화되어 있는지 확인합니다:
aws s3api get-object-lock-configuration --bucket DEPENDENCY_PROXY_BUCKET
Object Lock이 활성화된 경우 응답에 "ObjectLockEnabled": "Enabled"가 포함됩니다.
- 실패한 풀 중에 Workhorse 로그를 검사합니다.
InvalidRequest: Content-MD5 OR x-amz-checksum-메시지가 원인을 확인합니다.
문제를 해결하려면:
-
Workhorse에서 AWS SDK가 체크섬 헤더를 전송하도록 구성합니다. Workhorse 컨테이너에 다음 환경 변수를 모두 설정합니다:
AWS_REQUEST_CHECKSUM_CALCULATION=when_supportedAWS_RESPONSE_CHECKSUM_VALIDATION=when_supported
-
다음의 경우:
- Helm 차트로 설치된 GitLab의 경우
values.yaml에 변수를 추가합니다:
- Helm 차트로 설치된 GitLab의 경우
gitlab:
webservice:
extraEnv:
AWS_REQUEST_CHECKSUM_CALCULATION: when_supported
AWS_RESPONSE_CHECKSUM_VALIDATION: when_supported
그런 다음 값을 적용합니다:
helm upgrade gitlab gitlab/gitlab -f values.yaml
- Linux 패키지로 설치된 GitLab의 경우
/etc/gitlab/gitlab.rb에 변수를 추가합니다:
gitlab_workhorse['env'] = {
'AWS_REQUEST_CHECKSUM_CALCULATION' => 'when_supported',
'AWS_RESPONSE_CHECKSUM_VALIDATION' => 'when_supported'
}
그런 다음 재구성합니다:
sudo gitlab-ctl reconfigure
Workhorse가 새 환경 변수로 재시작된 후 풀을 다시 시도합니다. 다음 요청은 S3에 블롭을 저장하고 전체 레이어를 Docker 클라이언트에 반환합니다.