ํด๋น ๊ธ์ Jenkins์ Github Webhook์ ์ด์ฉํ CICD ํ์ดํ๋ผ์ธ ๊ตฌ์ฑํ๊ธฐ ์๋ฆฌ์ฆ ์ ๋๋ค. ์์ธํ ์ฌํญ์ ์๋ ๋งํฌ๋ฅผ ์ฐธ๊ณ ํด์ฃผ์ธ์!
๋ง์ฝ ํด๋น ์ค์ต ๋ด์ฉ์ ์ฝ๋๊ฐ ๊ถ๊ธํ๋ค๋ฉด ํ๋ก์ ํธ ๊นํ๋ธ ์์ ํ์ธํ ์ ์์ต๋๋ค.
- 1ํธ ์๋ฆฌ์ฆ๋ฅผ ์์ํ๋ฉฐ :: ์ปจํ ์ธ ๊ฐ์์ ๋๊ธฐ
- 2ํธ ํ๋ก ํธ์๋ ๊ฐ๋ฐํ๊ธฐ :: ๋ฆฌ์กํธ์ axios
- 3ํธ ๋ฐฑ์๋ ๊ฐ๋ฐํ๊ธฐ :: SpringBoot ์ h2
- 4ํธ ec2 ์์ฑ ๋ฐ Jenkins ์ค์น :: AWS EC2๋ก Jenkins ์๋ฒ ๋ง๋ค๊ธฐ
- 5ํธ Dockerizing ๋ฐ Nginx ์ค์ :: ๋ฐฐํฌ๋ฅผ ์ํ ๋์ปค ๋น๋์ Nginx์ ๋ฆฌ๋ฒ์ค ํ๋ก์
- 6ํธ ์นํ ์ค์ ํ๊ธฐ :: Github Webhook ์ฐ๋ํ๊ธฐ
- 7ํธ pipeline์ผ๋ก ๋ฐฐํฌํ๊ธฐ :: Jenkins Pipeline Script ์์ฑํ๊ธฐ
์์
- ํ๋ก ํธ ๋์ปค๋ผ์ด์ง
- gradle ์ค์น
- ๋ฐฑ์๋ ๋์ปค๋ผ์ด์ง
- nginx ๋ฆฌ๋ฒ์คํ๋ก์ ์ค์ ํ๊ธฐ
์ด๋ฒ ์๊ฐ์ ์ฐ๋ฆฌ๊ฐ ์์ ๋ง๋ ํ๋ก ํธ์๋์ ๋ฐฑ์๋ ์ ํ๋ฆฌ์ผ์ด์ ์ ์ปจํ ์ด๋ ํ ํ ์ ์๋๋ก SPEC ์ ๋ช ์ํ๋ Dockerfile ์ ์์ฑํ ๊ฒ์ด๋ค.
๋ํ EC2 ๋ด๋ถ์ ์กด์ฌํ๋ Nginx ๋ฅผ ์ด์ฉํด์ Reverse Proxy ๋ฅผ ํ์ฑํ ํ๊ณ Front์ Back ์ ๊ฐ๊ฐ ์ฐ๊ฒฐ์์ผ์ค ์ ์๋๋ก ํ ๊ฒ์ด๋ค.
1. ํ๋ก ํธ์๋ ๋์ปค๋ผ์ด์ง
์ฐ๋ฆฌ๊ฐ ์ด์ ์๊ฐ๋ถํฐ ๋ง๋ ํ๋ก ํธ์๋๊ฐ ์กด์ฌํ๋ ๋๋ ํ ๋ฆฌ๋ก ์ด๋ํด์ Dockerfile ์ ์์ฑํ์.
๊ทธ๋ฆฌ๊ณ ๋ค์๊ณผ ๊ฐ์ด ๋ช ์ํด์ค๋ค.
FROM node:latest
WORKDIR /frontend
COPY ./package*.json /frontend
RUN npm install
COPY / /frontend
RUN npm run build
CMD ["npx", "serve", "-s", "build"]
EXPOSE 5000
์์ Dockerfile์ ๊ฐ๋ตํ ํด์ํ์๋ฉด ๋ค์๊ณผ ๊ฐ๋ค.
WORKDIR /frontend
: ์ปจํ ์ด๋ ๋ด๋ถ์ working directory๋ฅผ ์์ฑํ๋ค.COPY ./package*.json /frontend
: ์์กด์ฑ ๋ชฉ๋ก์ด ์๋package.json
์ ์ปจํ ์ด๋ ๋ด๋ถ๋ก ๋ณต์ฌํ๋ค.RUN npm install
:package.json
์ ๋ช ์๋ ์์กด์ฑ๋ค์ ์ค์นํ๋ค.COPY / /frontend
: HOST PC์ ์์ค ์ฝ๋๋ฅผ ์ปจํ ์ด๋ ๋ด๋ถ๋ก ๋ณต์ฌํ๋ค.RUN npm run build
: npm์ผ๋ก build๋ฅผ ์คํํ๋ค.CMD ["npx", "serve", "-s", "build"]
: serve ๋ก build ๋๋ ํ ๋ฆฌ ์๋์ ์๋ ํ์ผ๋ก ์น ์๋น์ค๋ฅผ ์คํํ๋ค.EXPOSE 5000
: 5000 ํฌํธ๋ฅผ ๋ ธ์ถํ๋ค
ํด๋น ํ์ผ์ ์ฐ๋ฆฌ๊ฐ docker build
๋ช
๋ น์ด๋ฅผ ์ํํ ๋ ํ์ํ ์ธ์ ๊ฐ๋ค์ ํ๋์ ํ์ผ๋ก ๊ด๋ฆฌํ ์ ์๋๋ก ํ๋๋ฐ, ๋ค์์ CICD ํ์ดํ๋ผ์ธ์ด ๊ตฌ์ฑ๋ ๋ git ์์ pull ํ ์ฝ๋๋ค์ ์ด๋ฏธ์ง๋ก ๋ง๋๋ ์์
์ ํ์ํ๊ฒ ๋๋ค.
2. gradle ์ค์น
์ฐ๋ฆฌ๊ฐ CICD ํ์ดํ๋ผ์ธ์ ๋ง๋ค๊ณ ๋ฐฑ์๋๊ฐ ๋ฐฐํฌ๋๊ธฐ ๊น์ง๋ ๋ค์๊ณผ ๊ฐ์ ๊ณผ์ ์ ๊ฑฐ์น๋ค.
- ๊ฐ๋ฐ์๊ฐ git commit์ ํ๋ค.
- github webhook ์ด ์ด๋ฅผ ์ธ์งํ๋ค.
- jenkins ๊ฐ commit ๋ ์ฝ๋๋ฅผ git pull ํ๋ค
- gradle build ๋ฅผ ๊ฑฐ์น๋ค.
- dockerfizing ์ ์ํํ๋ค.
์ฌ๊ธฐ์ 4๋ฒ์งธ ๊ณผ์ ์ ์ํด์ ์ฐ๋ฆฌ์ ์ด์ ์๋ฒ, ์ฆ EC2 ์ธ์คํด์ค ๋ด๋ถ์์ Build ๋ฅผ ํ ์ ์๋ Build ๋๊ตฌ๊ฐ ํ์ํ๋ค.
๋๋ Gradle ์ ์ด์ฉํ ์์ ์ด๋ ssh๋ฅผ ์ด์ฉํด์ ์ธ์คํด์ค ๋ด๋ถ๋ก ์ ์ํ์.
๊ทธ๋ฆฌ๊ณ gradle ์ ์ค์นํด์ผ ํ๋๋ฐ, apt ์์ ์ ๊ณตํ๋ gradle ์ 4์ ๋ ๋ฒ์ ์ผ๋ก ํ์ฌ ๋ฒ์ ์ Spring Boot Application ์ ๋น๋ํ๋๋ฐ์ ๋ฌธ์ ๊ฐ ์๋ค.
๊ทธ๋์ ์๋์ผ๋ก gradle ์ ์ ๋ฐ์ดํธ ํด์ผ ํ๋ค.
$ sudo apt install -y gradle
$ wget https://services.gradle.org/distributions/gradle-7.1.1-bin.zip -P /tmp
$ sudo apt install -y unzip
$ sudo unzip -d /opt/gradle /tmp/gradle-7.1.1-bin.zip
$ sudo ln -s /opt/gradle/gradle-7.1.1 /opt/gradle/latest
์ด์ ๊ฐ์ ๊ณผ์ ์ ๊ฑฐ์ณ์ gradle ํํ์ด์ง์์ ์ง์ ๋ค์ด๋ฐ๊ณ zip์ ํด์ ํ๋ฉฐ ๋งํฌ๋ฅผ ์ฐ๊ฒฐํด์ฃผ์.
๊ทธ๋ฆฌ๊ณ ํฐ๋ฏธ๋์์ gradle ์ ์ ๋ ฅํด์ gradle.sh ๋ฅผ ์คํํ ๋, ์ฐ๋ฆฌ๊ฐ ์ค์นํ ๋ฒ์ ์ผ๋ก ์ฐ๊ฒฐ์ ํ๋ ค๋ฉด ๋ค์๊ณผ ๊ฐ์ด ํ๋ฉด ๋๋ค.
$ sudo gedit /etc/profile.d/gradle.sh
๊ทธ๋ฆฌ๊ณ ๋ค์๊ณผ ๊ฐ์ ์คํฌ๋ฆฝํธ๋ฅผ ์ ๋ ฅํด์ฃผ์
export GRADLE_HOME=/opt/gradle/latest
export PATH=${GRADLE_HOME}/bin:${PATH}
๊ทธ๋ฆฌ๊ณ ํด๋น ์คํฌ๋ฆฝํธ์ ์คํ ๊ถํ์ ๋ถ์ฌํ๊ณ , source ๋ช ๋ น์ด๋ก ์คํฌ๋ฆฝํธ๋ฅผ ๋ก๋ฉํ๋ค
$ sudo chmod +x /etc/profile.d/gradle.sh
$ source /etc/profile.d/gradle.sh
๊ทธ๋ฆฌ๊ณ gradle
๋ก ๋ฒ์ ์ ํ์ธํ๋ฉด 7.1.1 ๋ฒ์ ์ด ์ ์ค์น๋ ๊ฒ์ ์ ์ ์๋ค.
3. ๋ฐฑ์๋ ๋์ปค๋ผ์ด์ง
์ด์ ๋ค์ github ์ ์๋ ์ฐ๋ฆฌ์ ๋ฐฑ์๋ ์ด๋ฏธ์ง๋ฅผ ๋ง๋ค Dockerfile์ ์์ฑํด๋ณด๋๋ก ํ์.
์ฐ๋ฆฌ๋ ์ด์ ์๋ฒ, ์ฆ EC2 ์ธ์คํด์ค ๋ด๋ถ์์ Build๋ฅผ ํ ๊ฒ์ด๋ค.
/backend
๋๋ ํ ๋ฆฌ๋ก ๊ฐ์ ๋ค์๊ณผ ๊ฐ์ด ์์ฑํด์ฃผ์.
FROM openjdk:17-ea-11-jdk-slim
WORKDIR /server
COPY ./build/libs/jenkins-cicd-todo-0.0.1-SNAPSHOT.jar todo-server.jar
ENTRYPOINT ["java", "-jar", "todo-server.jar"]
ํด๋น ํ์ผ์ ๋ช
์๋ ์ ๋ณด๋ก ๋ณด์๋ฉด /backend
๋๋ ํ ๋ฆฌ์์ docker build .
์ ์ํํ๋ฉด /backend/build/libs
์๋์ ์๋ jar ํ์ผ์ ์ปจํ
์ด๋ ๋ด๋ถ๋ก ๋ณต์ฌํด์ ์ปจํ
์ด๋ ์คํ ์์ ์ jar๋ฅผ ์คํํ ๊ฒ์ด๋ค.
4. Nginx ๋ฆฌ๋ฒ์คํ๋ก์ ์ค์ ํ๊ธฐ
์ด์ nginx ์ค์ ์ ํด์ค์ผ ํ๋ค.
ssh ํด๋ผ์ด์ธํธ๋ฅผ ์ด์ฉํด์ EC2 ์ธ์คํด์ค์ ์ ์ํ์. ๊ทธ๋ฆฌ๊ณ /etc/nginx
์ผ๋ก ์ด๋ํด๋ณด์ ๊ทธ๋ผ nginx.conf ํ์ผ์ด ์์ํ
๋ฐ, ํด๋น ํ์ผ์ ์ญ์ ํ๊ณ ์๋ก์ด nginx.conf ํ์ผ์ ๋ง๋ค์.
$ cd /etc/nginx
$ sudo rm nginx.conf
$ sudo vi nginx.conf
ํด๋น ํ์ผ์์ reverse proxy ์ค์ ์ ํ ์ ์๋๋ฐ, ๋ค์์ ๋ณต์ฌํด์ ๋ฃ์ด์ค๋ค.
worker_processes 1;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
upstream front-server {
server 127.0.0.1:5000;
keepalive 100;
}
upstream backend-server {
server 127.0.0.1:8080;
keepalive 100;
}
server {
listen 80;
server_name localhost;
location / {
proxy_pass http://front-server;
proxy_set_header HOST $host;
proxy_set_header Referer $http_referer;
}
location /api {
proxy_pass http://backend-server;
proxy_set_header HOST $host;
proxy_set_header Referer $http_referer;
}
error_page 500 502 503 504 /50x.html;
location = 50x.html {
root /usr/share/nginx/html;
}
}
}
๊ทธ๋ฆฌ๊ณ sudo systemctl reload nginx
๋ฅผ ์ด์ฉํด์ nginx ๋ฅผ ์ฌ์คํํ๊ณ ec2 ์ธ์คํด์ค์ 80 ํฌํธ๋ก ์ ๊ทผํ๋ฉด ๋ค์๊ณผ ๊ฐ์ด nginx ๊ฐ 502 ์๋ฌ๋ฅผ ๋ฐํํ๊ฒ ๋๋ค.
์ฌ๊ธฐ๊น์ง ํ๋ค๋ฉด ์ ์์ด๋ค!
๋๊ธ