Harbor Private Registry 구현하기 (+HTTPS 보장을 위한 인증서 발급 및 클라이언트 별 접근 방법)

Harbor란?
- Harbor는 Docker 이미지를 저장, 관리 및 배포하기 위한 오픈 소스 컨테이너 레지스트리이다.
- Harbor는 컨테이너 이미지를 저장하기 위한 중앙 집중식 리포지토리를 제공하므로 팀이 조직 전체에서 이미지를 쉽게 공유하고 협업할 수 있게 된다.
- 이러한 핵심 기능 외에도 Harbor는 역할 기반 액세스 제어, 취약성 검색, 복제 및 널리 사용되는 CI/CD 파이프라인과의 통합을 비롯한 다양한 고급 기능 또한 제공한다.
- 전반적으로 Harbor는 컨테이너 관리 프로세스를 간소화하고 컨테이너화된 애플리케이션의 보안 및 규정 준수를 개선하려는 모든 조직에 유용한 도구이다.
Harbor 권장 사항 및 환경



구현 환경
- VirtualBox VM(CPU 4 Core, RAM 8GB, Disk 100GB)
1. Harbor server 생성하기
1) docker와 docekr-compose 설치 및 Harbor 다운로드

① docker 및 docker-compose 설치
#업데이트
~ $ sudo apt-get update
#docker
~ $ sudo apt-get install -y docker.io
~ $ sudo systemctl start docker
~ $ sudo systemctl enable docker
#docker-compose
~ $ sudo apt-get install -y docker-compose
#설치 확인
~ $ sudo systemctl status docker
~ $ docker-compose --version
② Harbor 다운로드
https://github.com/goharbor/harbor/releases
Github 확인 후 사용할 버전 다운로드
# 다운로드
~ $ wget https://github.com/goharbor/harbor/releases/download/v2.10.0/harbor-offline-installer-v2.10.0.tgz
https://github.com/goharbor/harbor/releases/download/v2.10.0/harbor-offline-installer-v2.10.0.tgz
#압축풀기: 공식문서에서는 szvf 옵션을 사용하지만, 오류가 발생해서 xvf 옵션 사용
~ $ tar xvf harbor-offline-installer-v2.10.0.tgz
2) 인증 기관 인증서 생성
Harbor – Configure HTTPS Access to Harbor
#인증서 디렉토리 생성
~ $ mkdir ~/cert
~ $ cd ~/cert
#CA 인증서 개인 키 생성
~/cert$ openssl genrsa -out ca.key 4096
#CA 인증서 생성: CN에 harbor를 설치할 서버의 IP주소 입력
~/cert$ openssl req -x509 -new -nodes -sha512 -days 3650 \
-subj "/C=KR/ST=Seoul/L=Seoul/O=AWS/OU=Cloudschool/CN=192.168.0.8" \
-key ca.key \
-out ca.crt
Openssl 명령어 상세
openssl req
: 이 명령은 인증서 서명 요청(Certificate Signing Request, CSR)을 생성하거나 처리하는 데 사용됩니다. 여기서는 직접 자체 서명된 인증서를 생성하기 위해 사용되고 있습니다.x509
: 이 옵션을 사용하면 CSR을 생성하는 대신 X.509 자체 서명 인증서를 직접 생성합니다.new
: 새로운 개인 키와 인증서 요청을 생성합니다.nodes
: 이 옵션은 개인 키를 암호로 보호하지 않겠다는 것을 의미합니다. 즉, 키 파일에 비밀번호를 설정하지 않습니다.sha512
: 인증서의 서명을 생성할 때 SHA-512 hash 알고리즘을 사용하겠다는 것을 지정합니다.days 3650
: 생성된 인증서는 3650일 동안 유효합니다. 즉, 약 10년간 유효한 인증서를 생성합니다.subj
: 이 옵션은 인증서의 주제(Subject) 필드를 직접 지정합니다. 국가(C), 주 또는 도(ST), 지역명(L), 조직명(O), 조직 단위명(OU), 공통 이름(CN) 등을 설정합니다. 예를 들어,/C=KR/ST=Seoul/L=Seoul/O=AWS/OU=Cloudschool/CN=192.168.0.8
은 한국 서울에 위치한 'AWS' 조직의 ‘Cloudschool' 부서에 대한 인증서이며, 공통 이름으로 IP 주소192.168.0.8
을 사용합니다.key ca.key
: 인증서 서명에 사용할 개인 키 파일의 이름을 지정합니다. 여기서는ca.key
파일을 사용합니다. 이 키 파일은 미리 생성되어 있어야 합니다.out ca.crt
: 생성된 인증서를 저장할 파일 이름을 지정합니다. 여기서는 파일 이름으로ca.crt
를 사용합니다.
3) 서버 인증서 생성
#개인키 생성
~/cert$ openssl genrsa -out 192.168.0.8.key 4096
#인증서 서명 요청(CSR)을 생성
~/cert$ openssl req -sha512 -new \
-subj "/C=KR/ST=Seoul/L=Seoul/O=AWS/OU=Cloudschool/CN=192.168.0.8" \
-key 192.168.0.8.key \
-out 192.168.0.8.csr
#x509 v3 확장 파일을 생성
~/cert$ vi v3.ext
#내용
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
extendedKeyUsage = serverAuth
subjectAltName = @alt_names
[alt_names]
IP=192.168.0.8
#저장
#Harbor 호스트에 대한 인증서 생성
~/cert$ openssl x509 -req -sha512 -days 3650 \
-extfile v3.ext \
-CA ca.crt -CAkey ca.key -CAcreateserial \
-in 192.168.0.8.csr \
-out 192.168.0.8.crt
*v3.ext 내용 상세
authorityKeyIdentifier=keyid,issuer
: 인증서의 발급 기관을 식별하는 데 사용되는 키 식별자와 발급자 정보를 포함합니다.basicConstraints=CA:FALSE
: 이 인증서가 CA(인증 기관) 인증서가 아님을 나타냅니다. 즉, 이 인증서로 다른 인증서를 발급할 수 없습니다.keyUsage
: 인증서의 키가 사용될 수 있는 방법을 명시합니다. 여기에는 디지털 서명, 부인 방지, 키 암호화, 데이터 암호화 등이 포함됩니다.extendedKeyUsage=serverAuth
: 이 인증서의 키가 서버 인증에 사용될 수 있음을 나타냅니다.subjectAltName=@alt_names
: 인증서에 대체 주체 이름을 포함시킵니다. 여기서는[alt_names]
섹션에 정의된 대체 이름들을 참조합니다.[alt_names]
: 대체 이름을 정의하는 섹션입니다.IP=192.168.0.8
은 이 인증서가 특정 IP 주소를 식별하는 데 사용될 수 있음을 나타냅니다.
4) Harbor 및 Docker에 인증서 제공
#/data/cert/ 폴더 생성
~/cert$ sudo mkdir -p /data/cert
#서버 인증서와 키를 Harbor 호스트의 인증서 폴더에 복사
~/cert$ sudo cp 192.168.0.8.crt /data/cert/
~/cert$ sudo cp 192.168.0.8.key /data/cert/
# Docker에서 사용할 수 있도록 crt을 cert로 변환
~/cert$ openssl x509 -inform PEM -in 192.168.0.8.crt -out 192.168.0.8.cert
#Docker 인증서 폴더 생성
~/cert$ sudo mkdir -p /etc/docker/certs.d/192.168.0.8/
#서버 인증서, 키 및 CA 파일을 Harbor 호스트의 Docker 인증서 폴더에 복사
~/cert$ sudo cp 192.168.0.8.cert /etc/docker/certs.d/192.168.0.8/
~/cert$ sudo cp 192.168.0.8.key /etc/docker/certs.d/192.168.0.8/
~/cert$ sudo cp ca.crt /etc/docker/certs.d/192.168.0.8/
#Docker 엔진 다시 시작
~/cert$ sudo systemctl restart docker
5) Harbor 배포 및 재구성
① harbor.yml 파일 수정
#harbor 폴더로 이동
~$ cd ~/harbor
# harbor.yml.tmpl 파일을 harbor.yml로 수정 후 파일 진입
~/harbor$ mv harbor.yml.tmpl harbor.yml
~/harbor$ vi harbor.yml
② 5, 17, 18번 라인 값 수정

certificate: /etc/docker/certs.d/192.168.0.8/192.168.0.8.cert
private_key: /etc/docker/certs.d/192.168.0.8/192.168.0.8.key
*harbor 접속 시 admin 계정의 password 및 DB password 수정

6) 설치 shell 실행
~/harbor$ sudo ./prepare
~/harbor$ sudo ./install.sh
*컨테이너 확인

~$ docker ps
CONTAINER ID IMAGE COMMAND CREATED
d1205ba77ef1 goharbor/nginx-photon:v2.10.0 "nginx -g 'daemon of…" 3 hours ago
2baa8aab4d6b goharbor/harbor-jobservice:v2.10.0 "/harbor/entrypoint.…" 3 hours ago
5bd5fec7025a goharbor/harbor-core:v2.10.0 "/harbor/entrypoint.…" 3 hours ago
556602954a66 goharbor/registry-photon:v2.10.0 "/home/harbor/entryp…" 3 hours ago
389d21ae459d goharbor/redis-photon:v2.10.0 "redis-server /etc/r…" 3 hours ago
a77957090799 goharbor/harbor-db:v2.10.0 "/docker-entrypoint.…" 3 hours ago
37c5337f9cf7 goharbor/harbor-registryctl:v2.10.0 "/home/harbor/start.…" 3 hours ago
0056333da9ea goharbor/harbor-portal:v2.10.0 "nginx -g 'daemon of…" 3 hours ago
269e56e9c370 goharbor/harbor-log:v2.10.0 "/bin/sh -c /usr/loc…" 3 hours ago
STATUS PORTS
Up 3 hours (healthy) 0.0.0.0:80->8080/tcp, :::80->8080/tcp, 0.0.0.0:443->8443/tcp,
Up 3 hours (healthy)
Up 3 hours (healthy)
Up 3 hours (healthy)
Up 3 hours (healthy)
Up 3 hours (healthy)
Up 3 hours (healthy)
Up 3 hours (healthy)
Up 3 hours (healthy) 127.0.0.1:1514->10514/tcp
NAMES
:::443->8443/tcp nginx
harbor-jobservice
harbor-core
registry
redis
harbor-db
registryctl
harbor-portal
harbor-log
*윈도우에서 Harbor Web 접속을 위한 인증서 생성
#윈도우용 .p12 인증서 생성
~/cert$ openssl pkcs12 -export -out 192.168.0.8.p12 -inkey 192.168.0.8.key \
-in 192.168.0.8.crt -certfile ca.crt
Enter Export Password: # pass123#
Verifying - Enter Export Password: # pass123#
#최종 생성된 인증서
~/cert$ ls
192.168.0.8.cert 192.168.0.8.crt 192.168.0.8.csr
192.168.0.8.key 192.168.0.8.p12 ca.crt ca.key v3.ext
2. OS별 Client 설정 (*실습을 위해 직접 파일 전달 방식 확인)
1) ubuntu Client에서 Harbor에 연결하기 위한 설정
① harbor VM 또는 Web에서 받은 인증서를 ubuntu Client에 복사
# 인증서를 모아둘 user의 디렉터리 생성
~$ mkdir cert && cd $_

# 저장한 .crt 인증서를 /etc/docker/certs.d/server 디렉터리 생성 후 복사
~/cert$ sudo mkdir -p /etc/docker/certs.d/192.168.0.8
~/cert$ sudo cp 192.168.0.8.crt /etc/docker/certs.d/192.168.0.8/
② harbor에 접속하기
# harbor에 Login
~$ docker login 192.168.0.8
Username: admin
Password: # pass123# | harbor.yml에서 작성했던 admin의 PW
WARNING! Your password will be stored unencrypted in /home/student/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store
Login Succeeded
③ 테스트용 Image를 Push하기
# Image tag시 형식은 [harvor domain]/[project name]/[image neme]:[tag]
~$ docker image tag phpserver:1.0 192.168.0.8/library/phpserver:1.0
~$ docker push 192.168.0.8/library/phpserver:1.0

2) Windows에서 harbor Web 접속하기
① Https 접속을 위한 .crt, .p12 인증서 설치



*필요 시 IIS(인터넷 정보 서비스)관리자로 서버 인증서 확인


② 웹 브라우저로 Harbor(192.168.0.8)로 접속 및 확인

*앞선 과정에서 Push한 Image 확인 가능


*검색을 통한 확인도 가능, 그 외 다양한 기능 제공

*Harbor API를 통해 다양한 DB 접근을 제공

3) MacOS에서 Harbor Web 접속하기
① 웹 브라우저로 Harbor(192.168.0.8) 접속하여 인증서 내려받기


② 내보내기로 받은 .cer파일을 실행하여 시스템 키체인에 등록하기
인증서 신뢰 → 항상 신뢰로 수정

③ 반영된 인증서 및 Harbor 접속 확인 (이하 Windows와 동일)
