Kubernetes 이야기

올바른 Dockerfile 작성하기 본문

Kubernetes/일반

올바른 Dockerfile 작성하기

kmaster 2022. 4. 19. 22:06
반응형

DockerHub에는 다양한 Docker Image가 존재한다. Official한 이미지를 사용하면 좋겠지만, 때로는 Official 이미지에 다양한 라이브러리와 개발된 라이브러리등을 넣어서 본인만의 Docker Image를 만들어야 하는 경우가 많다.

이러한 Docker 이미지를 만들기 위한 Dockerfile 작성 시 안정성 및 보안문제가 발생하지 않도록 작성하는 것이 무엇보다 중요하다.

 

루트가 아닌 사용자 계정으로 실행

 

많은 Base Image들이 Root 계정으로 실행되는 경우가 많다. Kubernetes에서는 아래와 같이 runAsNonRoot 옵션으로 root 사용자로 Container Image를 실행하지 못하도록 할 수 있다.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: test
spec:
  selector:
    matchLabels:
      control-plane: test
  replicas: 1
  template:
    spec:
      securityContext:
        runAsNonRoot: true
      containers:
        image: tomcat
...

하지만, securityContext 등의 설정이 관리가 되지 못하면 보안상 문제가 될 수 있기 때문에 Container Image를 만들때부터 non root 사용자로 만드는 것이 중요하다.

 

FROM alpine:3.8
RUN adduser -D myuser
USER myuser
ENTRYPOINT ...
CMD ["..."]

 

다중 레이어 피하기

 

Dockerfile의 경우 각각의 새로운 명령어 라인은 별도의 레이어가 형성된다.

FROM alpine

RUN apk update

RUN apk add curl

RUN apk add nodejs

RUN apk add nginx-1.16.1-r6

RUN apk add nginx-mod-http-geoip2-1.16.1-r6

COPY index.html /var/www/html/

EXPOSE 80

CMD [“nginx”,“-g”,“daemon off;”]

위와 같이 설치 후 불필요한 cache등은 삭제하는 것이 좋다. ( && 등을 효과적으로 사용해야 한다. )

FROM alpine

RUN apk update && apk add curl nginx nginx-mod-http-geoip2-1.16.1-r6 \

rm -rf /var/cache/apt/*

COPY index.html /var/www/html/

EXPOSE 80

CMD [“nginx”,“-g”,“daemon off;”]

 

적절한 .dockerignore 사용하기

 

.gitignoreㄹ처럼 현재 폴더 아래 불필요한 패키지들이 copy될 수 있는 상황이 있을 수 있기 때문에 .dockerignore를 사용하여 실수로 불필요한 파일들이 복사되는 경우를 막아야 한다. 특히 copy 명령어로 모든 파일이 복사될 수 있는 환경일 때 secret key 등의 파일이 container image에 포함되는 경우를 .dockerignore에서 선언하여 회피할 수 있다.

 

다단계 빌드 사용

 

다단계 빌드는 이미지를 두 번 이상 빌드하여 이미지 크기를 줄이는 방법이다.  Dockerfile의 각 명령은 이미지에 계층을 추가하며 다음 계층으로 이동하기 전에 필요하지 않은 아티팩트를 정리해야 한다 .

다단계 빌드에서는 FROMDockerfile에서 여러 문을 사용한다.  FROM명령은 다른 기반을 사용할 수 있으며 각각은 빌드의 새 단계를 시작한다. 

# syntax=docker/dockerfile:1
FROM golang:1.16
WORKDIR /go/src/github.com/alexellis/href-counter/
RUN go get -d -v golang.org/x/net/html  
COPY app.go ./
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app .

FROM alpine:latest  
RUN apk --no-cache add ca-certificates
WORKDIR /root/
COPY --from=0 /go/src/github.com/alexellis/href-counter/app ./
CMD ["./app"]

 

이미지 tag

 

Container 이미지 생성 시 tag 를 지정하지 않으면 자동으로 latest 로 지정된다. 이렇게 되면 어떤 Container Image를 사용하였는지 파악하기 어렵기 때문에 예상 밖의 보안 및 안정성 문제를 유발할 수 있다. 

 

최소한의 패키지

 

Container 이미지의 크기를 줄이는 것은 중요한 문제이다. 이미지를 줄이게 되면 Registry로 부터 로딩 시간을 단축할 수 있어 빠른 부팅을 할 수 있고, 디스크 용량도 줄일 수 있게 된다. 

Container 이미지에 필요한 최소한의 패키지 설치는 위와 같은 문제를 해결할 뿐 아니라, 보안 관점에서도 외부 공격을 줄일 수 있는 방안이 될 수 있다.

 

최소한의 패키지 설치를 위해 적절한 Base Image 선택이 중요하다. 공통 기본 기본 이미지에는 다음이 포함된다.

  • Alpine : 기본 이미지 중 가장 작은 옵션으로 Alpine Linux가 컨테이너 전용으로 구축한 운영 체제
  • Stretch / Buster / Jessie : Debian 릴리스의 코드명이며 이미지가 기반으로 하는 릴리스를 나타냄
  • Slim : 전체 공식 이미지와 비교하여 특정 애플리케이션을 실행하는 데 필요한 최소한의 패키지만 포함

이미지 취약성 검사

 

컨테이너에 대해 안정적인 보안 검사를 수행하기 위한 도구/기술등을 사용하여 취약성 검사를 하는 것은 중요한다. 범용적으로 사용되는 도구는 아래와 같다.

 

  • Clair
  • Anchore
  • Trivy

 

참고

https://docs.docker.com/develop/develop-images/dockerfile_best-practices/

https://sysdig.com/blog/dockerfile-best-practices/

https://dev.to/chrisedrego/21-best-practise-in-2021-for-dockerfile-1dji

반응형

'Kubernetes > 일반' 카테고리의 다른 글

OpenEBS  (0) 2022.04.22
nginx ingress를 사용하여 외부 application proxy 설정  (0) 2022.04.21
Nginx ingress - External OAUTH Authentication ( Google )  (0) 2022.04.17
Kubernetes Cluster 설계  (0) 2022.04.10
Bare metal VS VM Kubernetes  (0) 2022.04.09
Comments