
이름에 전부 Image, Artifact가 붙어서 처음 보면 “결국 이미지 아닌가?” 싶습니다. 😄 그런데 핵심은 “컨테이너 실행용 파일인가, 아니면 OCI 규격을 이용해 저장하는 다른 종류의 패키지인가?”입니다.
가장 먼저 큰 그림부터 잡으면 쉽습니다.
Harbor
│
├─ Container Image
│ └─ Docker Image
│
└─ OCI Artifact
├─ Helm Chart
├─ SBOM
├─ Signature
└─ 기타 OCI 패키지
즉, Container Image와 Docker Image는 실제 컨테이너 실행을 위한 이미지이고, OCI Artifact는 이미지뿐 아니라 Helm Chart 같은 다른 산출물까지 Registry에 저장할 수 있게 만든 더 넓은 개념입니다. OCI Registry는 컨테이너 이미지 외 다른 artifact 유형도 저장·배포할 수 있도록 확장되어 있습니다. (https://opencontainers.github.io)
1. 먼저 Container Image가 뭘까? 🐳
Container Image는 쉽게 말해:
컨테이너를 실행하기 위해 필요한 프로그램 + 라이브러리 + 설정을 포장한 실행 패키지
입니다.
Docker 공식 문서에서도 container image를 컨테이너 실행에 필요한 파일, 바이너리, 라이브러리, 설정을 포함하는 표준 패키지로 설명합니다. (Docker Documentation)
예를 들어 Python 웹서비스가 있다고 하겠습니다.
내 프로그램
app.py
필요한 Python
Python 3.12
필요한 라이브러리
Flask
requests
numpy
이걸 하나의 이미지로 묶습니다.
Container Image
├─ Linux 파일
├─ Python 3.12
├─ Flask
├─ requests
├─ numpy
└─ app.py
그리고 Kubernetes가 이것을 가져가서:
Container Image
↓
Container 실행
↓
Pod
하게 됩니다.
예:
containers:
- name: web
image: harbor.company.com/myproject/web:v1
여기서 web:v1이 Container Image입니다.
2. Docker Image는 뭐가 다른가?
여기서 중요한 포인트입니다.
Docker Image는 Container Image의 대표적인 형태라고 이해하면 됩니다.
쉽게 비유하면:
자동차
└─ 현대자동차
처럼 생각하면 됩니다.
Container Image
└─ Docker Image
과거에는 Docker가 컨테이너 생태계를 크게 주도해서 사람들이 흔히:
Container Image
=
Docker Image
처럼 불렀습니다.
실무에서도 여전히 거의 그렇게 말합니다.
예:
docker build -t myapp:v1 .
그러면:
myapp:v1
이라는 컨테이너 이미지가 만들어집니다.
그래서 이것을:
Docker Image
라고도 하고,
Container Image
라고도 부릅니다.
예
FROM python:3.12
COPY app.py /app/app.py
RUN pip install flask
CMD ["python", "/app/app.py"]
실행:
docker build -t myapp:v1 .
결과:
myapp:v1
이게 Docker로 만든 Container Image입니다.
3. 그러면 OCI는 뭐야? 🤔
여기서부터 중요합니다.
OCI는:
Open Container Initiative
의 약자입니다.
쉽게 말하면:
컨테이너 이미지와 Registry가 서로 호환되도록 표준 규격을 만드는 단체/표준
입니다.
왜 이런 표준이 필요했을까요?
예전에는:
Docker가 만든 Image
↓
Docker가 실행
라는 Docker 중심 구조였습니다.
그런데 Kubernetes가 커지면서:
Docker
containerd
CRI-O
Podman
Harbor
ECR
ACR
GHCR
등 수많은 제품이 등장했습니다.
만약 각각 자기 방식으로 이미지를 만들었다면:
Docker Image
→ Docker에서만 사용
Podman Image
→ Podman에서만 사용
containerd Image
→ containerd에서만 사용
같은 문제가 생깁니다.
그래서 OCI라는 공통 표준을 만든 것입니다.
OCI Image Specification은 이미지 manifest, config, layer 등 컨테이너 이미지를 구성하는 표준 구조를 정의합니다. (https://opencontainers.github.io)
4. 비유하면 USB 규격과 비슷합니다
이렇게 생각하면 쉽습니다.
과거:
회사 A 전용 케이블
회사 B 전용 케이블
회사 C 전용 케이블
너무 불편합니다.
그래서:
USB-C 표준
을 만들어 여러 장비에서 사용할 수 있게 합니다.
컨테이너도 비슷합니다.
OCI 표준
│
┌────────┼─────────┐
↓ ↓ ↓
Docker containerd Podman
Registry도:
OCI 표준
│
┌────────┼─────────┐
↓ ↓ ↓
Harbor ECR GHCR
처럼 OCI 규격을 이해할 수 있습니다.
5. OCI Image는 그러면 뭐야?
OCI 규격으로 표현된 컨테이너 실행용 이미지입니다.
대략 이런 구조를 가집니다.
OCI Image
│
├─ Manifest
│
├─ Config
│
└─ Layers
├─ Layer 1
├─ Layer 2
└─ Layer 3
예를 들어:
FROM ubuntu:24.04
RUN apt install python3
COPY app.py /app/
라고 했다면 개념적으로:
Layer 1
Ubuntu
Layer 2
Python 설치
Layer 3
app.py
처럼 여러 Layer로 저장됩니다.
OCI에서는 이런 이미지의 구성과 참조 관계를 표준화합니다. OCI 문서에서는 OCI image를 root filesystem 변경사항과 컨테이너 실행 파라미터의 집합으로 정의합니다. (https://opencontainers.github.io)
6. 그런데 OCI Artifact는 또 뭐야? 📦
여기가 오늘 질문의 가장 중요한 부분입니다.
Artifact는 그냥:
저장하고 배포할 가치가 있는 산출물
이라고 생각하면 됩니다.
OCI가 발전하면서 이런 생각이 나왔습니다.
Registry라는 좋은 저장소가 있는데
왜 Container Image만 저장하지?
Helm Chart도 저장하고
SBOM도 저장하고
Signature도 저장하면 안 돼?
그래서 OCI Registry를 컨테이너 이미지 이외의 artifact 저장에도 활용할 수 있게 되었습니다. (Open Container Initiative)
즉:
OCI Registry
├─ Container Image
├─ Helm Chart
├─ SBOM
├─ Signature
├─ Attestation
└─ 기타 Artifact
가 가능해진 것입니다.
7. 아주 중요한 관계
정확하게는 이렇게 보면 됩니다.
OCI Artifact
│
┌─────────┴──────────┐
│ │
Container Image Helm Chart 등
│
Docker Image
다만 실무에서는 OCI Artifact라는 말을 컨테이너 이미지가 아닌 OCI Registry 저장물을 가리킬 때 좁은 의미로 쓰기도 합니다.
그래서 Harbor 화면에서:
Artifacts
라고 나오면 반드시:
Docker Image만 있음
을 의미하는 것이 아닙니다.
8. Helm은 뭐였지?
Helm은 Kubernetes의 패키지 관리자입니다.
예를 들어 Kubernetes에 nginx를 설치하려면 원래 YAML 파일이 여러 개 필요할 수 있습니다.
deployment.yaml
service.yaml
configmap.yaml
ingress.yaml
secret.yaml
복잡하죠.
Helm은 이것들을 하나의 패키지처럼 묶어줍니다.
my-nginx-chart
│
├─ Chart.yaml
├─ values.yaml
└─ templates
├─ deployment.yaml
├─ service.yaml
└─ ingress.yaml
그리고 패키징하면:
my-nginx-1.0.0.tgz
가 됩니다.
이것을 Helm Chart라고 합니다.
9. Helm/OCI Artifact는 뭐야?
과거 Helm Chart는 보통 별도의 Helm Repository에 저장했습니다.
예:
Helm Client
↓
Helm Repository
↓
myapp-1.0.0.tgz
그런데 이제 Helm은 OCI Registry도 사용할 수 있습니다.
Helm Client
↓
Harbor
↓
OCI Registry
↓
myapp Helm Chart
Helm 공식 문서에 따르면 Helm은 OCI 기반 Registry에 패키징된 Helm Chart를 저장하고 공유할 수 있으며, Helm 3.8부터 OCI 지원이 기본적으로 활성화되어 있습니다. (Helm)
예를 들어:
helm push myapp-1.0.0.tgz \
oci://harbor.company.com/helm
라고 할 수 있습니다.
그러면 Harbor 안에:
Harbor
└─ helm
└─ myapp
└─ 1.0.0
형태로 저장됩니다.
이게 바로 Helm OCI Artifact입니다.
10. 가장 중요한 차이 ⭐
Container Image와 Helm Chart는 목적이 완전히 다릅니다.
Container Image
실제 프로그램을 실행합니다.
Container Image
↓
containerd
↓
Container
↓
Application 실행
예:
nginx:1.29
python:3.12
pytorch:2.x
myapp:v1
Helm Chart
Container Image를 어떻게 Kubernetes에 배포할 것인지 정의합니다.
Helm Chart
↓
Kubernetes YAML 생성
↓
Deployment
Service
Ingress
ConfigMap
PVC
...
즉 Helm Chart 자체가 실행되는 게 아닙니다.
11. 예를 들어 Harbor에 둘 다 있을 수 있습니다
예를 들어 우리가 myapp이라는 서비스를 만든다고 해보겠습니다.
Harbor:
harbor.company.com
project: myapp
├─ backend
│ ├─ v1.0
│ ├─ v1.1
│ └─ v1.2
│
└─ myapp-chart
├─ 1.0.0
├─ 1.1.0
└─ 1.2.0
그런데 실제 내용은 다릅니다.
backend:v1.2
Container Image
Ubuntu
Java
Spring Boot
app.jar
설정
myapp-chart:1.2.0
Helm Chart
Deployment.yaml
Service.yaml
Ingress.yaml
ConfigMap.yaml
values.yaml
즉:
Container Image
=
"무엇을 실행할 것인가?"
Helm Chart
=
"그걸 Kubernetes에서 어떻게 실행할 것인가?"
이 차이가 핵심입니다.
12. 실제 배포 흐름으로 보면 바로 이해됩니다
개발자가 프로그램을 만듭니다.
Source Code
↓
Build
↓
Container Image
↓
Harbor
예:
harbor.company.com/app/backend:v1
그리고 Helm Chart에는:
image:
repository: harbor.company.com/app/backend
tag: v1
replicaCount: 3
같은 설정이 들어갑니다.
전체 흐름:
Harbor
│
┌────────────┴────────────┐
│ │
Container Image Helm Chart
backend:v1 myapp:1.0.0
│ │
│ 배포 방법 정의
│ │
└──────────┬──────────────┘
↓
Helm
↓
Kubernetes
↓
Deployment 생성
↓
Pod
↓
backend:v1 Image Pull
↓
Container 실행
이 그림을 이해하면 거의 끝입니다.
13. Kubernetes 입장에서 보면 더 쉽습니다
예를 들어:
helm install myapp \
oci://harbor.company.com/helm/myapp
를 실행합니다.
먼저 Helm이 Harbor에서:
Helm Chart
를 가져옵니다.
그 안에는:
kind: Deployment
containers:
- name: backend
image: harbor.company.com/app/backend:v1
같은 내용이 있습니다.
그 다음 Kubernetes가 Deployment를 생성하고 Pod를 만들면서 다시 Harbor에서:
backend:v1
이라는 Container Image를 Pull합니다.
즉 Harbor에 두 번 접근할 수도 있습니다.
① Helm
↓
Harbor
↓
Helm Chart Pull
② Kubernetes Node
↓
Harbor
↓
Container Image Pull
중요한 차이입니다.
14. SBOM도 OCI Artifact가 될 수 있습니다
OCI Artifact가 Helm만 의미하는 것은 아닙니다.
예를 들어 SBOM:
Software Bill of Materials
즉:
이 이미지 안에
어떤 소프트웨어가 들어있는지
목록
입니다.
예:
backend:v1
├─ Ubuntu 24.04
├─ OpenSSL 3.x
├─ Python
├─ Flask
└─ requests
이런 정보를 담은 SBOM을 이미지와 연결해서 Registry에 보관할 수도 있습니다.
예:
Harbor
backend:v1
│
├─ Container Image
│
├─ SBOM
│
└─ Signature
OCI 1.1에서는 이미지나 다른 artifact 간의 관계를 표현하는 기능도 정식 규격에 포함되었습니다. (Open Container Initiative)
15. Signature도 Artifact입니다
예를 들어 보안상:
이 이미지는
우리 회사 CI/CD가 정상적으로 만든 이미지인가?
를 확인하고 싶습니다.
그러면:
backend:v1
│
└─ Signature
를 붙일 수 있습니다.
개념적으로:
Container Image
backend:v1
+
Digital Signature
↓
"회사 CI가 만든 정상 이미지"
처럼 사용할 수 있습니다.
16. 그래서 Harbor에서 Artifact라는 말을 많이 쓰는 이유
Harbor를 보다 보면:
Project
→ Repository
→ Artifacts
라는 표현을 볼 수 있습니다.
처음에는:
왜 Images라고 안 하고 Artifacts라고 하지?
라고 생각할 수 있습니다.
그 이유가 바로:
Harbor가 이제
Container Image만 저장하는 게 아니기 때문
입니다.
예를 들어 Repository 안에:
Container Image
Helm Chart
Signature
SBOM
기타 OCI Artifact
등을 다룰 수 있기 때문입니다.
17. 표로 한 번 정리해보겠습니다
구분의미실행 가능?대표 예
| Container Image | 컨테이너 실행 패키지 | ✅ | nginx, Python 앱 |
| Docker Image | Docker 생태계에서 만든/부르는 Container Image | ✅ | nginx:latest |
| OCI Image | OCI 표준을 따르는 Container Image | ✅ | myapp:v1 |
| OCI Artifact | OCI Registry에 저장 가능한 더 넓은 산출물 | 종류에 따라 다름 | Helm, SBOM, Signature |
| Helm Chart | K8s 배포 패키지 | ❌ | myapp-1.0.0.tgz |
| Helm OCI Artifact | OCI Registry에 저장한 Helm Chart | ❌ | oci://harbor/.../myapp |
18. 이미지라는 단어 때문에 헷갈리지 않는 방법
이렇게 외우시면 됩니다. ⭐
Container Image
프로그램 실행용 패키지
Docker Image
Container Image를
Docker 관점에서 부르는 이름
OCI Image
표준 규격을 따르는 Container Image
OCI Artifact
OCI Registry에 넣을 수 있는
여러 종류의 패키지
Helm OCI Artifact
OCI Registry에 넣은
Kubernetes Helm Chart
19. 컨테이너 이미지와 Helm의 관계를 식당으로 비유 🍜
이 비유가 가장 쉽습니다.
Container Image = 음식 재료가 준비된 밀키트
🍜 Container Image
면
육수
고기
양념
실제로 실행할 프로그램이 들어 있습니다.
Helm Chart = 조리법 + 식당 운영 지침
📋 Helm Chart
밀키트 3개 준비
냄비 3개 사용
8000번 포트 사용
외부 손님에게 공개
냉장고 10GB 사용
즉:
Container Image
=
무엇을 실행하는가
Helm Chart
=
어떻게 배포하는가
입니다.
20. 온프레미스 Kubernetes + Harbor에서는 이렇게 보시면 됩니다
실제 기업 환경을 기준으로 하면:
Harbor
│
┌─────────┴──────────┐
│ │
Images OCI Artifacts
│ │
│ ┌─────┼──────┐
│ │ │ │
Backend:v1 Helm SBOM Signature
Frontend:v2 Chart
│ │
└──────┬───────┘
↓
CI/CD
↓
ArgoCD
↓
Helm
↓
Kubernetes
↓
Pod
↓
Container 실행
따라서 Harbor를 단순히 “Docker 이미지 저장소”라고만 이해하면 조금 부족합니다.
현재 개념으로는:
Harbor = OCI Registry
컨테이너 이미지뿐 아니라 Helm Chart와 각종 OCI Artifact까지 관리할 수 있는 저장소
라고 이해하는 편이 더 정확합니다. Helm도 OCI Registry에 차트를 직접 저장하고 설치하는 방식을 공식 지원합니다. (Helm)
⭐ 최종 핵심 3줄
Docker Image ⊂ Container Image
Container Image = 프로그램 실행용
OCI Artifact = Container Image + Helm/SBOM/Signature 등까지 포괄하는 더 큰 저장 개념
그리고 다음에 Nexus → Harbor → Helm → ArgoCD → Kubernetes를 연결해서 보면, “왜 Nexus에는 JAR을 넣고 Harbor에는 Image와 Helm Chart를 넣는지”가 한 번에 정리됩니다.
'J-H-T > Harbor' 카테고리의 다른 글
| [다양한 Artifact 저장 / Container Image 저장] Nexus Repository & Harbor (0) | 2026.08.10 |
|---|
댓글