Network & Server Factory

개인 공부 기록

DevOps/Docker

[Docker] 컨테이너 네트워크와 볼륨 정리

1nfra 2026. 9. 28. 15:40
컨테이너는 기본적으로 자기만의 네트워크와 파일시스템을 가집니다. 이 글에서는 컨테이너끼리 이름으로 통신하는 bridge 네트워크, 밖에서 접속하게 하는 포트 매핑, 컨테이너를 지워도 데이터를 남기는 볼륨과 바인드 마운트를 Redis 예제로 정리합니다.

컨테이너부터 Kubernetes까지 시리즈 4편입니다. 이전 글은 [Docker] Dockerfile 작성과 멀티 스테이지 빌드 정리이고, 전체 순서는 시리즈 목차에 있습니다.

1. 네트워크 드라이버

1편에서 본 것처럼 컨테이너는 NET namespace로 자기만의 네트워크 인터페이스와 IP를 가집니다. 이 인터페이스를 어디에 연결할지 정하는 것이 네트워크 드라이버이고, 한 대의 호스트에서는 대부분 bridge를 씁니다.

 

방식 동작 용도
bridge 호스트 안에 가상 스위치를 만들고 컨테이너를 연결
밖으로 나갈 때는 호스트 IP로 NAT
기본값, 한 호스트의 컨테이너
host 호스트의 네트워크를 그대로 사용
포트 매핑 없이 호스트 포트를 바로 씀
네트워크 성능이 중요한 경우
none loopback만 있고 외부 연결 없음 네트워크가 필요 없는 작업
overlay 여러 호스트를 하나의 네트워크로 묶음 Docker Swarm
macvlan 컨테이너에 물리 네트워크의 MAC과 IP를 직접 부여 기존 네트워크에 장비처럼 붙일 때

2. bridge 네트워크와 포트 매핑

bridge 네트워크는 호스트 안의 가상 스위치입니다. 같은 스위치에 꽂힌 컨테이너끼리는 서로 통신하고, 밖에서 들어오는 연결은 -p 옵션으로 연 호스트 포트를 통해서만 들어옵니다. 사무실 내선 전화와 비슷해서, 내선끼리는 바로 통화하고 외부 전화는 대표 번호로 받아 내선으로 돌려 줍니다.

호스트 8080 포트로 들어온 요청은 web 컨테이너의 80 포트로 전달되고, web은 cache라는 이름으로 Redis에 접속합니다

 

Docker를 설치하면 bridge라는 기본 네트워크가 있고, --network를 지정하지 않은 컨테이너는 모두 여기에 붙습니다. 하지만 기본 bridge에서는 컨테이너 이름으로 서로를 찾을 수 없어서, 실무에서는 docker network create로 사용자 정의 bridge를 만들어 씁니다.

 

항목 기본 bridge 사용자 정의 bridge
이름으로 접속 불가, IP로만 가능 가능(내장 DNS 127.0.0.11)
격리 관련 없는 컨테이너도 모두 같은 네트워크 연결한 컨테이너끼리만 통신
연결 변경 컨테이너를 다시 만들어야 함 실행 중에 연결·해제 가능

 

포트 매핑은 -p 호스트포트:컨테이너포트 형식이고, 호스트 IP를 생략하면 호스트의 모든 IP에서 열립니다. DB처럼 밖에 열 필요가 없는 서비스는 -p 127.0.0.1:6379:6379처럼 로컬 주소에만 열거나, 아예 포트를 열지 않고 같은 네트워크의 컨테이너만 접속하게 합니다.

3. 볼륨과 바인드 마운트

2편에서 본 것처럼 컨테이너 안에서 쓴 파일은 쓰기 계층에 있어서 컨테이너를 지우면 사라집니다. DB 파일처럼 남겨야 하는 데이터는 컨테이너 밖의 저장 공간을 컨테이너 안 경로에 연결(마운트)해서 씁니다. 컨테이너가 호텔 방이라면 볼륨은 체크아웃해도 남는 개인 보관함입니다.

볼륨과 바인드 마운트는 컨테이너를 지워도 남고, tmpfs는 메모리에만 있어 함께 사라집니다

 

타입 특징 용도
Volume Docker가 만들고 관리하는 저장 공간
docker volume 명령으로 관리
DB 데이터 등 운영 데이터
Bind mount 호스트의 특정 경로를 그대로 연결
호스트 폴더 구조와 권한에 영향을 받음
설정 파일, 개발 중 소스 코드
tmpfs 호스트 메모리에만 저장, 컨테이너가 멈추면 사라짐 임시 파일, 디스크에 남기면 안 되는 값

4. 직접 해 보기

Redis 컨테이너로 이름 기반 통신과 데이터 유지를 확인합니다. Redis 자체는 [Redis] Redis란? 인메모리 데이터 저장소 개념과 구성 방식 정리에서 다뤘습니다. 먼저 사용자 정의 bridge를 만들고, 같은 네트워크의 다른 컨테이너에서 이름으로 접속합니다.

docker network create app-net
docker run -d --name cache --network app-net redis:8-alpine
docker run --rm --network app-net redis:8-alpine redis-cli -h cache ping

PONG이 돌아오면 cache라는 이름이 IP로 바뀌어 접속된 것입니다. 같은 명령에서 --network app-net만 빼고 실행하면 기본 bridge에 붙어서 cache라는 이름을 찾지 못하고 실패합니다.

 

다음은 볼륨입니다. Redis가 데이터를 파일로 남기도록 --appendonly yes를 주고, 데이터 폴더인 /data에 볼륨을 연결합니다.

docker volume create cache-data
docker run -d --name store --network app-net -v cache-data:/data \
  redis:8-alpine redis-server --appendonly yes
docker exec store redis-cli set visits 10
docker stop store && docker rm store

컨테이너는 지웠지만 볼륨은 남아 있습니다. 같은 볼륨을 연결해 새 컨테이너를 띄우면 값이 그대로 있습니다. docker rm -f로 바로 지우면 Redis가 마지막 쓰기를 파일에 남기기 전에 종료될 수 있어서 docker stop으로 먼저 멈춥니다.

docker run -d --name store --network app-net -v cache-data:/data \
  redis:8-alpine redis-server --appendonly yes
docker exec store redis-cli get visits

"10"이 나오면 성공입니다. docker volume inspect cache-data로 보면 실제 저장 위치(Mountpoint)가 /var/lib/docker/volumes/cache-data/_data로 나옵니다. 실습이 끝나면 docker rm -f cache store, docker volume rm cache-data, docker network rm app-net 순서로 정리합니다.

5. 운영 시 주의점

항목 조치
방화벽 우회 -p로 연 포트는 Docker가 iptables 규칙을 직접 추가해 ufw 같은 호스트 방화벽 설정을 거치지 않음
외부에 열지 않을 포트는 127.0.0.1에만 바인딩
컨테이너 IP 재시작하면 바뀔 수 있으므로 IP 대신 컨테이너 이름으로 접속
기본 bridge 이름으로 접속이 안 되고 모든 컨테이너가 섞이므로 서비스마다 사용자 정의 bridge 사용
볼륨 삭제 docker volume prune, docker compose down -v는 데이터를 지움
실행 전에 대상 확인
바인드 마운트 권한 컨테이너 안 사용자의 UID와 호스트 폴더 소유자가 다르면 쓰기 실패
읽기만 하면 :ro로 연결
백업 볼륨도 호스트 디스크에 있으므로 호스트가 고장 나면 함께 잃음
DB는 DB 자체 백업 기능으로 따로 백업

6. 정리

  • 한 호스트에서는 사용자 정의 bridge를 만들어 컨테이너끼리 이름으로 통신하고, 밖에서 접속할 포트만 -p로 엽니다.
  • -p로 연 포트는 호스트 방화벽 설정을 거치지 않으므로, 내부용 포트는 127.0.0.1에만 엽니다.
  • 남겨야 하는 데이터는 볼륨에, 설정 파일은 바인드 마운트로 연결하고, 볼륨도 따로 백업합니다.

다음 글 5편에서는 지금까지 docker run으로 하나씩 만든 네트워크, 볼륨, 컨테이너를 Docker Compose 파일 하나로 묶습니다.

참고

728x90
서울
--:--:--
-전체 글
-카테고리
오늘 방문