이전 글에서 Ubuntu 서버에 Nexus를 구축하고 Gradle 연동까지 끝냈다. 이번엔 두 가지를 추가한다.
- 사내 도메인으로 HTTPS 접근
- 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 repository → docker (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 repository → docker (hosted).
항목 값
| Name | docker-hosted |
| Online | ✅ |
| HTTP | ✅ 포트 5001 |
| HTTPS | (해제) |
| Blob store | default |
| Deployment policy | Allow redeploy 또는 Disable redeploy |
2-3. docker-group 생성
Create repository → docker (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 처리하면 백엔드 서비스마다 인증서 관리할 필요가 없다. 새 서비스 추가 시 도메인 추가 + 프록시 룰 추가만으로 통합 가능.
'Infra' 카테고리의 다른 글
| Rocky Linux LVM 디스크 확장, 왜 명령을 4번 쳐야 할까 (0) | 2026.05.10 |
|---|---|
| 다중 브랜치 개발 환경에서 Flyway 교차 오염 막기 (0) | 2026.05.04 |
| Nexus Repository Manager 구축하기 (0) | 2026.04.25 |