Deploy

🐳 Dockerfile vs Helm values ν™˜κ²½ λ³€μˆ˜ 관리

vividswan 2025. 3. 8. 15:55

배포 ν™˜κ²½ λ³€μˆ˜, μ–΄λ–»κ²Œ κ΄€λ¦¬ν•˜λŠ” 게 μ’‹μ„κΉŒ?

μž‘λ…„μ— μ§„ν–‰ν•œ ν”„λ‘œμ νŠΈμ—μ„œ μΏ λ²„λ„€ν‹°μŠ€ 기반의 사내 배포 νˆ΄μ„ ν™œμš©ν•΄ 개발, μŠ€ν…Œμ΄μ§•, 운영 ν™˜κ²½μ„ κ΅¬μΆ•ν•˜κ²Œ λ˜μ—ˆλ‹€. 그런데 배포 ν™˜κ²½λ³„λ‘œ ν™˜κ²½ λ³€μˆ˜λ₯Ό μ–΄λ–»κ²Œ 효율적으둜 관리할지 고민이 생겼닀.

μ™œ 이 문제λ₯Ό κ³ λ―Όν–ˆμ„κΉŒ?
κΈ°μ‘΄ λ°©μ‹μ—μ„œλŠ” 사내 배포 νˆ΄μ—μ„œ 직접 Docker에 ν™˜κ²½ λ³€μˆ˜λ₯Ό μž…λ ₯ν•΄μ•Ό ν–ˆλ‹€. μ΄λ ‡κ²Œ ν•˜λ©΄ 운영 ν™˜κ²½κ³Ό 개발 ν™˜κ²½μ„ 뢄리할 μˆ˜λŠ” μžˆμ§€λ§Œ, λ¬Έμ œλŠ” μ½”λ“œμƒμ—μ„œ μ–΄λ–€ ν™˜κ²½μ΄ μ μš©λ˜λŠ”μ§€ 확인할 수 μ—†λ‹€λŠ” μ μ΄μ—ˆλ‹€. 배포 섀정이 사내 툴 λ‚΄λΆ€μ—μ„œλ§Œ κ΄€λ¦¬λ˜λ‹€ λ³΄λ‹ˆ, μ½”λ“œλ§Œ λ΄μ„œλŠ” μ–΄λ–€ ν™˜κ²½μ—μ„œ μ‹€ν–‰λ˜λŠ”μ§€ μ•ŒκΈ° μ–΄λ €μ› λ‹€.

κ·Έλž˜μ„œ ν™˜κ²½ λ³€μˆ˜λ₯Ό μ½”λ“œμ—μ„œλ„ λͺ…ν™•νžˆ 확인할 수 μžˆμœΌλ©΄μ„œλ„, 관리가 더 νŽΈλ¦¬ν•œ 방법을 찾기둜 ν–ˆλ‹€. μ²˜μŒμ—λŠ” Dockerfileμ—μ„œ ν™˜κ²½μ„ μ„€μ •ν•˜λŠ” 방식을 κ³ λ €ν–ˆμ§€λ§Œ, 운영 ν™˜κ²½μ΄ μ»€μ§€λ©΄μ„œ 이 방식이 κ³Όμ—° μ΅œμ„ μΈμ§€ 의문이 λ“€μ—ˆλ‹€. μ—¬λŸ¬ κ°€μ§€ μ‹œλ„λ₯Ό 거친 끝에, μ΅œμ’…μ μœΌλ‘œ Helm의 values.yaml을 ν™œμš©ν•˜λŠ” λ°©μ‹μœΌλ‘œ μ „ν™˜ν•˜κ²Œ λ˜μ—ˆλ‹€.

이 κΈ€μ—μ„œλŠ” 처음 μ‚¬μš©ν–ˆλ˜ Dockerfile 기반 ν™˜κ²½ λ³€μˆ˜ 관리 방식과 Helm을 ν™œμš©ν•œ λ°©μ‹μ˜ 차이점, 그리고 μ΅œμ’…μ μœΌλ‘œ Helm을 μ„ νƒν•œ 이유λ₯Ό 정리해보렀고 ν•œλ‹€.


κΈ°μ‘΄ 방식: Dockerfileμ—μ„œ ARG와 ENVλ₯Ό ν™œμš©ν•œ ν™˜κ²½ μ„€μ •

μ²˜μŒμ—λŠ” Dockerfileμ—μ„œ ARG와 ENVλ₯Ό ν™œμš©ν•΄μ„œ 배포 ν™˜κ²½μ„ κ΅¬λΆ„ν•˜λŠ” λ°©μ‹μœΌλ‘œ 섀정을 μ§„ν–‰ν–ˆλ‹€. λΉŒλ“œ μ‹œμ μ—μ„œ ν™˜κ²½ λ³€μˆ˜λ₯Ό λ°›μ•„ ENVIRONMENT 값을 μ„€μ •ν•˜κ³ , 이λ₯Ό λŸ°νƒ€μž„μ—μ„œλ„ ν™œμš©ν•  수 μžˆλ„λ‘ κ΅¬μ„±ν•˜λŠ” 방식이닀.

κΈ°μ‘΄ λ°©μ‹μ˜ Dockerfile μ˜ˆμ‹œ

FROM openjdk:11

# λΉŒλ“œ μ‹œ ν™˜κ²½ λ³€μˆ˜λ₯Ό μ„€μ • (κΈ°λ³Έκ°’: dev)
ARG SPRING_PROFILES_ACTIVE=dev
ENV SPRING_PROFILES_ACTIVE=${SPRING_PROFILES_ACTIVE}

WORKDIR /app
COPY . .

CMD ["java", "-jar", "app.jar"]

 

πŸ” 이 μ½”λ“œμ˜ μ—­ν• 

이 Dockerfile은 Python μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ„ μ‹€ν–‰ν•˜λŠ” μ»¨ν…Œμ΄λ„ˆ 이미지λ₯Ό λΉŒλ“œν•˜λŠ” μš©λ„λ‘œ μž‘μ„±λ˜μ—ˆλ‹€.

  • ARG ENVIRONMENT=development: λΉŒλ“œ μ‹œμ μ— ν™˜κ²½ λ³€μˆ˜λ₯Ό 받을 수 μžˆλ„λ‘ μ„€μ •ν•˜λ©°, 기본값은 development둜 μ„€μ •λ˜μ–΄ 있음
  • ENV ENVIRONMENT=${ENVIRONMENT}: ARG둜 받은 값을 μ»¨ν…Œμ΄λ„ˆ λ‚΄λΆ€ ν™˜κ²½ λ³€μˆ˜λ‘œ μ €μž₯ν•΄ λŸ°νƒ€μž„μ—μ„œλ„ μ‚¬μš©ν•  수 μžˆλ„λ‘ μ„€μ •
  • WORKDIR /app: μ»¨ν…Œμ΄λ„ˆ λ‚΄λΆ€μ—μ„œ μž‘μ—… 디렉토리λ₯Ό /app으둜 μ„€μ •
  • COPY . .: ν˜„μž¬ λ””λ ‰ν† λ¦¬μ˜ λͺ¨λ“  νŒŒμΌμ„ μ»¨ν…Œμ΄λ„ˆμ˜ /app 디렉토리에 볡사
  • CMD ["python", "app.py"]: μ»¨ν…Œμ΄λ„ˆκ°€ 싀행될 λ•Œ python app.pyλ₯Ό μ‹€ν–‰ν•˜λ„λ‘ μ„€μ •

μ΄λ ‡κ²Œ ν•˜λ©΄ Docker 이미지λ₯Ό λΉŒλ“œν•  λ•Œ --build-arg ENVIRONMENT=production 같은 μ˜΅μ…˜μ΄λ‚˜ μ‚¬λ‚΄νˆ΄μ— νŒŒλΌλ―Έν„°λ₯Ό λ„£μ–΄μ„œ 운영 ν™˜κ²½κ³Ό 개발 ν™˜κ²½μ„ ꡬ뢄할 수 μžˆλ‹€. 기본값은 development둜 μ„€μ •ν•΄ λ‘μ—ˆκΈ° λ•Œλ¬Έμ— 별닀λ₯Έ μ„€μ • 없이도 개발 ν™˜κ²½μ—μ„œ λ™μž‘ν•˜λ„λ‘ ν–ˆλ‹€.

이 방식은 배포 ν™˜κ²½μ„ ꡬ뢄할 수 μžˆλŠ” μœ μš©ν•œ λ°©λ²•μ΄μ§€λ§Œ, λͺ‡ κ°€μ§€ λΆˆνŽΈν•œ 점이 μžˆμ—ˆλ‹€.

κΈ°μ‘΄ λ°©μ‹μ˜ μž₯점

  • λΉŒλ“œ μ‹œμ μ— ν™˜κ²½μ„ μ„€μ •ν•  수 μžˆμ–΄ 운영 ν™˜κ²½κ³Ό 개발 ν™˜κ²½μ„ λͺ…ν™•ν•˜κ²Œ ꡬ뢄할 수 μžˆλ‹€.
  • Dockerfile λ‚΄μ—μ„œ 직접 ν™˜κ²½ λ³€μˆ˜λ₯Ό 관리할 수 μžˆμ–΄ ꡬ쑰적으둜 μ΄ν•΄ν•˜κΈ° μ‰¬μš΄ νŽΈμ΄λ‹€.
  • λΉŒλ“œλœ 이미지 λ‚΄λΆ€μ—μ„œ ν™˜κ²½μ„ μ •μ˜ν•˜κΈ° λ•Œλ¬Έμ— λ³„λ„μ˜ μ„€μ • 없이 μ‹€ν–‰ν•  수 μžˆλ‹€.

κΈ°μ‘΄ λ°©μ‹μ˜ 단점

  • 이미지λ₯Ό ν™˜κ²½λ³„λ‘œ λ”°λ‘œ λΉŒλ“œν•΄μ•Ό ν•œλ‹€. 운영 ν™˜κ²½κ³Ό 개발 ν™˜κ²½μ„ 각각 λ‹€λ₯Έ μ΄λ―Έμ§€λ‘œ λ§Œλ“€μ–΄μ•Ό ν•˜λ―€λ‘œ 배포 ν”„λ‘œμ„ΈμŠ€κ°€ λ³΅μž‘ν•΄μ§„λ‹€.
  • Dockerfile을 μˆ˜μ •ν•΄μ•Ό ν™˜κ²½μ„ λ³€κ²½ν•  수 μžˆλ‹€. ENVIRONMENT 값을 λ°”κΎΈλ €λ©΄ Dockerfile을 μˆ˜μ •ν•˜κ±°λ‚˜, λΉŒλ“œ μ‹œλ§ˆλ‹€ --build-arg μ˜΅μ…˜μ„ λͺ…μ‹œμ μœΌλ‘œ μ€˜μ•Ό ν•œλ‹€.
  • Kubernetes ν™˜κ²½κ³Ό μžμ—°μŠ€λŸ½κ²Œ λ§žμ§€ μ•ŠλŠ”λ‹€. μΏ λ²„λ„€ν‹°μŠ€μ—μ„œ ConfigMapμ΄λ‚˜ Secret을 μ‚¬μš©ν•΄ ν™˜κ²½μ„ μ œμ–΄ν•˜λŠ” 것이 일반적인데, 이 방식은 Docker λΉŒλ“œ κ³Όμ •μ—μ„œ 이미 ν™˜κ²½μ΄ κ²°μ •λ˜κΈ° λ•Œλ¬Έμ— 운영 ν™˜κ²½μ—μ„œ μ‰½κ²Œ λ³€κ²½ν•˜κΈ° μ–΄λ ΅λ‹€.

Dockerfile을 ν™œμš©ν•œ 방식도 μΆ©λΆ„νžˆ ν™œμš©ν•  수 μžˆμ—ˆμ§€λ§Œ, Kubernetes ν™˜κ²½μ—μ„œ μš΄μ˜ν•˜κΈ°μ—λŠ” μ œμ•½μ΄ λ§Žμ•˜λ‹€. 특히 배포 ν™˜κ²½λ§ˆλ‹€ 이미지λ₯Ό λ‹€λ₯΄κ²Œ λΉŒλ“œν•΄μ•Ό ν•˜λŠ” 점이 λΉ„νš¨μœ¨μ μœΌλ‘œ λŠκ»΄μ‘Œλ‹€. κ·Έλž˜μ„œ λ‹€λ₯Έ 방법을 κ³ λ―Όν•˜κ²Œ λ˜μ—ˆλ‹€.


Helm values.yaml을 ν™œμš©ν•œ ν™˜κ²½ μ„€μ •

κΈ°μ‘΄ λ°©μ‹μ˜ 단점을 ν•΄κ²°ν•˜κΈ° μœ„ν•΄ Dockerfileμ—μ„œ ν™˜κ²½μ„ 직접 μ„€μ •ν•˜λŠ” λŒ€μ‹ , Helm의 values.yaml을 ν™œμš©ν•˜μ—¬ ν™˜κ²½μ„ κ΅¬λΆ„ν•˜λŠ” λ°©μ‹μœΌλ‘œ λ³€κ²½ν–ˆλ‹€.

Helm을 μ‚¬μš©ν•˜λ©΄ μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ˜ 섀정을 배포 μ‹œμ μ— λ™μ μœΌλ‘œ λ³€κ²½ν•  수 μžˆλ‹€. λ”°λΌμ„œ Docker μ΄λ―Έμ§€λŠ” ν•˜λ‚˜λ§Œ λΉŒλ“œν•˜κ³ , ν™˜κ²½μ— λ§žλŠ” 섀정값을 values.yaml을 톡해 μ μš©ν•  수 μžˆλ‹€.

μƒˆλ‘œμš΄ λ°©μ‹μ˜ μ„€μ • μ˜ˆμ‹œ

개발 ν™˜κ²½ (values-dev.yaml)

env:
  SPRING_PROFILES_ACTIVE: dev

운영 ν™˜κ²½ (values-prod.yaml)

env:
  SPRING_PROFILES_ACTIVE: production

Helm의 deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-backend
spec:
  template:
    spec:
      containers:
        - name: backend
          image: my-backend-image
          env:
            - name: SPRING_PROFILES_ACTIVE
              value: {{ .Values.env.SPRING_PROFILES_ACTIVE }}

이제 배포할 λ•Œ helm install λͺ…λ Ήμ–΄μ—μ„œ values.yaml을 μ„ νƒν•˜λŠ” κ²ƒλ§ŒμœΌλ‘œ ν™˜κ²½μ„ λ‹€λ₯΄κ²Œ μ μš©ν•  수 μžˆλ‹€.

# 개발 ν™˜κ²½ 배포
helm install my-backend ./helm-chart -f values-dev.yaml

# 운영 ν™˜κ²½ 배포
helm install my-backend ./helm-chart -f values-prod.yaml

이 λ°©μ‹μ—μ„œλŠ” Docker 이미지λ₯Ό ν•˜λ‚˜λ§Œ λΉŒλ“œν•˜λ©΄ 되고, 배포 μ‹œμ μ—μ„œ values.yaml을 톡해 ν™˜κ²½μ„ λ³€κ²½ν•  수 μžˆλ‹€. μ΄λŠ” Kubernetes ν™˜κ²½μ— 훨씬 μ ν•©ν•œ ꡬ쑰닀.

μƒˆλ‘œμš΄ λ°©μ‹μ˜ μž₯점

  • Docker 이미지λ₯Ό ν•œ 번만 λΉŒλ“œν•˜λ©΄ λœλ‹€. 운영 ν™˜κ²½κ³Ό 개발 ν™˜κ²½μ΄ λ™μΌν•œ 이미지λ₯Ό κ³΅μœ ν•  수 μžˆλ‹€.
  • ν™˜κ²½ λ³€μˆ˜λ₯Ό Helm values.yamlμ—μ„œ 관리할 수 μžˆλ‹€. ν™˜κ²½λ³„λ‘œ values.yaml을 λ”°λ‘œ λ§Œλ“€μ–΄ κ΄€λ¦¬ν•˜λ©΄ 섀정이 훨씬 깔끔해진닀.
  • Kubernetes λ„€μ΄ν‹°λΈŒν•œ 방식이닀. Kubernetesμ—μ„œλŠ” ConfigMapμ΄λ‚˜ Secret을 ν™œμš©ν•΄ ν™˜κ²½μ„ κ΄€λ¦¬ν•˜λŠ” 것이 일반적인데, 이 방식이 이에 μ ν•©ν•˜λ‹€.
  • 배포 μ‹œμ μ—μ„œ ν™˜κ²½μ„ λ™μ μœΌλ‘œ λ³€κ²½ν•  수 μžˆλ‹€. κΈ°μ‘΄ λ°©μ‹μ—μ„œλŠ” Dockerfileμ—μ„œ λΉŒλ“œ μ‹œ ν™˜κ²½μ„ μ •ν•΄μ•Ό ν–ˆμ§€λ§Œ, μ΄μ œλŠ” 배포할 λ•Œ μ„ νƒλ§Œ ν•˜λ©΄ λœλ‹€.

μƒˆλ‘œμš΄ λ°©μ‹μ˜ 단점

  • Helm을 μ‚¬μš©ν•˜μ§€ μ•ŠλŠ”λ‹€λ©΄ μ μš©ν•˜κΈ° μ–΄λ ΅λ‹€. 둜컬 개발 ν™˜κ²½μ—μ„œ docker run 같은 λ°©μ‹μœΌλ‘œ μ‹€ν–‰ν•  경우, ν™˜κ²½ 섀정을 λ”°λ‘œ 관리해야 ν•œλ‹€.
  • ν™˜κ²½μ΄ Helm에 μ’…μ†λœλ‹€. Kubernetesκ°€ μ•„λ‹Œ ν™˜κ²½μ—μ„œ μ‚¬μš©ν•˜λ €λ©΄ 좔가적인 섀정이 ν•„μš”ν•  수 μžˆλ‹€.

λ‚΄κ°€ μ„ νƒν•œ κ²°λ‘ : Helm values.yaml이 더 νš¨μœ¨μ μ΄μ—ˆλ‹€

이번 ν”„λ‘œμ νŠΈλ₯Ό μ§„ν–‰ν•˜λ©΄μ„œ Dockerfileμ—μ„œ ν™˜κ²½μ„ κ΄€λ¦¬ν•˜λŠ” 방식과 Helm을 ν™œμš©ν•˜λŠ” 방식을 비ꡐ할 수 μžˆμ—ˆλ‹€. μ—¬λŸ¬ κ°€μ§€ μ‹œλ„λ₯Ό ν•΄ λ³Έ κ²°κ³Ό, Helm values.yaml을 ν™œμš©ν•˜λŠ” 방식이 더 μœ μ—°ν•˜κ³ , 배포 ν™˜κ²½μ„ κΉ”λ”ν•˜κ²Œ 정리할 수 μžˆμ—ˆλ‹€λŠ” μ μ—μ„œ μ ν•©ν•˜λ‹€κ³  νŒλ‹¨ν–ˆλ‹€.

 

이 방식을 μ μš©ν•œ ν›„ Docker 이미지λ₯Ό λΉŒλ“œν•˜λŠ” 과정이 λ‹¨μˆœν•΄μ‘Œκ³ , 배포 ν™˜κ²½μ„ κ΄€λ¦¬ν•˜λŠ” 것이 훨씬 μ‰¬μ›Œμ‘Œλ‹€. 같은 이미지λ₯Ό μ‚¬μš©ν•˜λ©΄μ„œλ„ ν™˜κ²½λ³„ 섀정을 μœ μ—°ν•˜κ²Œ λ°”κΏ€ 수 μžˆμ–΄ μœ μ§€λ³΄μˆ˜ μΈ‘λ©΄μ—μ„œλ„ μž₯점이 λ§Žμ•˜λ‹€. λ˜ν•œ, 사내 배포 νˆ΄μ—μ„œ Docker에 직접 값을 λ„£μ–΄μ•Ό ν–ˆλ˜ λ²ˆκ±°λ‘œμ›€μ΄ 사라지고, Helmμ—μ„œ μ½”λ“œλ‘œ λͺ…μ‹œν•  수 μžˆμ–΄ μ‹€μˆ˜ 없이 관리할 수 있게 λ˜μ—ˆλ‹€.

 

λ¬Όλ‘  λͺ¨λ“  ν”„λ‘œμ νŠΈμ— 무쑰건 Helm이 정닡은 아닐 μˆ˜λ„ μžˆλ‹€. ν•˜μ§€λ§Œ λ‚΄κ°€ κ²½ν—˜ν•œ ν”„λ‘œμ νŠΈμ—μ„œλŠ” 이 방식이 더 μ ν•©ν–ˆκ³ , 더 νš¨μœ¨μ μ΄μ—ˆλ‹€. Kubernetesλ₯Ό ν™œμš©ν•˜λŠ” ν™˜κ²½μ΄λΌλ©΄, Dockerfileμ—μ„œ ARG와 ENVλ₯Ό ν™œμš©ν•˜λŠ” 것보닀 Helm values.yaml을 톡해 ν™˜κ²½μ„ λΆ„λ¦¬ν•˜λŠ” 것이 더 λ‚˜μ€ 선택일 κ°€λŠ₯성이 λ†’λ‹€.