docker 기반 nginx~react 개발 및 배포
1. 개발용 dockerfile과 배포용 dockerfile의 분리 및 stage
docs.docker.com/engine/reference/commandline/build/
Dockerfile과 Dockerfile.dev 두 파일을 생성하여 개발과 배포에서 각각 다른 Docker image를 사용하도록 합시다.
Dockerfile.dev
FROM node:alpine
WORKDIR /usr/src/app
COPY package.json ./
COPY package-lock.json ./
RUN yarn
# 로컬에 node_modules있으면 지워주자.
COPY ./ ./
CMD ["yarn", "start"]
Dockerfile
여기서 조금 다른 점은 'as builder'의 존재입니다.
builder의 경우 시작하는 FROM부터 다음 FROM까지 builder stage임을 명시해줍니다.
도커에는 stage라는 개념이 있는데, 다른 포스트에서 다뤄보록하겠습니다.
우선은 builder stage가 존재하며, as builder로 지정할 수 있다는 것,
run stage에서 builder 스테이지에 있는 파일을 가져올 때는 --from으로 명시해줘야 한다는 것을 알아둡시다.
# builder stage
FROM node:alpine as builder
WORKDIR '/usr/src/app'
COPY package.json .
COPY package-lock.json ./
RUN yarn
# 로컬에 node_module 있으면 지워줄 것
COPY ./ ./
RUN yarn build
# run stage
FROM nginx
EXPOSE 80
COPY --from=builder /usr/src/app/build /usr/share/nginx/html
Docker 명령어로 빌드시 (권장 안 됨. docker-compose 쓰세요 걍...)
docker build -t [name] . // Dockerfile 빌드
docker build -t react-sample . // Dockerfile을 참고하여 react-sample이란 이름으로 이미지 빌드함
docker build -f [dockerfile name] . // Dockerfile 외의 다른 이름을 가진 Dockerfile을 빌드함
docker build -f Dockerfile.dev . // Dockerfile.dev를 이용하며 이미지를 빌드함 이름은 none이 됨
docker build -f Dockerfile.dev -t react-sample-dev . // Dockerfile.dev를 이용. 이미지 이름은 react-sample-dev
그런데 사실 이런 문제들은, docker-compose를 사용하면 신경쓸 이유가 없는 것들입니다. build를 알아서 해주니까요.
서빙을 위해 nginx와 같이 yml을 작성해보았습니다.
version: "3"
services:
proxy:
image: nginx:alpine
container_name: proxy
ports:
- "80:80"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
restart: "unless-stopped"
react-dev:
build:
context: .
dockerfile: Dockerfile.dev
ports:
- "3000:3000"
volumes:
- /usr/src/app/node_modules # 로컬에 node_modules 없으니 매핑하지 말라
- ./:/usr/src/app # 매핑
stdin_open: true # docker run의 -i 옵션. react 한정으로 필요함.
docker 쓰면서 참 좋은 점이, 배포 환경을 실제로 로컬에서 작동 시켜봐서, 무의미한 커밋을 크게 줄일 수 있다는 점입니다.
너무 좋드아~~~
2. (node 한정) 로컬에 node_modules가 필요 없다.
다음을 개발용 dockerfile 내용이다. 흐름을 살펴보면, 당연히 node_module을 로컬에 가지고 있을 이유가 없다.
아니, 가지고 있으면 오히려 시간을 더 잡아먹는 악재다.
docker 기반 개발할 때는 로컬에 굳이 의존성 설치할 이유가 없어진다.
FROM node:alpine
WORKDIR /usr/src/app
COPY package.json ./
COPY package-lock.json ./
RUN yarn
# 이 단계에서 굳이 node_module을 가져올 필요는 없다.
# 컨테이너에 yarn으로 이미 설치했잖아.
COPY ./ ./
CMD ["yarn", "start"]
그 외의 자잘한 내용들)
- docker run에서 -it 옵션은 버릇처럼
- docker-compose up에서 --build는 버릇처럼
- React 이 녀석은 -i 옵션 주던가, stdin_open: true로 설정해놓을 것.
- test 코드가 있다면 별도 컨테이너를 따로 올릴 것.