[Infra] React Pipeline 구축
Dockerfile
## 1. Build React App
FROM node:alpine as builder
WORKDIR /app
COPY package*.json .
RUN npm ci --force
COPY . .
RUN npm run build
## 2. React를 Nginx로 Serve
FROM nginx:latest
RUN rm /etc/nginx/conf.d/default.conf
COPY ./nginx.conf /etc/nginx/conf.d
RUN ls -al
WORKDIR /usr/share/nginx/html
COPY --from=builder /app/dist /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
- nginx.conf
server {
listen 80;
location / {
root /usr/share/nginx/html;
index index.html;
try_files $uri $uri/ /index.html;
}
}
=> Dockerfile와 nginx.conf 파일을 frontend 폴더에 추가
Tool
- plugin - Nodejs 설치
- Jenkins 관리 - Tools 접속
- frontend 버전에 따라 nodejs 설정 -> 없는 경우, jenkins 컨테이너에 접속해서 직접 설치

Pipeline
- 멀티브런치를 이용해 분리했을 경우, Manged File > groovy file > pipeline jenkins 파일 생성해서 작성
pipeline {
agent any
tools {
nodejs "nodejs"
}
options {
disableConcurrentBuilds()
}
- tools: 파이프라인에서 사용할 도구를 정의, nodejs 도구를 사용
- options: 파이프라인 옵션을 설정, disableConcurrentBuilds()를 호출하여 동시 빌드를 비활성화
checkout
stages {
stage('Checkout') {
steps {
git branch: env.GIT_BRANCH, credentialsId: '{git 사용자 계정}', url: '{git url}'
script {
def branchName = sh(script: "git rev-parse --abbrev-ref HEAD", returnStdout: true).trim()
if (branchName != 'develop') {
echo "This job only runs on the develop branch. Current branch is ${branchName}. Aborting the build."
currentBuild.result = 'ABORTED'
return
}
}
}
}
- git branch를 통해 서버로 pull을 받음
Build
stage('Build Frontend') {
steps {
script {
def currentDir = sh(script: 'pwd', returnStdout: true).trim()
echo "The current directory is: ${currentDir}"
dir("./frontend") {
sh 'npm install'
sh 'npm run build'
}
dir("./frontend") {
sh 'docker rmi -f {docker image:tag}'
sh 'docker build -t {docker image:tag} .'
}
}
}
}
- frontend 폴더에서 frontend를 빌드한 후 docker image로 build
Deploy
stage('Deploy Frontend') {
steps {
script {
sh 'docker-compose down'
sh 'docker-compose up -d frontend'
}
}
}
- docker-compose로 기존에 올라간 컨테이너를 내리고, 다시 빌드한 이미지를 올림
docker-compose.yml
- 서버에서 jenkins > workspace > {해당 파이프라인 폴더} 경로 내에 추가
version: '3'
services:
frontend:
image: {frontend 빌드 이미지:tag}
container_name: frontend
networks:
- infra
ports:
- "3000:80"
environment:
- VIRTUAL_HOST=${HOST}
- LETSENCRYPT_HOST=${HOST}
- LETSENCRYPT_EMAIL=${EMAIL}
networks:
infra:
external: true
HealthCheck
- 제대로 올라갔는지 Health Check
stage('Health Check Frontend') {
steps {
script {
def maxRetries = 60
def retries = 0
def success = false
while (!success && retries < maxRetries) {
try {
response = sh(script: "curl -s -o /dev/null -w '%{http_code}' -k {사이트 url}", returnStdout: true).trim()
if (response == '200') {
success = true
echo "Service is up and running"
} else {
throw new Exception("Service response code: ${response}")
}
} catch (Exception ignored) {
retries++
echo "Attempt ${retries}/60: Service not ready, response code: ${response}"
if (response == '000') {
echo "Network connection failed, retrying..."
} else {
echo "Unexpected response code, retrying..."
}
sleep(time: 1, unit: 'SECONDS')
}
}
if (!success) {
error("Health check failed after ${maxRetries} attempts")
}
}
}
}
}
'Infra' 카테고리의 다른 글
| [Infra] BackEnd Blue-Green 배포 (1) | 2024.05.27 |
|---|---|
| [Infra] Spring Boot Pipeline 구축 (0) | 2024.05.25 |
| [Infra] Nginx 설정 (0) | 2024.05.25 |
| [Infra] Docker-Compose 를 통한 DB 구축 (0) | 2024.05.25 |
| [Infra] Docker 설치 (0) | 2024.05.25 |