본문 바로가기
AI Journey/클라우드

[Docker] Private Registry 구축 및 이미지 배포 워크플로우

by 보눔비스타 2026. 1. 7.

도커를 사용하다 보면 Docker Hub와 같은 퍼블릭 레지스트리가 아닌, 사내망이나 개인 환경에서만 접근 가능한 Private Registry(사설 저장소)가 필요한 수 있다.

보안상의 이유나 네트워크 대역폭 절약, 혹은 배포 속도 향상을 위해서다.

 

이번에는 공식 registry 이미지를 사용하여 로컬 환경에 사설 저장소를 구축하고, 서로 다른 두 개의 호스트간에 이미지를 푸시(Push)하고 풀(Pull)하는 전체 과정을 알아본다.

특히 SSL 인증서 없이 HTTP로 통신할 때 발생하는 문제와 이를 해결하기 위한 데몬 설정(daemon.json)에 대해서도 알아보자.

1. Private Registry 컨테이너 구동

가장 먼저 할 일은 이미지를 저장할 레지스트리 서버를 띄우는 것이다.

도커는 공식적으로 레지스트리 기능을 수행하는 이미지를 제공하므로, 이를 컨테이너로 실행하는 것만으로 간단히 구축할 수 있다.

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

 

  • -p 5000:5000: 레지스트리 서비스의 기본 포트는 5000번이다. 호스트의 5000번 포트와 컨테이너의 5000번 포트를 바인딩하여 외부에서 접근 가능하게 한다.
  • --restart=always: 도커 데몬이 재시작되거나 컨테이너가 예기치 않게 종료되었을 때 자동으로 재시작하도록 설정한다. 레지스트리는 인프라 성격의 서비스이므로 가용성이 중요하기 때문이다.
  • registry:2.6: 사용할 이미지와 태그 버전을 명시한다.

상태 확인

컨테이너가 정상적으로 떴는지 확인하고, 레지스트리 API가 응답하는지 테스트한다.

# 컨테이너 상태 확인
docker ps

# 레지스트리 API 응답 확인 (브라우저 또는 curl)
firefox http://localhost:5000/v2

 

브라우저나 curl로 http://localhost:5000/v2에 접속했을 때 빈 JSON 객체 {} 또는 버전 정보가 포함된 헤더가 반환된다면 레지스트리 서버가 정상적으로 동작하고 있는 것이다.

**참고로 /v2는 Docker Registry API의 버전 2 (Version 2)를 의미.

빈 JSON 객체 {}

 

버전 정보가 포함된 헤더

 

도커 클라이언트(브라우저)가 레지스트리에 접근할 때 가장 먼저 수행하는 Handshake 과정

2. 이미지 준비 및 태깅 (Tagging)

레지스트리에 올릴 샘플 이미지를 준비한다.

여기서는 가벼운 hello-world 이미지를 사용한다.

중요한 점은 이미지의 태그(Tag) 규칙이다.

도커는 docker push 명령을 수행할 때, 이미지 이름의 앞부분(Prefix)을 보고 어느 레지스트리로 보낼지 결정한다.

 

# 1. 샘플 이미지 다운로드
docker run hello-world

# 2. 이미지 확인
docker images

# 3. Private Registry용 태그 생성
# 형식: docker tag [원본이미지] [IP주소:포트]/[이미지명]:[버전]
docker tag hello-world:latest 123.456.100.789:5000/hello-world:0.0

# 4. 태깅 결과 확인
docker images

 

동작 원리

도커 허브(Docker Hub)에 올릴 때는 계정명이 앞에 붙지만,

사설 레지스트리에 올릴 때는 레지스트리의 주소(IP 또는 도메인)와 포트가 이미지 이름의 접두어로 붙어야 한다.

docker tag 명령은 원본 이미지를 복사하는 것이 아니라, 동일한 Image ID를 가리키는 새로운 alias를 생성하는 것이다.

따라서 docker images로 확인했을 때 IMAGE ID가 동일함을 알 수 있다.

 

이미지 태깅과 푸시의 흐름

 

3. insecure-registries 설정 (feat. 트러블슈팅)

도커 클라이언트는 기본적으로 레지스트리와 통신할 때 HTTPS(TLS)를 사용하도록 강제되어 있다.

우리가 구축한 레지스트리는 별도의 인증서 설정 없이 HTTP로 통신하기 때문에, 그냥 푸시를 시도하면 다음과 같은 에러가 발생한다.

http: server gave HTTP response to HTTPS client

 

이를 해결하기 위해 도커 데몬 설정 파일인 daemon.json을 수정하여 해당 사설 레지스트리를 '신뢰할 수 없는(insecure) 레지스트리' 목록에 추가해야 한다.

 

# 1. 설정 파일 편집
nano /etc/docker/daemon.json

# 2. 다음 내용 추가 (JSON 문법 주의)
{
  "exec-opts" : ["native.cgroupdriver=systemd"],
  "log-driver" : "json-file",
  "log-opts" : {"max-size" : "100m"},
  "storage-driver" : "overlay2",
  "insecure-registries" : ["123.456.100.789:5000"]
}

# 3. 도커 데몬 재시작 (설정 적용)
systemctl restart docker

 

설정 변경 후에는 반드시 systemctl restart docker로 데몬을 재시작해야 적용된다.

 

4. 이미지 푸시 (Push) 및 풀 (Pull) 테스트

메인 노드인 Ubuntu 머신에서 이미지를 푸시하고, 다른 노드(ex. Kali 머신, etc..)에서 해당 이미지를 받아오는 과정을 수행한다.

4-1. 이미지 푸시 (Ubuntu machine -> Registry)

docker push 123.456.100.789:5000/hello-world:0.0

The push refers to repository... 메시지와 함께 해시값이 출력되면 성공적으로 업로드된 것이다.

 

4-2. 이미지 풀 (Registry -> Kali machine)

이제 다른 머신(ex. Kali Linux)으로 이동하여 레지스트리에 있는 이미지를 다운로드 받는다.

중요한 점은 이미지를 받는 클라이언트 쪽에서도 insecure-registries 설정이 되어 있어야 한다는 것이다.

 

Kali 노드 설정 및 실행

# 1. Kali 노드에서도 daemon.json 설정
nano /etc/docker/daemon.json

{
 "insecure-registries" : ["123.456.100.789:5000"]
}

# 2. 도커 재시작
systemctl restart docker

# 3. 이미지 다운로드 (Pull)
docker pull 123.456.100.789:5000/hello-world:0.0

# 4. 다운로드 확인
docker images

 

 

전체 아키텍처 및 데이터 흐름