졸업 프로젝트를 진행하며 플젝 배포 링크를 제출해야했다.
우리는 백과 프론트를 따로 배포하고 있어 그냥 vercel 같은 편리한 배포 사이트를 이용해도 되었지만, 복습할 겸 도커와 EC2 로 배포를 결정했다.(백 프론트 같이 배포할때를 대비하여 도커 적응은 필수...)
✅패키지 매니저: npm
✅윈도우(Windows)
✅React(Create React App)
우선 현재 프로젝트의 루트 경로에 도커파일을 작성해줘야 한다.

위와 같이 루트경로에 Dockerfile.prod 파일을 생성해 주었다. 내부 코드는 아래와 같다.
FROM node:14 AS builder
# set working directory
WORKDIR /app
# install app dependencies
#copies package.json and package-lock.json to Docker environment
COPY package-lock.json ./
COPY package.json ./
# Installs all node packages
RUN npm ci
# Copies everything over to Docker environment
COPY . ./
RUN npm run build
#Stage 2
#######################################
#pull the official nginx:1.19.0 base image
FROM nginx
#copies React to the container directory
# Set working directory to nginx resources directory
# WORKDIR /usr/share/nginx/html
COPY config/nginx/default.conf /etc/nginx/conf.d/default.conf
# Remove default nginx static resources
RUN rm -rf ./usr/share/nginx/html/*
# Copies static resources from builder stage
COPY --from=builder /app/build /usr/share/nginx/html/
# Containers run nginx with global directives and daemon off
EXPOSE 3000
ENTRYPOINT ["nginx", "-g", "daemon off;"]
- 우선 작업 디렉토리를 /app 경로로 설정해준다.
- 작업 디렉토리에 npm ci 명령어를 통해 의존성을 설치해 준 뒤 다른 모든 파일들도 복사한다.
- 모든 과정이 끝나면 npm run build 를 통해 build 폴더가 생성되고, 해당 폴더는 초기에 설정해준 /app 경로에 들어가게 된다.
❗WHY npm ci
npm i 명령어도 있는데 왜 굳이 npm ci 명령어를 사용하나 생각할 수도 있다.
npm i는 package.json 파일을 기반으로 의존성을 설치하게 된다. 이는 개발시 새로운 패키지를 추가할 때 사용하는데 빌드시 사용하기에는 다소 위험하다.
package.json 파일에는 패키지의 버전들이 range로 설정되어있다. 한마디로 정확한 하나의 버전으로 설정되어 있지 않다는 얘기이다. 즉, 배포 때 npm i를 실행하면 빌드 때마다 패키지의 버전들이 약간씩 차이나게 될 수 있으며 이는 혼란을 야기할 수 있다.
따라서 개발 시에는 npm i로 패키지를 추가하되, 배포 및 다른 프로젝트의 로컬 초기 세팅 시에는 package-lock.json 파일을 기반으로 의존성을 설치하고 package-lock.json 파일의 내용을 바꿀 수 없는 npm ci 명령어를 활용하여 모두 같은 버전을 바라볼 수 있도록 하는 것이 안전하다.
그 후 NGINX 웹서버로 해당 리액트 플젝을 서빙해야 한다. NGINX를 베이스 이미지로 하는 단계를 거친다.
- nginx 설정 파일을 복사해준다. config/nginx/default.conf 파일은 아래에 첨부해두겠다.
- 기본 nginx의 정적 자원을 삭제해준다.
- /app 경로에 들어간 build 폴더에 담긴 정적자원을 복사해준다. --from 명령어를 통해 이전 스테이지에서 빌드 과정에서 생성된 결과만을 복사할 수 있다. (위에서는 이전 스테이지 빌드 과정을 AS builder를 통해 builder로 별칭을 설정해주었으므로 --from builder 를 통해 이 스테이지의 결과만을 복사한다.)
- 컨테이너를 실행할 때 접속할 포트를 노출해준다. 위에서는 3000번 포트를 노출해주었다.
server {
listen 3000;
root /usr/share/nginx/html;
index index.html;
location / {
try_files $uri /index.html;
}
error_log /var/log/nginx/api_error.log;
access_log /var/log/nginx/api_access.log;
}
루트 경로에 만들어준 config/nginx/default.conf 파일은 위와 같다.
- 3000번 포트를 노출해주었으므로 3000번 포트에 들어올 요청을 listen 하며 대기한다.
- 요청이 오면 위에서 빌드된 정적 파일들을 복사한 경로에서 파일을 찾아 호스팅해준다.
이제 해당 도커 파일을 이용하여 도커 이미지를 생성해 줄 준비가 되었다.
터미널에
docker build -f '도커파일 이름' -t '이미지이름:태그' .\
해당 명령어를 입력한 후 실행하여 이미지를 생성해준다. -f 옵션을 통해 실행할 도커파일을 지정해줄 수 있으며, -t 옵션을 통해 이미지 이름과 태그를 설정해준다.
그 후
docker image ls
명령어를 통해 만들어진 도커 이미지를 확인할 수 있다.

그 결과 설정한 이미지 이름과 태그로 된 이미지가 생성된 것을 확인할 수 있다.
그런데 이는 로컬에서만 생성된 것이므로 배포를 위해서라면 해당 이미지를 Docker hub 에 올려줘야한다.
Docker hub 에 해당 이미지를 올리기 위해서는
<USER>/<IMAGE_ID>:<TAG>
위의 규칙대로 이미지 이름을 설정해줘야 한다.
USER 는 Docker hub의 아이디를 말하며, 뒤에 이미지 이름과 태그를 설정해준다.
그럼 이제 규칙대로 이미지 이름을 다시 설정해주자!!
docker tag '이전 이미지이름' '규칙에 맞는 이미지이름'
해당 명령어로 이미지 이름을 변경해준 뒤 만들어진 이미지를 확인해보자.

위처럼 Docker hub 이미지의 규칙에 맞게 생성된 이미지를 확인할 수 있다.
docker push '이미지 이름'
이제 해당 명령어를 통해 Docker hub에 이미지를 올려보자.
Docker hub에 로그인 한 후 Hub를 확인해보면

이미지가 잘 push된 것을 확인할 수 있다.
보통 백과 프론트를 같이 배포할 시에는 여기까지만 하면 백엔드 측에서 해당 이미지를 가져다가 docker-compose 로 한번에 컨테이너를 실행시키는 식으로 이루어진다.
그러나 우리는 따로 배포를 진행하므로 AWS 인스턴스 생성 후, 해당 인스턴스에 도커 이미지를 불러온 뒤 컨테이너를 실행해 줄 것이다.
너무 길어지니 이 과정은 다음 포스팅에서...
'FrontEnd > React' 카테고리의 다른 글
Vite + Yarn Berry 구축기 - 1 (4) | 2023.12.06 |
---|---|
AWS EC2에 HTTPS 적용하기 (4) | 2023.11.28 |
배포 과정 Github Actions 로 자동화하기 (0) | 2023.11.27 |
Docker + AWS EC2 로 프론트 배포하기(2) (4) | 2023.11.26 |
Throttle & Debounce 란? (0) | 2023.08.31 |
졸업 프로젝트를 진행하며 플젝 배포 링크를 제출해야했다.
우리는 백과 프론트를 따로 배포하고 있어 그냥 vercel 같은 편리한 배포 사이트를 이용해도 되었지만, 복습할 겸 도커와 EC2 로 배포를 결정했다.(백 프론트 같이 배포할때를 대비하여 도커 적응은 필수...)
✅패키지 매니저: npm
✅윈도우(Windows)
✅React(Create React App)
우선 현재 프로젝트의 루트 경로에 도커파일을 작성해줘야 한다.

위와 같이 루트경로에 Dockerfile.prod 파일을 생성해 주었다. 내부 코드는 아래와 같다.
FROM node:14 AS builder
# set working directory
WORKDIR /app
# install app dependencies
#copies package.json and package-lock.json to Docker environment
COPY package-lock.json ./
COPY package.json ./
# Installs all node packages
RUN npm ci
# Copies everything over to Docker environment
COPY . ./
RUN npm run build
#Stage 2
#######################################
#pull the official nginx:1.19.0 base image
FROM nginx
#copies React to the container directory
# Set working directory to nginx resources directory
# WORKDIR /usr/share/nginx/html
COPY config/nginx/default.conf /etc/nginx/conf.d/default.conf
# Remove default nginx static resources
RUN rm -rf ./usr/share/nginx/html/*
# Copies static resources from builder stage
COPY --from=builder /app/build /usr/share/nginx/html/
# Containers run nginx with global directives and daemon off
EXPOSE 3000
ENTRYPOINT ["nginx", "-g", "daemon off;"]
- 우선 작업 디렉토리를 /app 경로로 설정해준다.
- 작업 디렉토리에 npm ci 명령어를 통해 의존성을 설치해 준 뒤 다른 모든 파일들도 복사한다.
- 모든 과정이 끝나면 npm run build 를 통해 build 폴더가 생성되고, 해당 폴더는 초기에 설정해준 /app 경로에 들어가게 된다.
❗WHY npm ci
npm i 명령어도 있는데 왜 굳이 npm ci 명령어를 사용하나 생각할 수도 있다.
npm i는 package.json 파일을 기반으로 의존성을 설치하게 된다. 이는 개발시 새로운 패키지를 추가할 때 사용하는데 빌드시 사용하기에는 다소 위험하다.
package.json 파일에는 패키지의 버전들이 range로 설정되어있다. 한마디로 정확한 하나의 버전으로 설정되어 있지 않다는 얘기이다. 즉, 배포 때 npm i를 실행하면 빌드 때마다 패키지의 버전들이 약간씩 차이나게 될 수 있으며 이는 혼란을 야기할 수 있다.
따라서 개발 시에는 npm i로 패키지를 추가하되, 배포 및 다른 프로젝트의 로컬 초기 세팅 시에는 package-lock.json 파일을 기반으로 의존성을 설치하고 package-lock.json 파일의 내용을 바꿀 수 없는 npm ci 명령어를 활용하여 모두 같은 버전을 바라볼 수 있도록 하는 것이 안전하다.
그 후 NGINX 웹서버로 해당 리액트 플젝을 서빙해야 한다. NGINX를 베이스 이미지로 하는 단계를 거친다.
- nginx 설정 파일을 복사해준다. config/nginx/default.conf 파일은 아래에 첨부해두겠다.
- 기본 nginx의 정적 자원을 삭제해준다.
- /app 경로에 들어간 build 폴더에 담긴 정적자원을 복사해준다. --from 명령어를 통해 이전 스테이지에서 빌드 과정에서 생성된 결과만을 복사할 수 있다. (위에서는 이전 스테이지 빌드 과정을 AS builder를 통해 builder로 별칭을 설정해주었으므로 --from builder 를 통해 이 스테이지의 결과만을 복사한다.)
- 컨테이너를 실행할 때 접속할 포트를 노출해준다. 위에서는 3000번 포트를 노출해주었다.
server {
listen 3000;
root /usr/share/nginx/html;
index index.html;
location / {
try_files $uri /index.html;
}
error_log /var/log/nginx/api_error.log;
access_log /var/log/nginx/api_access.log;
}
루트 경로에 만들어준 config/nginx/default.conf 파일은 위와 같다.
- 3000번 포트를 노출해주었으므로 3000번 포트에 들어올 요청을 listen 하며 대기한다.
- 요청이 오면 위에서 빌드된 정적 파일들을 복사한 경로에서 파일을 찾아 호스팅해준다.
이제 해당 도커 파일을 이용하여 도커 이미지를 생성해 줄 준비가 되었다.
터미널에
docker build -f '도커파일 이름' -t '이미지이름:태그' .\
해당 명령어를 입력한 후 실행하여 이미지를 생성해준다. -f 옵션을 통해 실행할 도커파일을 지정해줄 수 있으며, -t 옵션을 통해 이미지 이름과 태그를 설정해준다.
그 후
docker image ls
명령어를 통해 만들어진 도커 이미지를 확인할 수 있다.

그 결과 설정한 이미지 이름과 태그로 된 이미지가 생성된 것을 확인할 수 있다.
그런데 이는 로컬에서만 생성된 것이므로 배포를 위해서라면 해당 이미지를 Docker hub 에 올려줘야한다.
Docker hub 에 해당 이미지를 올리기 위해서는
<USER>/<IMAGE_ID>:<TAG>
위의 규칙대로 이미지 이름을 설정해줘야 한다.
USER 는 Docker hub의 아이디를 말하며, 뒤에 이미지 이름과 태그를 설정해준다.
그럼 이제 규칙대로 이미지 이름을 다시 설정해주자!!
docker tag '이전 이미지이름' '규칙에 맞는 이미지이름'
해당 명령어로 이미지 이름을 변경해준 뒤 만들어진 이미지를 확인해보자.

위처럼 Docker hub 이미지의 규칙에 맞게 생성된 이미지를 확인할 수 있다.
docker push '이미지 이름'
이제 해당 명령어를 통해 Docker hub에 이미지를 올려보자.
Docker hub에 로그인 한 후 Hub를 확인해보면

이미지가 잘 push된 것을 확인할 수 있다.
보통 백과 프론트를 같이 배포할 시에는 여기까지만 하면 백엔드 측에서 해당 이미지를 가져다가 docker-compose 로 한번에 컨테이너를 실행시키는 식으로 이루어진다.
그러나 우리는 따로 배포를 진행하므로 AWS 인스턴스 생성 후, 해당 인스턴스에 도커 이미지를 불러온 뒤 컨테이너를 실행해 줄 것이다.
너무 길어지니 이 과정은 다음 포스팅에서...
'FrontEnd > React' 카테고리의 다른 글
Vite + Yarn Berry 구축기 - 1 (4) | 2023.12.06 |
---|---|
AWS EC2에 HTTPS 적용하기 (4) | 2023.11.28 |
배포 과정 Github Actions 로 자동화하기 (0) | 2023.11.27 |
Docker + AWS EC2 로 프론트 배포하기(2) (4) | 2023.11.26 |
Throttle & Debounce 란? (0) | 2023.08.31 |