nocdev

Docker(10) 본문

devops/Docker

Docker(10)

nocdu 2023. 10. 8. 23:06

도커 이미지 다루기 - 이미지 경략화 전략

  1. 불필요한 패키지 및 파일 제외

    컨테이너 기술 자체가 하나의 컨테이너에 하나의 서비스를 운영하는 목적으로 개발되었기 때문에 컨테이너 하나에 OS, server 등 여러가지 서비스를 한번에 올리지 않는것이 좋다.

  2. 컨테이너 레이어 수 줄이기

    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
  3. 경량베이스 이미지

    애초에 이미지를 빌드할 때 베이스가 되는 이미지의 경량화 이미지를 선택한다.

    경량화 이미지에는 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 이미지의 용량차이를 확인할 수 있다.
    기본 node 16 이미지와 slim, alpine 이미지의 용량차이를 확인할 수 있다.

    slim 이미지로 생성한 컨테이너가 기존과 동일하게 동작하는지 확인해보자

    docker run -d -it -p8080:8080 nodejs-server:slim
    docker ps
    컨테이너가 정상적으로 동작 하였다.
    컨테이너가 정상적으로 동작 하였다.
    호스트 아이피의 8080 포트로 접속하니 이전과 동일하게 웹페이지가 동작하는것을 확인할 수 있다.
    호스트 아이피의 8080 포트로 접속하니 이전과 동일하게 웹페이지가 동작하는것을 확인할 수 있다.

    alpine 이미지로 생성한 컨테이너가 기존과 동일하게 동작하는지도 확인해보자

    docker rm -f 61
    docker run -d -it -p8080:8080 nodejs-server:alpine
    docker ps
    원활한 동작을 위해 기존 8080포트로 바인딩한 slim 컨테이너 삭제 후 alpine 이미지로 빌드한 nodejs 컨테이너를 실행하였다.
    원활한 동작을 위해 기존 8080포트로 바인딩한 slim 컨테이너 삭제 후 alpine 이미지로 빌드한 nodejs 컨테이너를 실행하였다.
    역시 동일하게 동작한다.
    역시 동일하게 동작한다.
  4. 멀티스테이지 파이프라인

    기존에 이미지를 빌드할 때 사용했던 방식은 명령어가 수행될 때마다 새로운 레이어를 생성하여 명령어를 수행하였지만 멀티스테이지 방법을 사용하면 레이어를 재사용 할 수 있다. 명령어부터 확인해보자

    #
    # 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 정도 경량화 된 것을 확인할 수 있다.
    기존 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:latest
    nodejs-server:slime
    nodejs-server:slime
    nodejs-server:alpine
    nodejs-server:alpine
    nodejs-server:alpine-multi
    nodejs-server:alpine-multi

    레이어 갯수의 차이가 많이 나는것을 확인할 수 있다.

'devops > Docker' 카테고리의 다른 글

Docker(11)  (0) 2023.10.09
Docker(9)  (0) 2023.10.02
Docker(8)  (0) 2023.10.01
Docker(7)  (0) 2023.09.30
Docker(6)  (0) 2023.09.29
Comments