본 포스팅은 인프런에서 강의하시는 John Ahn님의 '따라하며 배우는 도커와 CI환경'이라는 강의를 보며
제가 이해한 내용을 정리하는 포스팅입니다.
리엑트 다운
- 리엑트를 다운받기 위해서는 node를 먼저 다운 받아야함. node 공식 웹사이트에서 다운 받기
- 리엑트를 설치할 디렉토리에서 [c]npx create-react-app ./[\c]
도커를 이용하여 개발단계에서 리액트 실행하기
- 관용적으로, DockerFile을 '개발 단계를 위한 것' 과 '실제 배호 후'를 위한 것을 따로 작성하는 것이 좋다.
- 개발단계를 위해서 Dockerfile.dev를 만들자
- 이전 강의까지 사용했던 도커 파일과 동일하게 만들어주면 됨.
# Dockerfile.dev
FROM node:alpine as builder
WORKDIR '/usr/src/app'
COPY package.json .
RUN npm install
COPY ./ ./
RUN npm run build
- 오류:
- [c]docker build . [\c]는 해당 디렉토리에서 Dockerfile을 찾아 빌드하는데, 현재 Dockerfile이 없고 Dockerfile.dev만 있기 때문
- ➡ [c]docker build -f Dockerfile.dev . -t 이미지명[\c] 로 현재 사용하고 싶은 도커파일을 명시해야함.
- 팁
- 도커 환경에서 리액트 앱을 실행하려면, 로컬 환경에 굳이 node_modules 들이 필요하지 않다. [c]npm install[\c]시에 이미 컨테이너 안에 노드 모듈들이 생성이 된다.
- 만약 로컬에 node_modules 디렉토리가 있다면 이미지 빌드시 COPY ./ ./ 때문에 같이 copy되기 때문에 중복되는 프로세스임. (실제로 100s 나 빨리 빌드된다!)
생성된 도커 이미지로 리액트 앱 실행해보기
- 리액트는 기본적으로 3000번 포트에서 실행됨. 포트맵핑을 해준 후에 로컬에서 열어보자.
- [c]docker run -it -p 로컬포트:도커포트 이미지명[\c]
- localhost:로컬포트 로 접속
도커 볼륨을 이용한 소스코드 변경
- VOLUME: 이미지를 재빌드하지 않아도, 로컬에서의 소스코드 변경사항이 컨테이너에 바로 적용되는 것.(도커 컨테이너에서 로컬을 계속 참조하는 것임)
- 주의) 앞서 로컬에서 node_modules를 지웠었음. node_modules는 참조하지 말라는 것을 -v 옵션에서 명시해 줘야함.
- [c]docker run -it -p 3000:3000 -v /usr/src/app/node_modules -v %cd%:/usr/src/app bona/docker-react-app[\c]
도커 컴포즈로 좀 더 간단하게 앱 실행하기
- 매번 docker run 명령어에서 포트, 볼륨 지정하기 너무 번거롭다! ➡ Docker Compose로 간단하게 앱을 실행해보자
1. docker-compose.yml 파일 작성
# docker-compose.yml
version: "3"
services:
react:
build:
context: . # 도커 이미지를 구성하기 위한 파일과 폴더들이 있는 위치
dockerfile: Dockerfile.dev
ports:
- "3000:3000" # 로컬포트:컨테이너포트
volumes:
- /usr/src/app/node_modules # 로컬과 맵핑하지 않을 도커 디렉토리
- ./:/usr/src/app # 현 로컬디렉토리 ~ 도커 디렉토리
stdin_open: true # 리액트 앱을 끌 때 필요
- [c]docker compose up[\c] 로 리액트 앱 실행
리액트 앱 테스트하기
- 이미지 생성: [c]docker build -f dockerfile.dev . [\c]
- 앱 실행: [c]docker run -it 이미지이름 npm run test[\c]
- docker-compose에 tests 컨테이너 추가 설정
tests:
build:
context: .
dockerfile: Dockerfile.dev
volumes:
- /usr/src/app/node_modules
- ./:/usr/src/app
command: ["npm", "run", "test"]
==> 여기서 볼륨 안됨..
운영 환경을 위한 Nginx
- 개발 환경에서 리액트 컨테이너가 실행되는 과정
- 운영환경에서 리액트 컨테이너가 실행되는 과정
- 개발환경과 운영환경에서 서로 다른 서버를 사용해야 하는 이유?
- 각 서버의 필요한 기능이 다르기 때문.
- 개발환경의 서버의 경우, 소스코드가 자주 변하기 때문에 소스코드변경시 전체 앱을 다시 빌드해서 변경소스를 반영해주는 기능이 있음.
- 하지만 운영환경에서는 소스 변경을 매번 반영해줄 필요가 없음. 따라서 그런 기능들이 없고 가벼운 NGINX 서버를 사용.
운영환경 도커 이미지를 위한 Dockerfile 작성
- 개발환경 컨테이너의 소스파일들은 로컬의 'public', 'src' 디렉토리의 파일들을 사용하지만
- 운영환경 컨테이너의 소스파일들은 'build'라는 디렉토리의 코드를 참조해야함
- ➡ CMD에 npm run build로 이미지 내부에 빌드파일들을 생성해주고, 그 이후에 Nginx를 시작해줘야 함.
- npm run build는 리액트 배포시에 사용되는 명령어로, build폴더를 생성하고, 사이트를 배포할 때 꼭 필요한 파일들만 모아서 파일의 용량을 줄여준다.
- 운영환경을 위한 Dockerfile 생성 순서
- Builder stage: 빌드 파일 생성
- Run stage: Nginx를 가동하고, 생성된 빌드 폴더의 파일들을 웹 브라우저의 요청에 따라 제공해줌
# Dockerfile
# 1. Builder stage
FROM node:alpine as builder
WORKDIR '/usr/src/app'
COPY package.json .
RUN npm install
COPY ./ ./
RUN npm run build # 빌드파일들을 컨테이너 안 '/usr/src/app/build'에 생성.
# 2. Run stage
FROM nginx
EXPOSE 80
COPY --from=builder /usr/src/app/build /usr/share/nginx/html
- Builder stage 에서 npm run build를 통해 생성된 파일과 폴더들은 '/usr/src/app/build' 로 들어간다.
- [c]COPY --from=builder /usr/src/app/build /usr/share/nginx/html[\c]
- [c]--from=builder /usr/src/app/build[\c]: /usr/src/app/build 폴더가 builder 스테이지에서 온 것임을 명시
- nginx가 정적 파일들을 제공하기 위해서 참조하는 디렉토리는 ' /usr/share/nginx/html' (by Nginx 공식문서)
- 그러기 위해 /usr/src/app/build 의 파일들을 /usr/share/nginx/html 로 복사
- [c]docker build 이미지명[\c] 후 [c]docker run -p 8080:80 이미지명[\c]를 통해 컨테이너 실행. locahost:8080 접속