목차
- 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 등) 필수
'Infra & Network' 카테고리의 다른 글
| [Redis HA | Part 2] Redis Cluster — 샤딩 + HA (0) | 2026.04.30 |
|---|---|
| [Docker | Part 5] Docker 네트워크 원리 이해 (0) | 2026.04.30 |
| [Docker | Part 3] Docker Compose (0) | 2026.04.30 |
| [Docker | Part 2] Dockerfile + Multi-stage Build (0) | 2026.04.28 |
| [Docker | Part 1] Docker 핵심 구조 이해 (0) | 2026.04.23 |