인터넷 없는 환경에 컨테이너 배포하기 (에어갭)
인터넷이 막힌 에어갭(air-gap) 환경에 컨테이너 이미지를 반입하고 설치하는 방법과, "받아올 수 있다"는 가정 때문에 데이는 지점을 정리합니다.
결론부터 말하면, 필요한 모든 이미지를 미리 묶어 반입하고, 내부 사설 레지스트리에서만 받게 합니다. 그리고 코드와 스크립트에 숨은 "필요할 때 인터넷에서 받아온다"는 가정을 전부 걷어내야 합니다.
에어갭(air-gap)이란
에어갭은 보안을 위해 외부 인터넷과 물리적으로 분리된 환경을 말합니다. 고객사 데이터센터처럼 데이터가 밖으로 나가면 안 되는 곳에서 씁니다.
마트 없는 산장에 살림을 차리는 일에 비유할 수 있습니다. 인터넷이 되는 곳에서는 재료가 떨어지면 사 오면 되지만, 에어갭에서는 필요한 것을 하나도 빠짐없이 미리 싸 들고 들어가야 합니다.
왜 어려운가
에어갭이 어려운 이유는, 평소 설치가 인터넷에서 무언가를 받아오는 것을 전제로 하기 때문입니다. 컨테이너 이미지는 보통 외부 레지스트리(Docker Hub 등)에서 받아오는데, 에어갭에서는 그 경로가 막혀 있습니다.
게다가 받아야 할 것은 우리 서비스 이미지만이 아닙니다. 베이스 이미지, 사이드카, 데이터베이스, 모니터링 도 구까지 전부 필요합니다. 하나라도 빠지면 설치가 중간에 멈춥니다.

배포 방법 (네 단계)
에어갭 배포는 크게 네 단계입니다. ① 필요한 이미지를 빠짐없이 모으고, ② 묶어서 반입하고, ③ 내부 사설 레지스트리에 올리고, ④ 매니페스트가 그 레지스트리를 가리키게 합니다.

1. 필요한 이미지 목록 만들기
매니페스트(쿠버네티스 YAML, compose 파일 등)에서 쓰는 이미지를 전부 추출합니다. 베이스·사이드카까지 누락 없이 모읍니다.
# k8s 매니페스트에서 image: 줄만 추출
grep -rhoE 'image:\s*\S+' manifests/ | awk '{print $2}' | sort -u
2. 이미지를 묶어서 반입
인터넷이 되는 곳에서 이미지를 받아 하나의 파일로 묶습니다.
# 여러 이미지를 한 tar 로 저장
docker save -o bundle.tar app:1.0 postgres:16 nats:2.10 ...
# (또는 레지스트리 간 직접 복사: skopeo copy / crane)
이 bundle.tar를 USB·승인된 매체로 에어갭 안으로 반입합니다.
3. 내부 사설 레지스트리에 올리기
에어 갭 안에 사설 레지스트리를 띄우고, 반입한 이미지를 풀어 올립니다.
docker load -i bundle.tar
docker tag app:1.0 registry.internal:5000/app:1.0
docker push registry.internal:5000/app:1.0
4. 매니페스트가 내부 레지스트리를 가리키게
이미지 주소를 외부 레지스트리에서 내부 레지스트리로 바꿉니다. 설치는 이제 인터넷이 아니라 내부에서만 이미지를 받습니다.
# before: image: docker.io/library/app:1.0
image: registry.internal:5000/app:1.0
흔한 함정
- 의존 이미지 누락: 우리 앱만 챙기고 베이스·사이드카·DB를 빠뜨리기 쉽습니다. 매니페스트에서 기계적으로 전부 추출해 모읍니다.
- 사설 레지스트리 pull이 느림: 작은 이미지는 괜찮지만 큰 이미지는 레지스트리를 거치면 오래 걸립니다. 용량이 큰 이미지는 레지스트리를 거치지 않고 컨테이너 런타임으로 직접 반입하는 방법을 씁니다(
ctr image import등). - 설치 스크립트에 숨은 인터넷 가정: 패키지 설치, 외부 URL 다운로드 같은 코드가 곳곳에 숨어 있습니다. 막힌 환경에서 줄줄이 멈추므로, "받아온다"는 가정을 하나씩 찾아 제거합니다.
Q&A
- 사설 레지스트리 없이 그냥 이미지만 넣으면 안 되나요?
- 노드마다
docker load로 직접 넣을 수도 있지만, 노드가 늘면 관리가 힘듭니다. 사설 레지스트리를 한 번 띄워 두는 편이 깔끔합니다.
- 노드마다
- 어떤 이미지를 빠뜨렸는지 어떻게 확인하나요?
- 설치를 한 번 돌려 보고, 이미지 pull 실패 로그를 모읍니다. 그 목록을 다음 번들에 추가합니다. 처음부터 완벽히 모으긴 어렵습니다.
- 이미지 외에 또 챙길 것이 있나요?
- 있습니다. OS 패키지, 언어 런타임 의존성, 헬름 차트, 설치 스크립트가 받는 모든 외부 파일이 대상입니다.
참고자료
docker save/docker load,skopeo copy,crane- containerd
ctr image import