웹앱을 Nginx로 Dockerize 하기 (multi-stage build)
npm 혹은 yarn을 통해 관리되는 웹앱을 Nginx로 Dockerize하는 방법(웹앱의 Dockerfile 작성법)을 배워봅니다. 생각하는 과정을 통해 설명할 것이기 때문에 바쁘신 분들은 아래만 읽으셔도 좋습니다. 샘플로 create-react-app를 이용합니다.
1 | $ npx create-react-app my-app |
중간에 yarn eject를 통해 실제 개발 환경과 최대한 비슷하게 만들어 봅시다. start를 하면 웹 페이지가 나옵니다.
Dockerize
우리는 이 샘플 웹앱을 Dockerize 할 것입니다.1
2$ touch Dockerfile
$ touch .dockerignore
Dockerfile와 .dockerignore를 만들어 줍니다. 디렉터리 구조는 아래와 같습니다.
1 | . |
먼저 아래와 같이 Dockerfile을 수정해 봅니다.
1 | FROM node:10 |
COPY를 나눠서 해주는 이유는 cache를 적극적으로 이용하기 위해서입니다.
로컬 모듈과 디버깅 로그 복사를 막기 위해 .dockerignore도 작성해 줍니다. (CI/CD툴을 이용할 때는 필요하지 않습니다.)
1 | node_modules |
이제 실행해 보겠습니다. 포트 중복을 막기 위해 위에서 실행한 프로그램은 종료해주세요.
실행하기
1 | docker build -t naive_image . |
localhost:3001로 접속해보면 정상적으로 접속이 됩니다.
하지만 위의 Dockerfile은 문제가 있습니다. yarn start의 script를 살펴보면 webpack-dev-server를 이용합니다. 최적화와 보안에 신경을 써야 하는 우리는 이렇게 하면 안 됩니다. yarn build를 통해 생성된 정적 파일을 서빙해야 합니다.
그렇다면 Dockerfile에서 해주어야 할 것은 무엇일까요? 빌드와 빌드를 통해 생성된 정적 파일의 서빙입니다. 정적 파일의 서빙은 nginx로 할 것입니다. 다시 말씀드리면 빌드는 node, 서버는 nginx 입니다. 빌드와 실행 시 환경이 다를때 Dockerfile은 어떻게 해야 할까요?
Dockerfile에 nginx를 설치하는 과정을 넣을 수 있습니다만, 이러면 Docker image가 커지고 실행 시에 불필요한 파일 또한 많아집니다. 그럴 때 필요한 것이 Multi-stage build입니다.
Multi-stage build
1 | FROM node:10 as builder |
Dockerfile을 살펴보시면 FROM이 두 번 나옵니다. 빌드 시 필요한 Docker 이미지와 실행 시 필요한 Docker 이미지를 따로 해주고 12번 라인과 같이 첫 이미지에서 생성된 빌드 된 파일들을 복사해옵니다. CMD는 생략해서 nginx 기본 이미지에서 상속받습니다.
실행해 봅시다.
1 | docker build -t webapp . |
이번엔 localhost:8080로 접속할 수 있습니다.
1 | $ docker images |
도커 이미지의 사이즈가 확연히 차이 나는 걸 보실 수 있습니다.
핵심은 빌드와 실행 시 환경의 분리입니다.
Author: dbgsprw
Link: https://dbgsprw.github.io/2019/03/11/dockerize_webapp/
Copyright: All articles in this blog are licensed under CC BY-NC-SA 3.0 unless stating additionally.