Harbor로 프록시 기능이 있는 사설 Docker 저장소 직접 구축하기
서문
어느 알 수 없는 시점 (사실 기억이 안 남)부터 중국 본토의 서버는 Docker Hub(docker.io)에 직접 연결할 수 없게 되었다. 이는 모든 본토 서버에게 분명 타격이었지만, 다행히도 프록시 서비스가 점점 많아져서 완전히 못 쓰게 된 것은 아니다.
하지만 Docker Hub와 같은 처지인, GitHub에서 제공하는 Docker 이미지 서비스 ghcr.io는 프록시 서비스를 제공하는 곳이 거의 없다. 설령 제공하더라도 사설 저장소에 접근할 수 없었다(대부분 로그인이 안 돼서 그런 것이다).
두 프로젝트가 ghcr을 사용하면서 비공개로 설정했기 때문에, 본토 서버로는 전혀 가져올 수 없거나 가져오는 속도가 매우 느려서 본토 서버로 트래픽을 분산할 수 없었다. ghcr용 프록시 방안을 계속 찾던 중, 얼마 전에 Harbor라는 엔터프라이즈급 Docker 사설 저장소를 발견하게 되어 직접 구축해 보았다.
EP0: 사전 준비
서버 구성
먼저 다음이 필요하다:
- 서버 한 대. 가능하면 Linux여야 하며, 가능하면 Windows가 아니어야 한다
- SSH 원격 도구. Termius, Tabby, XShell 등 무엇이든 좋다(로컬 배포 시 무시 가능)
- 도메인(권장). 중국 본토에 배포할 때 도메인을 사용하려면 미리 ICP 비안을 받아야 한다
Harbor는 Docker 기반으로 실행되는 프로그램이므로, 서버에 Docker를 미리 설치해야 한다. 서버가 본토에 있다면 프록시도 미리 설정해 두어야 한다. 그렇지 않으면 이후 단계가 실패할 수 있다. 이를 위해 다음과 같은 선택지가 있다:
설치 패키지 다운로드
Harbor Releases를 열면 Release에서 다음과 같은 내용을 볼 수 있다.

harbor-offline-installer-v<버전>tgz는 오프라인 설치 패키지이고, harbor-online-installer-v<버전>tgz는 온라인 설치 패키지다. 실제 최신 버전에 맞춰 배포하자.
이 튜토리얼은 온라인 버전을 사용한다. 서버가 정말 Docker Hub에 연결할 수 없다면 오프라인 버전을 사용하자. 둘 다 사용법에는 차이가 없다. 차이점은 온라인 설치 패키지가 Docker Hub에서 이미지를 받아 배포하므로 상대적으로 가볍고 로컬 파일도 더 깔끔하다는 점이다.
파일을 서버에 다운로드하고 압축을 풀면 harbor라는 폴더가 생긴다.
harbor 폴더로 들어가서 디렉터리에 다음 내용이(하나라도 빠짐없이) 있다면 첫 단계를 완료한 것이다.

모든 파일
EP1: 구성
harbor.yml.tmpl을 harbor.yml로 이름 변경
harbor.yml.tmpl을 복사한 후 이름을 harbor.yml로 변경한다. 파일 이름을 직접 수정하지 말 것. 내용을 실수로 삭제해 심각한 결과를 초래할 수 있다.
cp harbor.yml.tmpl harbor.yml
비밀번호 수정
harbor.yml로 들어간다.
vim harbor.yml
harbor_admin_password를 찾는다.

Harbor12345를 다른 문자열로 변경한다. 이 문자열을 반드시 기억하자. 이 문자열이 곧 웹 콘솔에 로그인할 Admin 계정의 초기 비밀번호가 된다.
동시에 database.password도 다른 문자열로 변경하는 것을 권장한다(아래 그림 위치). 이 문자열은 Harbor가 배포할 데이터베이스의 접근 비밀번호가 되지만, 기억할 필요는 없다.

접근 주소 수정
harbor.yml 상단에서 hostname을 찾는다.

hostname을 실제 접근 주소로 변경한다. 반드시 도메인일 필요는 없으며, 서버의 IP를 적어도 된다.
포트 구성
여러 가지 이유로 대체로 세 가지 상황이 발생한다:
harbor.yml 저장
위 구성을 모두 마친 후 esc를 누르고 :wq를 입력하면 harbor.yml 수정이 완료된다.
EP2: 설치 스크립트 실행
명령줄에서 다음 명령을 실행한다.
bash install.sh
그러면 설치 단계로 들어간다.
Harbor has been installed and started successfully.가 표시되면 설치가 완료된 것이다.

동시에 전체 서비스가 가동되기 시작했다.
EP4: 웹 페이지 접속
2와 4 사이에 있는 숫자를 셀 줄 모름
구성한 hostname과 port에 따라 브라우저에서 Harbor에 접속한다.
그러면 다음과 같은 화면을 볼 수 있다.

로그인한다. 초기 계정(Admin 계정)의 사용자 이름은 admin이고, 비밀번호는 방금 설정한 harbor_admin_password다.
로그인하면 다음과 같은 화면을 볼 수 있다.

이제 전체 Harbor 서비스가 정상적으로 가동되고 있음을 확인할 수 있다.
EP5: 보안 작업
Admin 계정 비밀번호 변경
harbor.yml에서 기본 비밀번호를 이미 변경했지만, 안전을 위해 웹 페이지에서도 한 번 비밀번호를 변경하자.
오른쪽 상단의 사용자 아이콘을 클릭한 후 비밀번호 변경을 클릭하고, 나타나는 입력 창에 필수 항목을 모두 입력하면 된다.

새 사용자 생성
꼭 새 사용자를 만들어야 하는 것은 아니지만, 안전을 위해 Docker 로그인 전용 새 사용자를 만들 것을 권장한다.
왼쪽의 사용자 관리를 클릭한 후 사용자 생성을 클릭하고, 나타나는 입력 창에 필수 항목을 모두 입력하면 된다.

EP6: Docker에서 로그인
명령줄에 입력한다.
docker login <hostname>:<port>
그러면 대화형 입력이 나타난다.

먼저 Username(사용자 생성 시 설정한 사용자 이름)을 입력하고 Enter를 누른다. 그다음 Password(사용자 생성 시 설정한 비밀번호. Password 입력 시 입력 내용이 표시되지 않는다)를 입력하고 Enter를 누른다.
계정과 비밀번호가 모두 맞으면 다음 내용이 표시된다.

이제 서버가 Harbor에 연결되었으며, 모든 푸시와 풀(비공개 저장소 포함)이 원활하게 이루어진다.
EP-S-1: 프록시 구성
다른 서비스와 연결
Harbor 웹 페이지에 로그인한 후, 페이지 왼쪽의 저장소 관리를 클릭하고 새 대상을 클릭한다.

그러면 새 대상 창이 나타난다.
제공자 옵션을 조정하면 12개의 옵션이 있는 것을 볼 수 있다.

harbor 또는 Docker Registry를 선택하면 해당 서비스의 주소(즉 대상 URL)를 입력해야 한다. 이 두 옵션 외의 것을 선택하면 해당 서비스 주소를 입력할 필요가 없다.
여기서는 GitHub GHCR을 예로 든다(Google GCR이 아니다. 잘 보고 선택하자. 이 둘의 주소는 한 글자 차이다).

(GitHub 접근 토큰을 얻는 방법은 https://github.com/settings/tokens를 방문해 확인하자.)
구성 완료 후 확인을 누르면 된다.
프로젝트 설정
"프로젝트"란 무엇일까? Harbor에서 프로젝트는 하나의 독립된 저장 공간과 같다. 이미지가 저장되는 위치를 가리키며, 접근 관리(즉 이미지가 공개인지 비공개인지)는 각 이미지가 아니라 각 프로젝트를 기준으로 결정된다. 이는 많은 Docker 클라우드 서비스와 다르다.
페이지 왼쪽의 프로젝트를 클릭한 후 새 프로젝트를 클릭한다.


그다음 확인을 누르면 프로젝트 설정이 완료된다.

END: 이미지 가져오기
ghcr.io와 위 그림에서 구성한 프로젝트 이름 ghcr을 예로 들면, 원본 주소가 다음과 같다고 가정하자.
ghcr.io/NiuBoss123/114514:latest
Harbor 프록시를 거친 후 주소는 다음과 같이 바뀐다.
<hostname>:<port>/ghcr/NiuBoss123/114514:latest
즉, ghcr.io를 <hostname>:<port>/ghcr로 바꾸면 된다.
이후의 작업은 원본 주소와 동일하게 진행하면 된다.
후기
단지 프록시 하나 때문에 Harbor를 구축하는 건 너무 과한 걸까? 개인적으로는 확실히 과하다고 생각한다 (. 하지만 Harbor가 엔터프라이즈급 Docker 저장소라는 지위를 고려하면 그리 이상할 것도 없다.즉, 뭔가 만져보고 싶었다는 뜻)
어떤 사람들은 왜 Docker Registry를 쓰지 않느냐고 물을 수 있다. Docker Registry는 본질적으로 저장소일 뿐이라 웹 콘솔도, 프록시 기능도 없고, 이미지를 직접 올려야 한다. 사용하기가 꽤 번거롭다고 느껴진다(물론 Harbor도 번거롭긴 마찬가지다. 다만 Harbor가 좀 더 영리한 방법일 뿐 ().정말 영리한가?)
관련 링크
- Harbor 공식 사이트: goharbor.io
- Harbor GitHub 저장소: goharbor/harbor
(이 튜토리얼을 작성하는 동안 어떤 도메인도 피해를 입지 않았습니다.)