공부/docker

도커 교과서 ch06 (도커 볼륨)

KidAnt 2023. 12. 20. 16:28

도커 컨테이너에도 단일 드라이브로 된 파일시스템이 존재 -> 이미지 속 파일로 생성된다.

모든 컨테이너는 독립된 파일 시스템을 갖는다. -> 같은 이미지로 만든 컨테이너라도 추 후에 하나를 수정해도 나머지는 영향이 없다.

실습
user@DESKTOP-KU8L7UV:~/080258/ch06/exercises/random-number/linux$ sudo docker container run --name rn1 diamol/ch06-random-number
[sudo] password for user:
Unable to find image 'diamol/ch06-random-number:latest' locally
latest: Pulling from diamol/ch06-random-number
(중략)
user@DESKTOP-KU8L7UV:~/080258/ch06/exercises/random-number/linux$ sudo docker container run --name rn2 diamol/ch06-random-nu
mber

user@DESKTOP-KU8L7UV:~/080258/ch06/exercises/random-number/linux$ sudo docker container ls --all
CONTAINER ID   IMAGE                       COMMAND                  CREATED         STATUS                     PORTS     NAMES
bce599efd844   diamol/ch06-random-number   "/bin/sh -c ./random…"   2 minutes ago   Exited (0) 2 minutes ago             rn2
506312c5e2e6   diamol/ch06-random-number   "/bin/sh -c ./random…"   3 minutes ago   Exited (0) 3 minutes ago             rn1

#두 컨테이너는 같은 이미지지만 파일 시스템의 내용은 서로 다르다.

#docker container cp 명령으로 컨테이너와 로컬 컴퓨터 간 파일 복사하기
user@DESKTOP-KU8L7UV:~/080258/ch06/exercises/random-number/linux$ sudo docker container cp rn1:/random/number.txt number1.tx
t
Successfully copied 2.05kB to /home/user/080258/ch06/exercises/random-number/linux/number1.txt
user@DESKTOP-KU8L7UV:~/080258/ch06/exercises/random-number/linux$ sudo docker container cp rn2:/random/number.txt number2.tx
t
Successfully copied 2.05kB to /home/user/080258/ch06/exercises/random-number/linux/number2.txt

#출력
user@DESKTOP-KU8L7UV:~/080258/ch06/exercises/random-number/linux$ cat number1.txt
30845
user@DESKTOP-KU8L7UV:~/080258/ch06/exercises/random-number/linux$ cat number2.txt
21133
user@DESKTOP-KU8L7UV:~/080258/ch06/exercises/random-number/linux$
#분명 같은 이미지,경로의 같은 파일이지만 두 파일의 내용은 달랐다 -> 독립성 증명

컨테이너의 파일 시스템은 단일 디스크 형태이나 이 디스크는 도커가 여러 출처로부터 합쳐 만들고 컨테이너에 전달한 가상 파일 시스템이다.
-> 이러한 환경 출처는 기본적으로 이미지 레이어와 컨테이너 기록 가능 레이어로 구성되어 있다(이미지 레이어는 모두 공유, 기록 가능 레이어는 컨테이너 마다 따로 존재)

이미지 레이어: 모든 컨테이너에게 공유되어야 하니 읽기 전용, 이미지를 내려받은 순간부터 삭제할 때까지 로컬 컴퓨터의 이미지 레이어에 존재

기록 가능 레이어: 해당 컨테이너와 같은 생애주기, 컨테이너를 생성할때 생성되며 삭제할때 함께 삭제된다.
-> 기존 이미지 레이어에 있는 파일을 도커의 기록 중 복사(copy-on-write)방법을 이용해서 읽기 전용 파일을 수정
(컨테이너에서 이미지 레이어가 포함된 파일 수정 시도-> 도커가 파일을 쓰기 가능 레이어로 복사한 다음 쓰기 가능 레이어에서 파일을 수정함)

#실습
user@DESKTOP-KU8L7UV:~/080258/ch06/exercises/random-number/linux$ sudo docker container run --name f1 diamol/ch06-file-displ
ay
[sudo] password for user:
Unable to find image 'diamol/ch06-file-display:latest' locally
latest: Pulling from diamol/ch06-file-display
(중략)
Status: Downloaded newer image for diamol/ch06-file-display:latest
https://www.manning.com/books/learn-docker-in-a-month-of-lunches
#해당 컨테이너는 실행시 내부의 input.txt 파일의 내용을 출력한다. 즉 위의 링크는 해당 텍스트 파일의 내용물이다.

user@DESKTOP-KU8L7UV:~/080258/ch06/exercises/file-display$ echo "htttp://eltonstoneman.com" > url.txt
user@DESKTOP-KU8L7UV:~/080258/ch06/exercises/file-display$ sudo docker container cp url.txt f1:/input.txt
Successfully copied 2.05kB to f1:/input.txt
#해당 명령들을 시행하면 로컬에서 다른내용이 들어있는 새로운 파일이 생성된다 -> 컨테이너에서 url.txt 파일이 원래 있던 input.txt파일을 덮어씌운 것처럼 사용된다

user@DESKTOP-KU8L7UV:~/080258/ch06/exercises/file-display$ sudo docker container start --attach f1
htttp://eltonstoneman.com
#컨테이너 내부의 파일의 내용이 url.txt로 변경된 상태이다. 하지만 이미지는 바뀌지 않앗으므로 새로운 컨테이너를 만들면 초기대로 나올 것이다.

#실습2

user@DESKTOP-KU8L7UV:~/080258/ch06/exercises/file-display$ sudo docker container run --name f2 diamol/ch06-file-display
https://www.manning.com/books/learn-docker-in-a-month-of-lunches
#새 컨테이너를 실행해서 하면 원래 파일 내용이 출력된다 즉 f1 컨테이너 파일 내부를 수정해도 이미지의 영향은 없다.

user@DESKTOP-KU8L7UV:~/080258/ch06/exercises/file-display$ sudo docker container rm -f f1
f1
user@DESKTOP-KU8L7UV:~/080258/ch06/exercises/file-display$ sudo docker container cp f1:/input.txt .
Error response from daemon: No such container: f1
#컨테이너를 삭제하면 해당 컨테이너의 기록 가능 레이어와 수정된 데이터가 함께 삭제된다. 즉 컨테이너의 파일시스템은 일시적인 것이다.

도커의 어플리케이션 업데이트 방법: 새이미지를 빌드하고 -> 오래된 컨테이너 삭제 -> 새 이미지에서 실행한 컨테이너로 대체
(해당 과정에서 수정된 데이터는 모두 손실된다)

일시적 데이터를 캐싱하는 경우라면 새 컨테이너가 빈 캐시를 갖고 시작하더라도 별 문제 없지만 그렇지 않으면 큰 문제가 발생 -> 예시) "컨테이너로 임의의 DBMS를 돌렸는데 업데이트 했더니 DB가 다 사라졌네??"가 발생가능 -> 막대한 손실..

컨테이너의 가상 파일 시스템을 대체하기 위한 요소로써 도커 볼륨(docker volume)과 마운트(mount)가 존재한다.
-> 이들 요소는 컨테이너와 별개의 생애주기를 갖고 있으며 영구적인 데이터들을 보관할 수 있다.

 ----------------------------------------------------------------------------------------------------------------

도커 볼륨 -> 스토리지를 다루는 단위, 컨테이너와 독립적인 생애주기를 가진다, 영속성이 필요한 유상태 애플리케이션을 컨테이너에 연결할려면 필요하다

도커 볼륨을 사용하는 방법
- 수동으로 직접 볼륨을 생성해 컨테이너에 연결
- Dockerfile 스크립트에서 VOLUME 인스트럭션을 사용하는 방법 (VOLUME <대상 디렉토리>)

#예시 (todo-list Dockerfile)

FROM diamol/dotnet-aspnet

WORKDIR /app
ENTRYPOINT ["dotnet", "ToDoList.dll"]

# set in the base image - `/data` for Linux, `C:\data` for Windows
VOLUME /data


#실습 (볼륨 연결)

user@DESKTOP-KU8L7UV:~/080258/ch06/exercises/todo-list$ sudo docker container run --name todo1 -d -p 8010:80 diamol/ch06-todo-list
[sudo] password for user:
Unable to find image 'diamol/ch06-todo-list:latest' locally
latest: Pulling from diamol/ch06-todo-list
(중략)
Status: Downloaded newer image for diamol/ch06-todo-list:latest
9ca06e4d152793c0c1509745fc47cc0ef69693149be599060193f0643a84fc9a
#불륨이 따로 언급되지 않지만 위의 스크립트 처럼 불륨이 자동 연결 되어있음

user@DESKTOP-KU8L7UV:~/080258/ch06/exercises/todo-list$ sudo docker container inspect --format '{{.Mounts}}' todo1
[{volume 62fc1f8451eeef95bc204229e6f71dd348823c22bc0d93cd8da2bd4dfd0f5b96 /var/lib/docker/volumes/62fc1f8451eeef95bc204229e6f71dd348823c22bc0d93cd8da2bd4dfd0f5b96/_data /data local  true }]
#컨테이너 정보확인을 통해 Mount의 불륨 정보 확인 가능(ID, 원경로, 컨테이너 경로 등)

user@DESKTOP-KU8L7UV:~/080258/ch06/exercises/todo-list$ sudo docker volume ls
DRIVER    VOLUME NAME
local     62fc1f8451eeef95bc204229e6f71dd348823c22bc0d93cd8da2bd4dfd0f5b96
#docker volume 명령어를 통해 조회 및 삭제 등이 가능하다.

localhost:8010으로 접속시 TODO화면을 볼 수 있다. -> 만일 이 화면에서 특정 데이터를 저장하면 해당 데이터는 도커 볼륨에 저장된다.

또한 volumes-from 플래그를 사용하면 각 컨테이너가 같은 볼륨을 주목하게도 할 수 있다.

#실습2 (볼륨 공유)

user@DESKTOP-KU8L7UV:~/080258/ch06/exercises/todo-list$ sudo docker container run --name todo2 -d diamol/ch06-todo-list
3e3a8bab90caf6c2aa57f929f1bb3e6ba77b4572135aafc72feb94f5efdb5bc1
#기존의 이미지를 활용해서 새 볼륨과 새 컨테이너 생성

user@DESKTOP-KU8L7UV:~/080258/ch06/exercises/todo-list$ sudo docker container exec todo2 ls /data
#해당 컨테이너의 볼륨 /data에는 아무것도 없다.

user@DESKTOP-KU8L7UV:~/080258/ch06/exercises/todo-list$ sudo docker container run -d --name t3 --volumes-from todo1 diamol/c
h06-todo-list
a87d5c7c103f32e9c870b2983a265b5555b06b55cdd79b95ed8d4685d02d2bdb
#--volume-from이 아니다 --volumes-form이다 자세히보고 적자..
#todo1과 볼륨을 공유하는 t3를 생성

user@DESKTOP-KU8L7UV:~/080258/ch06/exercises/todo-list$ sudo docker container exec t3 ls /data
todo-list.db
#해당 볼륨은 todo의 컨테이너와 공유되므로 /data디렉토리에 애플리케이션에서 추가된 데이터가 보인다.

독립적인 환경을 요구하는 애플리케이션 컨테이너가 존재하므로 볼륨 공유는 파일 공유보다는 업테이트 간 상태를 보존하기 위한 용도로 사용하는 좋으며 이미지를 정의하는 것보다 명시적으로 관리하는 편이 낫다.

볼륨에 이름을 붙혀 생성하고 업데이트시 다른 컨테이너로 연결하면 된다.

#실습3 (볼륨 이동 + 업데이트)

user@DESKTOP-KU8L7UV:~/080258/ch06/exercises/todo-list$ target='/data'
#환경변수 선언 $target='/data'

user@DESKTOP-KU8L7UV:~/080258/ch06/exercises/todo-list$ sudo docker volume create todo-list
[sudo] password for user:
todo-list
#빈 볼륨 todo-list 생성

user@DESKTOP-KU8L7UV:~/080258/ch06/exercises/todo-list$ sudo docker container run -d -p 8011:80 -v todo-list:$target --name todo-v1 diamol/ch06-todo-list
1c5b222de39faee5359eba32ccc1a07299bc3d17c3bb4189882ec5e0c6932e88
#-v 플래그를 이용해 새 컨테이너에 todo-list불륨을 붙여서 생성 (컨테이너 파일 시스템 경로 /data에 todo-lsit 볼륨을 마운트)

웹브라우저 사용해 http://localhost:8011/에 접속 후 일정 몇건 추가

user@DESKTOP-KU8L7UV:~/080258/ch06/exercises/todo-list$ sudo docker container rm -f todo-v1
todo-v1
#-f 플래그를 붙혀 실행중인 todo-v1 컨테이너 강제 삭제

user@DESKTOP-KU8L7UV:~/080258/ch06/exercises/todo-list$ sudo docker container run -d -p 8011:80 -v todo-list:$target --name
todo-v2 diamol/ch06-todo-list:v2
#업데이트된 이미지로 새로운 컨테이너를 생성하고  -v로 기존 todo-list 볼륨을 연결

Dockerfile의 스크립트 VOLUME 옵션과 docker container 명령의 --volume플래그는 별개 기능이다.
-> VOLUME 옵션을 사용해 빌드된 이미지로 docker container run 명령에서 볼륨을 지정하지 않으면 항상 새로운 볼륨이 생성된다.
-> 해당 볼륨은 무작위 식별자를 가지므로 컨테이너를 삭제한 후 볼륨을 재사용 할려면 기록이 필요하다
-> 반면 --volume 플래그는 이미지에 볼륨이 정의돼 있든 말든 지정된 볼륨을 컨테이너에 마운트한다. 즉 이미지에 볼륨이 정의되 있더라도 무시되며 새로운 볼륨을 생성하지 않는다. (이미지 업데이트시 이방향을 주로 사용한다) 

이미지를 만드는 입장에서는 안정장치 삼아 VOLUME 옵션을 이미지 정의에 포함시켜 두는게 좋다 -> 사용자 데이터 유실 방지에 탁월하다.하지만 이미지의 기존 볼륨에 의지하지 말고 별도로 이름을 붙혀 사용하는 것을 권장한다.

-------------------------------------------------------------------------------------------------------------------

호스트의 스토리지에 컨테이너를 좀 더 직접적으로 연결할 수 있는 수단이 존재한다 -> 바인드 마운트(bind mount)

바인드 마운트
- 호스트 컴퓨터의 파일 시스템 디렉토리를 컨테이너 파일 시스템 디렉토리로 만들 수 있다.
- 볼륨과 마찬가지로 컨테이너 입장에서는 평험한 디렉토리로 인식된다.
- 사용자 입장에서는 컨테이너가 호스트 컴퓨터에 직접 접근이 가능하며 반대도 가능해지므로 선택지가 다양해진다.
- 사용시 호스트 컴퓨터의 파일 시스템을 명시적으로 지정해 컨테이너 데이터로 쓸 수 있다.(다양한 환경의 디스크/스토리지 사용가능)
- RAID가 적용된 디스크 구조를 가진 서버가 있다면 해당 스토리지를 애플리케이션의 DB에 저장할 고신뢰성 스토리지로 활용가능하다.

#실습1 (바인드 마운트 연결)

user@DESKTOP-KU8L7UV:~/080258/ch06/exercises/todo-list$ source="$(pwd)/databases" && target='/data'
#경로 문자열을 환경변수로 선언

user@DESKTOP-KU8L7UV:~/080258/ch06/exercises/todo-list$ sudo docker container run --mount type=bind,source=$source,target=$t
arget -d -p 8012:80 diamol/ch06-todo-list
[sudo] password for user:
96a91cd0dc61d920cc4de90798bcbd9fc8e9f20290543221e32aafd11c635067
#바인드 마운트를 적용하고 컨테이너를 실행(/data 디렉토리를 컨테이너 안에서 사용한다)

user@DESKTOP-KU8L7UV:~/080258/ch06/exercises/todo-list$ curl http://localhost:8012 | Out-Null
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  2468    0  2468    0     0  70321      0 --:--:-- --:--:-- --:--:-- 72588
Out-Null: command not found
#curl로 컨테이너에 http요청을 보내면 애플케이션이 시작되면서 /data에 DB파일이 생성된다.

user@DESKTOP-KU8L7UV:~/080258/ch06/exercises/todo-list$ ls ./databases/
todo-list.db
#컨테이너에서 생성된 파일 (호스트에서 직접 사용하거나 다른 파일 추가도 가능 물론 반대도 가능하다.)

양방향 수정을 위해서는 권한이 필요한데 기본적으로 컨테이너는 최소권한만 가지고 있기 때문에 Dockerfile의 USER 옵션을 통해 관리자 권한을 부여해 root나 ContainerAdministrator 계정으로 실행시킨다.

 #실습2 (바인딩 마운트를 이용한 컨테이너 설정 파일 전달)
user@DESKTOP-KU8L7UV:~$ cd 080258/ch06/exercises/todo-list
#폴더로 이동

user@DESKTOP-KU8L7UV:~/080258/ch06/exercises/todo-list$ source="$(pwd)/config"&&target='/app/config'
#환경변수 선언

user@DESKTOP-KU8L7UV:~/080258/ch06/exercises/todo-list$ sudo docker container run --name todo-configured -d -p 8013:80 --mount type=bind,source=$source,target=$target,readonly diamol/ch06-todo-list
3e4d4926f89e10f7e98e32513898e4c0c50db0cd40c7da1c78acb72244397a6f
#로그 레벨을 조정한 설정파일을 이용해서 컨테이너 속 애플리케이션이 이 설정파일을 읽어 조정하게 함

user@DESKTOP-KU8L7UV:~/080258/ch06/exercises/todo-list$ curl http://localhost:8013 | Out-null
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  2468    0  2468    0     0   145k      0 --:--:-- --:--:-- --:--:--  150k
Out-null: command not found
#작동 확인 및 로그 찍기

user@DESKTOP-KU8L7UV:~/080258/ch06/exercises/todo-list$ sudo docker container logs todo-configured
dbug: Microsoft.Extensions.Hosting.Internal.Host[1]
      Hosting starting
warn: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[60]
      Storing keys in a directory '/root/.aspnet/DataProtection-Keys' that may not be persisted outside of the container. Protected data will be unavailable when container is destroyed.
#debug 레벨 로그가 출력되는 것을 확인

-------------------------------------------------------------------------------------------------------------------------

바인드 마운트의 한계점 이해 시나리오 1

컨테이너의 마운트 대상 디렉터리가 이미 존재하고 이미지 레이어에 이 디렉토리의 파일이 포함되 있다면?
-> 이미 존재하는 대상 디렉토리에 마운트 하면 마운트의 원본 디렉토리가 기존 디렉토리를 완전히 대체
-> 이미지에 포함되어 있는 원래파일은 사용이 불가능하다.

#실습1 (바인드 마운트 한계1)

user@DESKTOP-KU8L7UV:~/080258$ cd ch06/exercises/bind-mount/
#파일 위치 이동

user@DESKTOP-KU8L7UV:~/080258/ch06/exercises/bind-mount$ source="$(pwd)/new"&&target='/init'
#환경변수 선언

user@DESKTOP-KU8L7UV:~/080258/ch06/exercises/bind-mount$ sudo docker container run diamol/ch06-bind-mount
[sudo] password for user:
Unable to find image 'diamol/ch06-bind-mount:latest' locally
...(중략)
Status: Downloaded newer image for diamol/ch06-bind-mount:latest
abc.txt
def.txt
#컨테이너 실행 시 /init 디렉토리 파일을 출력한다 -> 바인드 마운트가 되지 않은 컨테이너 미르모 이미지에 포함된 기존 파일 목록이 출력된다.


user@DESKTOP-KU8L7UV:~/080258/ch06/exercises/bind-mount$ sudo docker container run --mount type=bind,source=$source,target=$
target diamol/ch06-bind-mount
123.txt
456.txt
#/init 대상으로 바인드 마운트를 마운트해 컨테이너를 실행하면 원래 디렉토리 내용은 숨겨지고 바인드 마운트의 원본 디렉토리가 이를 대체한다.

바인드 마운트의 한계점 이해 시나리오 2

호스트의 파일 하나를 컨테이너에 이미 존재하는 디렉토리로 마운트하면 어떻게 될까?
-> 디렉토리의 파일이 합쳐져 이미지에서 온 파일과 포스트에서 마운트된 파일이 모두 나타난다(윈도우 컨테이너는 해당 기능을 제공하지 않아 동작이 다르다)

컨테이너 파일시스템은 윈도 컨테이너와 리눅스 컨테이너가 동작이 일치하지 않는 영역중 하나다.

바인드 마운트의 한계점 이해 시나리오 3

분산 파일 시스템을 컨테이너에 바인드 마인드하면 어떻게 될까? 컨테이너에서 실행되는 애플리케이션이 정상적으로 동작할까?
-> 분산 파일 시스템을 사용하면 네트워크 상의 모든 컴퓨터에서 데이터를 접근할 수 있지만 대게 분산 파일 시스템의 메커니즘은 윈도 파일 공유에 쓰이는 SMB, 애저 파일스, AWS S3등 로컬 컴퓨터 운영체제의 파일시스템과 다른 경우가 많다 -> 지원하지 않는 동작이 존재할 수 있다.

------------------------------------------------------------------------------------------------------------------

유니언 파일 시스템(Union File system): 도커가 제공하는 다양한 출처로부터 만든 단일 가상 디스크로 구성된 파일시스템
-> 도커가 자동적으로 최적화를 해주기 때문에 신경 쓸 필요는 없다.

컨테이너의 스토리지를 구성할때 고려야해야 하는 사항

- 기록 가능 레이어: 단기저장에 적합(비용이 비싼 계산, 네트워크 데이터 캐싱 등), 각 컨테이너마다 독립적인 레이어를 갖춤, 컨테이너가 삭제되면 저장된 데이터도 유실

- 로컬 바인드 마운트: 호스트와 컨테이너 간 데이터를 공유하기위해 사용, 로컬->컨테이너로 소스코드를 전달하기 위해 사용 시 수정한 내용이 이미지 빌드 없이도 즉시 컨테이너로 전달가능

- 분산 바인드 마운트: 네트워크 스토리지와 컨테이너 간에 데이터를 공유하기 위해 사용, 가용성성이 높으나 기능 및 성능에 차이 있을 수 있다, 읽기 전용으로 설정파일을 전달하거나 공유 캐시로 활용이 가능, 읽기 쓰기 기능으로 데이터를 저장해 동일 네트워크 상의 모든 컨테이너나 컴퓨터와 데이터를 공유하는데 적합

- 볼륨 마운트: 컨테이너와 도커 객체인 볼륨간의 데이터를 공유하기 위해 사용, 마운트 시 애플리케이션이 볼륨에 데이터를 영구적으로 저장, 컨테이너 교체식으로 업데이트를 진행해도 데이터를 유지 가능하다

- 이미지 레이어: 컨테이너의 초기 파일 시스템을 구성, 적층 구조 형태를 가진다, 후속레이어와 이전레이어의 내용이 서로 충돌하는 경우 후속 레이어의 내용이 적용, 레이어는 읽기 전용이며 여러 컨테이너가 공유

--------------------------------------------------------------------------------------------------------------------

연습문제

user@DESKTOP-KU8L7UV:~/080258/ch06/exercises/bind-mount$ sudo su root
root@DESKTOP-KU8L7UV:/home/user/080258/ch06/exercises/bind-mount# ^C
root@DESKTOP-KU8L7UV:/home/user/080258/ch06/exercises/bind-mount# docker container rm -f $(docker container ls -aq)
74ca316231eb
04eec6c96a9a
3e4d4926f89e
96a91cd0dc61
e0c16340a35c
a87d5c7c103f
3e3a8bab90ca
9ca06e4d1527
1ac3c9f1343f
bce599efd844
506312c5e2e6
#기존 컨테이너 root권한으로 제거

root@DESKTOP-KU8L7UV:/home/user/080258/ch06/lab# docker container run -d -p 8015:80 diamol/ch06-lab
9e572c6a2dea3bec37cd7df2cbe83f3c89c469627835b147fbed20df488d8a4b
#컨테이너 생성


#접속시 등록된 할일 4개

docker volume create todo-test
#볼륨 생성

#DB 파일의 다른 경로로 지정하는 구성 파일을 생성할 수 있으며 해당 경로는 볼륨안이 될 수도 있다.
#내부의 애플리케이션 config.json을 바꿔치기해 /new-data에 파일을 쓰도록 구성

root@DESKTOP-KU8L7UV:/home/user/080258/ch06/lab/solution# cat config.json
{
    "ConnectionStrings": {
      "ToDoDb": "Filename=/new-data/todo-list.db"
    }

root@DESKTOP-KU8L7UV:/home/user/080258/ch06/lab# configSource="$(pwd)/solution"
root@DESKTOP-KU8L7UV:/home/user/080258/ch06/lab# configTarget='/app/config'
root@DESKTOP-KU8L7UV:/home/user/080258/ch06/lab# dataTarget='/new-data'
#환경변수 선언

root@DESKTOP-KU8L7UV:/home/user/080258/ch06/lab# docker container run -d -p 8016:80 --mount type=bind,source=$configSource,target=$configTarget,readonly --volume todo-test:$dataTarget diamol/ch06-lab
61900473e24097dfab164469c194c9bdd21fab01eb7f962fdbe0c985ba30e6bd


도커 볼륨 초기화 명령
docker volume rm -f $(docker volume ls)

실습환경 초기화 명령
docker container rm -f $(docker container ls -aq)

이미지 차지 디스크 용량 회수 명령
docker image rm -f $(docker image ls -f reference='diamol/*' -q)