nocdev
Docker(10) 본문
도커 이미지 다루기 - 이미지 경략화 전략
- 불필요한 패키지 및 파일 제외
컨테이너 기술 자체가 하나의 컨테이너에 하나의 서비스를 운영하는 목적으로 개발되었기 때문에 컨테이너 하나에 OS, server 등 여러가지 서비스를 한번에 올리지 않는것이 좋다.
- 컨테이너 레이어 수 줄이기
Dockerfile 내 RUN 옵션이 선언될 때마다 레이어가 하나씩 늘어나게 된다. 최대한 압축 하여 RUN 명령어를 한번에 선언하는것이 좋다.
RUN apk add --no-cache bash curl git RUN git clone https://github.com/course-hero/slacktee /slacktee RUN apk del --no-cache git
RUN \ apk add --no-cache bash curl git && \ git clone https://github.com/course-hero/slacktee /slacktee && \ apk del --no-cache git
- 경량베이스 이미지
애초에 이미지를 빌드할 때 베이스가 되는 이미지의 경량화 이미지를 선택한다.
경량화 이미지에는 debian 의 slim계열과 linux alpine, stretch 등이 있다.
예를들면 node16버전의 용량은 909MB이지만 16-slim은 174MB, 16-apine은 110MB 로 용량차이가 많이 발생한다.
slim 이미지로 컨테이너를 실행 하여보자.
# # nodejs-server # # build: # docker build --force-rm -t nodejs-server . # run: # docker run --rm -it --name nodejs-server nodejs-server # FROM node:16:slim LABEL maintainer="FastCampus Park
" LABEL description="Simple server with Node.js" # Create app directory WORKDIR /app # Install app dependencies # A wildcard is used to ensure both package.json AND package-lock.json are copied # where available (npm@5+) COPY package*.json ./ RUN npm install # If you are building your code for production # RUN npm ci --only=production # Bundle app source COPY . . EXPOSE 8080 CMD [ "node", "server.js" ] docker build --force-rm -t nodejs-server:slim -f Dockerfile.slim ./ docker images
빌드 후 확인해보면 확연한 용량차이를 볼 수 있다. alpine 이미지로 컨테이너를 실행 하여보자.
# # nodejs-server # # build: # docker build --force-rm -t nodejs-server . # run: # docker run --rm -it --name nodejs-server nodejs-server # FROM node:16:alpine LABEL maintainer="FastCampus Park
" LABEL description="Simple server with Node.js" # Create app directory WORKDIR /app # Install app dependencies # A wildcard is used to ensure both package.json AND package-lock.json are copied # where available (npm@5+) COPY package*.json ./ RUN npm install # If you are building your code for production # RUN npm ci --only=production # Bundle app source COPY . . EXPOSE 8080 CMD [ "node", "server.js" ] ~ docker build --force-rm -t nodejs-server:alpine -f Dockerfile.alpine ./ docker images
기본 node 16 이미지와 slim, alpine 이미지의 용량차이를 확인할 수 있다. slim 이미지로 생성한 컨테이너가 기존과 동일하게 동작하는지 확인해보자
docker run -d -it -p8080:8080 nodejs-server:slim docker ps
컨테이너가 정상적으로 동작 하였다. 호스트 아이피의 8080 포트로 접속하니 이전과 동일하게 웹페이지가 동작하는것을 확인할 수 있다. alpine 이미지로 생성한 컨테이너가 기존과 동일하게 동작하는지도 확인해보자
docker rm -f 61 docker run -d -it -p8080:8080 nodejs-server:alpine docker ps
원활한 동작을 위해 기존 8080포트로 바인딩한 slim 컨테이너 삭제 후 alpine 이미지로 빌드한 nodejs 컨테이너를 실행하였다. 역시 동일하게 동작한다. - 멀티스테이지 파이프라인
기존에 이미지를 빌드할 때 사용했던 방식은 명령어가 수행될 때마다 새로운 레이어를 생성하여 명령어를 수행하였지만 멀티스테이지 방법을 사용하면 레이어를 재사용 할 수 있다. 명령어부터 확인해보자
# # nodejs-server # # build: # docker build --force-rm -t nodejs-server . # run: # docker run --rm -it --name nodejs-server nodejs-server # FROM node:16-alpine AS base LABEL maintainer="FastCampus Park
" LABEL description="Simple server with Node.js" # Create app directory WORKDIR /app # Install app dependencies # A wildcard is used to ensure both package.json AND package-lock.json are copied # where available (npm@5+) COPY package*.json ./ FROM base AS build RUN npm install # If you are building your code for production # RUN npm ci --only=production FROM base AS release COPY --from=build /app/node_modules ./node_modules # Bundle app source COPY . . EXPOSE 8080 CMD [ "node", "server.js" ] 위 명령어를 보게되면 AS 구문을 이용하여 해당 명령어를 수행 한 레이어를 alias 변수에 담아놓은 뒤 다음 명령어에서 해당 레이어를 참조하여 재 사용한다. 기존에 호스트 운영체제의 파일을 복사하여 빌드파일에 넣었지만 지금은 build 라는 이름의 레이어에서 파일을 복사하는것을 확인할 수 있다.
이미지를 빌드해보자.
docker build --force-rm -t nodejs-server:alpine-multi -f Dockerfile.alpine-multi ./ docker images
기존 alpine 이미지보다 4MB 정도 경량화 된 것을 확인할 수 있다. 위 명령어로 빌드한 이미지들이 기존 node16:latest와 레이어 갯수가 얼마나 차이 나는지 확인해보자.
docker image inspect nodejs-server:latest docker image inspect nodejs-server:slim docker image inspect nodejs-server:alpine docker image inspect nodejs-server:alpine-multi
nodejs-server:latest nodejs-server:slime nodejs-server:alpine nodejs-server:alpine-multi 레이어 갯수의 차이가 많이 나는것을 확인할 수 있다.