cloudwithbass

[Docker] https와 인증서를 이용해서 사설 도커 레지스트리 사용하기 본문

Docker and Jenkins

[Docker] https와 인증서를 이용해서 사설 도커 레지스트리 사용하기

여영클 2024. 7. 20. 15:24

 

 

 

 

목차

     

     

     

    1. 도커 레지스트리란?

    도커 이미지를 발행하거나(push) 가져올 수 있는(pull) stateless 서버 애플리케이션입니다.
    따라서 도커 허브나 Amazon ECR 또한 도커 레지스트리입니다.
    자바의 jar, 루비의 gem처럼 도커의 아티팩트(빌드 산출물)는 도커 이미지입니다.

    2. 도커 레지스트리 설치하기

    • 도커 허브와 Amazon ECR처럼 클라우드 방식의 도커 레지스트리를 사용할 수도 있습니다.
    • 하지만 많은 회사들에선 사내 네트워크에 아티팩트를 보관하는 정책을 갖고 있습니다.
    • 따라서 클라우드 방식이 아닌 자체 호스팅 방식의 도커 레지스트리를 설치하겠습니다.

    도커 레지스트리는 도커 이미지로 제공되므로 다음 명령을 통해 도커 레지스트리 컨테이너를 실행할 수 있습니다.

    docker run -d -p 5000:5000 --restart=always --name registry registry:2

    3. 인증서와 접속 제한 추가하기

    도커 레지스트리는 보안을 위해 SSL/TLS를 사용합니다.

    따라서 CA 인증서나 자체 서명 인증서가 필요한데, 저는 openssl을 통해 자체 서명 인증서를 생성하겠습니다.

    mkdir ~/certs
    openssl req -newkey rsa:4096 -nodes -sha256 -keyout $HOME/certs/domain.key -x509 \
      -days 365 -out $HOME/certs/domain.crt

    이후 국가 코드, 메일 등을 입력하면 ~/certs/ 위치에 domain.crt와 domain.key 파일이 생성됐을 것입니다.

     

    다음으로 접속 제한을 추가합니다.

    mkdir ~/auth
    docker run --entrypoint htpasswd httpd:2 -Bbn [사용자이름] [비밀번호] > /home/yyk/auth/passwords

    httpd:2 이미지의 htpasswd 도구를 사용해서 사용자와 비밀번호를 추가합니다.

    교재에서는 registry:2 이미지를 사용했지만, registry 2.7부터 htpasswd가 사라져서 httpd:2 이미지를 사용합니다.

    저는 테스트를 위해 사용자 이름에는 qwer을, 비밀번호에는 1234를 사용했습니다.

     

    이제 https 사용을 위해 443 포트에서 레지스트리 컨테이너를 실행합니다.

    docker run -d -p 443:443 --restart=always --name registry \
      -v /home/yyk/auth:/auth \
      -e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" \
      -e REGISTRY_AUTH_HTPASSWD_PATH=/auth/passwords \
      -v /home/yyk/certs:/certs \
      -e REGISTRY_HTTP_ADDR=0.0.0.0:443 \
      -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt \
      -e REGISTRY_HTTP_TLS_KEY=/certs/domain.key \
      registry:2

     

    주요 옵션 설명

    • -v /home/yyk/auth:/auth
      ~/auth 디렉터리를 컨테이너의 /auth 디렉터리에 마운트합니다.
    • -e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm"
      htpasswd 파일의 Realm을 Registry Realm으로 설정합니다.
    •   -e REGISTRY_AUTH_HTPASSWD_PATH=/auth/passwords
      htpasswd 파일의 경로를 설정합니다.
      중요한 점은 컨테이너의 '/auth/passwords'를 이용한다는 것입니다. 리눅스의 auth/passwords 파일이 아니므로 경로 설정을 잘 해야합니다.
    • -e REGISTRY_HTTP_ADDR=0.0.0.0:443
      Docker 레지스트리가 모든 네트워크의 443 포트를 통해 접근할 수 있도록 합니다.
    • -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt
      Docker 레지스트리에서 사용할 TLS 인증서 파일의 경로를 지정합니다.
      마찬가지로 컨테이너의 /certs/domain.crt를 사용합니다. 리눅스의 domain.crt가 아닙니다.
    • -e REGISTRY_HTTP_TLS_Key=/certs/domain.key 
      Docker 레지스트리에서 사용할 TLS 키 파일의 경로를 지정합니다.
      역시 마찬가지로 컨테이너의 /certs/domain.key를 사용합니다.

    /home/yyk/에서 yyk는 제 리눅스 유저명입니다.

    혹시라도 따라하실 분이 계신다면, 자신의 사용자 홈 디렉터리로 변경해야합니다.

    echo $HOME 명령으로 확인하실 수 있습니다.


    4. PUSH, PULL 테스트

    이제 레지스트리에서 PUSH, PULL이 잘 동작하는지 확인하기 위해 간단한 Dockerfile 작성 후 빌드합니다.

    #Dockerfile
    FROM ubuntu:20.04
    RUN apt-get update && \
        apt-get install -y python
    docker build -t ubuntu_with_python .

     

    이미지를 푸시하려면 [레지스트리_주소]/[이미지_이름]:[태그] 규칙에 따라 태그를 붙여야 합니다.

    레지스트리 컨테이너를 443포트에서 실행했으므로 이때 레지스트리 주소는 localhost:443이 됩니다.

    #태그 붙이기
    docker tag ubuntu_with_python localhost:443/ubuntu_with_python:1
    
    #레지스트리에 푸시
    docker push localhost:443/ubuntu_with_python:1

     

    이제 레지스트리에 푸시하면 다음과 같이 no basic auth credentials 에러가 발생합니다.

    이는 도커 로그인 정보가 /auth/passwords 내에 있는 유저가 아니기 때문입니다.

     

    이제 localhost:443 레지스트리에 로그인하겠습니다.

    이때 유저명과 패스워드는 /auth/passwords에 입력했던 것들로 로그인합니다.

    제 경우 Username qwer, Password 1234입니다.

     

    참고: 만약 /auth/passwords에 없는 유저로 로그인하면 실패합니다.

    Username을 잘못 입력한 경우

     

    아무튼, 로그인에 성공했으니 localhost:443 레지스트리에 이미지를 푸시합니다.

    푸시 중
    푸시 성공 !!

     

    pull 명령 또한 정상적으로 수행됩니다.