본문 바로가기

개발관련/Container

private한 container registry 만들기(docker registry)

반응형

registry는 Docker 이미지를 저장하고 배포 할 수있는 확장성이 뛰어난 상태 비 저장 서버 애플리케이션입니다.

registry는 Apache 라이선스에 따라 오픈 소스 입니다.

 

 

다음과 같은 경우 registry를 사용하는 것이 적절합니다.

  • 이미지가 저장되는 위치를 엄격하게 제어해야 하는 경우
  • 이미지 배포 파이프 라인을 완전히 소유하고 싶은 경우
  • 이미지 저장 및 배포를 사내 개발 워크 플로에 긴밀하게 통합하고 싶은 경우

 

아래 명령어를 통해 docker 를 이용하여 간단하게 registry 서비스를 배포할 수 있습니다. :

#!/bin/bash

CUR_PATH=`pwd`

docker run --detach \
    --publish 5000:5000 \
    --restart always \
    --volume $CUR_PATH/registry:/var/lib/registry \
    --name container-registry \
    registry:latest

 

 


 

외부에서 registry를 접근할 때

 

대부분 registry는 private한 컨테이너 이미지 저장소를 구축 해야할 때 많이 사용합니다.

따라서 외부에서 registry에 접근하도록 하려면 보안에 신경써야 합니다.

docker에서는 외부 접근이 되는 private registry를 운영할 때, 패킷 암호화를 위해 TLS를 사용하도록 권장하고 있습니다.

 

registry에서 TLS를 사용하기 위해서는 CA 인증서가 필요합니다.

보통은 CA 인증서 발급 기관에서 인증서를 발급받아 사용하지만, 해당 문서에서는 자체 인증서를 만들어 진행해 보도록 하겠습니다.

인증서는 registry 컨테이너를 띄우는 호스트에 생성하여 volume 마운트를 통해 컨테이너 내부로 전달하겠습니다.

 

Private Container Registry를 설치한 서버에서 아래 명령어를 순서대로 실행하여 자체 인증서를 생성합니다. :

# certs 라는 디렉터리를 만듭니다. 
# 해당 디렉터리는 registry 컨테이너를 띄울 때 컨테이너에 마운트 시킬 디렉터리 입니다.
# 해당 디렉터리 내에 자체 인증서를 생성하여 registry 컨테이너에 전달합니다.
$ mkdir certs && cd certs


# 해당 파일은 인증서를 사용할 IP를 설정하기 위해 필요합니다. 
# 이 설정을 하지 않으면 "x509: cannot validate certificate for because it doesn't contain any IP SANs" 에러를 발생합니다.
$ echo subjectAltName = IP:192.168.0.101,IP:127.0.0.1 > extfile.cnf
# 예) echo subjectAltName = IP:<호스트 서버의 IP 혹은 도메인명>,IP:127.0.0.1 > extfile.cnf  


# ssl 인증을 위한 key를 생성합니다.
$ openssl genrsa -out registry.key 2048

# ssl 인증을 위한 csr를 생성합니다.
$ openssl req -new -key registry.key -out registry.csr
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [XX]: # 엔터를 쳐서 넘어갑니다.
State or Province Name (full name) []: # 엔터를 쳐서 넘어갑니다.
Locality Name (eg, city) [Default City]: # 엔터를 쳐서 넘어갑니다.
Organization Name (eg, company) [Default Company Ltd]: # 엔터를 쳐서 넘어갑니다.
Organizational Unit Name (eg, section) []: # 엔터를 쳐서 넘어갑니다.
Common Name (eg, your name or your servers hostname) []: 192.168.0.101 # 호스트 서버의 IP 주소 혹은 도메인명을 입력합니다. 해당 문서에서는 예시로 192.168.0.101 이라는 IP 주소를 입력했습니다.
Email Address []: # 엔터를 쳐서 넘어갑니다.

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []: # 엔터를 쳐서 넘어갑니다.
An optional company name []: # 엔터를 쳐서 넘어갑니다.

# key, csr 파일 생성 확인
$ ls
extfile.cnf  registry.csr  registry.key


# ssl 인증을 위한 crt를 생성합니다.
$ openssl x509 -req -in registry.csr -CA registry.crt -CAkey registry.key -CAcreateserial -out registry.crt -days 365 -extfile extfile.cnf
Signature ok
subject=/C=XX/L=Default City/O=Default Company Ltd/CN=192.168.0.101
Getting CA Private Key


# crt 파일 생성 확인
$ ls
extfile.cnf  registry.crt  registry.csr  registry.key

 

 

 

위에서 직접 생성한 사설 인증서(registry.crt)를 이용하려면 Private Container Registry로 요청을 주고받는 다른 서버에게 해당 인증서가 신뢰할 수 있는 인증서라는 것을 인지시켜줘야 합니다. 이러한 작업을 하지 않으면 Private Container Registry로 push 혹은 pull 명령을 전송한 서버에서 x509: certificate signed by unknown authority라는 에러를 발생시켜 통신에 실패합니다.

따라서 아래와 같이 Private Container Registry를 이용할 다른 서버에서 인증서에 대한 작업을 진행해주어야 합니다. :

# 이 작업은 OS별로 다릅니다. 아래 작업 별 예시를 따릅니다.

# Ubuntu의 경우 :
$ cp registry.crt /usr/local/share/ca-certificates/registry.crt
$ update-ca-certificates
Updating certificates in /etc/ssl/certs...
1 added, 0 removed; done.
Running hooks in /etc/ca-certificates/update.d...
done.

# RED HAT Enterprise Linux의 경우 
$ cp registry.crt /etc/pki/ca-trust/source/anchors/registry.crt
$ update-ca-trust 

# 위의 예시들을 통해 작업을 완료했으면 Docker 데몬을 다시 시작해주어야 합니다.
# 아래 명령어를 통해 Docker를 다시 시작합니다.
$ systemctl restart docker
$ systemctl status docker
● docker.service - Docker Application Container Engine
   Loaded: loaded (/lib/systemd/system/docker.service; enabled; vendor preset: enabled)
   Active: active (running) since Mon 2020-10-26 12:01:34 KST; 1min ago


# 만약 위와 같이 진행해도 'x509: certificate signed by unknown authority' 에러가 발생하면,
# 공통적으로 아래와 같이 처리합니다.
$ mkdir /etc/docker/certs.d

$ mkdir /etc/docker/certs.d/192.168.0.101:5000
# 예) mkdir /etc/docker/certs.d/{<호스트 서버의 IP 혹은 도메인명>:<포트번호>}

$ cp registry.crt /etc/docker/certs.d/192.168.0.101:5000/

# Docker는 hostname을 port와 같이 사용할 경우, docker가 어떤 인증서가 사용되어야 하는지에 대해서 추측하지 않습니다.
# 예) 192.168.0.101:5000, 127.0.0.1:8080 등
#
# 따라서 포트 단위로 인증서를 제공해야 docker가 어떤 인증서를 사용해야 하는지 알 수 있습니다.
# 이를 위해서는 /etc/docker/certs.d/{hostname:port} 와 같이 
# 'private container registry 서버의 IP 혹은 도메인명:포트번호' 로 구분되는 디렉터리 하위에 인증서를 저장해두어야 합니다.

 

 

 

 

TLS를 사용하는 registry 컨테이너를 띄우기 위해 아래 명령어를 사용합니다. :

#!/bin/bash

CUR_PATH=`pwd`

docker run --detach \
    --publish 5000:5000 \
    --restart always \
    --name container-registry \
    --volume $CUR_PATH/registry:/var/lib/registry \
    --volume $CUR_PATH/certs:/certs \
    -e REGISTRY_HTTP_ADDR=0.0.0.0:5000 \
    -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/registry.crt \
    -e REGISTRY_HTTP_TLS_KEY=/certs/registry.key \
    registry:latest

# --volume $CUR_PATH/certs:/certs <- 인증서를 담을 디렉터리를 마운트
# -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/registry.crt <- 인증서 위치 및 파일명
# -e REGISTRY_HTTP_TLS_KEY=/certs/registry.key <- 인증서의 키의 위치 및 파일명

 

 

이제 모든 작업이 완료되었습니다.

해당 원격 private registry에 docker image를 push 하거나 pull 할 수 있습니다.

$ docker tag hello-world 192.168.0.101:5000/hello-world

# registry에 이미지를 push 하는 예시
# docker push <registry의 ip 주소 혹은 도메인명>:5000/<이미지명>
$ docker push 192.168.0.101:5000/hello-world
9c27e219663c: Layer already exists
latest: digest: sha256:90659bf80b44ce6be8234e6ff90a1ac34acbeb826903b02cfa0da11c82cbc042 size: 525

# registry에서 이미지를 pull 하는 예시
$ docker pull 192.168.0.101:5000/hello-world
Using default tag: latest
latest: Pulling from hello-world
Digest: sha256:90659bf80b44ce6be8234e6ff90a1ac34acbeb826903b02cfa0da11c82cbc042
Status: Image is up to date for 192.168.0.101:5000/hello-world:latest
192.168.0.101:5000/hello-world:latest

 


참고

 

Docker Registry

 

docs.docker.com

 

Test an insecure registry

 

docs.docker.com

 

Khbyun's blog

Novemberde's dev

novemberde.github.io

 

79. [Docker Registry] Docker Private Registry 에 보안을 적용하여 사용하기

이번 포스트에서는 Docker 가 제공하는 private registry (이미지 저장소) 를 deploy 하는 방법을 다룬다....

blog.naver.com

 

openssl 명령어

개요 테스트 환경 openssl 1.0.2 openssl 명령어 1. openssl 문법 openssl command [ command_opts ] [ command_args ] 참조 : https://www.openssl.org/docs/manpages.html 2. PEM 인코딩된 인증서를 ..

fliedcat.tistory.com

 

Docker registry Self-signed 인증서 사용하기

Docker private registry - 인증서 적용하기docker registry는 기본적으로 https 통신을 하도록 되어 있다. 예전 버전은 일반 http 통신이 가능한 것으로 보여지는데,어느 버전 이후부터는 그게 안되는 듯 보인

figo2264.github.io

 

반응형