포스트

Docker 기초 (7) - Volumes, Bind Mounts, and Networks

named volume과 bind mount부터 user-defined network, container 안 localhost의 함정까지 데이터 보존과 container 간 통신을 정리합니다.

Docker 기초 (7) - Volumes, Bind Mounts, and Networks

Docker 기초 시리즈의 7편입니다. 전체 목차는 0편에 있습니다.

volume과 bind mount

container 안에서 만든 파일은 그 container를 rm 하는 순간 사라집니다. 4편의 MySQL 예제에서 -v mysql-data:/var/lib/mysql을 뺐다면, container 삭제와 함께 INSERT 한 데이터도 삭제됩니다. 경고는 없습니다.

남길 데이터는 volume으로 container 밖에 둡니다. 방식은 두 가지입니다.

1
2
3
4
5
# 1) named volume: Docker가 관리하는 저장 공간
docker run -v mysql-data:/var/lib/mysql mysql:8.4

# 2) bind mount: 호스트의 경로를 그대로 연결
docker run -v $(pwd)/data:/app/data ml-study:0.1
 named volumebind mount
저장 위치Docker가 관리하는 영역호스트의 지정한 경로
적합한 데이터DB 데이터처럼 Docker 안에서만 쓰는 상태소스 코드, 데이터셋처럼 호스트에서도 다루는 파일
macOS 성능빠르다 (VM 내부에 있다)VM 경계를 넘느라 느릴 수 있다

bind mount는 개발 중에 특히 유용합니다. 호스트에서 코드를 고치면 container 안에 즉시 반영되므로, 수정할 때마다 image를 다시 빌드할 필요가 없습니다.

1
2
3
docker volume ls          # volume 목록
docker volume inspect mysql-data
docker volume rm mysql-data   # 사용 중인 container가 없어야 삭제된다

정리하면 image에는 코드와 의존성을, volume에는 상태를 담습니다. 이 분리가 “container는 언제든 지우고 다시 만든다”를 가능하게 합니다.

Network

container끼리 통신하려면 서로를 가리킬 주소가 필요합니다. user-defined network를 만들고 두 container를 같은 network에 넣으면, container 이름이 hostname이 됩니다.

1
2
3
docker network create dev
docker run -d --name pg --network dev -e POSTGRES_PASSWORD=dev postgres:16
docker run --rm -it --network dev postgres:16 psql -h pg -U postgres

두 번째 container가 -h pg, 즉 container 이름으로 접속합니다. 같은 network 안의 통신에는 -p가 필요 없습니다. -p는 호스트(밖)에서 container로 들어올 때만 필요한 옵션입니다.

방향별로 정리하면 다음과 같습니다.

  • container에서 container로: 같은 user-defined network에 두고 container 이름으로 접속합니다
  • 호스트에서 container로: -p로 연 포트를 통해 localhost로 접속합니다
  • container에서 호스트로: Docker Desktop은 host.docker.internal이라는 예약 주소를 제공합니다. Linux에서는 --add-host=host.docker.internal:host-gateway를 붙여야 같은 주소를 쓸 수 있습니다

container 안의 localhost

호스트에서 잘 되던 DB 접속이 container 안에서만 connection refused가 나는 증상은 대부분 이 함정입니다. container는 격리된 네트워크 공간을 가지므로, container 안의 localhost는 호스트가 아니라 container 자신을 가리킵니다. 접속 대상이 다른 container면 network와 이름으로, 호스트의 프로세스면 host.docker.internal로 접속해야 합니다.

다음 편에서 지금까지의 run 옵션과 network 구성을 파일 하나로 선언하는 Docker Compose를 다룹니다.

다음 글: Docker 기초 (8) - Docker Compose and Operations

이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.