Tech 학습 및 정리/CICD

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

펭잉 2025. 5. 12. 17:33

Harbor란?

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

Harbor 권장 사항 및 환경

Harbor 구동에 필요한 권장 리소스
구축에 필요한 Tool 또는 SW의 권장 버전
Harbor의 기본 프로토콜 및 Port Number

구현 환경

  • 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번 라인 값 수정

harbor.yml 파일 내부

  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 수정

password 수정 라인

6) 설치 shell 실행

~/harbor$ sudo ./prepare
~/harbor$ sudo ./install.sh

*컨테이너 확인

실행중인 harbor 컨테이너 조회

~$ 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 $_

WinSCP로 파일 복사 후 제공

# 저장한 .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(인터넷 정보 서비스)관리자로 서버 인증서 확인

IIS 관리자 사용을 위한 관리 콘솔 활성화
IIS 관리자로 인증서 확인

 

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

웹 브라우저로 Harbor 접속 *ID/PW는 설정값 사용

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

Harbor는 저장 단위를 Project 단위로 관리, library는 기본 Project
Project 단위 저장된 Image 확인 가능

 

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

Image 한 눈에 보기

 

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

Harbor 관리를 위한 API 목록 Swagger UI로 기본 제공

 

3) MacOS에서 Harbor Web 접속하기

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

사설 인증서 확인 절차
사설 인증서 내려 받기

 

② 내보내기로 받은 .cer파일을 실행하여 시스템 키체인에 등록하기

인증서 신뢰 → 항상 신뢰로 수정

인증서 파일 확인 및 시스템 키체인 등록

 

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

웹 브라우저 새로고침 후 인증서 인식 확인