티스토리 뷰
서론
최근 사이드 프로젝트를 진행하면서 docker registry를 직접 구축하는 과정을 경험했다. 보안 및 비용적인 측면 등을 고려하여 프로젝트에 사용될 이미지를 직접 구축한 private docker registry에서 관리하기로 결정하였기 때문이다.
오늘은 이를 구축한 과정과, 과정 중에 겪은 크고 작은 이슈들에 대해 소개해보고자 한다. 구축 과정에 있어 얻은 다양한 꿀팁을 소개하고 있으니, 이를 처음 시도하려는 분들의 시간을 크게 아껴줄 수 있는 포스트가 될 것이다.
Registry 구축
local registry를 구축하는 과정은 생각보다 매우 간단하다. Docker Hub에 Official Image로써 등록되어 있는 registry를 활용하여 손쉽게 구축할 수 있다.
위 이미지를 run 시켜주기만 하면 작동하지만, 그전에 몇 가지 작업을 먼저 진행하고자 한다.
첫 번째로, docker network를 생성해줄 것이다. Registry의 GUI 또한 컨테이너로 띄울 예정인데, GUI와 docker registry 간의 통신을 위해 network를 만드는 것이다.
두 번째로, 사용자 인증 정보를 만들어줄 것이다. 보안을 위해 개인 registry 구축을 선택하였으니, 기본적인 인증 절차는 추가해두려 한다. 그 외에도, 이미지 준비, 볼륨 마운트 준비 등의 과정을 소개하겠다.
0. image 준비
docker image pull registry:2
docker image pull hyper/docker-registry-web
본 포스트에선 위 두 가지 이미지를 활용할 것이다. 첫 번째 이미지는 registry 구축용, 두 번째 이미지는 registry의 GUI 구축용이다.
참고로, registry는 1과 2 버전으로 나뉘는 듯한데, 1은 python, 2는 Go라고 한다. 웬만하면 2를 쓰자. 그리고, 2 tag는 항상 2.x.x의 최신 버전으로 업데이트되고 있으므로 2를 쓰면 알아서 최신 버전을 받아온다.
그리고 3.0.0이 alpha로 나와있는 듯 하다. 뭐가 바뀔지는 잘 모르겠으나, 추후 3.0.0에 대한 정보가 확인되면 글을 수정해 보겠다.
1. docker network 생성
docker network create registry
registry와 registry GUI는 모두 컨테이너로 관리되므로, 공유될 network 없이는 서로 통신이 불가능하다. GUI에서 registry 정보를 받아갈 수 있도록 해당 network를 기반으로 컨테이너를 띄우려 한다.
물론 run 시에, --network host 옵션을 통해 호스트의 네트워크를 공유함으로써 간단히 통신 가능하도록 만들 수도 있다. 보안이 크게 중요시되지 않는다면 간단하게 이 방법을 사용해도 좋다.
추가로, 기존 포스트에 --link를 활용한 방식이 example로써 많이 소개되고 있는 듯하다. link는 곧 사라질 방식이라고 하니, network를 활용하도록 하자.
2. Volume Mount 할 directory 생성
mkdir -p /data/docker/auth
우리는 registry 데이터 영구 보존을 위해 /data를 volume으로 mount 할 예정이다. /data/docker/registry/v2/... 에 registry 관련 데이터들이 저장될 것이다.
추가로, 인증 관련 정보는 /data/docker/auth에 저장하려 한다. -p 옵션을 통해, 사용될 directory를 한꺼번에 생성하자.
3. 인증 정보 생성
우리는 간단히 ID와 PW를 통해 인증을 진행해 볼 것이다. 그 외의 더 다양한 인증 방식은 아래 Document의 Authentication 항목에서 확인할 수 있다.
docker run --entrypoint htpasswd registry:2 -Bbn user 1234 > /data/docker/auth/htpasswd
# 위 커맨드 실행 안될 경우
apt-get install apache2-utils
htpasswd -Bbn user 1234 > /data/docker/auth/htpasswd
registry는 htpasswd라는 서비스를 활용하여 HTTP basic authentication에서 사용될 인증 정보를 관리하고 있다. htpasswd는 사용자명 및 암호를 저장하는 일반파일을 생성해 주는 역할을 한다.
registry 컨테이너 내부에 htpasswd가 설치되어 있으므로, 이를 활용하는 방식이 사용되어 왔던 듯싶다. 그러나 2.7.1 이후 버전에서는 무언가 문제가 있어 이 방법을 활용할 수 없는 듯하다. (해당 링크 확인)
이를 해결하기 위해 registry:2.7.0을 사용해도 괜찮지만, 최신 버전을 사용하고 싶다면 로컬에 htpasswd를 직접 설치하면 된다. apache2-utils에 포함되어 있으므로, 이를 설치 후 인증 파일을 생성하자.
4. Run registry container!
docker run -d -p 5000:5000 \
--name registry \
--network registry \
-v /data:/var/lib/registry \
-v /data/docker/auth:/auth \
-e REGISTRY_AUTH=htpasswd \
-e REGISTRY_AUTH_HTPASSWD_REALM="Registry Realm" \
-e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd \
--restart=always \
registry:2
모든 준비가 끝났으니, 이제 registry 컨테이너를 동작시켜 보자. 위 커맨드를 사용하면 되는데, 각 옵션에 대한 설명은 아래와 같다.
- --network registry: 1번 과정에서 만들어둔 network와 연결한다.
- -v /data:/var/lib/registry: registry에 등록한 이미지를 영구 보존하기 위해, 로컬 스토리지와 마운팅 한다.
- -v /data/docker/auth:auth: 인증 정보를 사용하기 위해 마운팅 한다.
- -e REGISTRY_AUTH=htpasswd: registry 인증 방식을 결정한다.
- -e REGISTRY_AUTH_HTPASSWD_REALM="Registry Realm": 사용자에게 표시될 Realm 영역의 이름을 지정한다.
- -e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd: 인증 정보가 저장되어 있는 도커 내부 위치를 지정한다.
컨테이너가 성공적으로 시작됐다면, 우리는 registry 구축을 완료한 것이다. 생각보다 간단한 과정을 통해 자신만의 registry를 구축할 수 있음을 알게 되었다. 이제 이를 기반으로 이미지가 잘 올라가는지 테스트해 보고, GUI를 구축해 보자.
4.1. SSL 인증 적용 (Optional)
-e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/xxx.pem \
-e REGISTRY_HTTP_TLS_KEY=/certs/xxx.pem \
본 포스트에선 HTTPS까지 적용하지는 않을 것이다. 다만, Production으로 사용하고자 할 때엔 꼭 HTTPS 인증서를 적용해야 한다. 컨테이너를 띄울 때, 위 두 가지 옵션을 통해 간단히 SSL 인증서를 적용할 수 있다.
5. push
위 과정을 통해 registry 구축을 완료했다. 이제 이미지를 push 해보자.
docker tag redis:7.2.1 xxx.xxx.xxx.xxx:5000/redis:7.2.1
docker push xxx.xxx.xxx.xxx:5000/redis:7.2.1
샘플로 redis 이미지를 registry에 푸시해보려 한다. 위와 같이, "{registry의 URL}/{repository}:{tag}"와 같은 네이밍을 통해 어떤 registry로 해당 이미지를 push 할지 지정할 수 있다.
5.1. Insecure Registry 등록
다만, 위 과정을 거쳐온 상태로 이미지를 푸시하려 하면 아래와 같은 오류를 마주할 수 있다.
Get "https://home.ufxpri.dev:5005/v2/": http: server gave HTTP response to HTTPS client
이는 docker가 기본적으로 HTTPS를 통해 registry와 통신하려 하기 때문에 발생하는 오류다. 이를 해결하려면, 이미지를 pull 혹은 push 하려는 클라이언트의 docker 설정을 건드려야 한다.
"insecure-registries": [
"home.ufxpri.dev:5005"
]
일반적인 도커 사용자의 경우, /etc/docker/daemon.json라는 파일에 해당 설정을 삽입하면 되며, Docker Desktop 사용자의 경우 아래와 같이 Docker Engine 설정에 들어가 설정을 삽입해 주면 된다.
5.2. docker login
이제 push가 되겠거니 해서 커맨드를 실행시켜 보면, 이번엔 아래와 같은 오류를 마주할 수 있을 것이다.
no basic auth credentials
당연한 얘기지만, 우리가 아까 적용한 인증 정보를 바탕으로 로그인을 해야 해당 registry에 이미지를 등록할 수 있을 것이다.
docker login xxx.xxx.xxx.xxx:5000 --username user --password 1234
3번 과정에서 생성한 인증 정보를 통해 로그인을 진행해 보자. Login Succeeded란 메시지가 나왔다면, 이제 Push를 진행해보자.
docker push xxx.xxx.xxx.xxx:5000/redis:7.2.1
성공적으로 push가 진행되는 것을 확인할 수 있을 것이다! 이렇게, registry에 접근하는 과정까지의 소개를 마무리지었다. 마지막으로, GUI를 통해 내가 등록한 이미지를 확인해 보는 과정을 거쳐보자.
6. registry의 Web GUI 구축
docker run -d -p 8080:8080 \
--name registry-web \
--network registry \
-e REGISTRY_URL=http://registry:5000/v2 \
-e REGISTRY_NAME=xxx.xxx.xxx.xxx:5000 \
-e REGISTRY_BASIC_AUTH="dXNlcjoxMjM0" \
--restart=always \
hyper/docker-registry-web
0번에서 pull 해놓은 docker-registry-web 이미지를 활용하여 GUI 웹을 구축할 것이다. 각 옵션에 대한 설명은 아래와 같다.
- --network registry: 1번에서 생성한 network와 연결함으로써, registry container와 통신이 가능하도록 한다.
- -e REGISTRY_URL=http://registry:5000/v2: 해당 URL을 통해 registry에 repository 정보를 요청할 것이다. HOST명을 network명으로 지정해야 하는 점에 주의하자.
- -e REGISTRY_NAME=xxx.xxx.xxx.xxx:5000: 웹에 표시될 Registry의 이름이다.
- -e REGISTRY_BASIC_AUTH="dXNlcjoxMjM0"
- Registry에 접근하기 위해선, 우리가 3번 과정을 통해 지정한 인증 정보를 GUI도 알고 있어야 한다.
- 이를 위해, REGISTRY_BASIC_AUTH 환경변수로 인증 정보를 제공해야 한다.
- "ID:PW"를 Base64로 인코딩하여 전달해 주면 된다. 본 커맨드의 경우 user:1234를 Base64로 인코딩한 값을 전달해 주었다.
- 혹시 인코딩하는 법을 모른다면, 해당 링크에서 진행하면 된다.
6번 과정을 통해, 상당히 간단하게 내가 직접 등록한 이미지를 GUI로서 확인할 수 있게 되었다.
결론
간단하다면 간단하지만, 구축하는 과정에서 생각보다 이슈가 꽤나 있었다. 이를 해결하는 과정에서 새로 알아간 점, 혹은 꿀팁을 꽤나 많이 얻어간 듯하여 이를 공유하고자 포스트 작성을 하게 되었다.
ecr, azurecr 등의 완전관리형 프라이빗 레지스트리 사용이 비용적으로 부담된다면, 직접 Registry를 구축하는 방안을 고려해 보자. 생각보다 레지스트리 사용 비용이 꽤 나가는 편인데, 큰 절약이 될 것이다.
- Total
- Today
- Yesterday
- AWS
- 백엔드
- 넷플릭스
- 규칙없음
- 모델 추론
- 조직문화
- 개발자회고
- s3
- Ai
- ddd
- S3+CloudFront
- 모델 추론 최적화
- 회고
- Python
- Triton Inference Server
- 사이드프로젝트
- CloudFront
- memory leak
- 메모리 누수
- 웹사이트배포
- 정적웹사이트
- 토스
- 유난한도전
- uvicorn
- mlops
- Gunicorn
- 개발자동아리
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |