본문 바로가기
Cloud/Docker

도커 볼륨

by 민휘 2023. 4. 22.
도커 볼륨 필요한 이유 : 컨테이너 레이어에 쌓인 데이터는 컨테이너와 함께 삭제되므로 보관 필요
호스트와 볼륨 공유 : 컨테이너의 데이터 디렉터리를 호스트 디렉터리에 공유. 컨테이너 -> 호스트
볼륨 컨테이너 사용 : 위의 방법으로 만든 볼륨 컨테이너를 통해 호스트 디렉터리에 접근 가능한 컨테이너 실행. 컨테이너 -> 볼륨컨테이너 -> 호스트
도커 볼륨 사용 : 도커가 제공하는 볼륨이 데이터 저장소, 볼륨을 공유받는 컨테이너 실행. 컨테이너 -> 도커 볼륨

 

도커 볼륨이 필요한 이유

컨테이너 구조는 읽기 전용인 도커 이미지와 컨테이너를 운용하면서 쌓이는 데이터를 저장하는 컨테이너 레이어로 나뉜다. 이때 컨테이너를 삭제하면 데이터도 함께 삭제된다. 컨테이너는 삭제가 쉬워서 데이터를 보존할 필요가 있다. 컨테이너 데이터를 영속적인 데이터로 활용하는 쉬운 방법이 볼륨을 활용하는 것이다.

 

1. 호스트와 볼륨 공유

컨테이너의 데이터 디렉터리를 호스트 디렉터리에 공유한다.

컨테이너가 삭제되어도 데이터는 삭제되지 않을 것이다.

docker run 명령어에 -v [호스트 공유 디렉터리:컨테이너 공유 디렉터리] 옵션을 주면 된다.

 

mysql 컨테이너 디렉터리 공유하기

mysql 컨테이너의 기본 디렉터리는 /var/lib/mysql이다.

컨테이너의 디렉터리를 호스트에 미리 생성해둔 /home/wordpress_db에 공유하도록 설정한다.

docker run -d \\
> --name wordpressdb_hostvolume \\
> -e MYSQL_ROOT_PASSWORD=password \\
> -e MYSQL_DATABASE=wordpress \\
> -v /Users/minhwi/Docker_Volume/wordpress_db:/var/lib/mysql \\
> mysql

 

☄️ Mounts Denied Error

 

처음 이 명령어를 실행했을 때 Mounts Denied 오류를 만났다.

docker: Error response from daemon: Mounts denied:
The path /home/wordpress_db is not shared from the host and is not known to Docker.
You can configure shared paths from Docker -> Preferences... -> Resources -> File Sharing.
See <https://docs.docker.com/desktop/mac> for more info.

호스트 디렉터리에 도커가 mount 하는 권한이 없어서 발생한 오류이다.

도커 클라이언트에서 Preferences -> Resources -> FILE SHARING 메뉴에서 마운트 할 경로를 추가했다.

호스트의 /Users/minhwi/Docker_Volume/wordpress_db 폴더 안에 데이터베이스 관련 파일이 들어온 것을 볼 수 있다. 컨테이너를 삭제해도 데이터가 그대로 남아있다.

 

디렉터리 마운팅

아까 오류 메시지에서 Mount Denied 라는 메시지를 보았다.

도커가 호스트 디렉터리 관련 작업을 하다가 권한 거부를 받았을 것이다.

이때 mount는 무슨 뜻일까?

 

mount는 보조 기억 장치나 파일 시스템이 접근할 수 있는 경로를 디렉터리 구조에 편입시키는 작업이다.

컨테이너에 적용하면 외부 저장 장치는 컨테이너 디렉터리일 것이고, 디렉터리 구조는 호스트 디렉터리일 것이다.

도커가 컨테이너의 디렉터리를 호스트 디렉터리에 연결하던 과정에서 호스트 디렉터리에 접근할 수 있는 권한이 없어 해당 오류가 난 것으로 이해할 수 있다.

 

내부 동작

처음에 디렉터리를 공유한다고 했는데,

좀더 구체적으로 이야기하면 디렉터리에 동기화되는 것이 아니라

완전히 같은 디렉터리를 사용하게 된다. (참조가 같다는 뜻인가??)

호스트에 존재하지 않는 디렉터리를 공유하겠다고 넘겨주면,

호스트에 새 디렉터리가 생성되고 컨테이너 파일이 호스트로 복사된다.

반면 이미 파일이 들어있는 디렉터리를 공유한다고 넘겨주면,

원래 있던 파일은 사라지고 컨테이너 파일로 덮어씌워진다.

 

 

2. 볼륨 컨테이너

호스트 디렉터리를 마운트한 볼륨 컨테이너를 다른 컨테이너에 공유받는 방식이다.

볼륨을 공유받은 컨테이너는 볼륨 컨테이너를 통해 호스트 디렉터리를 간접적으로 사용한다.

볼륨 컨테이너를 만들자. 호스트 디렉터리 /Users/minhwi/Docker_Volume/wordpress_db 에 mysql 컨테이너의 기본 컨테이너인 /var/lib/mysql를 마운트했다.

docker run -d \\
--name wordpressdb_hostvolume \\
-e MYSQL_ROOT_PASSWORD=password \\
-e MYSQL_DATABASE=wordpress \\
-v /Users/minhwi/Docker_Volume/wordpress_db:/var/lib/mysql \\
mysql

 

--volumes-from 볼륨 컨테이너 이름 을 통해 공유받은 컨테이너를 실행했다.

내부에 들어가서 컨테이너의 디렉터리를 확인해보면 볼륨의 파일 내용을 확인할 수 있다.

docker run -it \\
--name volume_from_container \\
--volumes-from wordpressdb_hostvolume \\
ubuntu:14.04

root@bc5f5c9a5098:/# ls /var/lib/mysql
#ib_16384_0.dblwr  auto.cnf       binlog.000004  ca.pem           ibdata1    mysql.sock          server-cert.pem  undo_002
#ib_16384_1.dblwr  binlog.000001  binlog.000005  client-cert.pem  ibtmp1     performance_schema  server-key.pem   wordpress
#innodb_redo       binlog.000002  binlog.index   client-key.pem   mysql      private_key.pem     sys
#innodb_temp       binlog.000003  ca-key.pem     ib_buffer_pool   mysql.ibd  public_key.pem      undo_001

 

3. 도커가 관리하는 볼륨 생성

도커가 제공하는 볼륨을 활용해 데이터를 보존할 수 있다.

docker volume으로 시작하는 명령어를 사용한다.

 

✅ 도커 볼륨 생성

myvolume 이름을 가진 볼륨을 생성한다.

docker volume create --name myvolume

 

✅ 도커 컨테이너 공유받기

도커를 실행할 때 -v [볼륨 이름:컨테이너 디렉터리] 옵션으로 컨테이너가 사용할 볼륨을 지정한다.

이 컨테이너는 myvolume 볼륨을 공유받는다.

docker run -it --name myvolume_1 \\
-v myvolume:/root/ \\
ubuntu:14.04

 

볼륨에 데이터를 써보자.

컨테이너 /root 하위에 volume 파일을 만들고 hello, volume!을 작성했다.

root@8290959e7857:/# echo hello, volume! >> /root/volume
root@8290959e7857:/# exit

 

✅ 도커 볼륨 생성과 동시에 컨테이너 공유받기

myvolume 볼륨을 공유하는 다른 컨테이너를 실행했다.

컨테이너의 공유 디렉터리를 통해 볼륨에 쓴 데이터를 확인할 수 있다.

-v 볼륨이름:컨테이너디렉터리 옵션을 사용한다.

docker run -it --name myvolume_2 \\
-v myvolume:/root/ \\
ubuntu:14.04

root@3d5ea6e82f5f:/# cat /root/volume
hello, volume!

 

—mount 옵셥으로도 동일한 기능을 실행할 수 있다.

프로퍼티 이름을 작성할 수 있어 더 가독성이 좋은 것 같다.

docker run -it --name mount_option_1 \\
--mount type=volume,source=myvolume,target=/root \\
ubuntu:14.04

 

호스트의 디렉터리를 컨테이너 내부에 마운트할 경우 타입을 bind로 지정한다.

이때 source는 호스트 디렉터리 경로를 지정한다.

docker run -it --name mount_option_2 \\
--mount type=bind,source=/Users/minhwi/Docker_Volume,target=/root \\
ubuntu:14.04

 

볼륨을 공유받는 컨테이너 정보는 docker container inspect로 확인할 수 있다.

docker container inspect myvolume_1

# 결과
"Mounts": [
            {
                "Type": "volume",
                "Name": "myvolume",
# 호스트 디렉터리   "Source": "/var/lib/docker/volumes/myvolume/_data",
                "Destination": "/root",
                "Driver": "local",
                "Mode": "z",
                "RW": true,
                "Propagation": ""
            }
        ],

 

만든 도커 볼륨을 확인하고 삭제할 때는 이렇게.

docker volume ls
docker volume prune