[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)도 삭제됨 -> 볼륨 사용으로 해결!
- 호스트와 볼륨 사용
- -v [호스트의 공유 디렉터리]:[컨테이너의 공유 디렉터리]
- 호스트의 디렉터리를 컨테이너의 디렉터리에 마운트
- 볼륨 컨테이너
- -volumnes-from 옵션을 통해 -v 또는 –volumn 옵션을 적용한 컨테이너의 볼륨 디렉터리 공유 가능
- 도커 볼륨
- docker volumn 생성 후 활용
- 로컬 호스트에 저장됨
- 도커 엔진에 의해 생성되고 삭제됨
- -v [볼륨의 이름]:[컨테이너의 공유 디렉터리]
- 볼륨은 디렉터리 하나에 상응하는 단위
- 도커 엔진에서 관리
- 어디에 저장되는지 알 필요 없지만 docker inspect하면 알 수 있음
- 컨테이너가 아닌 외부에 데이터를 저장하고 컨테이너는 그 데이터가 동작하도록 설계하는 것을 스테이트리스(stateless) 하다고 말함 -> 바람직
- 컨테이너가 데이터를 저장하고 있어서 상태가 있는 경우를 stateful 하다고 말함 -> 지양
2.2.7 도커 네트워크
- 도커는 컨테이너 내부 IP를 순차적으로 할당 -> veth
- 컨테이너 재시작 할 때마다 변경됨
- 내부망(호스트)에서만 쓰므로 외부와 연결될 필요 X
- 각 컨테이너에 외부와의 네트워크를 제공하기 위해 컨테이너마다 가상 네트워크 인터페이스를 호스트에 생성 (veth로 시작)
- veth 인터페이스는 컨테이너가 생성될 때 토커 엔진이 자동 생성
- veth는 각 컨테이너의 eth0와 연결됨
- docker0 브리지는 각 veth 인터페이스와 바인딩 됨 -> host의 eth0 인터페이스와 연결시켜줌
- 브리지 네트워크
- 컨테이너 생성할 때 자동으로 연결되는 docker0 네트워크 활용
- 172.17.0.X IP 대역 순차 할당
- 사용자 정의 브리지는 새로 생성해 각 컨테이너에 연결
- 브리지 타입의 네트워크를 생성하면 IP 대역을 차례대로 할당
- 호스트 네트워크
- 호스트의 네트워크 환경 그대로 사용
- 호스트 머신에서 설정한 호스트 이름 물려받음
- 컨테이너 내부의 애플리케이션을 별도의 포트 포워딩 없이 바로 서비스 가능 -> 실제 호스트에서 애플리케이션을 외부에 노출하는 것과 같음
- 논 네트워크
- 아무런 네트워크를 쓰지 않는 것
- 외부와 연결이 단절됨
- 컨테이너 네트워크
- 다른 컨테이너의 네트워크 네임스페이스 환경 공유
- IP, 네트워크 인터페이스의 맥 (MAC) 주소 등 - 내부 IP 새로할당 X - 호스트에 veth로 시작하는 가상 네트워크 인터페이스 생성 X
- 브리지 네트워크의 –net-alias
- 특정 호스트 이름으로 컨테이너 여러개에 접근 가능
- 도커 엔진에 내장된 DNS가 호스트 이름이 같은 컨테이너로 변환. round robin 방식 사용
- DNS는 호스트 이름으로 유동적인 컨테이너 찾을 때 사용됨
- MacVLAN 네트워크
- 컨테이너는 물리 네트워크상에서 가상의 맥(MAC) 주소를 가지며 해당 네트워크에 연결된 다른 장치와의 통신이 가능해짐
- 기본적으로 할당되는 IP대역인 172.17.XX 아니고 네트워크 장비의 IP할당받기 때문 - 호스트와 통신 불가능 - 적어도 1개의 네트워크 장비와 서버 필요
2.2.8 컨테이너 로깅
- 기본적으로 JSON 형태로 log를 저장하지만 로깅 드라이버를 사용해 컨테이너 로그를 수집할 수 도 있음
- syslog 로그
- 유닉스 계열 운영체제에서 로그를 수집하는 오래된 표준 중 하나
- 커널, 보안, 시스템 등과 관련된 로그, 애플리케이션 로그 등 수집
- 유닉스 계열 체제에서는 syslog를 사용하는 인터페이스가 동일 -> 체계적인 로그 수집 가능
- 원격 서버에 syslog를 설치해서 로그 정보를 원격 서버로 보내기 가능
- fluentd 로깅
- 로그 수집 저장
- JSON 사용
- AWS S3, HDFS, MongoDB 등 다양한 저장소에 저장 가능
2.2.9 컨테이너 자원 할당
- 자원할당을 안하면 호스트의 자원을 전부 점유해 다른 컨테이너들 뿐 아니라 호스트 자체의 동작이 멈출 수 도 있음
- 컨테이너 메모리 제한
- 할당된 메모리를 초과하면 자동으로 종료됨
- 기본적으로 swap 메모리는 메모리의 2배로 설정됨
- 컨테이너 cpu 제한
- –cpu-shares
- 컨테이너에 가중치 할당
- 존재하는 cpu를 어느 비중만큼 나눠 쓸 것인지
-
–cpuset-cpu -호스트에 cpu가 여러개 있을 때 컨테이너가 특정 cpu만 사용하도록 설정
- –cpu-period, –cpu-quota
- 컨테이너의 CFS (Completely Fair Scheduler) 주기는 기본적으로 100ms로 설정되지만 주기 변경 가능
- –cpu-period의 기본값은 100000이며 100ms를 뜻함
- –cpu-quotasms –cpu-period에 설정된 시간 중 cpu 스케줄링에 얼마나 할당할 것인지 설정
- –cpus
- –cpu-period, –cpu-quota와 같은데 더 직관적
- cpu 개수 직접 지정
- 병렬처리를 위해 cpu를 마니 소모하는 워크로드를 수행해야 한다면 –cpuset-cpu 옵션을 사용하는게 좋음. 특정 컨테이너가 특정 cpu에서만 동작하는 cpu 친화성 보장. cpu 캐시 미스, 컨텍스 스위칭 최소화
- –cpu-shares
- Block I/O 제한
- 기본적으로 컨테이너 내부에서 파일을 읽고 쓰는 대역폭에 제한 X
- DIRECT I/O의 경우에서는 입출력만 제한됨. Buffered I/O는 제한 X
- 상대적인 값으로 입력
- 스토리지 드라이버와 컨테이너 저장 공간 제한
- 컨테이너 내부의 저장 공간을 제한하는 기능을 보편적으로 제공 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 -> 비효율적
- 도커 저장소 사용
- private은 유료
- Docker Private Registry 사용
- 직접 이미지 저장소 만들기
2.4 Dockerfile
2.4.1 이미지를 생성하는 방법
- 아무것도 존재하지 않는 이미지로 컨테이너 생성
- 어플리케이션을 위한 환경을 설치하고 소스코드 등을 복사해 잘 동작하는 것을 확인
- 컨테이너를 이미지로 커밋
- 장점: 이미지의 동작 보장할 수 있음
- 단점: 일일이 수작업으로 패키지 설치하고 소스코드를 깃에서 복제하거나 호스트에서 복사해야 한다.
=> 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등 가능
- Dockerfile에 서 빌드된 이미지 파일을 추가할 때 사용됨
- 컨텍스트는 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의 인자로 입력
- 단 실행할 스크립트 파일은 컨테이너 내부에 존재해야 함
- 어떤 설정 및 실행이 필요한지에 대해 스크립트로 정리
- ADD 또는 COPY로 스크립트를 이미지로 복사
- ENTRYPOINT를 이 스크립트로 설정
- 이미지를 빌드해 사용
- 스크립트에서 필요한 인자는 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 -> 실행중인 프로세스 목록 출력
- 도커의 구조는 두가지로 나뉨
- 클라이언트로서의 도커
- 도커 데몬은 API입력을 받아 도커 엔진의 기능을 수행하는데 이 API를 사용할 수 있도록 CLI 제공
- docker로 시작하는 명령어 입력하면 도커 클라이언트를 사용하는 것 -> 도커 클라이언트는 입력된 명령어를 로컬에 존재하는 도커 데몬에게 API로 제공
- 서버로서의 도커
- 실제로 컨테이너를 생성하고 실행하며 이미지 관리하는 주체
- 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번 포트로 도커 데몬을 제어함과 동시에 도커 클라이언트 사용 가능
- ex: dockerd -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 파일에 저장됨
- 스토리지 풀에서 공간을 할당받음
- 이미지의 스냅숏을 만들어 사우이 레이어 생성
- 이미지로부터 변경된 사항을 저장하는 컨테이너 레이어는 이 레이어들을 묶은 파운트 포인트에서 새로운 스냅샷을 생성해서 사용됨
- 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보다 빠름
댓글남기기