Docker Registry UI 구축 삽질기
Docker Registry UI 구축 삽질기
들어가며
개인 프로젝트에서 Docker Registry를 구축하고, 이를 편리하게 관리하기 위해 Registry UI를 연동하는 과정에서 여러 난관에 부딪혔습니다. 이 글에서는 Docker Registry와 Registry UI를 구축하면서 겪은 문제들과 해결 방법을 공유하고자 합니다.
초기 설정
처음에는 간단한 Docker Registry와 Joxit의 Docker Registry UI를 연동하는 기본적인 Docker Compose 파일을 작성했습니다:
1services:
2 # Docker Registry
3 registry:
4 image: registry:2
5 ports:
6 - "5000:5000"
7 restart: always
8 volumes:
9 - ./registry-data:/var/lib/registry
10 - ./registry-config:/etc/docker/registry
11 environment:
12 REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY: /var/lib/registry
13
14 # Registry UI
15 registry-ui:
16 image: joxit/docker-registry-ui:latest
17 ports:
18 - "8180:80"
19 environment:
20 - REGISTRY_URL=http://registry:5000
21 - REGISTRY_TITLE=My Private Registry
22 - SINGLE_REGISTRY=true
23 depends_on:
24 - registry
개선 사항 적용 시도
기본 설정으로는 Registry UI의 기능이 제한적이었고, 이미지 삭제 기능이나 컨텐츠 다이제스트 표시 등 추가 기능이 필요했습니다. 그래서 다음과 같은 향상된 설정을 적용하고자 했습니다:
1version: '3.8'
2services:
3 registry-ui:
4 image: joxit/docker-registry-ui:main
5 restart: always
6 ports:
7 - 80:80
8 environment:
9 - SINGLE_REGISTRY=true
10 - REGISTRY_TITLE=Docker Registry UI
11 - DELETE_IMAGES=true
12 - SHOW_CONTENT_DIGEST=true
13 - NGINX_PROXY_PASS_URL=http://registry-server:5000
14 - SHOW_CATALOG_NB_TAGS=true
15 - CATALOG_MIN_BRANCHES=1
16 - CATALOG_MAX_BRANCHES=1
17 - TAGLIST_PAGE_SIZE=100
18 - REGISTRY_SECURED=false
19 - CATALOG_ELEMENTS_LIMIT=1000
20 container_name: registry-ui
21
22 registry-server:
23 image: registry:2.8.2
24 restart: always
25 environment:
26 REGISTRY_HTTP_HEADERS_Access-Control-Allow-Origin: '[http://registry.example.com]'
27 REGISTRY_HTTP_HEADERS_Access-Control-Allow-Methods: '[HEAD,GET,OPTIONS,DELETE]'
28 REGISTRY_HTTP_HEADERS_Access-Control-Allow-Credentials: '[true]'
29 REGISTRY_HTTP_HEADERS_Access-Control-Allow-Headers: '[Authorization,Accept,Cache-Control]'
30 REGISTRY_HTTP_HEADERS_Access-Control-Expose-Headers: '[Docker-Content-Digest]'
31 REGISTRY_STORAGE_DELETE_ENABLED: 'true'
32 volumes:
33 - ./registry/data:/var/lib/registry
34 container_name: registry-server
문제 1: 배열 형태의 환경 변수 설정
첫 번째 문제는 Docker Compose에서 배열 형태의 환경 변수를 설정하는 것이었습니다. 특히 REGISTRY_HTTP_TLS_CLIENTCAS
같은 환경 변수는 배열로 설정해야 했는데, Docker Compose에서는 이를 직접 지원하지 않았습니다.
시도한 방법:
1environment:
2 REGISTRY_HTTP_TLS_CLIENTCAS:
3 - /certs/ca.crt
오류 메시지:
Service 'registry' configuration key 'environment' 'REGISTRY_HTTP_TLS_CLIENTCAS' contains ['/certs/ca.crt'], which is an invalid type, it should be a string, number, boolean or a null
그래서 문자열로 변경해봤지만:
1environment:
2 REGISTRY_HTTP_TLS_CLIENTCAS: /certs/ca.crt
또 다른 오류가 발생했습니다:
registry_1 | configuration error: error parsing /etc/docker/registry/config.yml: yaml: unmarshal errors:
registry_1 | line 1: cannot unmarshal !!str `/certs/...` into []string
해결책:
GitHub 이슈를 검색한 결과, 다음과 같은 세 가지 해결 방법을 찾았습니다:
- 인덱싱된 환경 변수를 사용하는 방법:
1environment:
2 REGISTRY_HTTP_TLS_CLIENTCAS_0: /certs/ca.crt
- YAML 배열 표기법을 사용하는 방법:
1environment:
2 REGISTRY_HTTP_TLS_CLIENTCAS: ' - /certs/ca.crt'
- config.yml 파일을 직접 생성하여 볼륨으로 마운트하는 방법:
1volumes:
2 - ./registry-config/config.yml:/etc/docker/registry/config.yml
문제 2: CORS 설정
Registry UI가 Registry API에 접근할 때 CORS 오류가 발생했습니다. Registry 서버에서 CORS 허용 설정이 필요했습니다.
원래 설정:
1REGISTRY_HTTP_HEADERS_Access-Control-Allow-Origin: '[http://registry.example.com]'
모든 오리진 허용으로 변경:
1REGISTRY_HTTP_HEADERS_Access-Control-Allow-Origin: '["*"]'
환경변수 설정시에, cors 설정할때에 꼭 더블 쿼테이션 처리 해주어야 합니다. 안그러면 계속 오류나더라구요.
CORS를 모든 오리진에서 허용하려면 대괄호 안에 별표를 넣는 형식을 사용해야 했습니다. 이는 Registry 내부에서 YAML 배열로 파싱되는 방식 때문입니다.
최종 Docker Compose 파일
여러 문제를 해결한 후 최종적으로 완성된 Docker Compose 파일은 다음과 같습니다:
1version: '3.8'
2services:
3 # Docker Registry
4 registry:
5 image: registry:2.8.2
6 ports:
7 - "5000:5000"
8 restart: always
9 volumes:
10 - ./registry-data:/var/lib/registry
11 - ./registry-config:/etc/docker/registry
12 environment:
13 REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY: /var/lib/registry
14 REGISTRY_HTTP_HEADERS_Access-Control-Allow-Origin: '[*]'
15 REGISTRY_HTTP_HEADERS_Access-Control-Allow-Methods: '[HEAD,GET,OPTIONS,DELETE]'
16 REGISTRY_HTTP_HEADERS_Access-Control-Allow-Credentials: '[true]'
17 REGISTRY_HTTP_HEADERS_Access-Control-Allow-Headers: '[Authorization,Accept,Cache-Control]'
18 REGISTRY_HTTP_HEADERS_Access-Control-Expose-Headers: '[Docker-Content-Digest]'
19 REGISTRY_STORAGE_DELETE_ENABLED: 'true'
20 container_name: registry-server
21
22 # Registry UI
23 registry-ui:
24 image: joxit/docker-registry-ui:main
25 ports:
26 - "8180:80"
27 restart: always
28 environment:
29 - SINGLE_REGISTRY=true
30 - REGISTRY_TITLE=My Private Registry
31 - DELETE_IMAGES=true
32 - SHOW_CONTENT_DIGEST=true
33 - NGINX_PROXY_PASS_URL=http://registry:5000
34 - SHOW_CATALOG_NB_TAGS=true
35 - CATALOG_MIN_BRANCHES=1
36 - CATALOG_MAX_BRANCHES=1
37 - TAGLIST_PAGE_SIZE=100
38 - REGISTRY_SECURED=false
39 - CATALOG_ELEMENTS_LIMIT=1000
40 depends_on:
41 - registry
42 container_name: registry-ui
43
44 # Gitea Runner
45 runner:
46 image: docker.io/gitea/act_runner:nightly
47 network_mode: "host" # 호스트 네트워크 사용
48 environment:
49 CONFIG_FILE: /config.yml
50 GITEA_INSTANCE_URL: "${INSTANCE_URL}"
51 GITEA_RUNNER_REGISTRATION_TOKEN: "${REGISTRATION_TOKEN}"
52 GITEA_RUNNER_NAME: "${RUNNER_NAME}"
53 GITEA_RUNNER_LABELS: "${RUNNER_LABELS}"
54 volumes:
55 - ./config.yml:/config.yml
56 - ./data:/data
57 - /var/run/docker.sock:/var/run/docker.sock
58 depends_on:
59 - registry
삽질 후기
Docker Registry와 Registry UI를 구축하는 과정은 예상보다 복잡했지만, 결국 모든 문제를 해결하고 원하는 기능이 동작하는 시스템을 구축할 수 있었습니다. 이 글이 비슷한 문제로 고민하는 분들에게 도움이 되었으면 합니다.
Docker 환경 구성, 특히 레지스트리 관련 설정에서는 세부적인 문법과 표현 방식이 중요하며, 때로는 직관적이지 않은 방식으로 문제를 해결해야 할 때도 있다는 것을 배웠습니다.