도커 데몬

ohyeon·2023년 4월 5일
0

도커의 구조

# which docker
/usr/local/bin/docker
# ps aux | grep docker 
ohyeon            9032   0.0  0.2 35284600  70884   ??  S    0:11.95 /Applications/Docker.app/Contents/MacOS/com.docker.backend -watchdog -native-api
ohyeon             10204   0.0  0.0 409223472   4384   ??  S  0:00.55 /Library/PrivilegedHelperTools/com.docker.vmnetd

"docker.backend" : Docker 엔진의 주요 컴퍼넌트 중 하나인 "dockerd"를 실행하는 역할



  • 클라이언트로서의 도커 : 도커 데몬은 API를 입력 받아 도커 엔진의 기능을 수행하는데 API를 사용할 수 있도록 CLI(Command Line Interface)를 제공
    ex) docker version, images, start .. etc

  • 서버로서의 도커

    • 컨테이너를 생성하고 실행하며 이미지, 컨테이너, 네트워크를 관리하는 주체 (dockerd 프로세스로서 동작)
    • 도커 데몬 : docker 엔진의 핵심 컴포넌트, 컨테이너화된 애플리케이션을 관리하고 실행하는 핵심 서비스

  • 도커 클라이언트는 입력 명령어를 로컬에 존재하는 도커 데몬에게 API로 전달
  • 도커 클라이언트는 /var/run/docker.sock에 위치하는 유닉스 소켓을 통해 도커 데몬의 API를 호출
  • tcp로 원격에 있는 도커 데몬을 제어 할 수도 있음



도커 데몬 실행 및 설정

우분투에서는 자동으로 서비스로 등록되어 호스트가 재시작되어도 자동으로 실행

// 도커 데몬 시작 정지 
# service docker start
# service docker stop 

도커 서비스는 dockerd로 도커 데몬을 실행할 수 있으며 dockerd 에 여러 옵션을 적용하여 사용

# service docker stop 
# dockerd 

// 도커 데몬에 여러 옵션 적용 

# dockerd --insecure-registry : 레지스트리 컨테이너 구축
          --log_driver : 컨테이너 로깅
          --storage-opt : 스토리지 백엔드 변경

-> 단, 도커 데몬을 실행하면 하나의 터미널을 차지하는 포그라운드(foreground) 상태로 실행되기 때문에 설정파일을 통해 서비스로 실행하는 것이 일반적임



도커 데몬 제어 : -H

-H 옵션은 도커 데몬의 API를 사용할 수 있는 방법을 추가, 아무런 옵션을 설정하지 않고 도커 데몬을 실행하면 도커 클라이언트인 /usr/local/bin/docker를 위한 유닉스 소캣 /var/run/docker.sock을 사용

# dockerd
# dockerd -H unix:///var/run/docker.sock 

-H 옵션에 IP주소와 포트번호를 입력하면 원격 API인 Docker Remote API로 도커를 제어할 수 있음

RESTful API 형식을 띠고 있어서 HTTP 요청으로 다른 서버의 도커를 제어할 수 있음

# dockerd -H tcp://0.0.0:2375 // 단 Remote API만을 위한 바인딩 주소를 입력했다면 
                              // 유닉스 소캣은 비활성화 되어 도커 클라이언트 사용이 불가 
# docker -H unix://var/run/docker.sock -H tcp://0.0.0:2375

도커 클라이언트가 도커 데몬에게 명령어를 수행하도록 요청할 때도 내부적으로 같은 API를 사용하므로 Remote API 또한 도커 클라이언트에서 사용 가능한 모든 명령어를 사용할 수 있음
-H 로 Remote API를 사용하려면 cURL 같은 HTTP 요청 도구를 사용함

docker-daemon:/# dockerd -H tcp://192.168.00.100:2375

client:/# curl 192.168.99.100:2375/version --silent | python -m json.tool

192.168.99.199:2375 를 도커 데몬에 바인딩하고, 192.168.99.100:2375/version을 URL로 http 요청을 보내 도커 버전을 확인할 수 있음

도커 데몬 보안 적용 : --tlsverify

도커를 설치하면 기본적으로 보안 연결이 설정되어 있지 않아 운영 환경에서 도커를 사용해야 한다면 보안을 적용하는 것이 바람직 하지 않음 (IP, Port 만으로 도커 제어 가능)

도커 데몬에 TLS 보안 적용을 위해 5개의 파일을 사용 (ca.pem, server-cert.pem, server-key.pem, cert.pem, key.pem ) 이 중 클라이언트 측에서 도커 데몬에 접근 하려면 ca.pem, cert.pem, key.pem 파일이 필요

  1. 서버측 파일 생성

    
    // 인증서에 사용될 키 생성 
    # mkdir keys && cd keys 
    # openssl genrsa -aes256 -out ca-key.pem
    
    // 공용 키 (public key)를 생성 
    # openssl req -new x509 -days 10000 -key ca-key.pem -sha256 -out ca.pem
    
    // 서버 측에서 사용될 키를 생성 
    # openssl genrsa -out server-key.pem 4096
    
    // 서버 측에서 사용될 인증서를 위한 인증 요청서 파일을 생성 
    # openssl req -subj "/CN={$DOCKER HOST IP or Domain}" -sha256 -new -key server-key.pem -out server.csr
    
    // 접속에 사용될 IP 주소를 extfile.cnt 파일로 저장 
    # echo subjectAltName = IP:{$DOCKER Host IP or Domain},IP:127.0.0.1" > extfile.cnf
    
    // 서버 측 인증서 파일 생성 
    # openssl x509 -req -days 365 -sha256 -in server.csr -CA ca.epm -CAkey ca-key.pem -CAreateserial -out server-cert.pem -extfile extfile.cnf
  2. 클라이언트 측에서 사용할 파일 생성

    ```
    
    // 클라이언트 측의 키 파일과 인증 요청 파일을 생성, extfile.cnt 파일에 extendedKeyUsage 항목 추가 
    # openssl genrsa -out key.pem 4096 
    
    # openssl -req -subj '/CN=client' -new -key key.pem -out client.csr
    # echo extendedKeyUsage = clientAuth > extfile.cnt 
    
    // 클라이언트 측의 인증서 생성 
    
    # openssl x509 -req -days 30000 -sha256 -in client.csr -CA ca.pem -CAkey ca-key.pem -CAcreateserial -out cert.pem -extfile extfile.cnt
     
    // 쓰기 권한을 삭제 후 읽기 전용 파일로 생성 
    # chmod -v 0400 ca-key.pem server-key.pem ca.pem server-cert.pem cert.pem 
    
    // 도커 데몬의 설정 파일이 존재하는 디렉터리로 파일을 옮김 (~/.docker)
    # cp {ca, server-cert, server-key, cert, key}.pem ~/.docker
    ```
    
    이 후 보안 적용을 위해 -tlsverify 옵션을 추가해 --tlscacert, --tlscert, --tlskey 파일 위치를 입력하여  확인 
    ```
    # dockerd --tlsverify \ 
    --tlscacert=/root/.docker/ca.pem \
    --tlscert=/root/.docker/server-cert.pem \
    --tlskey=/root/.docker/server-key.pem \
    -H=0.0.0.0:2376 \
    -H unix:///var/run/docker.sock
    
    
    // 클라이언트에서 접근 시에도 옵션을 주어 접근해야 함 
    
    # docker -H 192.168.99.100:2376 \ 
    --tlscacert=/root/.docker/ca.pem \
    --tlscert=/root/.docker/cert.pem \
    --tlskey=/root/.docker/key.pem \
    --tlsverify version 
    
    // 위의 과정이 번거로우니 환경변수로 설정하여 접근
    
    # export DOCKER_CERT_PATH="/root/.docker"
    # export DOCKER_TLS_VERIFY=1 
    ```



도커 스토리지 드라이버 변경 : --storage-driver

도커는 특정 스토리지 백엔드 기술을 사용해 도커 컨테이너와 이미지를 저장하고 관리함
일부 운영체제는 도커를 설치할 때 기본적으로 사용하도록 설정된 스토리지 드라이버가 있음 (데비안 : overlay2, CentOS : devicemapper)

# docker info | grep "Storage Driver"
Storage Driver : overlay2 

도커를 사용하는 환경에 따라 스토리지 드라이버는 자동으로 지정되지만 도커 데몬 실행 옵션에 스토리지 드라이버를 변경할 수 있음 (OverlayFS, AUFS, Btrfs, Devicemapper, VFS , ZFS ...)

이 중 하나만 선택해 도커 데몬에 적용할 수 있으며 적용된 스토리지 드라이버에 따라 컨테이너와 이미지가 별도로 생성됨

스토리지 드라이버의 원리

개념적으로 이미지는 읽기 전용 파일로 사용되며 컨테이너는 이 이미지 위에 얇은 컨테이너 레이어를 생성함으로써 컨테이너의 고유한 공간을 생성함

실제로는 컨테이너 내부에서 읽기와 새로운 파일 쓰기, 기존의 파일 쓰기 작업이 일어날 때는 드라이버에 따라 Copy-on-Write(CoW), Redirect-on-Write(RoW) 개념을 사용 - 도커 스토리지 드라이버는 CoW, RoW를 지원해야 함

스냅샷의 기본 개념 : "원본 파일은 읽기 전용으로 사용하되 이 파일이 변경 되면 새로운 공간으로 할당"
-> 스토리지를 스냅샷으로 만들면 파일 위치 저장, 변경 내역 관리함으로써 스냅샷을 사용

A, B, C 파일이 스냅샷으로 생성되었을 때 읽기 작업을 수행하는 경우 파일시스템의 원본 파일에 접근해 내용을 읽으면 되지만 쓰기 작업을 수행할 경우 원본 파일을 유지하면서도 변경된 사항을 저장할 수 있어야 함 -> 이를 해결하는 방법에 따라 CoW, RoW로 나눠지게 됨

  1. CoW : 스냅샷의 파일에 쓰기 작업을 수행할 때 스냅샷 공간에 원본 파일을 복사한 뒤 쓰기 요청을 반영 (복사를 위해 파일 읽는 작업 + 스냅샷 공간에 쓰고 변경된 사항을 쓰는 작업, 총 2번의 쓰기 작업으로 오버헤드가 발생)
  1. RoW : CoW와 다르게 한 번의 쓰기 작업만 발생, 스냅샷 공간에 복사하는 것이 아닌 스냅샷에 기록된 원본 파일은 스냅샷 파일로 묶은 뒤 변경 사항을 새로운 장소에 할당 받아 덮어쓰는 형식




도커 컨테이너와 이미지에 적용을 하면 이미지 레이어는 각 스냅샷에 해당하고, 컨테이너는 이 스냅샷을 사용하는 변경점
컨테이너를 이미지로 만들면 변경된 사항이 스냅샷으로 생성되고 하나의 이미지 레이어로서 존재하게 됨

-> 이를 수행하는 방법에 따라 여러 스토리지 드라이브 (AUFS, Devicemapper, OverlayFS, Btrfs, ZFS ..) 존재



도커 데몬 모니터링

많은 수의 도커 서버를 효율적으로 관리하기 위해, 도커로 컨테이너 애플리케이션을 개발하다 문제가 생겼을 때 원한을 찾기 위해, PaaS로 제공하기 위해 실시간으로 도커 데몬의 상태를 체크하기 위해 다양한 방법으로 모니터링을 할 수 있음

도커 데몬 디버그 모드

도커 데몬의 상태를 알아내는 방법 이며 Remote API의 입출력뿐만 아니라 로컬 도커 클라이언트에서 오가는 명령어를 출력함

# dockerd -D // -D 옵션을 통해 디버그 모드 실행 

위의 디버그 모드는 너무 많은 로그를 출력하기 때문에 도커에서 제공하는 명령어를 통해 모니터링을 할 수 있음

events : 도커 데몬에 어떤 일이 일어나고 있는지 실시간 스트림 로그로 보여줌

# docker events 
# docker system events

attach, commit, copy, create 등의 컨테이너 관련 명령어, delete, import, load, pull, push 등의 이미지 관련 명령어, 볼륨, 네트워크, 플러그인 등에 관한 명령어를 확인할 수 있음

// --filter 옵션을 통해 원하는 정보만 확인할 수 있음 (container, image, volumne network, plugin, daemon)
# docker events --filter "type=image" 

stats : 실행 중인 모든 컨테이너의 자원 사용량을 스트림으로 출력

실행중인 모든 컨테이너의 CPU, 메모리 제한 및 사용량, 네트워크 입출력(I/O), 블록 입출력 정보를 출력

# docker stats 
CONTAINER ID   NAME      CPU %     MEM USAGE / LIMIT   MEM %     NET I/O     BLOCK I/O   PIDS
c1c8ca08d5d0   ubuntu    0.00%     864KiB / 7.674GiB   0.01%     806B / 0B   0B / 0B     1

// --no-stream으로 한번만 출력 가능 
# docker stats --no-stream

system df : 도커에서 사용하고 있는 이미지, 컨테이너, 로컬 볼륨의 개수, 크기, 확보 가능한 공간을 출력

# docker system df

CAdvisor : 구글이 만든 컨테이너 모니터링 도구로, 컨테이너별 실시간 자원 사용량 및 도커 모니터링 정보를 시각화 해서 보여줌

# docker run \
  --volume=/:/rootfs:ro \ 
  --volume=/var/run:/var/run:ro \
  --volume=/sys:/sys:ro \
  --volume=/var/lib/docker/:/var/lib/docker:ro \ 
  --volume=/dev/disk/:/dev/disk:ro \
  --publish=8080:8080 \
  --detach=true \ 
  --name=cadvisor \ 
  google/cadvisor:latest



파이썬 Remote API 라이브러리를 이용한 도커 사용

-H 옵션을 원격의 도커 데몬을 제어하기 위해 사용하는 것도 좋은 방법이지만 컨테이너 애플리케이션이 수행해야 할 작업이 많거나 애플리케이션 초기화 등에 복잡한 과정이 포함되어 있으면 도커를 제어하는 라이브러리를 사용해 쉽게 해결 가능 함

Go, C#, C++, Python, Dart, Java 등 사용 가능

도커 클라이언트 객체를 생성하여 도커 엔진을 제어할 수 있음, 이때 base_url에 http://192.168.0.100:2375 와 같이 도커 데몬에 접근할 수 있는 IP 주소와 포트번호를 입력해야 함

# python3 

>>> import docker 
>>> client = docker.DockerClient(base_url="unix://var/run/docker.sock')
>>> client.info()


>>> container = client.run('nginx', detach=True, ports={'80/tcp' : 80 }) # docker run -d -p 80:80 nginx 와 동일 

0개의 댓글