개요
그동안 사이드 프로젝트를 배포한 것을 돌이켜보면 윈도우 로컬 환경에서 작업을 하고 ec2에서 만든 인스턴스 서버를 통해 배포를 진행하였다. 하지만 각각의 프론트와 백엔드를 위해서는 인스턴스를 두 개씩은 만들어야했다.
docker를 사용하면 하나의 인스턴스에서 프론트와 백엔드를 모두 가동시킬 수 있다. 자연스레 비용은 줄어들 것이다.
또한 인스턴스간에 왔다갔다 하면서 작업할 필요도 없다.
디렉토리 구조
reactchat/
├── front(프론트 작업폴더)
└── Dockerfile
└── nginx/
└── nginx.conf
├── docker-compose.yml
└── renew_certificates.sh
필요한 파일들
Dockerfile (docker image로 만들 설정들)
# Stage 1: Build React App
FROM node:20-alpine as build
WORKDIR /src
COPY package.json package-lock.json ./
RUN npm ci
COPY . .
RUN npm run build
# Stage 2: Serve React App with Nginx and Certbot
FROM nginx:alpine
# Install certbot and other necessary packages
RUN apk add --no-cache certbot certbot-nginx bash
# Copy built React app to Nginx public directory
# /src/dist는 여러분의 npm run build하고 나서 생긴 빌드 폴더명에 따라 /src/[빌드폴더명]로 변경
COPY --from=build /src/dist /usr/share/nginx/html
# Copy custom Nginx configuration file
COPY nginx/nginx.conf /etc/nginx/nginx.conf
# Copy the script to renew certificates
COPY renew_certificates.sh /usr/local/bin/renew_certificates.sh
# 갱신 스크립트에 권한부여 이후에 스크립트를 직접 실행가능 or cron job에서 실행
RUN chmod +x /usr/local/bin/renew_certificates.sh
# Expose port 443
EXPOSE 443
CMD ["sh", "-c", "nginx -g 'daemon off;' & /usr/local/bin/renew_certificates.sh"]
docker-compose.yml
(docker image를 어떻게 실행할지)
services:
front:
build:
context: ./front
image: kingheedo/reactchat-front:latest
ports:
- "443:443"
volumes:
- /etc/letsencrypt:/etc/letsencrypt
- /var/lib/letsencrypt:/var/lib/letsencrypt
nginx/nginx.conf (nginx 설정 파일)
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
#your-domain.com에는 여러분의 구입한 도메인입력
server {
listen 443 ssl;
server_name your-domain.com www.your-domain.com;
ssl_certificate /etc/letsencrypt/live/your-domain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/your-domain.com/privkey.pem;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
try_files $uri $uri/ /index.html;
}
}
}
renew_certificates.sh (인증서 갱신을 위한 스크립트)
#!/bin/bash
while true; do
certbot renew --nginx --quiet
sleep 12h
done
설치 및 진행하기
* ec2 서버에서 깃에서 코드를 다운받는 부분은 생략
* git bash나 터미널로 ec2 서버 진입 후 진행
docker 설치
- sudo apt-get update
- sudo apt-get install -y ca-certificates curl gnupg lsb-release
- curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
- echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
- sudo apt-get update
- sudo apt-get install -y docker-ce docker-ce-cli containerd.io
- sudo systemctl start docker
- sudo systemctl enable docker
docker-compose 설치
- sudo curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
- sudo chmod +x /usr/local/bin/docker-compose
- sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose
- sudo docker-compose --version
nginx 및 certbot 설치
- sudo apt-get update
- sudo apt-get install -y nginx certbot python3-certbot-nginx
초기인증서 발급
- sudo certbot --nginx -d your-domain.com -d www.your-domain.com --non-interactive --agree-tos --email <이메일주소>
docker 가동
- sudo systemctl start docker
- sudo systemctl enable docker
- sudo systemctl status docker
docker 로그인(사용자의 username, password로 로그인하기)
docker login
docker 빌드하기
- sudo docker-compose build
docker container 실행하기
- sudo docker-compose up -d
결과
welcome nginx가 렌더링된다면
빌드한 결과물이 렌더링이 되지 않다면 nginx의 정적파일 경로에 빌드한 파일이 존재하지 않을 가능성이 높다.
이럴 때는 직접 실행한 컨테이너를 진입해야한다.
# Docker 컨테이너 확인
1. sudo docker ps
# Docker 컨테이너 내부로 진입
2. sudo docker exec -it <container_id> /bin/sh
# 빌드된 파일이 있는지 확인(로컬에서 npm run build해서 나온 빌드폴더와 내용물이 동일한지 확인)
3. cd /usr/share/nginx/html
4. ls
느낀점
docker 배포 문제로 거의 하루 반나절 걸린거같다..
webpack설정에서 빌드시 htmlwebpacplugin으로 index.html을 빌드폴더인 dist안에 생성하지 않고있어서
배포시 welcome nginx가 나오는 index.html만 나왔었다.
결국 docker로 배포시에 nginx가 관리하는 빌드파일폴더에서 실제로 빌드결과물이 잘나왔는지 꼭 잘 대조하는것이 필요하다.
나 역시 빌드결과물 리스트만보고 index.html내용은 확인도 안하고 꺼버려서 시간이 더 오래 걸렸다.
그리고 <script src="./app.js"></script>
index.html body내부의 스크립트가 실제 nginx가 관리하는 폴더경로에서 번들링한 js 파일을 제대로 가르키고 있는지 확인도 필요하다.
이는 window로컬환경에서 빌드 테스트후 html을 실행해서 해당 자바스크립트 파일이 제대로 실행 되고 있는지 확인이 필요하다.
여태 webpack을 크게 건드는 일이 없었는데 이번일로 webpack의 중요성을 느끼게 되었다.
'배포' 카테고리의 다른 글
ec2에 docker 설치, nginx 설치, https 인증서 발급 및 인증서 자동갱신 하는법 (0) | 2024.07.03 |
---|