도커 이미지 업데이트

도커 이미지로 컨테이너를 만들며 실행까지 성공했다. 그런데 만약 수정사항이 생기면 어떻게 해야 할까? `docker build`와 `docker run`작업을 통해 이미지를 다시 빌드하고 재생성된 이미지로 컨테이너를 재실행해야 한다. 물론 동작은 잘 되지만 이게 최선일까.

맨 위에서 말한 고민에는 이런 문제점 들이 포함된다.

  1. 지금은 애플리케이션이 작아서 그나마 문제가 없지만, 변경 범위나 내용에 상관없이 모든 종속성을 다시 설치해야 한다.

  2. 다시 빌드하고 다시 실행하는 과정이 너무 번거롭다.

그렇다면 어떻게 이 부분을 효율적으로 개선할 수 있을까?

1. 항상 전체 종속성 다운로드 개선 - Dockerfile 수정하자!

# syntax=docker/dockerfile:1
FROM node:12-alpine
RUN apk add --no-cache python2 g++ make
WORKDIR /app
COPY . .
RUN yarn install --production
CMD ["node", "src/index.js"]

위에 내용은 기존에 만들었던 파일이다. 조금 수정해 보자.

# syntax=docker/dockerfile:1
FROM node:12-alpine
RUN apk add --no-cache python2 g++ make
WORKDIR /app
COPY package.json yarn.lock ./
RUN yarn install --production
COPY . .
CMD ["node", "src/index.js"]

이렇게 하면 COPY package.json yarn.lock ./ 단계에서 변화가 있을 경우에만 다음 단계에서 종속성을 다시 받게되고, 아무런 변화가 없다면 캐시(cache)를 이용해 이 과정이 생략된다.

수정하고 다시 실행해 보자.

최초 빌드시 종속성 설치과정에서 69.6s 소요

종속성에 변화 없는 내용만 수정시 0s 소요

그리고 이번에는 추가 종속성을 설치하여, 변화를 줬을 경우

참고 - 여러 파일 COPY하는 법

방법은 여러개가 있는걸로 알지만 내가 사용하는 방법은 아래와 같다.

# ...
COPY package.json yarn.lock ./
#...

파일을 쭈욱 나열해 주고, 기존에는 .만 사용했지만 멀티 파일의 경우 뒤에 역슬러시를 하나 더 붙여 줘야 한다.

2. 빌드 프로세스를 개선하자(수정 -> 다시 빌드 -> 다시 실행) - Docker Volume

위 1번 과정을 통해 비효율적인 종속성 설치 문제를 해결했지만, 여전히 수정 사항이 있을때마다 이미지를 다시 빌드하고, 컨테이너를 다시 실행해야만 변경된 내용이 반영이 되고 있다. 이러한 작업은 시간을 오래 소요하면서도 이미지를 자주 빌드해야 해서 리소스도 많이 소모된다.

Docker Volume이란?

도커 볼륨이란 도커 컨테이너에서 호스트 디렉토리에 있는 파일들을 참조해서 사용하는 방식이다. (공식 문서)

도커 볼륨을 이용하면 기존에는 COPY 지시자를 통해 호스트의 디렉토리에 있는 파일을 그대로 도커 컨테이너로 복사한 것을, 복사하지 않고 도커 컨테이너에서 호스트의 디렉토리에 있는 파일을 계속 참조해서 사용할 수 있다.

계속 참조하고 있으므로 소스 코드를 변경해도 다시 COPY를 사용해 이미지를 빌드할 필요가 없다.

  • 초기에는 bind-mounts라는 방법을 사용했으나, 도커 볼륨에 비해 제한적이고 맥이나 윈도우에서 bind-mounts보다 더 나은 성능을 내기 때문에 도커 볼륨을 많이 사용한다.

  • bind-mounts는 호스트의 디렉토리 구조와 OS에 의존하지만, volume의 경우 완전히 docker에 의해 관리된다.

명령어 -v or --mount

볼륨을 생성할 때는 두 가지 옵션을 이용하여 볼륨을 생성할 수 있다. 결론적으로 볼륨을 생성한다는 것은 같으나, 사용 방식에 있어 차이점이 있어 둘 다 알아만 놓으면 될거 같다.(공식 문서)

도커 볼륨을 사용해 애플리케이션 실행

이전에 나왔던 공식 예제를 도커 볼륨을 통해 실행해 보자.

$ docker run -dp 3000:3000 -v /app/node_modules -v $(pwd):/app getting-started

일단 컨테이너가 제대로 시작된 것을 확인할 수 있다.

매핑한 주소로 이동해도 화면도 잘 나온다.

일단 기존과 동일하게 잘 동작되는지 확인되었다면, 내용을 조금만 수정해 보고 이미지를 다시 빌드하지 않고 컨테이너만 위 명령어를 통해 다시 실행해 보고 변경이 되는지 확인해 보자.

참고) docker run -dp 3000:3000 -v /app/node_modules -v $(pwd):/app getting-started 왜 이렇게 명령했나?

위에 설명에서도 말했듯이 도커 볼륨은 기존 호스트의 파일을 참조하게 되는데, 그 참조에 대한 바인딩을 위 명령어로 해준 것이다. 경로를 왜 그렇게 작성했는지는 아래 그림을 보고 이해해 보자.

재빌드 없이 컨테이너 재시작으로 업데이트 되는지 확인하기

You have no todo items yet! Add one above! 텍스트를 수정 후 컨테이너를 재시작 해보자.

  1. 기존 동작중인 컨테이너 중지

  2. 변경할 내용 코드에 반영 후 변경 사항 저장

  3. 도커 볼륨 재실행

  4. 기존 페이지 새로고침

  • 여기까지만 공부하고 docker-compose 정의 파일(YAML)을 작성하는 법을 배우니, 백엔드에서 사용하고 있는 도커 컴포즈의 기능을 알거 같다. 다음주에 연말 휴무때 우리 프로젝트를 뜯어볼 예정이다.

Last updated