โ€ข
5 min read

๋‚˜๋งŒ์˜ Docker Registry ๊ตฌ์ถ•ํ•˜๊ธฐ

Table of Contents

์˜ค๋Š˜์€ ๊ณต์‹ ๋ฌธ์„œ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ Docker Registry๋ฅผ ๊ตฌ์„ฑํ•ด์„œ ์™ธ๋ถ€์—์„œ ์ ‘๊ทผ์ด ๊ฐ€๋Šฅํ•œ ๋‚˜๋งŒ์˜ Private Registry๋ฅผ ๋งŒ๋“ค์–ด๋ณด๋ ค ํ•œ๋‹ค.

Docker Registry๋ž€?

Registry๋Š” ์ปจํ…Œ์ด๋„ˆ ์ด๋ฏธ์ง€๋ฅผ ์ €์žฅํ•˜๊ธฐ ์œ„ํ•œ ์ €์žฅ์†Œ์ด๋‹ค. ์ด๋ฏธ์ง€๋ฅผ ์—…๋กœ๋“œ ์‹œํ‚ค๊ณ , ๋‹ค์šด๋กœ๋“œ ํ•ด์„œ ์‚ฌ์šฉํ•˜๊ณ  ํ•˜๋Š” ๋“ฑ์˜ ๋™์ž‘์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋„์™€์ค€๋‹ค. ๊ฐ€์žฅ ๋„๋ฆฌ ์•Œ๋ ค์ ธ ์žˆ๋Š” Registry๋กœ๋Š” Docker Hub๋ฅผ ๊ผฝ์„ ์ˆ˜ ์žˆ๋‹ค.

๊ทธ๋Ÿฌ๋ฉด Docker Hub ์“ฐ๋ฉด ๋˜์ž–์•„?

๋ฌผ๋ก  ๊ตณ์ด ๋‚˜๋งŒ์˜ Registry๋ฅผ ๊ตฌ์„ฑํ•˜์ง€ ์•Š๊ณ , Docker Hub๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์ด๋ฏธ์ง€๋ฅผ ์—…๋กœ๋“œํ•  ์ˆ˜๋„ ์žˆ๋‹ค. ํ•˜์ง€๋งŒ Docker Hub๋Š” ๋ฌด๋ฃŒ ๊ณ„์ •์— ํ•œํ•ด์„œ๋Š” Private Registry๋ฅผ ์ œ๊ณตํ•˜์ง€ ์•Š๊ณ , ๋ชจ๋“  ์ด๋ฏธ์ง€๊ฐ€ ๊ณต๊ฐœ๋œ๋‹ค. ๋‚ด๊ฐ€ ์ƒ๊ฐํ•˜๋Š” Private Registry๊ฐ€ ํ•„์š”ํ•œ ์ด์œ ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

์ƒ์šฉ ์„œ๋น„์Šค๋ผ๋ฉด

๋‹น์—ฐํžˆ ์ƒ์šฉ ์„œ๋น„์Šค์˜ ๊ฒฝ์šฐ ๋ฐฑ์—”๋“œ ์„œ๋ฒ„ ์‹คํ–‰ํŒŒ์ผ ๊ทธ ์ž์ฒด๋กœ ๋ณผ ์ˆ˜ ์žˆ๋Š” ์ด๋ฏธ์ง€๋ฅผ Publicํ•˜๊ฒŒ ๋…ธ์ถœํ•˜๊ณ  ์‹ถ์ง€ ์•Š์„ ๊ฒƒ์ด๋‹ค. ๋น„์ฆˆ๋‹ˆ์Šค๋ฅผ ๋‹ด๋‹นํ•˜๋Š” ์„œ๋ฒ„์˜ ์‹คํ–‰ ๊ฐ€๋Šฅ๋ณธ์„ ๋…ธ์ถœํ•˜๋Š” ๊ทธ ์ž์ฒด๊ฐ€ ๊ต‰์žฅํžˆ ๋ถ€๋‹ด์ด ๋  ๊ฒƒ์ด๋‹ค.

์‚ฌ์ด๋“œ ํ”„๋กœ์ ํŠธ๋ผ๋„

Docker ์ด๋ฏธ์ง€๋ฅผ ๋งŒ๋“ค์–ด์„œ ์ปจํ…Œ์ด๋„ˆ์— ์˜ฌ๋ฆฌ๊ณ  ์‹ถ๋‹ค๋Š” ๊ฒƒ์€ ์•„๋งˆ ๋ฐฐํฌ๋ฅผ ์—ผ๋‘์— ๋‘๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์ผ ๊ฐ€๋Šฅ์„ฑ์ด ๋†’๋‹ค. ๊ทธ๋Ÿฐ๋ฐ ์„œ๋ฒ„๋ฅผ ๋นŒ๋“œํ•ด์„œ ์ปจํ…Œ์ด๋„ˆ ์ด๋ฏธ์ง€๋กœ ๋งŒ๋“ ๋‹ค๋Š” ๊ฒƒ์€ ๋Œ€๋ถ€๋ถ„์˜ ํ™˜๊ฒฝ์—์„œ ๋™์ผํ•˜๊ฒŒ ๋™์ž‘ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜๋Š” ์˜๋„๊ฐ€ ํฌ๋‹ค. ์ฆ‰, ์„œ๋ฒ„์—์„œ DB์— ์ ‘์†ํ•˜๋Š” ์ •๋ณด๋‚˜, ๋‹ค๋ฅธ API ์„œ๋ฒ„๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•œ API Key ๋“ฑ์˜ ์ •๋ณด๊ฐ€ ์ปจํ…Œ์ด๋„ˆ ์ด๋ฏธ์ง€ ๋‚ด์— Raw ํ•˜๊ฒŒ ์ €์žฅ๋ผ ์žˆ์„ ๊ฐ€๋Šฅ์„ฑ์ด ๋†’๋‹ค๋Š” ๊ฒƒ์ด๋‹ค. ์ด๋Ÿฐ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด Hashicorp Vault๋‚˜ AWS Secrets Manager ์™€ ๊ฐ™์€ ์ˆ˜๋‹จ์„ ์‚ฌ์šฉํ•  ์ˆ˜๋„ ์žˆ๊ฒ ์ง€๋งŒ ์ด๋Ÿฐ ์†”๋ฃจ์…˜์— ๋Œ€ํ•œ ์ ‘๊ทผ ์—ญ์‹œ๋„ Key์— ์˜ํ•ด์„œ ๋Ÿฐํƒ€์ž„์— ์ˆ˜ํ–‰๋  ํ™•๋ฅ ์ด ๋†’๋‹ค. ์ฆ‰, ๋ฐฐํฌ๊ฐ€ ๊ฐ€๋Šฅํ•œ ์ด๋ฏธ์ง€๋ฅผ ๋…ธ์ถœํ•˜๋Š” ๊ฒƒ ์ž์ฒด๊ฐ€ ๊ต‰์žฅํžˆ ์œ„ํ—˜ํ•˜๋‹ค๋Š” ์˜๋ฏธ์ด๋‹ค. ๋”ฐ๋ผ์„œ ์ปจํ…Œ์ด๋„ˆ ์ด๋ฏธ์ง€ ์ž์ฒด๋ฅผ Publicํ•˜๊ฒŒ ๋…ธ์ถœํ•˜์ง€ ์•Š๋Š” ๊ฒƒ์ด ๊ฐ€์žฅ ๊ดœ์ฐฎ์€ ์„ ํƒ์ง€ ์ค‘ ํ•˜๋‚˜๊ฐ€ ๋  ์ˆ˜ ์žˆ๋‹ค.

๊ตฌ์„ฑ ๋ฐฉ๋ฒ•

์ด๋Ÿฐ Registry๋ฅผ ๊ตฌ์„ฑํ•˜๊ธฐ ์œ„ํ•ด ์˜์™ธ๋กœ ๋‹ค์–‘ํ•œ ์†”๋ฃจ์…˜์ด ์กด์žฌํ•œ๋‹ค. ์ถฉ๋ถ„ํ•œ ์ปดํ“จํŒ… ํŒŒ์›Œ๋ฅผ ํ™•๋ณดํ•  ์ˆ˜ ์žˆ๋‹ค๋ฉด, Harbor์™€ ๊ฐ™์€ ์†”๋ฃจ์…˜์„ ๋„์ž…ํ•˜๋Š” ๊ฒƒ์„ ๊ณ ๋ คํ•ด๋ณผ๋งŒ ํ•˜๋‹ค. Web UI๋ฅผ ์ œ๊ณตํ•ด์ฃผ๊ธฐ ๋•Œ๋ฌธ์— ์‚ฌ์šฉ์„ฑ์ด ๊ต‰์žฅํžˆ ์ข‹์•„์ง€๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ๋‚˜์˜ ๊ฒฝ์šฐ ์ž‘๊ณ  ๊ท€์—ฌ์šด M1 Mac Mini์— ๊ฐœ๋ฐœ ์„œ๋ฒ„๋ฅผ ๋„์›Œ๋‘๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์—, ๊ฐ€๋ณ๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก Docker์—์„œ ์ œ๊ณตํ•˜๋Š” ๊ณต์‹ ์ด๋ฏธ์ง€๋ฅผ ์‚ฌ์šฉํ•˜๋„๋ก ํ•˜๊ฒ ๋‹ค. ๊ณต์‹ ๋ฌธ์„œ๋ฅผ ์ฐธ๊ณ ํ•˜๋ฉด, ์•„๋งˆ ๋กœ์ปฌ ํ™˜๊ฒฝ์—์„œ ๋ฐ”๋กœ ๋„์›Œ๋ณด๋Š” ๊ฒƒ์€ ๋ฌด๋ฆฌ๊ฐ€ ์—†์„ ๊ฒƒ์ด๋‹ค. ๊ทธ๋Ÿฐ๋ฐ ๋‚˜์˜ ๊ฒฝ์šฐ Docker Compose๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ nginx, ์ธ์ฆ API, ๊ณ„์ • API, MySQL, Postgres, Grafana ๋“ฑ๋“ฑ ๋งŽ์€ ์„œ๋น„์Šค๋“ค์„ ๋„์›Œ ๊ด€๋ฆฌํ•˜๊ณ  ์žˆ๋‹ค. ๋”ฐ๋ผ์„œ Docker Compose๋ฅผ ํ†ตํ•ด ๊ตฌ์„ฑ์„ ์ง„ํ–‰ํ•ด๋ณด๊ฒ ๋‹ค.

Docker Compose ์„ค์ • ์˜ˆ์‹œ

version: "3.8"

services:
  registry:
    restart: always
    image: registry:2
    ports:
      - 5005:5000
    environment:
      REGISTRY_HTTP_TLS_CERTIFICATE: /etc/letsencrypt/live/your.domain.here/fullchain.pem
      REGISTRY_HTTP_TLS_KEY: /etc/letsencrypt/live/your.domain.here/privkey.pem
      REGISTRY_AUTH: htpasswd
      REGISTRY_AUTH_HTPASSWD_PATH: /auth/htpasswd
      REGISTRY_AUTH_HTPASSWD_REALM: Registry Realm
    volumes:
      - /your-letsencrypt-dir-here/conf:/etc/letsencrypt
      - /your-registry-volume-dir-here/data:/var/lib/registry
      - /your-registry-volume-dir-here/auth:/auth
  • ํ•ด๋‹น Compose ํŒŒ์ผ์€ ๊ณต์‹ ๋ฌธ์„œ์˜ ์ด ๋ถ€๋ถ„๊ณผ ๊ฑฐ์˜ ์œ ์‚ฌํ•˜๋‹ค.
  • ์ผ๋‹จ registry ์ปจํ…Œ์ด๋„ˆ์˜ inbound port๋Š” 5000์œผ๋กœ ์„ค์ •๋ผ ์žˆ๋‹ค.
  • ์ฃผ์š”ํ•˜๊ฒŒ ๋ด์•ผ ํ•  ๋ถ€๋ถ„์€ environment ๋ถ€๋ถ„์ด๋‹ค.
  • ์•„๋ž˜์— ๋ถ€๊ฐ€์ ์ธ ๋‚ด์šฉ๋“ค๊ณผ ํ•จ๊ป˜ ํ•ด๋‹น ์„ค์ •์„ ๋œฏ์–ด๋ณด์ž.

์™ธ๋ถ€์—์„œ ์ ‘๊ทผ ๊ฐ€๋Šฅํ•œ Registry ๋งŒ๋“ค๊ธฐ

  • ๊ณต์‹ ๋ฌธ์„œ์—์„œ ์ด ๋ถ€๋ถ„์„ ์ฐธ๊ณ ํ–ˆ๋‹ค.
  • ๊ณต์‹ ๋ฌธ์„œ์— ๋”ฐ๋ฅด๋ฉด, ๋จผ์ € Registry๋ฅผ TLS๋กœ ๋ณดํ˜ธํ•ด์•ผ ํ•œ๋‹ค๊ณ  ํ•œ๋‹ค.
  • ์ฆ‰, HTTPS๋ฅผ ์œ„ํ•œ ํ‚ค๊ฐ€ ํ•„์š”ํ•˜๋‹ค๋Š” ๋œป์ด๋‹ค.
  • ๊ณต์‹ ๋ฌธ์„œ์—์„œ๋Š” crt์™€ key ํŒŒ์ผ์„ ์‚ฌ์šฉํ–ˆ์ง€๋งŒ, ๋‚˜์˜ ๊ฒฝ์šฐ Certbot์„ ์ด์šฉํ•˜์—ฌ API ์„œ๋ฒ„๋‚˜ Grafana ๋“ฑ์˜ ์ธ์ฆ์„œ๋ฅผ ๋งŒ๋“ค์–ด ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์—ˆ๊ธฐ ๋•Œ๋ฌธ์—, registry๋ฅผ ์œ„ํ•œ Certbot ์ธ์ฆ์„œ๋ฅผ ์ƒ์„ฑํ•ด์ฃผ์—ˆ๋‹ค.
    • ์ƒ์„ฑ์— ์‚ฌ์šฉํ•œ ๋ช…๋ น์–ด๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.
certbot certonly --webroot --email myemail@gmail.com \
--agree-tos --config-dir /your-letsencrypt-dir-here/conf \
--logs-dir /your-letsencrypt-dir-here/log \
--work-dir /your-letsencrypt-dir-here/work \
-d registry.mydomain.com
  • ๊ทธ๋ฆฌ๊ณ  Compose ํŒŒ์ผ์— REGISTRY_HTTP_TLS_CERTIFICATE, REGISTRY_HTTP_TLS_KEY ์„ค์ •์„ ์žก์•„์ฃผ์—ˆ๋‹ค.
    • ์ฐธ๊ณ ๋กœ, ํ•ด๋‹น environment๋Š” ์ปจํ…Œ์ด๋„ˆ ์•ˆ์—์„œ ์‚ฌ์šฉํ•  ๊ฒฝ๋กœ๋ฅผ ์žก๋Š” ๋ถ€๋ถ„์ด๋‹ค. ๋”ฐ๋ผ์„œ, volumes ์„ค์ •์„ ํ†ตํ•ด์„œ ์ ์ ˆํ•˜๊ฒŒ ํ˜ธ์ŠคํŠธ ๋จธ์‹ ์˜ ๋””๋ ‰ํ† ๋ฆฌ์™€ ์ปจํ…Œ์ด๋„ˆ ์•ˆ์˜ ๋””๋ ‰ํ† ๋ฆฌ๋ฅผ ๋งคํ•‘์‹œ์ผœ์ค˜์•ผ ํ•œ๋‹ค.

์™ธ๋ถ€ ์ ‘๊ทผ ์ธ์ฆ ์„ค์ •ํ•˜๊ธฐ

  • ๊ณต์‹ ๋ฌธ์„œ์—์„œ ์ด ๋ถ€๋ถ„์„ ์ฐธ๊ณ ํ–ˆ๋‹ค.
  • ์ฐธ๊ณ ๋กœ, TLS๋กœ ๋ณดํ˜ธํ•˜์ง€ ์•Š์œผ๋ฉด ์ธ์ฆ ๊ด€๋ จ ์„ค์ •์„ ํ•  ์ˆ˜ ์—†๋‹ค. ๋”ฐ๋ผ์„œ ์ธ์ฆ์„œ ๊ด€๋ จ ์ดํ•ด๋ฅผ ๊ฐ„๋‹จํ•˜๊ฒŒ๋ผ๋„ ์ˆ™์ง€ํ•˜๋Š” ํŽธ์ด ๋‚˜์„ ๊ฒƒ์ด๋‹ค.
  • ์ธ์ฆ์— ๊ฐ€์žฅ ๊ฐ„๋‹จํ•˜๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์€ Basic Auth๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด๋‹ค.
    • HTTP Basic Auth์™€ ๋น„์Šทํ•˜๊ฒŒ ๊ตฌํ˜„๋˜์–ด ์žˆ๋Š” ๋“ฏ ํ•˜๋‹ค.
  • ๋‚˜๋Š” ์˜ˆ์ œ๋Œ€๋กœ htpasswd ๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์ธ์ฆ์„ ์„ค์ •ํ–ˆ๋‹ค.
  • ์ฐธ๊ณ ๋กœ, htpasswd ๋ฐฉ๋ฒ•์„ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ID / PW ์Œ์„ ๋งŒ๋“ค์–ด์ค˜์•ผ ํ•œ๋‹ค.
    • ์ƒ์„ฑ์— ์‚ฌ์šฉํ•œ ๋ช…๋ น์–ด๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.
htpasswd -c ./htpasswd yourid
  • ๊ทธ๋ฆฌ๊ณ  ์ƒ์„ฑํ•œ htpasswd ํŒŒ์ผ์„ Compose ํŒŒ์ผ์˜ volumes ์„ค์ •์„ ํ™œ์šฉํ•˜์—ฌ ์ปจํ…Œ์ด๋„ˆ ์•ˆ์œผ๋กœ ๋ฐ€์–ด๋„ฃ์–ด์ฃผ๋ฉด ๋œ๋‹ค.
  • ์ธ์ฆ์— ํ•„์š”ํ•œ ํŒŒ์ผ์„ ๋ฐ€์–ด๋„ฃ์—ˆ์œผ๋‹ˆ, ์ด์ œ Compose ํŒŒ์ผ์˜ environment ์„ค์ •์„ ํ†ตํ•ด htpasswd ๋ฅผ ์‚ฌ์šฉํ•˜๋„๋ก ํ•˜๋ฉด ๋œ๋‹ค.
    • ์š” ์ค‘์—์„œ REGISTRY_AUTH_HTPASSWD_REALM ์ด๋ผ๋Š” ์‹ ๊ธฐํ•œ ์„ค์ •์ด ์žˆ๋Š”๋ฐ, Registry Realm ์œผ๋กœ ์„ค์ •ํ•˜๋ฉด, Registry ์˜์—ญ์— ๋Œ€ํ•ด ์ ‘๊ทผํ•˜๋Š” ๊ฒƒ์— ๋Œ€ํ•œ ์ž๋™ ๋กœ๊ทธ์ธ ์„ค์ •๊ฐ™์€ ๊ฒƒ์œผ๋กœ ๋ณด๋ฉด ๋œ๋‹ค.

์™„๋ฃŒ

์ƒ๊ฐ๋ณด๋‹ค ์–ด๋ ค์šด ๋ถ€๋ถ„ ์—†์ด ์„ค์ •์„ ์™„๋ฃŒํ•  ์ˆ˜ ์žˆ์—ˆ๋‹ค. ์ด์ œ Docker Compose๋ฅผ ํ†ตํ•ด ์ปจํ…Œ์ด๋„ˆ๋ฅผ ๋„์›Œ์ฃผ๋ฉด, ๋‚˜๋งŒ์˜ Private Registry๋ฅผ ๊ตฌ์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค. Registry๊ฐ€ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ๋–ด๋Š”์ง€ ํ™•์ธํ•˜๊ณ  ์‹ถ์œผ๋ฉด, https://registry.yourdomain.com:{port}/v2๋กœ ์ ‘๊ทผํ•ด๋ณด์ž. ์•„๋งˆ HTTP Basic Auth ๋กœ๊ทธ์ธ ์ฐฝ์ด ๋ฐ˜๊ฒจ์ค„ ๊ฒƒ์ด๋‹ค. nginx๋ฅผ Registry ์•ž๋‹จ์— ๋ถ™์—ฌ๋†“๊ณ  ์‚ฌ์šฉํ•  ์ˆ˜๋„ ์žˆ๋Š”๋ฐ, ๊ทธ๋Ÿฌ๋ฉด ์ปจํ…Œ์ด๋„ˆ ์ด๋ฏธ์ง€์˜ ์‚ฌ์ด์ฆˆ์— ๋”ฐ๋ผ ๋˜ nginx ์„ค์ •์„ ๋งŒ์ ธ์•ผ ํ•˜๋Š” ์ค‘๋ณต ๊ด€๋ฆฌ๊ฐ€ ๋“ค์–ด๊ฐˆ ๊ฒƒ ๊ฐ™์•„ ์ผ๋‹จ์€ Registry๋Š” nginx๋ฅผ ๊ฑฐ์น˜์ง€ ์•Š๊ฒŒ ๋„์›Œ๋’€๋‹ค. ๋‚ด ๊ฒฝ์šฐ GitHub Actions๋ฅผ ํ†ตํ•ด ์š” ์ปจํ…Œ์ด๋„ˆ๋กœ ์ด๋ฏธ์ง€๋ฅผ ์—…๋กœ๋“œํ•ด์„œ Mac Mini๋กœ API ๊ฐœ๋ฐœ ์„œ๋ฒ„๋ฅผ ์„œ๋น™ํ•˜๋„๋ก ์„ค์ •ํ•ด์„œ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋‹ค.

๋.