[Docker] 도커 엔진

업데이트:

2.1 도커 이미지와 컨테이너

2.1.1 도커 이미지

  • 컨테이너 생싱 시 필요
  • 읽기 전용
  • [저장소이름]/[이미지 이름]:[태그]
    • 저장소 이름: 이미지가 저장된 장소. default는 도커 허브의 공식 이미지
    • 이미지 이름: 이미지의 역할
    • 태그: 버전관리, revision

2.1.2 도커 컨테이너

  • 이미지의 목적에 마즌 파일이 들어있는 파일 시스템과 격리된 시스템 자원 및 네트워크를 사용할 수 있는 독립된 공간이 생성됨.
  • 이미지 종류에 따라 알맞은 설정과 파일 갖고있음
  • 이미지를 읽기 전용으로 사용하되 이미지에서 변경된 사항만 컨테이너 계층에 저장 -> 원래 이미지는 영향 X
  • 컨테이너와 호스트 상호 독립

2.2 도커 컨테이너 다루기

2.2.4 컨테이너를 외부에 노출

  • ifconfig의 eth0의 IP와 포트를 host IP에 바인딩 해야 외부에서 접근 가능 docker run -i -t –name mywebserver -p 80:80
    • 80 (앞) : host port
    • 80 (뒤) : container port
    • host의 특정 port와 container의 port binding

2.2.5 컨테이너 애플리케이션 구축

  • 한 컨테이너에 하나의 프로세스만 실행하는 것이 도커의 철학
  • -d 옵션으로 run 하면 detach 모드로 run 가능
  • -e는 docker 내부에 환경변수 생성 가능
  • -link는 ip를 알 필요 없이 hostname으로 접근 하도록 설정
    • deprecated 됐고 도커 bridge로 동일한 기능 사용 가능

2.2.6 도커 볼륨

  • 도커 이미지는 읽기 전용이므로 컨테이너의 변경 사항만 별도로 저장해서 각 컨테이너의 정보 보존
  • but 컨테이너를 삭제하면 컨테이너 계층에 저장되어 있는 정보 (ex database)도 삭제됨 -> 볼륨 사용으로 해결!
  1. 호스트와 볼륨 사용
    • -v [호스트의 공유 디렉터리]:[컨테이너의 공유 디렉터리]
    • 호스트의 디렉터리를 컨테이너의 디렉터리에 마운트
  2. 볼륨 컨테이너
    • -volumnes-from 옵션을 통해 -v 또는 –volumn 옵션을 적용한 컨테이너의 볼륨 디렉터리 공유 가능
  3. 도커 볼륨
    • docker volumn 생성 후 활용
    • 로컬 호스트에 저장됨
    • 도커 엔진에 의해 생성되고 삭제됨
    • -v [볼륨의 이름]:[컨테이너의 공유 디렉터리]
  • 볼륨은 디렉터리 하나에 상응하는 단위
  • 도커 엔진에서 관리
  • 어디에 저장되는지 알 필요 없지만 docker inspect하면 알 수 있음
  • 컨테이너가 아닌 외부에 데이터를 저장하고 컨테이너는 그 데이터가 동작하도록 설계하는 것을 스테이트리스(stateless) 하다고 말함 -> 바람직
  • 컨테이너가 데이터를 저장하고 있어서 상태가 있는 경우를 stateful 하다고 말함 -> 지양

2.2.7 도커 네트워크

  • 도커는 컨테이너 내부 IP를 순차적으로 할당 -> veth
  • 컨테이너 재시작 할 때마다 변경됨
  • 내부망(호스트)에서만 쓰므로 외부와 연결될 필요 X
  • 각 컨테이너에 외부와의 네트워크를 제공하기 위해 컨테이너마다 가상 네트워크 인터페이스를 호스트에 생성 (veth로 시작)
  • veth 인터페이스는 컨테이너가 생성될 때 토커 엔진이 자동 생성
  • veth는 각 컨테이너의 eth0와 연결됨
  • docker0 브리지는 각 veth 인터페이스와 바인딩 됨 -> host의 eth0 인터페이스와 연결시켜줌
  1. 브리지 네트워크
    • 컨테이너 생성할 때 자동으로 연결되는 docker0 네트워크 활용
    • 172.17.0.X IP 대역 순차 할당
    • 사용자 정의 브리지는 새로 생성해 각 컨테이너에 연결
    • 브리지 타입의 네트워크를 생성하면 IP 대역을 차례대로 할당
  2. 호스트 네트워크
    • 호스트의 네트워크 환경 그대로 사용
    • 호스트 머신에서 설정한 호스트 이름 물려받음
    • 컨테이너 내부의 애플리케이션을 별도의 포트 포워딩 없이 바로 서비스 가능 -> 실제 호스트에서 애플리케이션을 외부에 노출하는 것과 같음
  3. 논 네트워크
    • 아무런 네트워크를 쓰지 않는 것
    • 외부와 연결이 단절됨
  4. 컨테이너 네트워크
    • 다른 컨테이너의 네트워크 네임스페이스 환경 공유
    • IP, 네트워크 인터페이스의 맥 (MAC) 주소 등 - 내부 IP 새로할당 X - 호스트에 veth로 시작하는 가상 네트워크 인터페이스 생성 X
  5. 브리지 네트워크의 –net-alias
    • 특정 호스트 이름으로 컨테이너 여러개에 접근 가능
    • 도커 엔진에 내장된 DNS가 호스트 이름이 같은 컨테이너로 변환. round robin 방식 사용
    • DNS는 호스트 이름으로 유동적인 컨테이너 찾을 때 사용됨
  6. MacVLAN 네트워크
    • 컨테이너는 물리 네트워크상에서 가상의 맥(MAC) 주소를 가지며 해당 네트워크에 연결된 다른 장치와의 통신이 가능해짐
    • 기본적으로 할당되는 IP대역인 172.17.XX 아니고 네트워크 장비의 IP할당받기 때문 - 호스트와 통신 불가능 - 적어도 1개의 네트워크 장비와 서버 필요

2.2.8 컨테이너 로깅

  • 기본적으로 JSON 형태로 log를 저장하지만 로깅 드라이버를 사용해 컨테이너 로그를 수집할 수 도 있음
  1. syslog 로그
    • 유닉스 계열 운영체제에서 로그를 수집하는 오래된 표준 중 하나
    • 커널, 보안, 시스템 등과 관련된 로그, 애플리케이션 로그 등 수집
    • 유닉스 계열 체제에서는 syslog를 사용하는 인터페이스가 동일 -> 체계적인 로그 수집 가능
    • 원격 서버에 syslog를 설치해서 로그 정보를 원격 서버로 보내기 가능
  2. fluentd 로깅
    • 로그 수집 저장
    • JSON 사용
    • AWS S3, HDFS, MongoDB 등 다양한 저장소에 저장 가능

2.2.9 컨테이너 자원 할당

  • 자원할당을 안하면 호스트의 자원을 전부 점유해 다른 컨테이너들 뿐 아니라 호스트 자체의 동작이 멈출 수 도 있음
  1. 컨테이너 메모리 제한
    • 할당된 메모리를 초과하면 자동으로 종료됨
    • 기본적으로 swap 메모리는 메모리의 2배로 설정됨
  2. 컨테이너 cpu 제한
    1. –cpu-shares
      • 컨테이너에 가중치 할당
      • 존재하는 cpu를 어느 비중만큼 나눠 쓸 것인지
    2. –cpuset-cpu -호스트에 cpu가 여러개 있을 때 컨테이너가 특정 cpu만 사용하도록 설정

    3. –cpu-period, –cpu-quota
      • 컨테이너의 CFS (Completely Fair Scheduler) 주기는 기본적으로 100ms로 설정되지만 주기 변경 가능
      • –cpu-period의 기본값은 100000이며 100ms를 뜻함
      • –cpu-quotasms –cpu-period에 설정된 시간 중 cpu 스케줄링에 얼마나 할당할 것인지 설정
    4. –cpus
      • –cpu-period, –cpu-quota와 같은데 더 직관적
      • cpu 개수 직접 지정
      • 병렬처리를 위해 cpu를 마니 소모하는 워크로드를 수행해야 한다면 –cpuset-cpu 옵션을 사용하는게 좋음. 특정 컨테이너가 특정 cpu에서만 동작하는 cpu 친화성 보장. cpu 캐시 미스, 컨텍스 스위칭 최소화
  3. Block I/O 제한
    • 기본적으로 컨테이너 내부에서 파일을 읽고 쓰는 대역폭에 제한 X
    • DIRECT I/O의 경우에서는 입출력만 제한됨. Buffered I/O는 제한 X
    • 상대적인 값으로 입력
  4. 스토리지 드라이버와 컨테이너 저장 공간 제한
    • 컨테이너 내부의 저장 공간을 제한하는 기능을 보편적으로 제공 X
    • but 도커의 스토리지 드라이버나 파일 시스템 등이 특정 조건을 만족하는 경우에만 제한적으로 사용 가능
    • 나중에 설명 더 해줌

2.3 도커 이미지

  • 도커 허브라는 중앙 이미지 저장소에서 이미지 내려받음

2.3.1 도커 이미지 생성

  • 컨테이너에서 변경사항을 만든 후 docker commit

2.3.2 이미지 구조 이해

  • 이미지를 커밋할 때 컨테이너에서 변경된 사항만 새로운 레이어로 저장
  • docker rmi하면 삭제됨
    • 실행중인데 강제로 삭제하면 이미지 레이어 파일을 실제로 삭제하지 않고 이미지 이름만 삭제
      • docker rmi -f
      • 이름이 으로 변경되고 dangling 이미지가 됨. docker image prune을 통해 한번에 삭제 가능
    • 이미지를 사용중인 컨테이너 stop 후 이미지를 삭제하면 정상적으로 삭제 가능
    • 해당 이미지를 사용한 commit이 있다면 이미지 파일이 삭제가 되는 것이 아니라 레이어에 부여된 이름만 삭제됨

2.3.3 이미지 추출

  • docker save를 하면 컨테이너의 커맨드, 이미지 이름과, 태그 등 이미지의 모든 메타데이터를 퐇마해 하나의 파일로 추출 가능
  • 단일 파일로 저장하는 것은 효율적인 방법이 아님

2.3.4 이미지 배포

  • 파일로 배포시 용량이 너무 크면 힘듦 & 도커의 이미지 구조인 레이어 사용 x -> 비효율적
  1. 도커 저장소 사용
    • private은 유료
  2. Docker Private Registry 사용
    • 직접 이미지 저장소 만들기

2.4 Dockerfile

2.4.1 이미지를 생성하는 방법

  1. 아무것도 존재하지 않는 이미지로 컨테이너 생성
  2. 어플리케이션을 위한 환경을 설치하고 소스코드 등을 복사해 잘 동작하는 것을 확인
  3. 컨테이너를 이미지로 커밋
  • 장점: 이미지의 동작 보장할 수 있음
  • 단점: 일일이 수작업으로 패키지 설치하고 소스코드를 깃에서 복제하거나 호스트에서 복사해야 한다.

=> build 명령어를 제공

  • 완성된 이미지를 생성하기 위해 컨테이너에 설치해야하는 패키지, 추가해야하는 소스코드, 실행해야 하는 명령어와 셸 스크립트 등을 하나에 파일에 기록 -> 읽어서 컨테이너에서 작업을 수행한 뒤 이미지로 만들어냄

=> 이것이 Dockerfile이다

  • 이미지 대신 Dockerfile 배포 가능
  • 장점:
    • 이미지 생성 방법이 기록됨
    • 이미지 빌드, 배포에서 유리
    • 이미지 생성 자동화
    • 쉽게 배포 가능
    • 이미지 신뢰하지 못하거나 직접 생성해서 사용하고 싶을 때

2.4.2 Dockerfilie 작성

  • 도커엔진은 Dockerfile을 읽어들일 때 기본적으로 현재 디렉터리에 있는 Dockerfile이라는 이름을 가진 파일 선택
  • 빈 디렉터리에 저장하는 것이 좋음 => context 때문
  • 일반적으로 명령어는 대문자로 표기. 소문자도 괜찮음
  • 위에서 아래로 한 줄씩 차례로 실행

FROM

  • 생성할 이미지의 베이스가 될 이미지
  • 반드시 한 번 이상 입력
  • docker run에서 이미지 이름 입력했을때와 동일

MAINTAINER

  • 이미지를 생성한 개발자 벙보
  • Dockerfile을 작성한 사람과 연락할 수 있는 메일 등
  • 도커 1.13.0 이후 사용 X
    • LABEL maintainer … 로 대체 사용

LABEL

  • 이미지에 메타데이터 추가
  • 키:값 형태로 저장
  • 여러개 메타데이터 저장 가능
  • docker inspect 명령어로 이미지 정보 구해서 확인 가능

RUN

  • 이미지 만들기 위해 컨테이너 내부에서 명령어 실행
  • 이미지 빌드할 때 별도의 입력을 받아야하는 RUN이 있으면 build 명령어는 이를 오류로 간주하고 종료시킴

ADD

  • 파일을 이미지에 추가
  • 파일을 Dockerfile이 위치한 디렉터리인 컨텍스트에서 가져옴

WORKDIR

  • 명령어를 실행할 디렉터리
  • bash shell의 cddhk rkxdma
  • 여러번 사용시 cd를 여러번 사용한 것과 같음

EXPOSED

  • 빌드로 생성된 이미지에서 노출할 포트 설정
  • run 명령어에서 모든 노출된 컨테이너의 포트를 호스트에 퍼블리시하는 -p flag와 함께 사용됨

CMD

  • 컨테이너가 시작될 때 마다 실해앟ㄹ 명령어를 설정
  • 한번만 사용 가능

2.4.3 Dockerfile 빌드

2.4.3.1 이미지 생성

docker build -t mybuild:0.0 ./

  • -t: 생성될 이미지의 이름 설정. 사용 안하면 16진수 형태의 이름으로 저장 됨
  • ./: Dockerfile이 저장될 경로

docker run -d -P –name myserver mybuild:0.0

  • -P: 설정된 EXPOSE의 모든 포트를 호스트에 연결. 노출된 포트를 사용 가능한 포트에 차례로 연결

2.4.3.2 빌드 과정 살펴보기

빌드 컨텍스트

  • 이미지를 빌드하면 가장 먼저 빌드 컨텍스트를 읽어 들임
  • 빌드 컨텍스트: 이미지를 생성하는데 필요한 각종 파일, 소스코드, 메타데이터 등을 담고있는 디렉터리. Dockerfile이 위치한 디렉터리
    • Dockerfile에 서 빌드된 이미지 파일을 추가할 때 사용됨
      • ADD, COPY등 가능
  • 컨텍스트는 build 명령어의 맨 마지막에 지정된 위치에 있는 파이 모두 포함 =>따라서 Dockerfile이 위치한 곳에는 이미지를 빌드하는데 필요한 파일만 있는 것이 바람직
    • 속도가 느려지거나 호스트 메모리 지나치게 점유할 수 도 있음
      • 이를 방지가히 위해 .gitignore과 유사한 .dockerignore 파일 작성하여 이 파일에 명시된 이름의 파일을 커넥스트에서 제외
      • .dockerignore은 컨텍스트의 최상위 경로, 즉 build 명령어 맨 마지막에 오는 경로인 Dockerfile이 위치한 경로와 같은 곳에 위치해야함
  • 제외목록에 포함되지만 특수한 파일만 포함하도록 설정 하고 싶다면 ! 사용

Dockerfile을 이용한 컨테이너 생성과 커밋

  • 명령어 한 줄일 실행될 때마다 컨테이너가 하나씩 생성되며 이를 이미지로 커밋

-> 새로운 layer 생성됨

=> 이미지 빌드가 완료되면 Dockerfile의 명령어 줄 수 만큼의 레이어가 존재하게 되며 중간에 컨테이너도 같은 수 만큼 생성되고 삭제됨

캐시를 이용한 이미지 빌드 한번 이미지 빌드를 마치고 난 뒤 다시 같은 빌드를 진행하면 이전 이미지 빌드에서 사용했던 캐시를 사용함

-> 이전에 빌드했던 Dockerfile에 같은 내용이 있으면 build 명령어는 새로 빌드하지 않고 같은 명령어 줄까지 이전에 사용한 이미지 레이어를 활용해 빌드

  • 빌드 중 오류가 발생했을 시 build 명령어가 중지되며 이미지 레이어 생성을 위해 마지막으로 생성된 임시 컨테이너가 삭제되지 않은 채로 남게 됨
  • 빌드가 완전하지 않기 때문에 : 으로 이미지가 생성됨
  • 캐시 기능이 필요하지 않을 떄도 있음
    • ex) git clone을 했을 때 캐시를 사용하면 repo에 변경사항이 생겨도 이전 캐시 사용해서 빌드
    • –no-cache 옵션을 사용해 캐시를 사용하지 않고 처음부터 빌드
  • 캐시로 사용할 이미지 직접 지정 가능
    • docker build –cache-from nginx -t my_extend_nginx:0.0

2.4.3.3 멀티 스테이지를 이용한 Dockerfile 빌드하기

하나의 Dockerfile안에 여러개의 FROM 이미지를 정의함으로써 빌드 완료시 최종저그올 생성될 이미지의 크기를 줄이는 역할 반드시 필요한 실행파일만 최종 이미지 결과물에 포함시킴으로써 이미지 크기를 줄일 때 유용하게 사용 가능

2.4.4 기타 Dockerfile 명령어

2.4.4.1 ENV, VOLUME, ARG, USER

ENV

  • Dockerfile에서 사용될 환경변수 저장
  • ${ENV_NAME} 또는 $ENV_NAME의 형태로 사용
  • Dockerfile뿐만 아니라 이미지에도 저장 => 빌드된 이미지로 컨테이너를 생성하면 이 환경변수 사용 가능
  • run 명령어에서 -e 옵션을 같은 이름의 환경변수를 사용하면 기존의 값 덮어쓰여짐
  • {$env_name:-value}는 env_Name이 설정되어있지 안흥면 value를 값으로 사용
  • 반대로 {$env_name:+value}는 env_name이 설정되어있다면 value를 값으로 사용하고 설정되어있지 않다면 빈 문자열 사용

VOLUME

  • 빌드된 이미지로 컨테이너를 생성했을 때 호스트와 공유할 컨테이너 내부의 디렉터리 설정
  • 여러개를 JSON 배열 형식으로 사용 가능

ARG

  • build 명령어를 실행할 때 추가로 입력을 받아 Dockerfile 내에서 사용될 변수의 값 설정
  • 기본값 지정 가능
  • docker build –build-arg my_arg=/home -t myarg:0.0
  • ARG와 ENV의 값을 사용하는 방법은 ${}로 같으므로 Dockerfile에서 ARG로 설정한 변수를 ENV에서 같은 이름으로 다시 정의하면 –build-arg 옵션에서 설정하는 값은 ENV에 의해서 덮어쓰여짐

USER

  • 컨테이너 내에서 사용될 사용자 계정의 이름이나 UID를 설정하면 그 아래의 명령어는 해당 사용자 권한으로 실행됨
  • 일반적으로 RUN 사용자 그룹과 계정을 생성한 뒤 사용
  • 루트 권한이 필요하지 않다면 USER 사용 권장
    • 기본적으로는 root 사용자 사용하도록 설정됨 but 컨테이너가 호스트 root 권한을 가질 수 있다는 것을 의미 -> 바람직 하지 않음
    • 최종 배포할 때 이미지 자체에 다른 사용자 설정 권장

2.4.4.2 Onbuild, Stopsignal, Healthcheck, Shell

Onbuild

  • 빌드된 이미지를 기바능로 하는 다른 이미지가 Dockerfile로 생성될 때 실행할 명령어를 추가
  • ONBUILD, FROM, MAINTAINER를 제외한 RUN, ADD 등 이미지가 빌드될 때 수행되야 하는 각종 Dockerfile의 명령어를 나중이 빌드될 이미지를 위헤 미리 저장
  • 부모 이미지의 자식 이미지에만 적용됨
  • 자식 이미지는 ONBUILD 속성 상속 X

STOPSIGNAL

  • 컨테이너가 정지될 때 사용될 시스템 콜의 종류 지정
  • Default는 SIGTERM이지만 STOPSIGNAL로 컨테이너가 종료되는데 사용될 신호 선택 가능
  • docker run에서 –stop-signal로 컨테이너 개별적으로 설정 가능

HEALTHCHECK

  • 이미지로부터 생성된 컨테이너에서 동작하는 애플리케이션의 상태를 체크하도록 설정
  • 컨테이너 내부에서 동작중인 애플리케이션의 프로세스가 종료되지는 않았으나 애플리케이션이 동작하고 있지 않은 상태 방지 위해 사용

SHELL

  • 기본쉘은 리눅스에서 “/bin/sh -c” 윈도우에서 “cmd /S /C”
  • SHELL 옵션에서 JSON 배열 형식으로 지정 가능

2.4.4.3 ADD, COPY

COPY

  • 로컬 디렉터리에서 읽어들인 컨텍스트로부터 이미지에 파일 복사
  • 형식은 ADD와 같음
  • ADD와의 차이점은 COPY는 로컬의 파일만 이미지에 추가할 수 있지만 ADD는 외부 URL 및 tar 파일에서도 파일을 추가할 수 있음
  • COPY의 기능이 ADD에 포함됨
  • 하지만 ADD는 URL이나 tar파일을 추가할 경우 그대로 추가하는 것이 아니라 자동으로 해체해서 추가하기 때문에 어떤 파일이 추가될지 몰라 권장하지 않음

2.4.4.4 ENTRYPOINT, CMD

ENTRYPOINT와 CMD의 차이점

  • CMD와 유사
  • CMD와 동일하게 컨테이너가 시작될 때 명령이 지정됨
  • 하지만 ENTRYPOINT는 커맨드를 인자로 받아 사용할 수 있는 스크리브의 역할 가능
  • entrypoint가 설정되지 않았다면 cmd에 설정된 명령어를 그대로 실행하지만 entrypoint가 설정됐다면 cmd는 단지 entrypoint에 대한 인자의 기능 함
  • CMD와 ENTRYPOINT가 둘 다 설정되지 않으면 컨테이너는 생성되지 않고 에러를 출력하므로 반드시 둘 중 하나를 설정해야 함

ENTRYPOINT를 이용한 스크립트 실행

  • 일반적으로 스크립트 파일을 entrypoint의 인자로 사용해 컨테이너가 시작될 때마다 해당 스크립트 파일을 실행하도록 설정 -> 스크립트 파일의 이름을 entrypoint의 인자로 입력
    • 단 실행할 스크립트 파일은 컨테이너 내부에 존재해야 함
      1. 어떤 설정 및 실행이 필요한지에 대해 스크립트로 정리
      2. ADD 또는 COPY로 스크립트를 이미지로 복사
      3. ENTRYPOINT를 이 스크립트로 설정
      4. 이미지를 빌드해 사용
      5. 스크립트에서 필요한 인자는 docker run 명령어에서 cmd로 entrypoint의 스크립트에 전달

JSON 배열 형태와 일반 형식의 차이점

  • CMD와 ENTRYPOINT에서 설정하려는 명령어를 /bin/sh로 사용할 수 없다면 JSON 배열의 형태로 명령어를 전달해야함 -> 그렇지 않는다면 앞에 /bin/sh -c 가 추가됨
  • JSON 형태로 명령어를 입력하면 입력된 명령어가 그대로 이미지에 사용됨

2.4.5 Dockerfile로 빌드할 때 주의할 점

  • 이미지는 레이어가 쌓이는 형태로 저장되기 때문에 실제로 컨테이너에서 사용하지 못하는 파일이 이미지 레이어로 존재할 수 있음
    • 저장공간은 차지하지만 실제로는 의미 없을 수 있음
  • Dockerfile로 작성할 때 &&으로 각 RUN 명령어를 하나로 묶는 것 => RUN이 하나의 이미지 레이어가 될 수 있음. 레이어 수를 줄이는데도 사용 가능
  • 다른 사람이 빌드한 이미지에 불필요한 이미지 레이어가 들어있다면 해당 이미지로 컨테이너를 생성하고 docker export, import를 사용해 컨테이너를 이미지로 만듦으로써 이미지 크기 줄이기 가능. -> 크기는 줄어들지만 이전 이미지에 저장되어있던 각종 이미지 설정은 잃어버리게 됨

2.5 도커 데몬

2.5.1 도커의 구조

  • which -> 파일이 위치한 경로 출력
  • ps aux -> 실행중인 프로세스 목록 출력
  • 도커의 구조는 두가지로 나뉨
    1. 클라이언트로서의 도커
      • 도커 데몬은 API입력을 받아 도커 엔진의 기능을 수행하는데 이 API를 사용할 수 있도록 CLI 제공
      • docker로 시작하는 명령어 입력하면 도커 클라이언트를 사용하는 것 -> 도커 클라이언트는 입력된 명령어를 로컬에 존재하는 도커 데몬에게 API로 제공
    2. 서버로서의 도커
      • 실제로 컨테이너를 생성하고 실행하며 이미지 관리하는 주체
      • dockerd 프로세스로서 동작
      • 외부에서 API 입력을 ㅂ다아 도커 엔진의 기능을 수행하는데, 도커 프로세스가 실행되어 서버로서 입력 받을 준비가 된 상태를 도커 데몬이라고 함

2.5.2 도커 데몬 실행

  • service docker start/ service docker stop
  • 우분투에서는 도커가 설치되면 자동으로 서비스로 등록되므로 호스트가 재시작되더라도 자동으로 실행 됨
  • 레드햇 계열에서는 도커를 설치해도 자동으로 실행되도록 설정되지 않음 -> 자동으로 실행되도록 하려면 systemctl enable docker
  • dockerd를 입력하면 도커 데몬이 실행됨

2.5.3 도커 데몬 설정

  • 옵션을 주고 dockerd 명령어로 도커 데몬을 직접 실행하는 것 보다 도커 설정 파일을 수정한 뒤 도커 데몬이 설정 파일을 읽어 서비스로 실행되게 하는 것이 일반적

-> 도커 설정 파일의 DOCKER_OPTS에 입력하면 됨

2.5.3.1 도커 데몬 제어: -H

  • 도커 데몬의 API를 사용할 수 있는 방법을 추가
  • -H에 IP주소와 포트 번호를 입력하면 원격 API인 Docker Remote API로 도커 제어 가능
  • Remote API는 로컬에 있는 도커 데몬이 아니더라도 제어 가능
  • RESTful API 형식을 띠고 있으므로 HTTP 요청으로 도커 제어 가능
    • ex: dockerd -H tcp://0.0.0.0:2375는 모든 네트워크 인터페이스의 IP주소와 2375번 포트를 바인드해 입력 받음
      • 이런경우 유닉스 소켓은 비활성화 되므로 도커 클라이언트 사용 불가 -> docker로 시작하는 명령어 사용 불가
      • 따라서 일반적으로 -H unix:///var/run/docker.sock도 동시에 설정해줌
        • dockerd -H unix:///var/run/docker.sock -H tcp://0.0.0.0:2375 하면 호스트의 모든 네트워크 인터페이스 카드에 할당된 IP주소와 2375번 포트로 도커 데몬을 제어함과 동시에 도커 클라이언트 사용 가능
  • Remote API와 내부적으로 같은 API를 사용하므로 도커 클라이언트에서 사용 가능한 모든 명령어 사용 가능
  • DOCKER_HOST를 설정해 원격에 있는 도커 제어 가능
  • 또는 클라이언트에 -H 옵션을 설정해 제어할 원격 도커 데몬 설정

2.5.3.2 도커 데몬에 보안 적용: –tlsversify

  • 기본적으로 보안 연결 설정 x -> 바람직 x. 바인딩된 IP주소와 포트 번호만 알면 도커 제어할 수 있음
  • 도커 데몬
    • ca.pem
    • server-cert.pem
    • server-key.pem
  • 도커 클라이언트
    • ca.pem
    • cert.pem
    • key.pem
  • 파일 생성이 완료되면 TLS 보안 적용을 활성화하기 위해 -tlsverify옵션 추가하고 –tlscacert, –tlscert, –tlskey에 각각 보안을 적용하는데 필요한 파일 위치 입력
  • 도커의 Remote API를 사용하는 포트는 보안이 적용돼 있지 않다면 2375번 포트를, 보안이 적용돼 있다면 2376번 포트를 사용하도록 설정
  • DOCKER_CERT_PATH는 도커 데몬 인증에 필요한 파일 위치를, DOCKER_TLS_VERIFY는 TLS인증을 사용할지 말지 설정하는 환경변수들

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

  • 스토리지는 사용하는 환경에 따라 자동으로 정해짐
    • 우분투와 같은 데비안 계열 운영체제는 overlay2
    • 구 버전의 CentosOS와 같은 운영체제는 devicemapper
  • –storage-driver를 사용해 선택 가능
    • OverlayFS
    • AUFS
    • Btrfs
    • Devicemapper
    • VFS
    • ZFS
  • 하나만 선택해 도커 데몬에 적용 가능
  • 적용된 스토리지 드라이버에 따라 컨테이너와 이미지 별도 새엇됨

스토리지 드라이버의 원리

  • 스냅숏의 기본 개념:
    • 원본 파일은 읽기 전용으로 사용하되 이 파일이 변경되면 새로운 공간을 할당한다
    • 스토리지를 스냅숏으로 만들면 스냅숏안에 어느 파일이 어디에 저장돼 있는지가 목록으로 저장됨
    • 스냅숏 안의 파일에 변화가 생기면 변경된 내역을 따로 관리
      • 해결 방법에 따라 CoW(Copy-on-Write)와 RoW(Row-on-Write)로 나뉨
  • CoW는 스냅숏의 파일에 쓰기 작업을 수행할 때 스냅숏 공간에 원본 파일을 복사한 뒤 쓰기 요청 반영
    • 복사하기 위해 파일을 읽는 작업 한 번, 파일을 스냅숏 공간에 쓰고 변경된 사항을 쓰는 작업 한 번, 총 2번의 쓰기 일어남 -> 오버헤드 발생
  • RoW는 CoW와 다르게 한 번의 쓰기 적업만 일어남
    • 파일을 스냅숏 공간에 복사하는 것이 아니라 스냅숏이 기록된 원본 파일을 스냅숏 파일로 묶은(Freeze) 뒤 변경된 사항을 새로운 장소에 할당받아 덮어씀
    • 스냅숏 파일은 그대로 사용하되 새로운 블록은 변경사항으로써 사용
  • 스냅숏이라는 개념으로 스냅숏 파일을 불변 상태로 유지할 수 있다는 것만 기억

AUFS 드라이버 사용

  • 데비안 계열에서 기본적으로 사용할 수 있는 드라이버
  • 도커에서 오랜기간 사용해왔기 때문에 안정성 측면에서 우수
  • but 기본적으로 커널에 포함 x -> 일부 운영체제 (RHEL, CentOS)에서 사용불가
  • 여러개의 이미지 레이어를 유니언 마운트 지점(Union Mount Point)로 제공 -> 컨테이너 레이어가 여기에 마운트해서 이미지를 읽기 전용으로 사용
  • 컨테이너 레이어로 전체 파일을 복사하고 이 파일을 변경함으로써 변경사항 반영
    • 가장 위 레이어부터 탐색하기 때문에 시간이 오래걸릴 수 도 있음
  • 커네이너의 실행, 삭제 등의 컨테이너 관련 수행 작업이 매우 빨라 PaaS에 적합한 드라이버로 꼽힘

Devicemapper

  • 레드헷 계열의 리눅스 배포판을 위해 개발된 스토리지 드라이버
  • 대부분의 리눅스 배포판에서 사용할 수 있다는 장점이 있지만 성능상의 이유로 더 이상 사용하지 않는 것이 권장됨
  • 이미지와 컨테이너의 데이터가 분리된 디렉터리로 저장되는 것이 아닌 data 파일로 이루어진 pool에서 블록 단위로 할당 받는 구조
  • 컨테이너와 이미지 블록의 정보는 metadata 파일에 저장됨
    1. 스토리지 풀에서 공간을 할당받음
    2. 이미지의 스냅숏을 만들어 사우이 레이어 생성
    3. 이미지로부터 변경된 사항을 저장하는 컨테이너 레이어는 이 레이어들을 묶은 파운트 포인트에서 새로운 스냅샷을 생성해서 사용됨
  • allocate-on-demand라는 원리로 컨테이너 내부에서 새로우 파일 기록
    • devicemapper이 풀에서 필요한 만큼의 64kb 크기의 블록 개수를 할당해서 쓰기 작업을 수행하는 것
    • 이미지에 존재하던 데이터에 쓰기 작업을 수행할 때는 변경하려는 원본 파일의 블록을 컨테이너에 복사한 뒤 컨테이너 내부에 복사된 블록파일을 수정
  • AUFS 드라이버와 달리 전체 파일을 복사하지 않는다는 점에서 성능상의 이점이 있지만 컨테이너를 생성하고 삭제하는 등의 작업은 빠른 편이 아님
  • devicemapper라는 데이터 풀 안에 컨테이너와 이미지 데이터를 저장하기 때문에 멀티테넌시 환경을 위해 각 컨테이너와 이미지를 분리해 관리하는 것이 불가능
    • 실제 운영 환경에서 PaaS와 같은 용도로 사용하는 것을 권장 x

Overlay FS 드라이버 사용하기

  • 레드헷 계열 및 라즈비안, 우분투 등 대부분의 운영체제에서 도커를 설치하면 자동으로 사용되도록 서정되는 드라이버
  • AUFS와 비슷한 원리로 동작하지만 좀 더 간단한 구조로 사용되며 성능 또한 좀 더 좋아서 최신 버전의 도커는 Overlay FS를 기본적으로 사용함
  • Overlay2가 overlay에 비해 성능이 좀 더 우수하며 이미지를 구성하기 위해 여러개의 레이어 구조를 지원 -> overlay2가 권장됨
  • overlay는 다른 스토리지 드라이버와 달리 계층화된 이미지 구조 사용 x -> lowerdir이라는 단일화된 이미지 레이어 사용
  • overlay 드라이버는 컨테이너를 사용하기 위해 도커를 merged, upperdir, lowerdir의 구조로 나눔
    • lowerdir: 도커의 이미지 레이어
    • uppserdir: 도커의 컨테이너 레이어
  • 다른 스토리지 드라이버와 다르게 여러 계층의 이미지 준재 x. 여러개의 이미지 레이어를 하나의 컨테이너 마운트 지점에 통합
  • upperdir에는 컨테이너에서 발생한 변경사항을 담고있음
  • upperdir은 이미지 레이어에 해당하는 lowerdir과 함께 마운트되어 최종적으로 컨테이너 내부에 보여지게 됨
    • 이것이 컨테이너 마운트 지점인 merged 디렉터리
  • AUFS와 유사하게 이미지에 존재하는 파일에 쓰기 작업을 수행할 때 파일을 컨테이너 레이어인 uppserdir로 복사해 사용 -> 크기가 큰 파일에 쓰기 작업을 수행할 때는 uppserdir에 복사하는 시가능로 인해 작업 수행에 지장이 생길 수 있으나 AUFS와 다르게 계층화된 다중 레이어 구조가 아니기 때문에 복사할 파일을 찾는 과정에서는 AUFS보다 빠름

태그:

카테고리:

업데이트:

댓글남기기