Docker Volume 및 Docker 로 MySql 컨테이너 설정, 데이터 영구 저장

2022. 12. 1. 19:09·Docker

들어가며

이번 게시글에서는 Docker Volume 에 대한 이해 및 MySql 을 Docker 컨테이너로 세팅하고 데이터베이스 데이터를 영구적으로 저장하는 방법을 알아보고자 합니다.

Docker Volume

Docker 컨테이너에 저장되는 데이터는 기본적으로 Docker 컨테이너가 삭제될 때 함께 사라집니다.

그러나 MySql 컨테이너와 같이 DB를 구동하는 컨테이너에서는 Docker 컨테이너의 생성, 삭제 여부에 관계없이 데이터를 영속적으로 저장해야 합니다. 

이렇게 Docker 컨테이너의 생성, 삭제 여부와 관계없이 데이터를 영속적으로 저장할 수 있도록 Docker는 두가지 옵션을 제공합니다. 그 중 하나가 바로 Docker Volume 입니다.

 

Docker Volume 과 관련된 명령어는 다음과 같습니다.

volume 생성

$ docker volume create [volume 이름]
$ docker volume create testdb-volume

volume 조회

$ docker volume ls

volume 상세정보 보기

$ docker volume inspect [volume name]
$ docker volume inspect testdb-volume

volume 삭제

$ docker volume rm [volume name]
$ docker volume rm testdb-volume

Docker Volume 암시적 생성 및 제거

MySQL:latest image 의 Dockerfile 을 보면 다음과 같습니다.

# ...
VOLUME [/var/lib/mysql]
# ...

이는 해당 Docker image 가 실행될 때, 컨테이너 내의 /var/lib/mysql 디렉터리가 호스트 PC의 /var/lib/docker/volumes/${volume_name}/_data에 마운트된다는 의미입니다.

(volume 이름은 임의의 해쉬값으로 생성됩니다.)

 

mysql:latest 를 실행해 봅니다.

$ docker run --name testdb -e MYSQL_ROOT_PASSWORD=ron -d mysql

이렇게 하면, docker는 /var/lib/mysql 디렉토리를 외부 volume 을 사용해 마운트합니다.

다음 명령어로 실행된 docker 컨테이너에 마운트된 volume을 확인할 수 있습니다.

$ docker inspect testdb

출력된 결과를 보면, docker host 내 /var/lib/docker/volumes/fadc9f58e88133d456c5d7373a81aab77a7d82cc128cdfc0694bdd9485a3800f/_data 디렉토리가 있고, 이 경로의 내용이 /var/lib/mysql로 마운트되어 있음을 알 수 있습니다.

 

다음 명령을 실행하면 현재 docker host에 있는 volume 목록을 확인할 수 있습니다.

$ docker volume ls

출력된 volume 목록을 보면 해시값으로 volume 이름이 생성되어 있고, fadc9f58... 으로 시작하는 volume이 local 드라이버를 사용해 만들어져 있음을 알 수 있습니다. 

mysql 컨테이너가 마운트하고 있는 volume 에 기록을 남기기 위해 다음과 같이 testdb 라는 이름을 가진 데이터베이스를 만들어보겠습니다.

# mysql 클라이언트 접속
$ docker exec -it testdb mysql --password=ron
# testdb 데이터베이스 생성
$ create database testdb;
# mysql 클라이언트 빠져나오기
$ exit;

이제 testdb 컨테이너에는 testdb 라는 이름의 database 가 만들어졌습니다.

testdb 컨테이너 가동을 멈추고 다시 시작해보겠습니다.

# testdb 컨테이너 가동 중단
$ docker container stop testdb
# testdb 컨테이너 시작
$ docker container start testdb

# testdb 데이터베이스가 존재하는지 확인하기 위해 mysql 클라이언트 접속
$ docker exec -it testdb mysql --password=ron

# database 목록 확인
$ show databases;
# database 목록 확인 후 mysql 클라이언트 빠져 나오기
$ exit;

확인 결과 여전히 testdb database 가 남아있습니다.

 

그렇다면 아예 컨테이너를 삭제 후 다시 만들면 어떻게 될까?

# testdb 컨테이너 가동 중단
$ docker container stop testdb
# testdb 컨테이너 삭제
$ docker container rm testdb

# testdb 컨테이너 생성 및 시작
$ docker run --name testdb -e MYSQL_ROOT_PASSWORD=ron -d mysql

# testdb 컨테이너 상세정보 확인
$ docker inspect testdb

# docker volume 목록 확인
$ docker volume ls

testdb 컨테이너 상세정보 확인 결과는 다음과 같습니다.

처음에 만들었던 컨테이너의 volume 이름은 fadc9f58... 이었는데, 방금 만들어진 컨테이너의 volume 이름은 6ca7aea8e... 으로 바뀌었음을 알 수 있습니다.

 

docker volume 목록 확인 결과는 다음과 같습니다.

앞서 만들어졌던 volume 과 방금 만들어진 volume 이 전부 존재합니다.

 

그렇다면 처음에 만들었던 컨테이너에 존재하는 testdb 가 방금 만들어진 컨테이너에 존재할까요? 한번 확인해보겠습니다.

# testdb 데이터베이스가 존재하는지 확인하기 위해 mysql 클라이언트 접속
$ docker exec -it testdb mysql --password=ron

# database 목록 확인
$ show databases;
# database 목록 확인 후 mysql 클라이언트 빠져 나오기
$ exit;

testdb 라는 이름의 db 가 존재하지 않습니다.

 

이렇게 docker 가 암시적으로 만든 volume은 docker 컨테이너가 docker stop 되고 docker rm, 즉 제거될 때 함께 제거됩니다. 따라서 새로운 docker 컨테이너 생성 시 새로운 volume 이 생성됩니다.

Docker Volume의 명시적 생성

docker 컨테이너의 생성, 삭제 여부에 상관없이 데이터를 영속적으로 저장하기 위해서는 컨테이너 생성 시 명시적으로 volume 을 만들어 사용합니다. 이렇게 생성된 volume은 컨테이너가 제거된 다음에도 계속 남아 있습니다.

 

다음 명령을 실행해 명시적으로 volume 을 생성할 수 있습니다.

# testdb-volume 이름을 가진 volume 생성(명시적 volume 생성)
$ docker volume create testdb-volume

# volume 목록 확인
$ docker volume ls

이렇게 생성된 명시적 volume은 다음 명령을 실행해 docker image에 정의된 volume의 마운트 디렉토리에 연결할 수 있습니다.

$ docker run --rm -d --name testdb -e MYSQL_ROOT_PASSWORD=ron -v testdb-volume:/var/lib/mysql mysql

--rm 옵션 : 컨테이너 가동을 멈출 때 제거하겠다는 의미입니다.

-v 옵션 : 명시적으로 만든 volume을 /var/lib/mysql 의 경로에 매핑하도록 했습니다. 

혹시 컨테이너가 제거되더라도 이 volume 은 docker host 내에 유지됩니다.

# mysql 클라이언트 접속
$ docker exec -it testdb mysql --password=ron
# testdb 데이터베이스 생성
$ create database testdb;
# mysql 클라이언트 빠져나오기
$ exit;

 

이 testdb 컨테이너를 중지하면, 완전히 --rm 옵션으로 인해 컨테이너가 삭제되지만, volume은 여전히 남아있음을 알 수 있습니다.

# testdb 컨테이너 가동 중지
$ docker stop testdb

# 컨테이너 목록 확인
$ docker container ls --all

# Volume 목록 확인
$ docker volume ls

 

이제 testdb 컨테이너를 다시 만들어보고 이전에 삭제된 컨테이너에서 생성한 testdb 데이터베이스가 존재하는지 확인해보겠습니다.

# testdb 컨테이너 생성
$ docker run --rm -d --name testdb -e MYSQL_ROOT_PASSWORD=ron -v testdb-volume:/var/lib/mysql mysql

# mysql 클라이언트 접속
$ docker exec -it testdb mysql --password=ron

# 데이터베이스 목록 확인
$ show databases;

# mysql 클라이언트 빠져 나오기
$ exit

testdb-volume에 저장되어 있던 testdb 라는 데이터베이스는 여전히 존재함을 알 수 있습니다

결론

docker 컨테이너의 생성, 삭제 여부에 상관없이 데이터를 영속적으로 저장하기 위해서는 컨테이너 생성 시 명시적으로 volume 을 만들어 사용해야 합니다. 이렇게 생성된 volume은 컨테이너가 제거된 다음에도 계속 남아 있습니다.

출처

https://joont92.github.io/docker/volume-container-%EC%B6%94%EA%B0%80%ED%95%98%EA%B8%B0/ 

 

[docker] volume container 추가하기

volume container란? 일반적으로 docker container는 컨테이너 내부에 데이터를 관리하므로, 컨테이너가 파기되면 데이터가 모두 날라가게 된다 이는 mysql 같은 데이터 스토리지를 사용할 경우 위험하게

joont92.github.io

https://24hours-beginner.tistory.com/282 

 

[docker] ubuntu에서 docker를 이용하여 database 구축하기 (mariadb)

0. docker? 더보기 https://24hours-beginner.tistory.com/236 [Docker] 도커란? 내가 생각했을 때 도커의 설명은 아키텍쳐로 끝나는듯 하다. Docs가 잘 되어 있으니 Docs를 읽자. https://docs.docker.com/get-started/overview/ Do

24hours-beginner.tistory.com

https://www.youtube.com/watch?v=YK-V8aq32WA 

 

'Docker' 카테고리의 다른 글

[Docker] vi: command not found 에러 해결  (0) 2022.12.02
로컬에서 Docker 를 이용한 Express 서버 어플리케이션 개발  (0) 2022.12.01
도커 컨테이너 환경변수 주입  (0) 2022.11.10
계속해서 restart 상태인 컨테이너 디버깅하기  (0) 2022.11.10
[Error] unable to start container process: exec: "bash"  (0) 2022.11.10
'Docker' 카테고리의 다른 글
  • [Docker] vi: command not found 에러 해결
  • 로컬에서 Docker 를 이용한 Express 서버 어플리케이션 개발
  • 도커 컨테이너 환경변수 주입
  • 계속해서 restart 상태인 컨테이너 디버깅하기
rondeveloper
rondeveloper
  • rondeveloper
    Ron's learning record
    rondeveloper
  • 전체
    오늘
    어제
    • 분류 전체보기 (102)
      • k8s (2)
      • AWS (1)
      • 리눅스 (5)
      • Docker (8)
      • 라이브러리 & 프레임워크 (14)
        • React (2)
        • NestJS (8)
        • Spring (0)
        • Django (3)
        • FastAPI (1)
      • 웹 (2)
        • Nginx (1)
      • 프로그래밍 언어 (29)
        • HTML (0)
        • CSS (0)
        • JavaScript (21)
        • Python (3)
        • Node.js (0)
        • TypeScript (4)
        • Java (1)
      • Today I learned (9)
      • 알고리즘 (9)
        • 백준 (0)
        • 프로그래머스 (8)
        • 개념 (1)
      • 티끌모아 태산 (5)
        • 하루에 영단어 하나씩 (5)
        • 독서 (0)
      • 시행착오 (3)
      • 데이터베이스 (2)
        • MySQL (0)
      • 컴퓨터 과학 (8)
        • 네트워크 (2)
        • 운영체제 (0)
        • 데이터베이스 (2)
        • 자료구조 (4)
      • 포트폴리오 (4)
        • JJINCAFE IN SEOUL (4)
        • CODEUNICORN (0)
      • 회고 (0)
      • CICD (1)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    생활코딩
    redis
    IP 주소
    Python
    프로그래머스
    nestjs
    리눅스
    조인
    컨테이너
    Kubectl
    코딩테스트
    Kubernetes
    도커
    Til
    javascript
    레벨2
    mysql
    배열
    기초
    모듈
    typeorm
    FastAPI
    typescript
    Docker
    스택
    반복문
    자바스크립트
    iterable
    django
    네트워크
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.5
rondeveloper
Docker Volume 및 Docker 로 MySql 컨테이너 설정, 데이터 영구 저장
상단으로

티스토리툴바