Docker Volume

최병훈·2024년 10월 15일
post-thumbnail

1)도커 볼륨이 필요한 이유

  • 컨테이너는 프로세스
  • 컨테이너는 기본적으로 메모리에 데이터를 저장하고 사용하며 파일에 저장하는 것도 가능합니다.
  • 컨테이너는 삭제되면 소유하고 있던 모든 것들을 삭제합니다.
  • 데이터의 영속성을 유지할 수가 없습니다.
  • 데이터의 영속성 때문에 볼륨을 사용

2)타입

  • bind mount: 호스트 컴퓨터의 파일 시스템 과 직접 연결하는 방식
  • volume: 도커 엔진의 파일 시스템과 연결하는 방식
  • tmpfs mount: 메모리에 일시적으로 저장하는 방식
  • 컨테이너 간에도 설정 가능

3)생성

  • 생성

    docker volume create 볼륨이름
    docker volume create my-appvol-1
  • 조회

    docker volume ls

  • 상세보기
    docker volume inspect my-appvol-1

4)볼륨 설정

  • --mount 옵션을 이용해서 source 와 target을 설정
    docker run --mount source=볼륨이름, target=연결할디렉토리 이미지이름
    docker run -d --name vol-test1 --mount source=my-appvol-1,target=/app ubuntu:20.04
  • -v 옵션을 이용해서 직접 매핑
    docker run -d --name vol-test2 -v my-appvol-1:/var/log ubuntu:20.04
  • 없는 볼륨이름을 이용하면 자동 생성
    docker run -d --name vol-test3 -v my-appvol-2:/var/log ubuntu:20.04

5)볼륨 삭제

  • 볼륨 삭제
    docker volume rm 볼륨이름
    docker volume rm my-appvol-1
  • 컨테이너에 연결되어 있으면 삭제 안됨
    docker volume rm my-appvol-1 명령을 수행하면 연결된 컨테이너가 있다고 에러 메시지가 출력됨
  • 현재 만들어진 2개의 볼륨 삭제
    • 컨테이너를 삭제
      docker stop vol-test1 vol-test2 vol-test3
      docker rm vol-test1 vol-test2 vol-test3
    • 볼륨을 삭제
      docker volume rm my-appvol-1 my-appvol-2

6)bind mount

  • 호스트 컴퓨터의 디렉토리 와 컨테이너의 디렉토리를 직접 매핑

  • 방법

    • -- mount 이용
      --mount type=bind,source=호스트컴퓨터디렉토리,target=컨테이너디렉토리
    • -v 이용
      -v 호스트컴퓨터디렉토리:컨테이너디렉토리
  • 사용자가 파일 또는 디렉토리를 생성하면, 해당 호스트 파일 시스템의 소유자 권한으로 만들어진다. 만약 존재하지 않는 파일 또는 디렉토리를 생성하면 기본적으로 루트 사용자(root)의 소유로 생성된다.

  • 컨테이너 실행 시 지정하여 사용하고 컨테이너 제거 시 바인드 마운트는 해제되지만 호스트 디렉토리는 유지가 됩니다.

실습

  • 실습을 위한 디렉토리를 생성

    mkdir /home/bh/target
  • --mount 옵션으로 centos:8 의 /var/log 디렉토리 와 연결

    docker run -dit --name bind-test1 --mount type=bind,source=/home/bh/target,target=/var/log centos:8
  • -v 옵션으로 centos:8 의 /var/log 디렉토리 와 연결
    docker run -dit --name bind-test2 -v /home/bh/target:/var/log centos:8
  • 없는 디렉토리 와 연결
    docker run -dit --name bind-test3 -v /home/bh/target1:/var/log centos:8
    • /home/bh/target1 디렉토리가 root의 소유로 생성된다.
  • 없는 디렉토리에 권한을 부여해서 연결
    docker run -dit --name bind-test4 -v /home/bh/target_ro:/app1:ro -v /home/bh/target_rw:/app2:rw centos:8

7)tmpfs mount

  • 임시적으로 연결
  • 컨테이너가 중지되면 마운트가 제거되고 내부에 기록된 파일도 유지되지 않음
  • 중요한 파일을 임시로 저장하기 위해서 사용
  • 컨테이너 실행 시 지정하여 사용하고 컨테이너 해제 시 자동 해제

실습

  • mount 옵션을 이용해서 tmpfs 연결을 수행하는데 httpd:2 의 /var/www/html 파일을 임시로 연결
    • mount 옵션 이용
      docker run -dit --name tmpfs-test1 --mount type=tmpfs,destination=/var/www/html httpd:2
    • tmpfs 옵션 이용
      docker run -dit --name tmpfs-test2 --tmpfs /var/www/html httpd:2

8)활용

데이터베이스의 데이터 지속성 유지

  • 데이터의 지속성 유지를 위해서 볼륨 생성

    docker volume create mysql-data-vol
  • 볼륨과 연결해서 mysql:5.7 이미지를 컨테이너로 생성

    docker run -it -d --name=mysql-server -e MYSQL_ROOT_PASSWORD=mypassword -e MYSQL_DATABASE=dockertest -v mysql-data-vol:/var/lib/mysql mysql:5.7
  • 데이터 수정

    • 쉘에 접속

      docker exec -it mysql-server /bin/bash
    • 데이터베이스 사용을 위해서 mysql에 접속

      mysql -uroot -p

    • 데이터베이스 확인

      show databases;

    • 데이터베이스 사용 설정

      use dockertest;
    • 테이블 생성

      create table mytab(c1 int, c2 char);
    • 데이터 추가

      insert into mytab values(1, 'a');
    • 데이터 확인

      select * from mytab;

  • 컨테이너를 삭제

    docker stop mysql-server
    docker rm mysql-server
  • 이전에 만든 볼류 과 연결해서 컨테이너를 재생성해서 이전 데이터가 유지되는지 확인

    docker run -it -d --name=mysql-server -e MYSQL_ROOT_PASSWORD=mypassword -e MYSQL_DATABASE=dockertest -v mysql-data-vol:/var/lib/mysql mysql:5.7

nginx 이미지의 컨테이너는 /var/log/nginx 디렉토리를 볼륨에 연결

  • 볼륨으로 사용할 디렉토리를 생성하면서 연결
    docker run -d -p 8011:80 -v /home/bh/nginx-log:/var/log/nginx nginx:1.19
  • host 디렉토리에 ls 명령으로 파일 확인
    ls -l nginx-log
  • cat 명령으로 access.log 파일 확인
    cat nginx-log/access.log
    • 현재 access 가 없었기 때문에 log 내역이 없다.
  • curl 명령으로 nginx 컨테이너에 요청을 보내기
    curl localhost:8011
  • 다시 cat 명령으로 access.log 파일 확인
    cat nginx-log/access.log
  • 실시간으로 로그 파일 확인
    tail -f nginx-log/access.log

9)linux 의 awk

  • 파일로부터 레코드를 선택하고 선택된 레코드에 포함된 값을 조작하거나 데이터화하는 것을 목적으로 사용하는 프로그램
  • 텍스트 파일의 전체 내용을 출력할 수 있고 특정 필드만 출력하는 것이 가능
  • 아파치 웹 서비스의 access.log는 하나의 레코드 처럼 기록
    IP - - 날짜시간 요청방식 프로토콜 사이즈…
  • 줄단위로 전체 출력

    awk {print} nginx-log/access.log

  • 특정 필드만 출력

    awk '{print $1, $4, $5}' nginx-log/access.log

  • 연산

    awk '{sum +=  $10} END {print sum}' nginx-log/access.log

10)컨테이너 간 데이터 공유를 위한 데이터 컨테이너 생성

  • 다른 컨테이너 와 볼륨을 공유할 수 있는데 이 경우에는 --volumes-from 컨테이너이름 을 이용하면 됩니다.

  • 컨테이너 간 데이터 공유를 위한 컨테이너

    • 데이터 공유를 위한 도커 컨테이너 실행

      docker run -it -d -v /data-volume --name=datavol ubuntu:18.04
    • 위의 컨테이너 와 데이터를 공유하는 컨테이너 생성

      docker run -it --volumes-from datavol ubuntu:18.04
      echo 'testing data container' > /data-volume/test-volume1.txt
      cat /data-volume/test-volume1.txt

    • 데이터 공유를 위한 도커 컨테이너에 접속해서 파일 확인

      docker exec -it datavol bash
      cat /data-volume/test-volume1.txt

11)볼륨을 유용하게 사용

  • httpd(apache 웹 서버) 의 경우 welcome 파일의 위치는 /usr/local/apache2/htdocs 디렉토리에 위치하고 있습니다.

  • docker cp를 이용한 메인 화면 수정

    • 컨테이너 실행
      docker run --name apache1 -d -p 8101:80 httpd
    • curl 명령을 통해 확인
      curl localhost:8101
  • 컨테이너 내부의 파일을 호스트 컴퓨터로 복사

    docker cp apache1:/usr/local/apache2/htdocs/index.html index.html
  • index.html 파일을 호스트 컴퓨터에서 수정

    vi index.html
  • 수정한 내용 복사(수정할 때 마다 작업을 수행)

    docker cp index.html apache1:/usr/local/apache2/htdocs/index.html
  • curl 명령을 통해 확인

    curl localhost:8101

  • 바인드 마운트를 이용한 welcome 파일 수정

    • 컨테이너 생성

      docker run --name apache2 -v /home/bh/apache:/usr/local/apache2/htdocs -d -p 8102:80 httpd
    • curl localhost:8102 로 확인

    • apache 디렉토리에 index.html 파일을 생성

      sudo vi /home/bh/apache/index.html
    • curl localhost:8102 로 확인

12)자원 사용에 대한 제약

  • 볼륨에 대한 자원 사용 확인

    • 리눅스에서 자원 사용량을 확인

      df -h

    • 컨테이너 내부에서도 동일한 명령을 수행

      docker exec -it apache2 /bin/bash
      df -h

      현재는 컨테이너의 자원 사용 가능 사이즈 와 호스트 컴퓨터의 자원 사용 가능 사이즈가 동일

  • 리눅스 자원 모니터링

    • top : 리눅스 전체의 자원 소비량 및 개별 액티브 프로세스의 자원 사용량

    • htop : top 보다 향상된 자원 사용량 제공, 별도로 설치해야 함

    • sar (system active report): 다양한 옵션을 이용해서 시스템 전반의 사용량에 대한 세부적인 모니터링을 제공하는데 쉘 스크립트에 포함해서 사용하는데 sysstat 를 별도로 설치해야 합니다.
      sar 2 10(2초 마다 10번 수집)

    • iostat, df : 디스크 성능 지표를 수집
      iostat는 sar 사용법이 동일

    • vmstat, free: 메모리 성능 측정
      vmstat는 sar 사용법이 동일하고 free -mt 명령으로 마지막 사용량을 MB 단위로 표시

    • dstat : 시스템 전반의 자원 사용량에 대한 모니터링 제공, dstat를 별도 설치
      dstat 명령으로 수행

    • iptraf-ng : 유입되는 네트워크 인터페이스 별 패킷양, 프로토콜 등을 통해서 네트워크 트래픽 모니터링, iptraf-ng를 별도로 설치
      iptraf-ng 명령으로 수행

  • 위의 도구들을 이용해서 서버 자원을 모니터링을 해서 예방적 차원의 관리 작업 과 효율성을 확인할 수 있음

  • 컨테이너를 사용하는 docker run 이나 docker create 명령과 함께 자원 할당 제어를 사용하지 않는다면 생성되는 컨테이는 호스트 운영체제의 모든 자원을 자유롭게 사용하고 과도한 자원 사용도 가능

  • 클라우드 네이티브 환경에서는 컨테이너를 사용하는 목적이 소규모의 애플리케이션 서비스인데 이 작은 애플리케이션 서비스가 잘못된 설정으로 시스템에 부하를 유발한다면 다른 컨테이너의 동작 간섭 뿐 아니라 호스트 운영체제 전반이 영향을 받게 됩니다.

  • 도커에서는 여러 런타임 제약 옵션을 제공하며 컨테이너 생성 후에도 docker update 명령을 이용해서 변경이 가능

  • 리소스 런타임 제약은 리눅스 커널이 제공하는 cgroup 기능을 통해 가능

  • cgroup 확인

    grep cgroup /proc/mounts
    docker info | grep Cgroup
  • nginx 이미지에 메모리 1기가 할당한 컨테이너 생성

    docker run -d --name=nginx_mem_1g --memory=1g nginx 
  • 확인

    docker inspect nginx_mem_1g | grep \"Memory\"

  • cpu 제약

    • --cpus: 1개의 cpu 인 경우는 비율이 되고 여러 개의 cpu 인 경우는 개수
      --cpus=0.2: 1개인 경우는 20%를 사용
      --cpus=1.5: 여러 개 인 경우 1.5개를 사용

    • --cpu-period: 기간 제한 옵션으로 컨테이너의 CFS는 밀리세컨드 단위로 지정
      --cpu-period=100000 의 형태로 지정

    • --cpu-quota: 시간 할당량
      --cpu-quota=50000 의 형태로 지정하는데 --cpu-period 와 같이 사용

    • --cpuset-cpus: 여러 개의 cpu 인 경우 특정 cpu의 코어 번호를 이용해서 할당
      --cpuset-cpus=”0,3”: 0번 과 3번 코어 이용
      --cpuset-cpus=”0-2”: 0, 1, 2번 코어 사용

    • --cpu-shares: 공평한 스케쥴링을 원칙으로 하는데 가중치를 부여해서 사용하는 것이 가능

  • cpu 제약 실습

    docker run -d --name cpu_1024 --cpu-shares 1024 leecloudo/stress:1.0 stress --cpu 4
    docker run -d --name cpu_256 --cpu-shares 256 leecloudo/stress:1.0 stress --cpu 4
    ps -aux | grep stress | grep -v grep

    • 이런 테스트를 할 때는 무한 루프로 동작하는 애플리케이션을 만들어서 확인합니다.
    • 2개 이상 실행시키게 되면 일련번호 형태로 프로세스 ID가 만들어진 것이 하나의 컨테이너가 실행한 것입니다.
  • 메모리 사용량 제한

    • 메모리

      • 물리적인 메모리 와 스왑 메모리(가상 메모리)로 나누는데 물리적인 메모리는 실제 메모리 크기를 의미하고 스왑 메모리는 메모리가 부족할 때 하드디스크의 일정 부분을 빌려와서 사용하는 메모리
      • 보통의 경우 스왑 메모리를 물리적 메모리의 두배로 설정하는데 스왑 메모리를 사용하게 되면 속도는 느려지게 됩니다.
    • 옵션

      • memory 또는 m: 물리적인 메모리의 최대값이고 허용되는 최소값은 4m
      • memory-swap: 스왑할 수 있는 메모리 양을 지정하는데 0을 주면 컨테이너 스왑 사용을 해제하는 것이고 -1이면 무제한
      • kernel-memory: 커널 메모리 설정, 모든 cgroup이 필요한 메모리 크기가 장비의 메모리보다 클 때 사용
    • ubuntu:14.04 이미지를 이용하여 컨테이너를 생성하는데 메모리의 크기를 1기가로 제한

      docker run -it -d --name=ubuntu_1g --memory=1g ubuntu:14.04
      docker inspect ubuntu_1g | grep -i memory

    • 애플리케이션이 사용하는 메모리 양보다 적게 설정되는 경우 오류가 발생: kafka를 사용할 때 이 오류가 많이 발생

0개의 댓글