이번 글에서는 Nginx + React 배포 자동화에 대해 적어보려 한다.
이 글은 Jenkins 서버와 웹 서버가 다른 VM을 이용하고 있음을 전제합니다.
또한 Jenkins 서버 및 Jenkins VM은 선처리가 되어있음을 전제합니다.
인프라 구성 요소
Jenkins Git Webhook Docker Nginx React 자동 배포 흐름
VM 생성 ssh 설정 파일 수정 git Docker 설치 ssh 연결 테스트
Docker 위에 React 정적 빌드 파일을 얹은 Nginx 컨테이너 띄우기
Jenkins와 Git Webhook 연결
Jenkins 배포 자동화 처리와 ssh 연결
VM - GCP
Jenkins VM - Debian
Nginx VM - CentOS
Github project - Organization project, public repository
React - Vite를 통해 빌드
nginx VM은 GCP를 통해서 생성했고 centOS를 사용한다.
우리는 Jenkins 서버와 Nginx 서버의 VM이 다르기 때문에 ssh를 위해 설정 파일을 수정해야 한다.
sudo vi /etc/ssh/sshd_config
debian과 centOS 둘 다 동일하다.
여기서 봐야할 몇 가지 설정
# 공개키를 통한 ssh 접속 가능
PubkeyAuthentication yes
# Password를 통한 ssh 접속 불가능
#PasswordAuthentication yes
PasswordAuthentication no
# ssh를 통해 Root로 바로 접속 불가능
PermitRootLogin no
설정 완료 후 centOS는 sudo systemctl restart sshd
debian은 sudo service sshd restart
nginx VM에 우리는 도커, git을 설치해야 한다. 이는 다른 분들의 글로 대체하겠다.
CentOS 7 : Docker 설치, 사용 방법, 예제, 명령어
[CentOS 7] Git 설치 및 설정
우리는 jenkins VM에서 ssh를 통해 nginx VM으로 접속해야 한다.
따라서 jenkins VM에서 ssh 키를 생성 후 비밀키를 jenkins 컨테이너에 마운트 시켜줘야 한다. 컨테이너는 기본적으로 stateless이기 때문에 jenkins 컨테이너를 재실행할 때마다 키를 직접 넣어줘야 한다면 곤란하다.
마운트는 docker run -v [마운팅 시킬 위치]:[컨테이너 내 마운팅 위치]
옵션을 통해 가능하다.
공개키는 nginx VM의 ~/.ssh/authorized_keys
에 넣어준다.
이제 jenkins container로 들어가서 ssh 접속을 시도해 보자.
# jenkins 컨테이너 접속
sudo docker exec -it [jenkins container] bash
# jenkins 컨테이너에서 nginx VM에 접속
ssh -i [id_rsa 비밀키 위치] [nginx VM user]@[nginx VM IP]
여기까지 완료했다면 jenkins에서 nginx VM으로의 ssh 접속 테스트는 완료이다.
혹시 host key를 확인하는 작업이 생긴다면 이를 처리하기 위해 이 글을 읽어보자.
[Linux] ssh 접속시 host key checking 비활성화하기
두 가지 방법이 있다.
1. Dockerfile을 제작해서 이미지로 빌드 후 컨테이너 생성
2. Docker hub에서 nginx 이미지 가져와서 컨테이너 조립 후 이미지로 빌드
글이 길어질 것 같아서 1번에 대해 써보겠다.
# Dockerfile
FROM nginx
COPY ./default.conf /etc/nginx/conf.d/default.conf
# default.conf
server {
listen 80;
listen [::]:80;
server_name localhost;
#access_log /var/log/nginx/host.access.log main;
location / {
root /usr/share/nginx;
index index.html index.htm;
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
# proxy the PHP scripts to Apache listening on 127.0.0.1:80
#
#location ~ \.php$ {
# proxy_pass http://127.0.0.1;
#}
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#
#location ~ \.php$ {
# root html;
# fastcgi_pass 127.0.0.1:9000;
# fastcgi_index index.php;
# fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
# include fastcgi_params;
#}
# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
#location ~ /\.ht {
# deny all;
#}
}
default.conf는 기본에서 수정을 별로 하지 않았다.
이에 대해 얘기해 보자면 먼저 Docker, Nginx, React의 구조에 대해 설명을 해야 한다.
React는 빌드 시 index.html 기타 등등의 정적 파일이 생성된다.
React 빌드 시 dist 폴더가 생성되고(Vite로 빌드 시), 이 파일은 Nginx 웹서버를 통해 유저들에게 보인다.
Docker를 통해 Nginx 컨테이너를 실행하며, 빌드 파일은 컨테이너 외부. 즉, VM에 둔다. 빌드 파일을 마운팅 하여 Nginx 컨테이너에서 사용하는 구조이다. 이렇게 되면 자동 배포에서 Nginx 컨테이너를 restart 할 필요도 없다. 이를 위해 default.conf에서 location을 마운팅 한 빌드 파일 위치로 설정하였다.
Nginx 컨테이너의 /usr/share/nginx에 dist 파일을 마운팅하였다.
이제 Dockerfile을 빌드하고, docker run을 통해 이미지를 컨테이너화하면서 실행하겠다.
docker build -t [태그명] [도커파일 위치]
docker run -v [.../dist]:/usr/share/nginx/ -d -p 80:80 [태그명]
이제 VM IP로 들어가보면 react 정적 파일이 Nginx에 올라가서 작동하고 있는 것을 확인할 수 있다.
앞으로 Jenkins만 제대로 역할 수행하면 된다.
먼저 Github의 본인 repository를 가보자.
Settings - Webhooks - Add webhook
payload URL에는 젠킨스 URL + /github-webhook/을 입력한다
예시 : http://[Jenkins VM IP]:8080/github-webhook/
Content type : application/json
나는 푸쉬할 때만 Jenkins가 반응 오도록 설정해놓았다.
Github Developer setting을 위해 다른 분이 설명을 잘 해놓았다.
[Jenkins] 젠킨스와 깃허브 연동(GitHub Web Hook)
Github의 설정을 끝냈다면 Jenkins로 가자.
Jenkins - Jenkins 관리 - Manage Credentials
Global credentials - Add credentials
credentials 등록 과정 중 secret에 깃허브 developer setting에서 받은 값을 넣는다.
이제 Jenkins Dashboard에서 새로운 item을 Freestyle project
로 생성한다.
이건 다른 글을 참고하도록 하자.
main branch에 푸쉬했을 때, Jenkins에 반응이 온다면 성공이다.
이제 여기서부터가 중요하다. 우리는 Jenkins VM과 nginx VM이 다르기 때문에, Jenkins가 알아서 ssh 연결부터 git pull, 빌드를 처리해야 한다.
이를 위해 Jenkins pipeline 및 SSH Agent Plugin이 필요하다.
젠킨스 플러그인 중 SSH Agent Plugin 설치
Global credentials - add Credentials
에서 SSH Username with private key로 생성한다. 여기서의 비밀키는 Jenkins VM의 비밀키이다.
새로운 item - pipeline
선택
젤 밑에 pipeline script에 이제 SSH 접속 후의 코드를 작성한다.
예시
pipeline {
agent any
stages {
stage('ssh connection and build') {
steps {
sshagent (credentials: ['credential 이름']) {
sh "ssh -o StrictHostKeyChecking=no []@[] '명령어'"
}
}
}
}
}
그리고 freestyle project에서 git의 webhook을 받으면 pipeline 프로젝트를 다음 빌드 프로젝트 대상으로 넘겨줘야 하기 때문에 freestyle project의 빌드 후 조치에서 Build other projects
를 선택, Projects to build에는 pipeline 프로젝트 이름을 써준다.
이렇게 해서 Jenkins + Git Webhook + Docker + Nginx + React 배포 자동화 처리의 과정을 알아봤다. 3일 정도 이 과정을 위해 소요했고, 이 글은 생략된 부분이 많아 그대로 따라 하기엔 무리가 있다고 생각한다. 하지만 이 글을 통해 배포 자동화 흐름에 대해 이해할 수 있을 것이다.