Server

[Nexus] Nexus를 통한 Private Image Registry 구축

테런 2024. 6. 14. 13:34
Overview
  • Docker Image 저장소로 Docker Hub, Harbor, AWS ECR 등을 많이 사용합니다. 이 글에서는 Nexus를 통한 Private Image Registry 구축을 진행하도록 하겠습니다. HTTP에서는 사용이 다소 제한적이라서 무료 도메인과 Let's Encrypt를 통해서 HTTPS를 적용한 후에 진행하도록 하겠습니다. HTTP에서 진행하고자 한다면 insecure registries 설정을 확인해보시길 바랍니다.

 

Prerequisite
  • AWS EC2 (최소 t2.medium)

 

Docker 설치
[Docker] Ubuntu에 Docker 설치하기

 

Docker Compose 설치
[Docker] Ubuntu에 Docker Compose 설치하기

 

Nginx 설치 (Reverse Proxy)
// EC2에 접속
$ ssh -i {*-key.pem} ubuntu@{ip}

// Nginx 설치
$ sudo apt update
$ sudo apt install nginx

// 상태 확인 (active)
$ sudo systemctl status nginx

// 웹 브라우저로 접속해서 확인 > http://{Public IP}
// 아래 그림처럼 접속이 된다면 성공

// Default Page HTML
$ cat /var/www/html/index.nginx-debian.html

// Nginx 삭제
$ sudo apt-get remove --purge nginx nginx-full nginx-common

Nginx Default Page

 

Docker Image Size Limit 해제
$ sudo su -
$ vi /etc/nginx/nginx.conf
http {
    ...
    # disable any limits to avoid HTTP 413 for large image uploads
    client_max_body_size 0;
    ...
}

$ systemctl restart nginx

 

Free Wildcard DNS 서비스
개발을 진행하다보면 HTTPS 적용을 해야하는 상황이 많이 발생합니다. 개발 단계에서는 도메인이 없는 경우가 많아서 HTTP로만 진행하는 경우가 많습니다. HTTPS에서만 동작하는 것이 기본인 오픈소스들이 많고, 상용에서도 HTTPS가 필수적으로 적용되어야 하기 때문에 개발 단계에서도 HTTPS를 적용해서 진행하는 것이 효율적입니다.

HTTPS를 적용하기 위해서 전제 조건은 도메인이 있어야 합니다. 도메인을 구매할수도 있지만, 개발 환경에서는 Free Wildcard DNS 서비스를 통해서 무료 도메인으로 진행할 수 있습니다.
* Free Wildcard DNS 서비스
1. nip.io
2. sslip.io
와일드카드(Wildcard) 인증서란, 도메인(FQDN) 의 하위 서브 도메인 호스트에 대해서 무제한 적용할수 있는 SSL 인증서 타입입니다. 즉, 서브 도메인에 대해서는 무제한입니다. *.{Public IP}.nip.io

예를 들어, 웹 브라우저에서 아래처럼 입력한 후 접속해보시길 바랍니다.

abc.{Public IP}.nip.io
dev.{Public IP}.nip.io
dev.argocd.{Public IP}.nip.io
dev.gitlab.{Public IP}.nip.io

 

HTTPS 적용 (Let's Encrypt)
웹 서버와 도메인이 준비됐으니 HTTPS 적용하도록 하겠습니다.
// Certbot 설치
$ sudo su -
$ snap install --classic certbot
$ ln -s /snap/bin/certbot /usr/bin/certbot

// Key 생성
$ certbot --nginx -d {Public IP}.nip.io -d www.{Public IP}.nip.io

Saving debug log to /var/log/letsencrypt/letsencrypt.log
Enter email address (used for urgent renewal and security notices)
 (Enter 'c' to cancel): 이메일 입력
                                                                            
Please read the Terms of Service at
https://letsencrypt.org/documents/LE-SA-v1.4-April-3-2024.pdf. You must agree in
order to register with the ACME server. Do you agree?
(Y)es/(N)o: Y

Would you be willing, once your first certificate is successfully issued, to    
share your email address with the Electronic Frontier Foundation, a founding    
partner of the Let's Encrypt project and the non-profit organization that       
develops Certbot? We'd like to send you email about our work encrypting the web,
EFF news, campaigns, and ways to support digital freedom.
(Y)es/(N)o: Y
Account registered.
Requesting a certificate for {Public IP}.nip.io and www.{Public IP}.nip.io

Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/{Public IP}.nip.io/fullchain.pem
Key is saved at:         /etc/letsencrypt/live/{Public IP}.nip.io/privkey.pem
This certificate expires on 2024-09-10.
These files will be updated when the certificate renews.
Certbot has set up a scheduled task to automatically renew this certificate in the background.

Deploying certificate
Successfully deployed certificate for {Public IP}.nip.io to /etc/nginx/sites-enabled/default
Successfully deployed certificate for www.{Public IP}.nip.io to /etc/nginx/sites-enabled/default
Congratulations! You have successfully enabled HTTPS on https://{Public IP}.nip.io and https://www.{Public IP}.nip.io
We were unable to subscribe you the EFF mailing list because your e-mail address appears to be invalid. You can try again later by visiting https://act.eff.org.
 
// 인증서 확인
$ certbot certificates
Found the following certs:
  Certificate Name: {Public IP}.nip.io
    Serial Number: 32626a227986ca703a59194081d708c7e70
    Key Type: ECDSA
    Domains: {Public IP}.nip.io www.{Public IP}.nip.io
    Expiry Date: 2024-09-10 03:01:08+00:00 (VALID: 89 days)
    Certificate Path: /etc/letsencrypt/live/{Public IP}.nip.io/fullchain.pem
    Private Key Path: /etc/letsencrypt/live/{Public IP}.nip.io/privkey.pem
    
// 성공적으로 Key가 생성되었는지 확인
$ ls /etc/letsencrypt/live/{Public IP}.nip.io
README  cert.pem  chain.pem  fullchain.pem  privkey.pem

// Certbot이 자동으로 Nginx에 HTTPS 설정
$ cat /etc/nginx/sites-available/default

// 웹 브라우저에서 확인
https://{Public IP}.nip.io
https://www.{Public IP}.nip.io

 

Nexus 설치
* 참고 링크
https://hub.docker.com/r/sonatype/nexus3/
https://help.sonatype.com/en/sonatype-nexus-repository-system-requirements.html
// Nexus Volume 생성
$ docker volume create --name nexus-data

// 5000 포트는 Nexus Docker Registry
// 8081 포트는 Nexus UI
$ docker run -d -p 5000:5000 -p 8081:8081 --name nexus --ulimit nofile=65536:65536 -v nexus-data:/nexus-data sonatype/nexus3

$ docker ps
$ docker volume ls
$ docker volume inspect nexus-data

// Admin 계정 비밀번호
$ sudo cat {Mountpoint}/admin.password

 

Nexus HTTPS 적용 (Let's Encrypt)
$ sudo su -

// Nexus Docker Registry
$ certbot --nginx -d nexus-docker.{Public IP}.sslip.io

// Nexus UI
$ certbot --nginx -d nexus-ui.{Public IP}.sslip.io

// 성공적으로 Key가 생성되었는지 확인
$ ls /etc/letsencrypt/live/
// Certbot이 자동으로 Nginx에 HTTPS 설정
// Nginx를 Reverse Proxy로 사용할 것이니 경로를 수정해야 합니다.
// 아래와 같은 server 블록을 찾고, location 부분을 수정합니다.
$ vi /etc/nginx/sites-available/default

// Nexus Docker Registry
server {

        # SSL configuration
        #
        # listen 443 ssl default_server;
        # listen [::]:443 ssl default_server;
        #
        # Note: You should disable gzip for SSL traffic.
        # See: https://bugs.debian.org/773332
        #
        # Read up on ssl_ciphers to ensure a secure configuration.
        # See: https://bugs.debian.org/765782
        #
        # Self signed certs generated by the ssl-cert package
        # Don't use them in a production server!
        #
        # include snippets/snakeoil.conf;

        root /var/www/html;

        # Add index.php to the list if you are using PHP
        index index.html index.htm index.nginx-debian.html;
    server_name nexus-docker.{Public IP}.sslip.io; # managed by Certbot


        location / {
                proxy_set_header Host $host;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_set_header X-Forwarded-Proto $scheme;
                proxy_set_header Upgrade $http_upgrade;
                proxy_set_header Connection "upgrade";
                proxy_set_header X-Real-IP $remote_addr;
                proxy_pass http://localhost:5000; # Nexus Docker Registry
        }
        
        # pass PHP scripts to FastCGI server
        #
        #location ~ \.php$ {
        #       include snippets/fastcgi-php.conf;
        #
        #       # With php-fpm (or other unix sockets):
        #       fastcgi_pass unix:/run/php/php7.4-fpm.sock;
        #       # With php-cgi (or other tcp sockets):
        #       fastcgi_pass 127.0.0.1:9000;
        #}

        # deny access to .htaccess files, if Apache's document root
        # concurs with nginx's one
        #
        #location ~ /\.ht {
        #       deny all;
        #}


    listen [::]:443 ssl; # managed by Certbot
    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/3.34.225.130.nip.io/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/3.34.225.130.nip.io/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}

// Nexus UI
server {

        # SSL configuration
        #
        # listen 443 ssl default_server;
        # listen [::]:443 ssl default_server;
        #
        # Note: You should disable gzip for SSL traffic.
        # See: https://bugs.debian.org/773332
        #
        # Read up on ssl_ciphers to ensure a secure configuration.
        # See: https://bugs.debian.org/765782
        #
        # Self signed certs generated by the ssl-cert package
        # Don't use them in a production server!
        #
        # include snippets/snakeoil.conf;

        root /var/www/html;

        # Add index.php to the list if you are using PHP
        index index.html index.htm index.nginx-debian.html;
    server_name nexus-docker.{Public IP}.sslip.io; # managed by Certbot


        location / {
                proxy_set_header Host $host;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_set_header X-Forwarded-Proto $scheme;
                proxy_set_header Upgrade $http_upgrade;
                proxy_set_header Connection "upgrade";
                proxy_set_header X-Real-IP $remote_addr;
                proxy_pass http://localhost:8081; # Nexus UI
        }
        
        # pass PHP scripts to FastCGI server
        #
        #location ~ \.php$ {
        #       include snippets/fastcgi-php.conf;
        #
        #       # With php-fpm (or other unix sockets):
        #       fastcgi_pass unix:/run/php/php7.4-fpm.sock;
        #       # With php-cgi (or other tcp sockets):
        #       fastcgi_pass 127.0.0.1:9000;
        #}

        # deny access to .htaccess files, if Apache's document root
        # concurs with nginx's one
        #
        #location ~ /\.ht {
        #       deny all;
        #}


    listen [::]:443 ssl; # managed by Certbot
    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/3.34.225.130.nip.io/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/3.34.225.130.nip.io/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}

// Nginx 재실행
$ systemctl restart nginx

// 웹 브라우저에서 확인
https://nexus-ui.{Public IP}.sslip.io -> Nexus가 접속되면 성공

 

Nexus Admin 로그인 및 기본 정보 설정

위에서 확인한 비밀번호로 로그인
익명 사용자는 접근 불가하도록 설정

 

Nexus Image Registry 생성

상단 톱니바퀴 > 왼쪽 탭 'Blob Stores' > Create Blob Store

 

Create Blob Store

 

왼쪽 탭 'Repositories' > Create repository

 

docker (hosted) 선택

 

Nginx를 Reverse Proxy로 사용하고 있으므로 HTTP 체크

 

Nexus Image Registry > Docker Build & Push 테스트
// 테스트할 간단한 Spring Boot 코드
$ git clone https://github.com/hyunkwanko/demo.git

// Dockerfile 확인
$ cd demo

// Nexus Docker Registry 로그인
// Username과 Password는 Nexus 계정 입력
// Login Succeeded가 나와야 정상
$ docker login nexus-docker.{Public IP}.sslip.io -u admin
Password: 
WARNING! Your password will be stored unencrypted in /home/ubuntu/snap/docker/2915/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store

Login Succeeded

// Docker Build
// docker build -t nexus-docker.{Public IP}.sslip.io/{Registry Name}:{Tag} {Dockerfile Path}
$ docker build -t nexus-docker.{Public IP}.sslip.io/demo:0.0.1 .

// 생성된 이미지 확인
$ docker images
REPOSITORY                                 TAG       IMAGE ID       CREATED              SIZE
nexus-docker.{Public IP}.sslip.io/demo   0.0.1     ffd809fbf590   About a minute ago   336MB

// Docker Push
$ docker push nexus-docker.{Public IP}.sslip.io/demo:0.0.1
The push refers to repository [nexus-docker.{Public IP}.sslip.io/demo]
de2286461ce9: Pushed
5a8f0ac5756e: Pushed
db8dd125714b: Pushed
0321c6619a4f: Pushed
21fa11835a3c: Pushed
d4fc045c9e3a: Pushed
0.0.1: digest: sha256:94bd8aceaddd168592b83c0d6a98f02faea2da66e5d78ff1e2a2dff0bc814f72 size: 1579

상단 박스 > 왼쪽 탭 'Browse' > docker-registry

 

이미지 확인

 

Nexus Image Registry > Docker Pull 테스트
// Docker Image 리스트 확인
$ docker images
REPOSITORY                                 TAG       IMAGE ID       CREATED              SIZE
nexus-docker.{Public IP}.sslip.io/demo   0.0.1     ffd809fbf590   About a minute ago   336MB

// Image 삭제
$ docker rmi nexus-docker.{Public IP}.sslip.io/demo:0.0.1

// Docker Image 리스트 확인
$ docker images
REPOSITORY        TAG       IMAGE ID       CREATED      SIZE

// Docker Pull
$ docker pull nexus-docker.{Public IP}.sslip.io/demo:0.0.1

// Docker Image 리스트 확인
$ docker images
REPOSITORY                                TAG       IMAGE ID       CREATED       SIZE
nexus-docker.{Public IP}.sslip.io/demo   0.0.1     ffd809fbf590   2 hours ago   336MB

 

마무리
Nexus를 통한 Private Image Registry 구축을 완료했습니다.
다음 글에서 Kubernetes Cluster와 Gitea, ArgoCD, Nexus를 통한 CI/CD 구축을 진행해보도록 하겠습니다. 감사합니다.

'Server' 카테고리의 다른 글

[Ubuntu] USB 연결 및 파일 복사(백업)  (0) 2024.06.26
[Server] Nginx 리버스 프록시(Reverse Proxy) 개념 및 구축  (0) 2024.06.12
OAuth2.0이란?  (0) 2023.04.02
JWT(Json Web Token)란?  (0) 2023.04.01