Infra/IaC

[Docker] Dockerfile 경량화

jykim23 2023. 10. 26. 15:36

출처 : 패캠 gitops

 

 

Dockerfile 기초

Dockerfile 정의 : 컨테이너의 구성정보를 프로비저닝한 텍스트 template 파일

Dockerfile 흐름 : Dockerfile -> docker build -> image registry(dockerhub) -> deploy docker image 

Dockerfile 명령어 : https://docs.docker.com/engine/reference/builder/

빌드 명령어 : docker build -t IMAGE_NAME:TAG [-f DOCKERFILE_NAMEDOCKERFILE_LOCATION

 

Dockerfile 최적화 : 경량의 컨테이너 서비스 제공

dockerfile 작성 고려 사항 : https://docs.docker.com/develop/develop-images/dockerfile_best-practices/

빌드시간, 이미지 크기, 재사용성, 보안, 유지보수성 등

 

최적화 목적 : 컨테이너의 경량의 가상화 서비스

 - 기존의 base image 들 또한 지향점에 필요한 프로그램, 라이브러리, 실행파일만 보유한다.

 - 애플리케이션에 필요한 추가 구성 요소를 포함시키는 경우 복잡성, 의존성 문제를 피해야 하고 빠른 컨테이너 배포를 위해 최소한의 설정과 구성을 권장한다.

 

최적화1 : 불필요한 바이너리 제거.

 - 불필요한 패키지 설치 배제, 설치된 패키지는 autoremove, clear로 정리

 - 개발환경과 동일한 버전 설치 : apt install -y --no-install-recommends <패키지>

 - '.dockerignore' 파일 : '.gitignore'와 같은 역할. 빌드에 불필요한 파일을 제외한다.

 

최적화2 : 경량화된 base image 선택(alpine, scratch...)

 - scratch : Go언어(gcc 컴파일)를 사용하여 정적 링크 바이너리를 만들어서 Dockerfile에 참조하면 애플리케이션으로만 구성된 경량화 된 이미지 구성 가능.

  - 

 - Alpine Linux : minimal 보다 더 경량화된 base image. 잠재적인 취약점이 비교적 적어 보안에 이점

 

최적화3 : multi-stage build 최종 이미지 크기 최소화

https://docs.docker.com/build/building/multi-stage/

 - multi-stage build(다단계 빌드) : 여러개의 base image를 사용한 docker build

 - Dockerfile FROM 명령어를 복수로 작성하여 분리도니 작업 공간(stage)을 제공

 - 1st stage(빌드도구)에서 생성된 실행파일 등을 두 번째 stage에 제공, 마지막에 실행된 stage 작업이 Docker image로 최종 생성되어 이미지 크기가 감소. 마지막 이미지를 alpine 사용.

 

최적화4 : Dockerfile Layer 최소화

 - Layer 최대 : 127줄

 - Layer 압축 : RUN apt update && apt install -y package1 && apt install -y package2 && apt clean && rm -rf /var/lib/apt/lists/*

 

 

최적화5 : one application - on container

 - 장점키워드 : 애플리케이션 확장성, 버전관리, 소스코드 모듈화, 장애 발생 서비스 지속성 보장, 수평 확장성, 컨테이너의 재사용성, 컨테이너 리소스 제어 편의성.

 - 하나의 컨테이너에 복수의 애플리케이션을 설정하면 결합성이 높아지고 확장성이 떨어진다.

 - 하나의 컨테이너에 하나의 애플리케이션 동작은 컨테이너 간의 독립성을 보장함과 동시에 애플리케이션 버전관리, 소스코드 모듈화 등 장정이 있다.

 - 모놀리식 구성보다 결합 해제된 애플리케이션(Decouple applications) 설계, 마이크로서비스(MSA) 지향적 설계를 고려해야 장애 발생하여도 애플리케이션 자체가 유지될 수 있다.

 - 컨테이너의 재사용성 예시 : 3-Tier 웹 서비스

 - 컨테이너에 여러 애플리케이션 작동하면 리소스(CPU,MEM,I/O) 소비도 높아진다.

 

최적화6 : using cache

 - Docerkfile을 통해 이미지를 빌드하면 자동으로 각 명령어 단위로 캐싱(caching, 임시 이미지 생성)한다.

 - 동일한 명령의 실행은 이 캐싱을 통해 재사용(Using cache 출력)되기 떄문에 빌드 속도를 빠르게 하고, 캐싱에 사용된 명령줄이 변경이 되면(캐시 사용시 checksum을 통해 검증) 기존 캐싱은 사용하지 못하고 재 캐싱된다.

 - 캐싱 효과를 높이기 위해 명령어의 위치를 명확히 해야 한다. 일정하게 유지될 명령은 Dockerfile의 상단에 배치된(패키지 설치 등의 단계)하고, 변경될 수 있는 명령은 하단에 배치(COPY 같은 빌드 단계)하면 기존 캐시를 부정할 가능성이 줄어든다.

 

최적화7 : 보안 강화

 - Dockerfile은 사용자를 지정하지 않으면 root 사용자를 사용한다. root 권한이 필수는 아니다.

 - Docker container 실행 시 암시적으로 Docker Host에 대한 root acces 권한을 갖게 되어 잠재적인 보안 문제를 갖게 된다. 따라서, 의도하자면 컨테이너 애플리케이션 실행을 통해 Docker Host에 대한 권한이 쉽게 상승(escalation)하게 된다.

 - 예로, 이미지는 컨테이너 보안 측면에서 첫번째 고려 대상이다. 이미지가 보호되지 않고 제대로 구성되지 않으면 다른 여러가지 수단에 의해 컨테이너의 경계를 벗어나 호스트에 액세스할 수 있기 때문에 컨테이너 이미지의 공격 대상 영역을 줄이는 노력이 요구된다.

 - 이미지 서명이 사용되면 Docker는 매니페스트의 서명을 확인하여 콘텐츠가 신뢰할 수 있는 소스에서 생성되었고 위조, 변조가 발생하지 않았음을 보장한다.

  - Docker Signer (docker trust sign)

  - Notary (by Harbor)

  - DCT (Docker Contents Trust) -> export DOCKER_CONTENT_TRUST=1

 - Dockerfile 에서 USER 명령어 사용으로 root 사용자 접근을 억제한다. USER 명령은 RUN, ENTRYPOINT 또는 CMD 명령을 실행하기 위한 특정 사용자를 지정할 경우 사용한다.

 - 일반적으로 이미지 안에 무엇이 있는지 모르므로 Docker hub에서 인증된 이미지만 사용하고, 이미지에 취약성이 있는지 확인 후 사용을 권장

  - 취약성 목록 : https://vulnerablecontainers.org

 - 익숙하지 않은 이미지를 사용하는 경우 'DIVE'를 사용하여 이미지 검사 수행한다.

  - SETUID, SETGID 비트가 있는 모든 바이너리를 찾아 제거해야 한다. 이러한 바이너리는 권한 상승에 사용될 수 있다.

 

 

 


'Infra > IaC' 카테고리의 다른 글

[Docker] Swarm mode  (0) 2023.10.26
[Docker] compose  (0) 2023.10.26
[Docker] docker volume 데이터 지속성 및 데이터 관리  (1) 2023.10.26
[Docker] 리소스 모니터링과 자원 할당 관리  (0) 2023.10.24
[Docker] Network 관리  (2) 2023.10.20