본문 바로가기
Infra

Nexus Repository Manager에 HTTPS 적용하고 Docker Registry 추가하기

by Machine-Geon 2026. 4. 28.
반응형

이전 글에서 Ubuntu 서버에 Nexus를 구축하고 Gradle 연동까지 끝냈다. 이번엔 두 가지를 추가한다.

  1. 사내 도메인으로 HTTPS 접근
  2. Docker Registry 통합 운영

이전 글: Nexus Repository Manager 구축하기

환경

  • Nexus가 동작 중인 우분투 서버 (이전 글에서 구축한 상태)
  • 사내에 Nginx Proxy Manager(NPM)가 도커 컨테이너로 운영 중
  • 와일드카드 인증서(*.example.com)가 NPM에 발급되어 있음
  • AWS Route 53에서 도메인 관리

사전 이해: 트래픽 흐름

작업 들어가기 전에 트래픽이 어떻게 흐르는지 먼저 정리한다.

[클라이언트]
  ↓ https://nexus.example.com
  ↓ DNS 풀이: 공인 IP
  ↓ TCP 443
[라우터]
  ↓ 443 → NAS:10443 포트포워딩
[NAS의 NPM 컨테이너]
  ↓ TLS handshake, SNI 확인
  ↓ 와일드카드 인증서로 응답
  ↓ 도메인별 룰 매칭 → 백엔드로 프록시
  ↓ HTTP 평문 (사내망 내부)
[Nexus 서버:8081]

핵심은 SSL Termination이다. NPM이 외부와는 HTTPS로 통신하고 백엔드(Nexus)와는 평문 HTTP로 통신한다. 사내망 안이라 평문이어도 안전하다. Nexus 자체는 SSL을 신경 쓸 필요가 없다.
라우터는 도메인을 모른다. IP+포트만 보고 NAS로 전달한다. NPM이 처음으로 도메인을 인식하고 분기하는 구조다.

1. Nexus 웹 UI에 HTTPS 적용

작업은 두 단계.

1-1. Route 53에 도메인 추가

AWS Route 53 콘솔에서 호스팅 존에 레코드 생성.

레코드 이름: nexus
유형: CNAME
값: lab.example.com
TTL: 300

CNAME으로 기존 게이트웨이 도메인을 가리키게 하는 패턴.

1-2. NPM에 Proxy Host 추가

NPM 관리 페이지(http://nas.example.com:10081)에서 Add Proxy Host.
Details 탭:
항목 값

Domain Names nexus.example.com
Scheme http
Forward Hostname/IP <Nexus 서버 IP>
Forward Port 8081
Block Common Exploits ON
Websockets Support ON

SSL 탭:
항목 값

SSL Certificate *.example.com 와일드카드 선택
Force SSL ON
HTTP/2 Support ON
HSTS ON

저장하면 NPM이 자동으로 nginx 설정을 생성하고 reload한다. 인증서 갱신도 NPM이 관리.

1-3. 동작 확인

curl -I https://nexus.example.com

HTTP/2 200 또는 302 응답이 오면 정상. 브라우저로 접속하면 자물쇠 아이콘과 함께 Nexus 로그인 페이지가 보인다.

반응형

2. Nexus에 Docker Repository 생성

Docker Registry는 별도 포트가 필요하다. Nexus UI에서 세 개의 저장소를 만든다.
저장소 HTTP 포트 역할

docker-proxy (없음) Docker Hub 캐싱
docker-hosted 5001 사내 이미지 저장
docker-group 5000 proxy + hosted 통합

2-1. docker-proxy 생성

Nexus UI → Settings → Repository → Repositories → Create repositorydocker (proxy).
항목 값

Name docker-proxy
Online
Remote storage https://registry-1.docker.io
Docker Index Use Docker Hub
Blob store default

HTTP/HTTPS 체크박스는 모두 해제. proxy는 외부 포트가 필요 없다.

2-2. docker-hosted 생성

Create repositorydocker (hosted).
항목 값

Name docker-hosted
Online
HTTP ✅ 포트 5001
HTTPS (해제)
Blob store default
Deployment policy Allow redeploy 또는 Disable redeploy

2-3. docker-group 생성

Create repositorydocker (group).
항목 값

Name docker-group
Online
HTTP ✅ 포트 5000
HTTPS (해제)
Blob store default
Member repositories docker-hosted, docker-proxy 순서
Writable repository docker-hosted

순서가 중요하다. hosted를 위에 두면 같은 이미지명이 양쪽에 있을 때 hosted가 우선.

2-4. Realms 활성화

도커는 토큰 기반 인증을 사용한다. 별도 Realm 활성화 필요.
Nexus UI → Settings → Security → Realms.
Available 목록에서 Docker Bearer Token Realm을 찾아 우측 화살표로 Active 목록으로 이동. Save.
이게 없으면 docker login이 동작하지 않는다.

3. Docker Registry에 HTTPS 적용

Docker Registry도 별도 도메인을 만들어 NPM이 받게 한다. 같은 패턴이다.

3-1. 별도 도메인이 필요한 이유

Docker 클라이언트는 OCI Distribution Spec에 따라 도메인 루트의 /v2/ 경로로 통신한다.

GET https://registry.example.com/v2//manifests/

도메인 루트의 /v2/를 도커가 점유하므로, Nexus 웹 UI와 같은 도메인을 path로 분리해서 쓰면 충돌 위험이 있다. 별도 도메인을 두는 게 표준 패턴이다.

3-2. Route 53에 도메인 추가

레코드 이름: nexus-docker
유형: CNAME
값: lab.example.com

docker.example.com이 더 짧지만, Nexus 관련임을 명시하는 게 운영상 헷갈리지 않다.

3-3. NPM에 Proxy Host 추가

Details 탭:
항목 값

Domain Names nexus-docker.example.com
Scheme http
Forward Hostname/IP <Nexus 서버 IP>
Forward Port 5000 (docker-group)
Block Common Exploits ON
Websockets Support ON

5001(hosted)이 아닌 **5000(group)**으로 보내야 한다. group이 hosted와 proxy를 모두 포함하므로 pull/push 둘 다 처리 가능.
SSL 탭:
항목 값

SSL Certificate *.example.com 와일드카드
Force SSL ON
HTTP/2 Support ON
HSTS ON

저장 후 Online 상태가 되면 끝.

4. 클라이언트에서 사용

HTTPS이므로 insecure-registries 설정 불필요. 표준 도커 사용법 그대로.

4-1. 로그인

docker login nexus-docker.example.com

ID/비밀번호 입력. Login Succeeded 나오면 정상.

4-2. Pull 테스트

Docker Hub 이미지를 Nexus 통해 받기.

docker pull nexus-docker.example.com/library/alpine:latest

Docker Hub 공식 이미지는 library/ 접두사가 붙는다. 처음 받을 때는 외부에서 가져오느라 약간 느리고, 두 번째부터는 캐시에서 즉시.

4-3. Push 테스트

docker tag alpine:latest nexus-docker.example.com/test/alpine:1.0.0
docker push nexus-docker.example.com/test/alpine:1.0.0

4-4. Nexus UI에서 확인

https://nexus.example.com → Browse:

  • docker-proxy에 library/alpine 폴더 (pull 결과 캐싱)
  • docker-hosted에 test/alpine 폴더 (push 결과)

둘 다 보이면 정상 동작.

5. 서버 방화벽 설정

ufw로 정리. Nexus 서버는 NPM이 접근하면 되므로 도커 관련 포트도 외부 노출은 불필요하다.

# SSH
sudo ufw allow 22/tcp

# Nexus 포트들 (사내 NPM이 접근)
sudo ufw allow 8081/tcp
sudo ufw allow 5000/tcp
sudo ufw allow 5001/tcp

sudo ufw enable

이 포트들이 외부에 노출되는 건 아니다. 라우터에 5000/5001/8081 포트포워딩 룰이 없으므로 외부 인터넷에서는 도달할 수 없고, 사내망 NPM만 접근 가능.

6. 최종 구조

[사용자]
  │
  ├─ 웹 UI / Maven / npm  → https://nexus.example.com
  └─ Docker             → https://nexus-docker.example.com
                          ↓
                        [라우터: 443 → NAS:10443]
                          ↓
                        [NPM]
                          ├─ nexus.example.com → <서버>:8081
                          └─ nexus-docker.example.com → <서버>:5000
                                                          ↓
                                                  [Nexus 서버]
                                                    ├─ 8081 (웹 UI/Maven/npm)
                                                    └─ 5000 (docker-group)
                                                        ├─ docker-hosted (5001)
                                                        └─ docker-proxy

모든 외부 트래픽이 443으로 들어와 NPM이 SSL 처리하고 도메인별로 분기. Nexus 서버는 평문 HTTP만 동작하며 인증서 관리 부담 없음.

7. 사용자 가이드 작성 시 참고

팀에 공유할 때 안내할 핵심 정보.

Gradle/Maven/npm

URL: https://nexus.example.com
저장소: maven-public, npm-public 등
인증: 공용 계정

Docker

Registry: nexus-docker.example.com
로그인: docker login nexus-docker.example.com
Pull: docker pull nexus-docker.example.com/library/<image>
Push: docker push nexus-docker.example.com/<image>:<tag>

insecure-registries 설정 안내 불필요. HTTPS 표준이므로 클라이언트 추가 설정 없이 바로 사용 가능.

마치며

Nexus 같은 통합 저장소는 Java(Maven, Gradle), JavaScript(npm), Docker를 한 곳에서 관리할 수 있다. Docker는 OCI 스펙상 도메인 루트의 /v2/ 경로를 점유하므로 별도 포트가 필요하고, 이를 외부에 노출하려면 별도 도메인 + 리버스 프록시 패턴이 표준이다. 리버스 프록시 앞단에서 SSL Termination 처리하면 백엔드 서비스마다 인증서 관리할 필요가 없다. 새 서비스 추가 시 도메인 추가 + 프록시 룰 추가만으로 통합 가능.

반응형