Cloud

Private Docker Registry 구축 및 보안 강화

dog-pawwer 2025. 2. 17. 18:27
반응형

Private Docker Registry 구축 및 보안 강화

사설 Docker Registry를 구축하고, 보안성을 강화하여 안전한 이미지 저장소를 운영할 수 있도록 한다.

과제 설명

기업 내부에서 사용하는 Docker 이미지를 안전하게 관리하기 위해 Docker Private Registry를 구축하고, TLS(SSL) 인증 및 접근 제어를 적용하여 보안성을 높이는 실습을 진행한다.

활용 툴

  • Docker, Docker Compose
  • OpenSSL
  • htpasswd
  • GitLab CI/CD

1. Docker Private Registry 기본 구축*

  • registry:2 공식 이미지를 활용하여 로컬 Private Registry 컨테이너 실행
    • 볼륨 설정 : 이후에 설정을 변경하는 과정에서 여러번 Registry를 내리고 다시 올리기 때문에 볼륨 설정하여, Docker 레지스트리의 저장소 데이터를 영구적으로 유지
# Registry 데이터를 저장할 디렉터리 생성
mkdir -p ~/docker-registry/data

# Registry 컨테이너 실행
docker run -d \
  --name registry \
  -p 5000:5000 \
  -v ~/docker-registry/data:/var/lib/registry \
  --restart=always \
  registry:2

  • insecure-registries 설정 (daemon.json 수정)
    • Docker Daemon (자체 서명된 인증서를 사용하는 레지스트리 추가 설정)
sudo vi /etc/docker/daemon.json

# 아래처럼 변경
{
  "insecure-registries": ["192.168.1.8:5000"]
}
sudo systemctl restart docker
  • docker tag 및 docker push 명령어를 사용하여 이미지를 Private Registry에 업로드
    • 예시로 'BusyBox' 이미지 사용
    • (BusyBox는 리눅스 유틸리티를 하나의 실행 파일로 제공하는 경량화된 소프트웨어)
# BusyBox 이미지 다운로드
docker pull busybox

# 태그 변경 (Private Registry용)
docker tag busybox localhost:5000/busybox

# Private Registry로 Push
docker push localhost:5000/busybox

  • docker pull을 통해 저장된 이미지 정상 다운로드 확인
# 이미지를 로컬에서 삭제해도 Registry에 저장된 이미지를 다시 받을 수 있는지 pull 체크
docker rmi busybox
docker pull localhost:5000/busybox

2. Registry 보안 설정 (TLS/SSL 인증 적용)

  • OpenSSL을 사용하여 자체 서명된 SSL 인증서 생성
    • 참고 : 실습이기 때문에 localhost로 설정해놓았지만, 실제 환경에서는 FQDN을 사용하는 것이 좋다.
    • FQDN : 완전한 도메인 이름
mkdir -p ~/docker-registry/certs
cd ~/docker-registry/certs

# 자체 서명된 SSL 인증서 생성
openssl req -newkey rsa:4096 -nodes -sha256 -keyout registry.key -x509 -days 365 -out registry.crt \
-subj "/C=KR/ST=Seoul/L=Seoul/O=MyCompany/OU=IT Department/CN=localhost"
-----
Country Name (2 letter code) [AU]:KR
State or Province Name (full name) [Some-State]:Seoul
Locality Name (eg, city) []:Seoul
Organization Name (eg, company) [Internet Widgits Pty Ltd]:DockerTest
Organizational Unit Name (eg, section) []:IT Department
Common Name (e.g. server FQDN or YOUR name) []:localhost
Email Address []:test@email.com
  • 4096비트 RSA 개인키와 해당 키로 서명된, 1년(365일) 동안 유효한 자체 서명된 인증서를 각각 지정된 파일에 저장

  • 생성된 인증서 확인하기
# 생성된 인증서 확인
ls -l

  • 생성한 인증서를 Registry에 적용하여 HTTPS 기반 통신 구성
    • Docker Private Registry를 TLS(SSL) 인증서를 사용하여 보안된 상태로 실행
    • 실행 중인 registry 컨테이너를 중지 → SSL 포함[HTTPS]으로 다시 실행
docker stop registry
docker rm registry

docker run -d \
  --name registry \
  -p 5000:5000 \
  -v ~/docker-registry/data:/var/lib/registry \
  -v ~/docker-registry/certs:/certs \
  -e REGISTRY_HTTP_TLS_ADDR=0.0.0.0:5000 \
  -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/registry.crt \
  -e REGISTRY_HTTP_TLS_KEY=/certs/registry.key \
  --restart=always \
  registry:2

  • curl을 활용하여 TLS 적용 여부 확인
curl -k https://localhost:5000/v2/_catalog

3. 기본 인증(Basic Authentication) 설정

  • htpasswd를 사용하여 사용자 계정을 생성하고 인증 적용
sudo apt install apache2-utils -y

# 사용자 계정 생성 (예: admin)
mkdir -p ~/docker-registry/auth
htpasswd -Bc ~/docker-registry/auth/htpasswd admin

  • Registry 컨테이너에 기본 인증 적용
docker stop registry
docker rm registry

docker run -d \
  --name registry \
  -p 5000:5000 \
  -v ~/docker-registry/data:/var/lib/registry \
  -v ~/docker-registry/certs:/certs \
  -v ~/docker-registry/auth:/auth \
  -e REGISTRY_HTTP_TLS_ADDR=0.0.0.0:5000 \
  -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/registry.crt \
  -e REGISTRY_HTTP_TLS_KEY=/certs/registry.key \
  -e REGISTRY_AUTH=htpasswd \
  -e REGISTRY_AUTH_HTPASSWD_REALM="Registry Realm" \
  -e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd \
  --restart=always \
  registry:2
  • -e REGISTRY_AUTH=htpasswd : 방식으로 사용자 인증 적용
  • -e REGISTRY_AUTH_HTPASSWD_REALM="Registry Realm : 로그인 창에 표시되는 인증 영역의 이름
  • -e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd : htpasswd 파일 경로 지정

  • docker login 명령어를 활용하여 인증 확인
docker logout localhost:5000
docker login localhost:5000

  • 인증 없이 접근 시 차단되는지 테스트
    • 인증없이 접근시 "UNAUTHORIZED"가 뜬다.

4. Docker 이미지 서명 및 무결성 검증

Docker Content Trust (DCT) 활성화 및 서명된 이미지 푸시

  • DCT 개념 참고
  • DCT는 Notary를 사용하여 서명을 관리한다.
  • Notary Server 관련 Trouble Shooting
    • 계속해서 인증서 오류 발생 (TLS 인증서 만료)
      • TLS 인증서가 2023년 4월에 만료되어, 2025년 현재 시점에 접속할 때 인증서 검증에 실패

jinho@ubuntu:~/docker-registry$ # NTP 서비스 중지

sudo systemctl stop systemd-timesyncd

# 특정 시간까지 설정하고 싶다면

sudo date -s "2022-03-01 12:00:00"
2022. 03. 01. (화) 12:00:00 UTC
jinho@ubuntu:~/docker-registry$ date
2022. 03. 01. (화) 12:00:01 UTC
  • 실패

  • 결론) 지금 인증서에 문제가 있는 것 같음

Hi all, Doug Singer here -- DevSecOps Engineer for Modern Technology Solutions, INC.
In the process of doing some R&D for our dept, I was investigating this project. Ran into the x509 expiration issue and found this thread. Looks like this PR may resolve the issue we're having, so I will keep an eye on it. Thank you, all.

  • Private Registry를 사용할 경우 별도의 Notary 서버를 실행
cat << EOF > docker-compose.yml
version: '2'
services:
  notary-server:
    image: theupdateframework/notary-server:latest
    ports:
      - "4443:4443"
    environment:
      - NOTARY_SERVER_STORAGE_BACKEND=memory
    restart: always

  notary-signer:
    image: theupdateframework/notary-signer:latest
    environment:
      - NOTARY_SIGNER_STORAGE_BACKEND=memory
    restart: always
EOF
cat << EOF > config.yml
version: 0.1
storage:
  filesystem:
    rootdirectory: /var/lib/registry
http:
  addr: :4443
  headers:
    X-Content-Type-Options: [nosniff]
auth:
  token:
    realm: "https://auth.docker.io/token"
    service: "registry.docker.io"
    issuer: "auth.docker.io"
    rootcertbundle: /root/certs/auth.cert
EOF
  • alpine 이미지를 사용해서 DCT를 활성화하고 서명된 이미지를 푸시

  • 서명되지 않은 이미지 업로드 시도 및 차단 여부 확인
    • 실패
반응형