개요
도커 이미지를 저장하는 대표적인 저장소로 도커 허브(https://hub.docker.com/) 가 있다. 퍼블릭 저장소를 기본으로 제공하는 Docker Hub는 전 세계적으로 널리 사용되고 있지만, 기업 또는 개인이 자체적인 이미지 저장소로 활용하기 위해서는 Private 환경 구성이 필요한 경우가 많다.
Docker Hub는 무료 플랜 기준으로 Private 저장소를 1개만 제공하며, 추가 Private 저장소 사용이나 기업 단위 관리 기능은 유료 플랜 가입이 필요하다. 또한, 저장 용량이나 이미지 Pull 제한 등 사용 정책이 존재하기 때문에 비용이나 보안 요구 사항에 따라 별도의 Private Registry 구축을 고려하게 된다.
본 글에서는 Docker Image 를 Private 하게 관리하기 위해 Self-Hosted, AWS ECR, NCP Container Registry 을 간단하게 사용해본다.
Test Image 생성
각 Registry 테스트를 위하여 테스트용 이미지를 생성한다. 테스트에 사용하는 이미지는 hashicorp/http-echo (https://hub.docker.com/r/hashicorp/http-echo) 이미지이다. hashicorp/http-echo 는 인수를 입력받은 값을 출력하는 간단한 웹 서버이다.
아래의 Dockerfile을 하나 생성한다.
# Dockerfile
FROM hashicorp/http-echo
CMD ["-listen=:8080", "-text=hello world ver1.0"]
빌드 후 컨테이너를 실행한다.
$ docker build -t my-echo:1.0 .
$ docker run -d --name my-echo-container-v1-0 -p 8080:8080 my-echo:1.0
http://localhost:8080 혹은 http://{HOST_IP}:8080 에 접속하여 정상적으로 적용 되었음을 확인한다.
Self-Hosted
Registry 서비스 구성
docker 에서 registry 를 구성할 수 있도록 Official Image(https://hub.docker.com/_/registry) 를 제공하고 있다.
아래와 같이 run 명령어로 간단하게 실행 하거나 docker-compose.yml 을 작성하여 실행한다.
$ docker run -d --name docker-registry -p 5000:5000 registry:latest
# docker-compose.yml
version: '3.8'
services:
docker-registry:
image: registry:latest
container_name: docker-registry
restart: on-failure
ports:
- "5000:5000"
volumes:
- ./registry-data:/var/lib/registry
$ docker compose up -d
Image build & push
Docker Image를 빌드하고 푸시하는 가이드는 아래와 같다.
# image build
$ docker build -t {[IMAGE_NAME]:[IMAGE_TAG]} .
# tag (로컬에 있는 이미지를 업로드하기 위한 태그로 변경)
$ docker tag {[IMAGE_NAME]:[IMAGE_TAG]} {HOST_NAME}:5000/{[IMAGE_NAME]:[IMAGE_TAG]}
# push (로컬에 있는 이미지 업로드)
$ docker push {HOST_NAME}:5000/{[IMAGE_NAME]:[IMAGE_TAG]}
# 업로드 이미지 조회
$ curl -XGET localhost:5000/v2/_catalog
Image Pull
$ docker pull {HOST_NAME}:5000/{[IMAGE_NAME]:[IMAGE_TAG]}
만약 위와 같은 절차를 통해 로컬이 아닌 다른 네트워크에서 push 를 시도한다면 http: server gave HTTP response to HTTPS client 오류와 함께 push 되지 않을 것이다. 그 이유는 docker 는 기본적으로 HTTPS가 미적용된 레지스트리는 PUSH가 안된다. Sever에 **HTTPS 인증서(사설 포함)**를 발급 받거나, Client에 insecure-registries 설정해야 한다.
insecure-registries 로 HTTP 허용
pull/push 를 시도하는 클라이언트에서 아래 경로(centos 기준)에 해당 옵션을 추가하고 docker 재시작 한다.
$ vi /etc/docker/daemon.json
.
.
.
{
"insecure-registries": [
"{HOST_NAME}:5000"
]
}
$ systemctl restart docker
SSL 인증서(사설) 생성
Private Registry 를 HTTPS 적용을 위해 SSL 인증서를 생성하고 Nginx 을 통해 SSL 인증서와 계정 인증을 처리한 뒤, 내부 docker-registry로 요청을 프록시 하도록 구현한다.
ROOT 인증서(CA) 생성
$ mkdir certs & cd $_
# ca.key 생성
$ openssl genrsa -out ./certs/ca.key 2048
# ca.crt 생성
$ openssl req -x509 -new -key ./certs/ca.key -days 1000 -out ./certs/ca.crt
컨테이너 인증서 생성
# domain.key 생성
$ openssl genrsa -out ./certs/domain.key 2048
# domain.csr 생성
$ openssl req -new -key ./certs/domain.key -subj /CN={HOST_IP} -out ./certs/domain.csr
# SAN (Subject Alternative Name) 설정
$ echo subjectAltName=IP:{HOST_IP} > extfile.cnf
# 인증서 서명
$ openssl x509 -req -in ./certs/domain.csr -CA ./certs/ca.crt -CAkey ./certs/ca.key -CAcreateserial -out ./certs/domain.crt -days 10000 -extfile extfile.cnf
Nginx 컨테이너 생성
❓Nginx :가볍고 빠른 웹 서버 + 리버스 프록시 서버 + 로드밸런서
계정 파일 생성(htpasswd)
# htpasswd 설치
$ yum install httpd-tools
# htpasswd 생성
$ mkdir auth && cd $_
$ htpasswd -c htpasswd {USER_NAME}
nginx.conf 생성
$ vim nginx.conf
.
.
.
upstream docker-registry {
server registry:5000;
}
server {
listen 443 ssl;
server_name {HOST_IP};
ssl_certificate /etc/nginx/certs/domain.crt;
ssl_certificate_key /etc/nginx/certs/domain.key;
client_max_body_size 0;
chunked_transfer_encoding on;
location /v2/ {
# 특정 docker client 차단
if ($http_user_agent ~ "^(docker/1\\.(3|4|5(?!\\.[0-9]-dev))|Go).*$") {
return 404;
}
auth_basic "registry.localhost";
auth_basic_user_file /etc/nginx/auth/htpasswd;
add_header 'Docker-Distribution-Api-Version' 'registry/2.0' always;
proxy_pass <http://docker-registry>;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 900;
}
}
nginx 컨테이너 실행
아래와 같이 run 명령어로 간단하게 실행 하거나 앞서 작성한 docker-compose.yml 에 추가 작성하여 실행한다.
$ docker run -d --name nginx -p 443:443 --link docker-registry:registry \\
-v $(pwd)/nginx.conf:/etc/nginx/conf.d/nginx.conf \\
-v $(pwd)/certs/:/etc/nginx/certs \\
-v $(pwd)/auth/:/etc/nginx/auth \\
nginx:latest
# docker-compose.yml
.
.
.
nginx:
image: nginx:latest
container_name: nginx
ports:
- "443:443"
restart: always
depends_on:
- docker-registry
volumes:
- ./nginx.conf:/etc/nginx/conf.d/nginx.conf
- ./certs/:/etc/nginx/certs
- ./auth/:/etc/nginx/auth
인증서 등록 (클라이언트)
# 인증서 복사
$ sudo mkdir -p /etc/docker/certs.d/10.52.254.98/
$ sudo cp domain.crt /etc/docker/certs.d/10.52.254.98/ca.crt
# Docker service 재시작
$ sudo systemctl restart docker
Docker 로그인
$ docker login {HOST_IP}
Cloud - AWS Elastic Container Registry (ECR)
AWS 에서는 Elastic Container Registry (ECR)을 이용하여 private Registry를 관리할 수 있다.
서비스에 관한 자세한 설명은 AWS ECR (https://aws.amazon.com/ko/ecr) 문서를 참고한다.
요금
AWS의 ECR은 저장소 스토리지 요금과 데이터 전송 요금이 합산되어 청구된다. 각 청구되는 기준은 아래와 같다.
- 저장소 스토리지 요금
- 프라이빗 리포지토리 (Private) : AWS 프리 티어 일부로 매월 500MB 1년간 무료 (초과시 월 0.10 USD / GB)
- 퍼블릭 리포지토리 (Public) : 월 50GB 항상 무료 (초과시 월 0.10 USD / GB)
- 데이터 전송 요금
- 프라이빗 리포지토리 (Private)
- 데이터 수신 : 무료
- 데이터 송신 (동일 리전) : 무료
- 데이터 송신 (다른 리전 혹은 인터넷) : (월 USD 0.126 / GB)
- 퍼블릭 리포지토리 (Public)
- 데이터 수신 : 무료
- 데이터 송신 (동일 리전) : 무료
- 데이터 송신 (다른 리전 혹은 인터넷) : 익명 사용자 월 500GB 무료, AWS 계정 사용자 월 5TB 무료 (초과시 월 0.09 USD / GB)
- 프라이빗 리포지토리 (Private)
Repository 생성
- 일반 설정 - 리포지토리 이름
- 일반 설정 - 이미지 태그 변경 가능성
- 암호화 설정 - 암호화 구성
❗️ AWS Repository 생성에 앞서 IAM 계정을 생성해야 하며, aws cli 설치 및 configure 을 지정해야 한다.
Image build & push
푸시 명령 보기를 통해 아래와 같이 본인의 리포지토리에 맞는 커멘드로 사용할 수 있다.
커멘드 사용에 앞서 aws cli 설치 및 configure 을 지정한다.
# AWS CLI 설치
$ sudo yum install -y awscli
# 인증 정보 입력 (Access Key, Secret Key는 AWS 콘솔 → IAM → 사용자 → 보안 자격 증명 에서 발급 가능)
$ aws configure
.
.
.
AWS Access Key ID [None]: {AWS Access Key}
AWS Secret Access Key [None]: {AWS Secret Key}
Default region name [None]: ap-northeast-2
Default output format [None]: json
각 커멘드 가이드는 아래와 같다.
# docker login
$ aws ecr get-login-password --region ap-northeast-2 | docker login --username AWS --password-stdin {AWS_ID}.dkr.ecr.ap-northeast-2.amazonaws.com
# login check
$ cat ~/.docker/config.json
# image build
$ docker build -t {[IMAGE_NAME]:[IMAGE_TAG]} .
# tag (로컬에 있는 이미지를 ECR 업로드하기 위한 태그로 변경)
$ docker tag {[IMAGE_NAME]:[IMAGE_TAG]} {AWS_ID}.dkr.ecr.ap-northeast-2.amazonaws.com/{[AWS_REPOSITORIES_NAME]:[IMAGE_TAG]}
# push (로컬에 있는 이미지 업로드)
$ docker push {AWS_ID}.dkr.ecr.ap-northeast-2.amazonaws.com/{[AWS_REPOSITORIES_NAME]:[IMAGE_TAG]}
AWS 콘솔에서 push 된 이미지를 확인한다.
Image Pull
docker pull <AWS_ID>.dkr.ecr.ap-northeast-2.amazonaws.com/{[AWS_REPOSITORIES_NAME]:[IMAGE_TAG]}
AWS의 ECR과 관련하여 좀 더 자세한 내용은 본 문서를 참고한다 (https://docs.aws.amazon.com/AmazonECR/latest/userguide/getting-started-cli.html)
Cloud - NCP Container Registry
네이버 클라우드에서는 “Container Registry”를 이용하여 Private Registry 를 관리할 수 있다.
서비스에 관한 자세한 설명은 NCP Container Registry (https://www.ncloud.com/product/containers/containerRegistry#overview) 문서를 참고한다.
요금
네이버 클라우드의 Container Registry 서비스는 기본적으로 무료이다. 다만 Image 를 Object Storage 에 쌓기 때문에 별도의 Object Storage 비용이 청구된다.
하지만 VPC 환경에서 운영할 경우 아래의 금액이 청구된다.
Registry 생성
레지스트리 이름과 버킷을 지정하여 새로운 Container Registry 를 생성한다.
❗️Container Registry 생성에 앞서 이미지 저장을 위해 사전에 Object Storage 버킷을 생성해야 한다.
Image build & push
이용 가이드를 통해 아래와 같이 본인의 레지스트리에 맞는 커멘드로 사용할 수 있다.
각 커멘드 가이드는 아래와 같다.
# docker login
$ docker login {REGISTRIES_NAME}.kr.ncr.ntruss.com
.
.
.
Username: {Access Key ID}
Password:{Secret Key}
# login check
$ cat ~/.docker/config.json
# Image build
$ docker build -t {[IMAGE_NAME]:[IMAGE_TAG]} .
# tag (AWS ECR과 다른 점은 push 할 이미지명이 리포지토리 이름은 아니다.)
$ docker tag {[IMAGE_NAME]:[IMAGE_TAG]} {REGISTRIES_NAME}.kr.ncr.ntruss.com/{[IMAGE_NAME]:[IMAGE_TAG]}
# push
$ docker push {REGISTRIES_NAME}.kr.ncr.ntruss.com/{[IMAGE_NAME]:[IMAGE_TAG]}
네이버 클라우드 콘솔에서 push 된 이미지를 확인한다.
Image Pull
# pull
$ docker pull {REGISTRIES_NAME}.kr.ncr.ntruss.com/{[IMAGE_NAME]:[IMAGE_TAG]}
NCP의 Container Registry 과 관련하여 좀 더 자세한 내용은 본 문서를 참고한다. (https://guide.ncloud-docs.com/docs/containerregistry-overview)
Ref
[Self-Hosted]
- https://cocococo.tistory.com/entry/Docker-Private-레지스트리-구축-및-사용-방법
- https://devbksheen.tistory.com/entry/도커-사설-레지스트리Docker-Private-Registry에-이미지-배포하기
- https://velog.io/@lijahong/0부터-시작하는-Docker-공부-Private-Registry-구현
[AWS]
'Study > Server' 카테고리의 다른 글
[Kube] Kubernetes - Deployment (6) (2) | 2024.07.22 |
---|---|
[Kube] Kubernetes - Pod (5) (2) | 2024.07.22 |
[Kube] Kubernetes - kubectl 명령어 (4) (2) | 2024.07.19 |
[Kube] Kubernetes - 실습 환경 구성 (3) (2) | 2024.07.16 |
[Kube] Kubernetes - 특징 및 아키텍처 (2) (4) | 2024.07.16 |