Infra & Network

[Docker | Part 4] Volume + Network + Registry

hrbds 2026. 4. 30. 17:03

목차

  • WHY — 왜 Volume / Network / Registry가 필요한가
  • Volume — 데이터 영속성
  • Network — 컨테이너 격리
  • Registry — 이미지 배포
  • 전체 요약

1. WHY — 왜 이걸 알아야 하는가

세 가지 문제가 있다.

① 데이터가 날아간다 : MySQL 컨테이너를 삭제하면 DB 데이터가 사라진다. Part1에서 배운 쓰기 가능 레이어가 컨테이너와 함께 소멸하기 때문이다 → Volume으로 해결

② 네트워크 격리가 필요하다 : 모든 컨테이너가 같은 네트워크에 있으면 DB에 누구나 접근 가능하다 → Network로 해결

③ 이미지를 서버에 전달해야 한다 : 로컬에서 빌드한 이미지를 K8s 서버에 어떻게 올리나? → Registry로 해결


2. Volume — 데이터 영속성

Volume 없을 때

docker run -d \
  --name mysql-no-volume \
  -e MYSQL_ROOT_PASSWORD=ari1234 \
  -e MYSQL_DATABASE=aridb \
  mysql:8

# 데이터 삽입
docker exec -it mysql-no-volume mysql -uroot -pari1234 -e \
  "USE aridb; CREATE TABLE ari_card (id INT, name VARCHAR(50)); INSERT INTO ari_card VALUES (1, 'Legendary Ari');"

# 컨테이너 삭제 후 재생성
docker rm -f mysql-no-volume
docker run -d --name mysql-no-volume ...

# 데이터 확인
docker exec -it mysql-no-volume mysql -uroot -pari1234 -e \
  "USE aridb; SELECT * FROM ari_card;"
# ERROR 1146: Table 'aridb.ari_card' doesn't exist  ← 데이터 소멸

컨테이너가 삭제되면 쓰기 가능 레이어도 함께 사라진다. 그 안에 저장된 데이터도 날아간다.

Volume으로 해결

docker run -d \
  --name mysql-with-volume \
  -e MYSQL_ROOT_PASSWORD=ari1234 \
  -e MYSQL_DATABASE=aridb \
  -v mysql-data:/var/lib/mysql \
  mysql:8

-v mysql-data:/var/lib/mysql — mysql-data Named Volume을 컨테이너의 /var/lib/mysql에 마운트한다.

컨테이너 내부           Docker Volume (외부)
/var/lib/mysql   ←→   mysql-data

동기화가 아니라 마운트다. 같은 저장소를 바라보는 것이라 별도 복사 과정이 없다.

 

컨테이너를 삭제하고 재생성해도 데이터가 존재하는 것을 확인할 수 있다.

docker rm -f mysql-with-volume
docker run -d --name mysql-with-volume -v mysql-data:/var/lib/mysql ...

docker exec -it mysql-with-volume mysql -uroot -pari1234 -e \
  "USE aridb; SELECT * FROM ari_card;"

+------+---------------+
| id   | name          |
+------+---------------+
|    1 | Legendary Ari |   ← 데이터 유지
+------+---------------+

 

Volume 종류 3가지

구분 명령어 설명
Named Volume -v mysql-data:/var/lib/mysql Docker가 관리, 경로 신경 안 써도 됨 → 실무 표준
Bind Mount -v /home/user/data:/var/lib/mysql 호스트 특정 경로에 직접 마운트 → 로컬 개발 시 유용
tmpfs --tmpfs /tmp 메모리에만 저장, 컨테이너 종료 시 소멸 → 임시 데이터용

Volume 관련 명령어

# Volume 목록 확인
docker volume ls

# Volume 상세 정보 (실제 저장 경로 확인)
docker volume inspect mysql-data

# Volume 삭제
docker volume rm mysql-data

# 사용하지 않는 Volume 전체 삭제
docker volume prune

docker compose down과 Volume

docker compose down            # 컨테이너 + 네트워크 삭제, Volume 유지
docker compose down --volumes  # Volume(DB 데이터)까지 삭제

3. Network — 컨테이너 격리

기본 네트워크의 문제

Volume 없이 띄운 컨테이너는 기본 bridge 네트워크에 연결된다.

모든 컨테이너가 같은 네트워크에 있으면 누구나 DB에 접근 가능하다.

네트워크 분리 구조

[Clinet]
    │
    ▼
[frontend-net]
    │
    ▼
[ari-app]  ← frontend-net + backend-net 양쪽 연결
    │
    ▼
[backend-net]
    │
    ▼
[MySQL / Redis]  ← 외부에서 직접 접근 불가

실습

# 네트워크 생성
docker network create frontend-net
docker network create backend-net

# MySQL을 backend-net에만 연결
docker run -d \
  --name mysql-with-volume \
  --network backend-net \
  -e MYSQL_ROOT_PASSWORD=ari1234 \
  -e MYSQL_DATABASE=aridb \
  -v mysql-data:/var/lib/mysql \
  mysql:8

# ari-app을 backend-net으로 시작
docker run -d \
  --name ari-app \
  --network backend-net \
  redis:7.2

# ari-app을 frontend-net에도 추가 연결
docker network connect frontend-net ari-app

격리 확인

# frontend-net에만 있는 컨테이너에서 MySQL 접근 시도
docker run -d --name frontend-only --network frontend-net redis:7.2
docker exec -it frontend-only sh -c "getent hosts mysql-with-volume"
# (아무것도 안 나옴) ← 접근 불가

# ari-app에서 MySQL 접근 (양쪽 네트워크 연결됨)
docker exec -it ari-app sh -c "getent hosts mysql-with-volume"
# 172.20.0.2      mysql-with-volume  ← 접근 가능

frontend-only에서는 MySQL이 보이지 않고, ari-app에서는 접근 가능하다. 네트워크 격리가 정확히 동작하고 있다.

Network 관련 명령어

# 네트워크 목록 확인
docker network ls

# 네트워크 상세 정보 (연결된 컨테이너 확인)
docker network inspect backend-net

# 네트워크 생성
docker network create backend-net

# 실행 중인 컨테이너에 네트워크 추가 연결
docker network connect frontend-net ari-app

# 네트워크 삭제
docker network rm frontend-net backend-net

4. Registry — 이미지 배포

Registry란

이미지를 저장하고 배포하는 저장소다.

docker build → 이미지 생성
     │
     │ docker push
     ▼
Registry (Docker Hub or 자체 Registry)
     │
     │ docker pull
     ▼
K8s 서버 / 팀원 PC

Docker Hub vs 자체 Registry

Docker Hub 자체 Registry (Harbor 등)

사용 대상 오픈소스, 개인/소규모 보안이 중요한 기업
비용 무료 (공개) / 유료 (비공개) 자체 구축 비용
보안 외부 서버에 이미지 저장 내부망에서만 관리
속도 외부 네트워크 속도 의존 내부망이라 빠름

금융, 의료 등 규제 산업이나 고객사 코드가 포함된 경우 자체 Registry가 필수다.

이미지 태깅 전략

latest를 쓰면 안 되는 이유:

  • 어떤 버전인지 알 수 없음
  • K8s에서 캐시된 이전 이미지를 그대로 쓸 수 있음
  • 롤백이 불가능함

실무 표준은 git SHA 기반 태깅이다:

# git SHA 기반 (CI/CD 표준)
docker build -t hrbds/ari-app:abc1234 .

# 버전 기반
docker build -t hrbds/ari-app:1.0.0 .

실습 — Docker Hub Push / Pull

# 로그인
docker login

# 태깅
docker tag ari-app-final:latest hrbds/ari-app:1.0.0

# push
docker push hrbds/ari-app:1.0.0
# 1.0.0: digest: sha256:7653... size: 856

# 로컬 이미지 삭제 후 pull 검증
docker rmi hrbds/ari-app:1.0.0
docker pull hrbds/ari-app:1.0.0
# Digest: sha256:7653...  ← push할 때와 동일한 다이제스트 확인

 

Docker Hub든 자체 Registry든 명령어는 동일하다. 차이는 이미지 태그에 Registry 주소가 포함되느냐 차이다.

# Docker Hub
docker push hrbds/ari-app:1.0.0

# 자체 Registry
docker push registry.mycompany.com/ari-app:1.0.0

# 자체 Registry 로그인
docker login registry.mycompany.com

5. 전체 요약

Volume
├── Named Volume: Docker가 관리, 컨테이너 삭제해도 데이터 유지
├── Bind Mount: 호스트 경로 직접 마운트 (로컬 개발용)
└── tmpfs: 메모리 저장, 컨테이너 종료 시 소멸

Network
├── 네트워크 분리로 DB 직접 접근 차단
├── 앱 컨테이너만 frontend + backend 양쪽 연결
└── getent hosts [서비스명]으로 DNS 접근 가능 여부 확인

Registry
├── latest 태그 금지 → git SHA 또는 버전 기반 태깅
├── Docker Hub / 자체 Registry 명령어 동일
└── 보안 중요 환경 → 자체 Registry (Harbor 등) 필수