
위의 그림에서 보면 컨테이너 계층과 이미지 계층으로 나누어져 있는 것을 볼 수 있습니다.
보통 우리가 도커 이미지를 빌드 할 때 docker build -t app [경로] 명령어를 실행하면 Dockerfile이라는 명세서를 기반으로 도커 이미지가 빌드가 됩니다.
이 이미지는 레이어 구조로 되어있는데, Dockerfile 내에 작성되어 있는 여러 명령어들이 순차적으로 레이어가 쌓이듯이 저장된다고 보면 됩니다.
예를 들어, 우분투 이미지를 Base로 사용한다고 하면
Layer 1 : Base 우분투 레이어 설치
Layer 2 : 우분투 운영체제에서 필요로 하는 패키지들을 설치(ex. apt-get으로 패키지 설치하는 내용)
Layer 3 : 패키지를 설치(ex. 파이썬 패키지를 설치한다.)
Layer 4 : 소스코드를 복사를 한다면 복사한 내용이 Layer4에 저장(ex. 소스코드의 수정)
Layer 5 : Entrypoint 업데이트(ex. 컨테이너의 Entrypoint를 변경을 한다.)
도커 컨테이너와 이미지는 레이어 구조를 취하면서 여러 장점을 가지게 됩니다.
만약, 추후에 이미지에 특정 변경사항을 가한다고 했을 때, 만약 소스코드 상에 변경이 있었다면 Layer 1 ~ Layer 3까지는 변경될 필요가 없습니다.
그러므로, Layer 1 ~ Layer 3까지는 변경을 하지 않고 Layer 4, Layer 5가 생성이 됩니다.
이러한 방식으로 도커 이미지는 이미지의 여러 버전들이 생긴다고 하더라도 저장 공간을 차지하지 않는 레이어 구조를 가지고 있습니다.
이 도커 이미지를 도커 컨테이너로 docker run 명령어로 이미지를 실행하면 컨테이너가 됩니다.
실행한 컨테이너는 두 가지 레이어를 가지게 됩니다.
첫 번째는 이미지 계층(Image Layer), 두 번째는 컨테이너 계층(Container Layer)입니다.
- 이미지 계층(Image Layer)에서 이미지는 항상 동일하고 Read Only(읽기 전용)으로 사용하게 됩니다. 이 읽기 전용 이미지 레이어에는 변경사항을 적용할 수 없습니다.
- 컨테이너 계층(Container Layer)은 컨테이너 상에서 새로운 파일을 쓴다거나 할 때는 기본적으로 Container Layer에 파일을 쓰게 되는데, 이 Container Layer는 Read Write 권한을 가지고 있습니다. 중요한 점은 컨테이너가 종료되고 나면 Container Layer는 컨테이너 종료 시 함께 삭제가 됩니다.

도커 이미지로 컨테이너를 생성하면 이미지는 읽기 전용이 되며 컨테이너의 변경 사항만 별도로 저장해서 각 컨테이너의 정보를 보존합니다. 이미 생성된 이미지는 읽기 전용이므로 어떠한 경우로도 변경되지 않고, 컨테이너 계층에 원래 이미지에서 변경된 파일시스템 등을 저장합니다.
이미지에 mysql을 실행하는 데 필요한 애플리케이션 파일이 들어있다면 컨테이너 계층에는 워드프레스에서 쓴 로그인 정보나 게시글 등과 같이 데이터베이스를 운용하면서 쌓이는 데이터가 저장됩니다. 예를 들면, 위에서 생성했던 mysql 컨테이너는 mysql:5.7라는 이미지로 생성됐지만 wordpress 블로그를 위한 데이터베이스 등의 정보는 컨테이너가 갖고 있습니다. 즉, 위의 그림과 같은 구조가 됩니다.
그러나, 여기에는 치명적인 단점이 존재합니다. mysql 컨테이너를 삭제하면 컨테이너 계층에 저장되어 있던 데이터베이스의 정보도 삭제된다는 점입니다. 도커의 컨테이너는 생성과 삭제가 매우 쉬우므로 실수로 컨테이너를 삭제하면 데이터를 복구할 수 없게 됩니다. 이를 방지하기 위해 컨테이너의 데이터를 영속성(Persistent) 데이터로 활용할 수 있는 방법이 몇 가지 있습니다. 그중 가장 활용하기 쉬운 방법이 바로 볼륨(Volume)을 활용하는 것입니다.
즉. Docker volume(볼륨)은 컨테이너와 호스트 운영체제 간에 데이터를 공유하거나 저장하기 위한 기능으로, 볼륨을 사용하면 데이터의 지속성을 유지하면서 컨테이너를 생성하거나 삭제할 수 있다. Docker 볼륨은 컨테이너의 파일 시스템이나 디렉토리를 호스트 시스템의 특정 경로와 연결하여 데이터를 저장하고 관리할 수 있도록 해준다.
Docker 볼륨을 사용하는 주요 이점은 다음과 같다.
- 데이터 지속성 : 컨테이너가 종료되더라도 볼륨에 저장된 데이터는 유지. 이를 통해 컨테이너 재시작, 업데이트, 삭제 등의 작업에서 데이터를 보존할 수 있음.
- 공유 데이터 : 여러 컨테이너 간에 데이터를 공유하거나 컨테이너와 호스트 간에 데이터를 주고받을 수 있음.
- 백업 및 복원 : 볼륨을 사용하여 중요한 데이터를 백업하고 필요한 경우 복원할 수 있음.
2. 컨테이너 상에서 볼륨을 영구적으로 사용할 수 있는 방법
(1) 호스트 볼륨 공유하기
호스트 볼륨을 이용한다는 것은 호스트 운영체제의 디렉터리를 컨테이너 내에 마운트 시키는 작업을 말하며 가장 간단하고 직관적인 방법입니다.
아래 명령어를 입력해서 mysql 데이터베이스 컨테이너를 실행해 줍니다.
아래 명령어를 입력해서 워드프레스 웹 서버 컨테이너를 생성합니다.
워드프레스 컨테이너에 -p 옵션으로 컨테이너의 80 포트를 외부에 노출했으므로 docker ps 명령어에서 확인한 wordpress_hostvolume 컨테이너의 호스트 포트로 워드프레스 컨테이너에 접속할 수 있습니다.
중요한 점은 -v 옵션으로 /home/wordpress_db:/var/lib/mysql로 설정해 준 것입니다.
이는 호스트의 /home/wordpress_db 디렉터리와 컨테이너의 /var/lib/mysql 디렉터리를 공유한다는 뜻입니다.
즉, -v 옵션에 [호스트의 공유 디렉터리]:[컨테이너의 공유 디렉터리]를 입력해 주면 됩니다.
만약, /home/wordpress_db 디렉터리를 호스트에 생성하지 않았어도 도커는 자동으로 이를 생성해 줍니다.
실제로 데이터베이스 관련 파일이 있는지 확인합니다.

mysql을 구동하는 데 필요한 각종 파일이 공유되었습니다. mysql, performance_schema, sys, wp 디렉터리는 mysql에 존재하는 실제 데이터베이스에 대응됩니다.
컨테이너를 삭제하고 데이터베이스의 데이터가 보존되는지 확인합니다. 다음 명령어를 입력해 방금 생성한 두 개의 컨테이너를 삭제합니다.
다시 /home/wordpress_db 디렉터리를 확인하면 mysql 컨테이너가 사용한 데이터가 그대로 남은 것을 확인할 수 있습니다.

-v 옵션을 써서 컨테이너의 디렉터리를 호스트와 공유한 것을 그림으로 나타내면 아래와 같습니다.

컨테이너의 /var/lib/mysql 디렉터리는 호스트의 /home/wordpress_db 디렉터리와 동기화되는 것이 아니라 완전히 같은 디렉터리입니다.
위 예시의 경우 원래 호스트에는 /home/wordpress_db 디렉터리가 존재하지 않았습니다. -v 옵션을 사용함으로써 호스트에 /home/wordpress_db 디렉터리가 생성되었고, 이 디렉터리에 파일이 공유되었습니다. 결과적으로 컨테이너의 파일이 호스트로 파일이 복사된 것입니다.

만약, 호스트에 이미 디렉터리와 파일이 존재하고 컨테이너에도 존재한다면 어떻게 될까요?
예를 들면, volume_test라는 이미지가 있고 이 이미지에는 /home/testdir 디렉터리가 존재하고 그 안에 test라는 파일이 존재합니다.
그리고, 아래 명령어를 통해 컨테이너를 생성하고 -v 옵션으로 호스트 볼륨을 공유합니다.
그러면 -v 옵션의 값인 /home/tesdir 디렉터리를 확인하면 원래 존재했던 test 파일이 없어지고 호스트에서 공유된 파일만 존재하게 됩니다.
즉, 이미지에 원래 존재하던 디렉터리에 호스트의 볼륨을 공유하면 컨테이너의 디렉터리 자체가 덮어씌워집니다. 정확히 말하면 -v 옵션을 통한 호스트 볼륨 공유는 호스트의 디렉터리를 컨테이너의 디렉터리에 마운트 합니다.
또한, 아래처럼 디렉터리 단위의 공유뿐 아니라 단일 파일 단위의 공유도 가능하며 동시에 여러 개의 -v 옵션을 쓸 수도 있습니다.
(2) 볼륨 컨테이너

볼륨 컨테이너를 이용하는 방법은 볼륨을 특정 애플리케이션 컨테이너에서 마운트를 시키는 것이 아니라, 볼륨 컨테이너(위 그림에서 Data-only Container)에서 볼륨 마운트만 진행을 하고 아무것도 하지 않는 컨테이너를 만들어서 애플리케이션 컨테이너가 볼륨 컨테이너를 참조하게 해서 마치 볼륨 컨테이너같이 사용할 수 있습니다. 그러면 Data-only Container의 마운트 목록을 애플리케이션 컨테이너가 공유 받을 수 있습니다.
컨테이너를 생성할 때 -v 옵션 대신 --volumes-from 옵션으로 컨테이너를 지정하면 -v 또는 --volume 옵션을 적용한 컨테이너의 볼륨 디렉터리를 공유할 수 있습니다. 이는 직접 볼륨을 공유하는 것이 아닌 -v 옵션을 적용한 컨테이너를 통해 공유하는 것입니다.
먼저 호스트 볼륨을 공유하는 volume_override 라는 이름의 컨테이너를 생성해 줍니다. volume_override 컨테이너는 우분투 포칼 이미지를 이용하고 있고 호스트의 $(pwd)/html를 /user/share/nginx/html에 마운트를 하고 있습니다.
그리고 아래 명령어를 입력하여 --volumes-from 옵션을 사용하여 volume_override 컨테이너에서 볼륨을 공유 받는 컨테이너를 생성해 줍니다.
docker ps로 확인하면 volume_override, seunghwan_nginx1, seunghwan_nginx2 세 개의 컨테이너가 정상적으로 실행이 된 것을 확인할 수 있습니다.


--volumes-from 옵션을 적용한 컨테이너와 볼륨 컨테이너 사이의 관계를 그림으로 나타내면 위 그림과 같습니다.
여러 개의 컨테이너가 동일한 컨테이너에 --volumes-from 옵션을 사용함으로써 하나의 볼륨을 공유해서 사용할 수 있습니다.
이러한 구조를 활용하여 호스트에서 볼륨만 공유하고 별도의 역할을 하지 않는 일명 '볼륨 컨테이너'로 활용해서 컨테이너를 활용할 수 있습니다. 즉, -v 대신 --volumes-from 옵션을 사용함으로써 볼륨 컨테이너를 연결해 데이터를 간접적으로 공유 받는 방식입니다.
docker inspect seunghwan_nginx1를 입력해서 Mounts 목록에 보면 Source와 Destination을 보면
호스트의 /home/ubuntu/html -> 컨테이너의 /usr/share/nginx/html 로 마운트 된 것을 확인할 수 있습니다.

docker exec 명령어로 seunghwan_nginx1 컨테이너에 접속해서 /usr/share/nginx/html에 마운트가 잘 되었는지 확인해 보겠습니다.
아래 결과를 보시면 정상적으로 마운트가 잘 된 것을 확인할 수 있습니다.

(3) 도커 볼륨
볼륨을 사용하는 세 가지 방법 중 도커 볼륨은 도커에서 제공하는 볼륨 관리 기능입니다.
볼륨을 사용하는 방법 중 보통 호스트 볼륨이나 도커 볼륨을 가장 많이 사용합니다.
호스트 볼륨과의 차이점은 호스트에 마운트 할 경로를 지정했어야 했지만
도커 볼륨은 도커가 제공하는 볼륨 관리 기능을 통해서 볼륨을 생성하고 삭제하고 관리를 할 수 있습니다.
이렇게 생성된 볼륨은 도커가 관리하는 특정 호스트 경로에 데이터가 저장이 됩니다.
기본적으로는 도커에 데이터가 저장되는 /var/lib/docker/volumes/{...}/_data 에 데이터가 저장되는데
구체적으로는 /var/lib/docker/volumes/volume이름/_data에 도커 디렉터리에 볼륨 이름으로 데이터가 생성되고 데이터가 저장됩니다.
도커 볼륨을 다루는 명령어는 docker volume으로 시작합니다.
docker volume 명령어로 생성한 볼륨은 아래와 같은 구조로 활용됩니다. 도커 볼륨도 마찬가지로 여러 개의 컨테이너에 공유되어 활용될 수 있습니다.

① 도커 볼륨 생성
docker volume create 명령어로 도커 볼륨을 생성할 수 있습니다.

② 도커 볼륨 목록 확인
docker volume ls 명령어로 생성된 볼륨을 확인할 수 있습니다.

③ 도커 볼륨 정보 확인
docker volume inspect 명령어로 마운트 경로 등의 볼륨 정보를 확인할 수 있습니다.
Driver는 볼륨이 쓰는 드라이버를, Label은 볼륨을 구분하는 라벨을 나타내며, Mountpoint는 해당 볼륨이 실제로 호스트의 어디에 저장됐는지를 의미합니다.

위의 명령어를 보면 먼저, docker volume create 명령어를 통해서 myvolume이라는 이름의 볼륨을 생성해 줍니다.
그리고 생성한 myvolume 도커볼륨을 mysql 컨테이너를 띄울 때 /var/lib/mysql 컨테이너 경로에다가 마운트 해줍니다.
형식은 아래와 같습니다.
* 참고로 /var/lib/mysql 경로는 mysql이 데이터를 쌓는 경로.

mysql이 실행되면서 공유 디렉터리인 컨테이너의 /var/lib/mysql 디렉터리도 같이 초기화가 되고
결국, 도커 볼륨도 같이 공유하므로 ls 명령어로 확인해 보면 마찬가지로 초기화되어 있는 것을 확인할 수 있습니다.
seunghwan_mysql 컨테이너가 myvolume 컨테이너를 사용하는지 확인하는 다른 방법은
docker container inspect 명령어를 이용하는 것입니다. docker container inspect 명령어는 컨테이너의 상세한 정보를 출력하는데, 그중 볼륨 마운트에 대한 정보도 포함되어 있기 때문입니다.

Source 항목에 도커 볼륨의 경로가 출력되고, Destination에 공유 디렉터리의 경로가 출력되었습니다.

참고로, 도커 볼륨의 내용물 중 ibdata1을 제거해 주고 실행해 주세요. 제거하지 않으면 아래와 같은 에러가 발생합니다.
발생하는 이유는 mysql 데이터와의 충돌 문제가 발생합니다. 제거해도 어차피 다시 재생성 되므로 안심하고 삭제하셔도 됩니다.
'Docker' 카테고리의 다른 글
[Docker] 도커 이미지 - 개념 정리 및 명령어(생성, 삭제, 추출) (0) | 2025.02.19 |
---|---|
[Docker] 도커 컨테이너 - 컨테이너 로깅(Logging) (0) | 2025.02.19 |
[Docker] 도커 네트워크 명령어 정리 (1) | 2025.02.19 |
[Docker] 도커 네트워크 구조 (0) | 2025.02.19 |
[Docker] 도커 컨테이너 - 라이프사이클 및 명령어 (0) | 2025.02.19 |