<준비물>
1. 비쥬얼박스 VM 설치 (아래링크 참고)
Oracle VM VirtualBox 관리자 설치 - 01
https://www.virtualbox.org/wiki/Downloads Downloads – Oracle VM VirtualBox Download VirtualBox Here you will find links to VirtualBox binaries and its source code. VirtualBox binaries By downloading, you agree to the terms and conditions of the respectiv
myungho.tistory.com
2. 우분투 v20.04 설치 후 고정 IP 설정 (아래링크 참고)
우분투 20.04 고정IP 설정
$ cd etc/netplan $ sudo nano 00-installer-config.yaml 노랑색 표시 되있는 것처럼 포트포워딩을 해준다. 저는 위사진과 같이 NAT네트워크 localNetwork를 사용하였습니다. 다른 네트워크환경을 하시면 맞춰서 포
myungho.tistory.com
3. 우분투 각종 패키지
## ifconfig
$ sudo apt install net-tools
4. gradle 상위 version 설치 (참고)
https://codechacha.com/ko/installing-gradle/
Ubuntu - Gradle 최신 버전 설치 방법
Ubuntu에서 Gradle 최신 버전 설치 방법을 소개합니다. Apt로 Gradle 설치, 직접 다운로드 및 설치, SDKMAN으로 Gradle 설치, sudo apt install gradle. 원하는 버전을 Gradle Releases에서 확인하고 다음 명령어로 다운
codechacha.com
5. Docker + Docker-compose 설치 한다.
Docker Documentation
docs.docker.com
docker 사이트에 자세히 나와있다.
6. 배포할 react 프로젝트 + springboot 프로젝트를 만드셔야합니다. 이부분은 다들 기본적으로 하실 수 있다 생각하고 생략하겠습니다. react와 springboot의 개념이 없다면 기초부분만 보고 와서 배포하셔도 될것 같습니다.
이제 준비물은 끝났다.
젠킨스로 무중단 배포를 진행하기전에 저는 nginx reverse proxy 로 spring + react를 배포 할려고 합니다.
nginx reverse proxy에 관한 자료는 구글에 많이 있으니 참고하여 아키를 보면 금방 이해가 될 것 입니다.
nginx를 쓰는 이유와 젠킨스를 현재 쓰지 않는 이유 그리고 각종 기능들의 자세한 설명은 다음에 무중단 배포하면서 자세히 적도록 하겠습니다. 지금은 간단한 배포 까지만 하도록 하겠습니다.
저도 해딩하면서 독학으로 공부하다보니 부족한점이 있어도 많은 이해 부탁드립니다.
먼저 우리가 해야할 일은 Dockerfile 작성입니다.
front, backend Docker file을 분리해서 작성해야 합니다.
front-Dockerfile
FROM node:16-alpine as builder
WORKDIR /usr/src/app
COPY package.json ./
RUN npm install -g npm@8.19.3
RUN npm install react-scripts@5.0.1 -g --silent
# can't resolve 'react/jsx-runtime' 에러 나면 이 3가지를 설치해주시면 됩니다.
RUN npm yarn # 추가 yarn 설치
RUN yarn add react@latest # 추가 리액트 최신버전
RUN yarn add react-dom@latest # 추가 리액트돔 최신버전
COPY ./ ./
RUN npm run build
FROM nginx
EXPOSE 3000
COPY default.conf /etc/nginx/conf.d/default.conf
COPY --from=builder /usr/src/app/build /usr/share/nginx/html
## can't resolve 'react/jsx-runtime' 에러 나면 이 3가지를 설치해주시면 됩니다. ( 저는 이거 정보가 너무 없어서 1주일 넘게 삽질 했습니다.... 여러분은 삽질하지마세요.... )
간단히 설명드리면
1. FROM node:16 버전을 설치 하고 builder라는 변수를 준 것 입니다.
2. WORKDIR /usr/src/app 라는 docker 컨테이너 안에 폴더를 생성합니다.
3. COPY package.json을 docker 컨테이너 ./ 경로에 복사합니다. (여기서 중요! - package.json은 Dockerfile 작성하는 디렉토리에 같이 있어야합니다.

4. RUN
1) npm 버전을 저는 8.19.3으로 변경하였습니다. (현재 우분투에서 배포할때 9.2.0이라는 에러가 나는데 굳이 9.2.0을 설치안해도 되니 버전을 바까주시면 될것 같습니다.
2) 그다음 react script가 없다는 에러 때문에 저는 react script 5.0.1 버전을 설치해 주었습니다.
3) react-dom도 없다고 에러 나서 저는 같이 설치해 주었습니다.
4) 그리고 다음 copy는 현재 Dockerfile에 있는 파일들을 docker컨테이너에 복사해줍니다.
5) 마지막으로 npm run build를 해줍니다.
다음은 운영배포에 필요한 부분입니다.

nginx를 설치 후 3000포트로 연결하고
default.conf를 /etc/nginx/conf.d/default.conf 경로에 복사합니다. 이유는 나중에 nginx 설명에 함께 들으면 쉽습니다.
마지막 copy는 운영배포에 필수 이니 넣어주시면 됩니다. build한 경로를 nginx html이랑 연결한다고 생각하시면 됩니다.
backend-Dockerfile
FROM adoptopenjdk/openjdk11
MAINTAINER KIMMYUNGHO <kimzzan1234@gmail.com>
VOLUME /tmp
ARG JAR_FILE_PATH=build/libs/*.jar
COPY ${JAR_FILE_PATH} ricky.jar
ENTRYPOINT ["java", "-jar", "-Duser.timezone=Asia/Seoul","ricky.jar"]
EXPOSE 8080
백엔드 dockerfile은 간단하기 때문에 생략하겠습니다.
그다음으로 docker-compose를 작성하겠습니다.
version: '3.4'
services:
nginx:
image: nginx
container_name: nginx_web
networks:
- front-network
- back-network
ports:
- "80:80"
links:
- was:spring
- web:react
depends_on:
- was
- web
was:
image: spring
container_name: spring_was
build:
context: .
dockerfile: Dockerfile
ports:
- "8080:8080"
networks:
- front-network
- back-network
links:
- db:db_mysql
- web:react
depends_on:
- db
web:
image: react
container_name: react_web
build:
context: ./react_front
dockerfile: Dockerfile
ports:
- "3000:3000"
networks:
- front-network
links:
- was:spring
volumes:
- /usr/src/app/node_modules
- ./react_front:/usr/src/app
depends_on:
- db
db:
image: mysql
container_name: db_mysql
networks:
- back-network
environment:
- MYSQL_DATABASE=ricky_schema
- MYSQL_USER=ricky
- MYSQL_PASSWORD=1234
- MYSQL_ROOT_PASSWORD=password
volumes:
- /build/DB/mysql:/var/lib/mysql
ports:
- "3306:3306"
networks:
front-network:
driver: bridge
back-network:
driver: bridge
저는 networks를 front와 back으로 나누었습니다. 그리고 SSL 도메인 HTTPS를 적용하는 법은 다음 시간에 적도록 하겠습니다. 지금은 배포가 우선이니 Docker-compose에 관한건 따로 공부를 하셔야합니다. Docker-compose 작성법은 Docker 경로에 작성해 둘테니 참고하시면 됩니다. 그리고 nginx는 이미 front에서 이미지를 생성하였기 때문에 nginx는 따로 dockerfile을 작성하지 않습니다.
아그리고 저는 Docker-compose 파일 경로는 spring boot 프로젝트 에 작성하였습니다. docker-compose 경로에 보시면

이런식으로 넣었습니다.
자 이제 docker 준비는 끝났습니다.
제일중요한 default.conf , nginx.conf를 작성해야합니다.
default.conf
server {
listen 3000;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
try_files $uri $uri/ /index.html;
}
}

react 프로젝트에 default.conf와 Dockerfile, packge.json을 같이 둬야합니다.
그다음 nginx.conf 입니다.
server {
listen 80;
server_name ricky.sop;
location /api {
proxy_pass http://was:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
location / {
proxy_pass http://web:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
<nginx.conf와, default.conf 두개 작성하는 이유>
nginx 컨테이너 안에 접속해 보면
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log notice;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
keepalive_timeout 65;
include /etc/nginx/conf.d/*.conf;
}
이런식으로 nginx.conf가 있습니다. 실제로는 이것을 실행합니다. 그치만 맨아래보시면 include를 하기때문에 etc/nginx/conf.d/ 경로에 있는 *.conf라는 파일들은 전부 include 됩니다. 그래서 conf 이름은 아무렇게나 지어도 상관은 없습니다.
사실 자세히 설명드리지 못해 죄송합니다. 퇴근 후 피곤한상태로 작성하다보니 다음 nginx 작성할때 꼼꼼히 하나씩 써드리겠습니다. 그럼 이해가 빨리 되실겁니다.
여기 까지 작성이 되었으면 github에 commit push 합니다.
이제 vm에 접속하여 배포를 하도록 하겠습니다.
맨처음으로 접속하고 sudo -i로 root 권한으로 변경하겠습니다.
$ mkdir server
$ cd server
$ git clone [프로젝트가 있는 github 경로] ## clone으로 프로젝트를 내려받습니다.
$ cd [내려받은 깃 디렉토리이동]
$ gradle build --exclude-task test ## gradle build 하여 스프링 jar파일 생성
$ docker compose up -d ## docker compose 실행합니다.
npm 빌드가 끝나고 난 후
포워딩한 ip:3000을 접속하시면 끝입니다.
실수로 잘못했다면
docker 컨테이너를 stop 해주시고
$ docker system prune -a -f ## 도커 이미지 컨테이너 전부삭제 명령어
$ docker volume rm $(docker volume ls -qf dangling=true) ## 도커 볼륨 전부삭제 명령어
기존 포트가 만약 있다면
$ sudo lsof -i :[포트번호] ## 확인 후
$ sudo kill -9 [PID] ## 포트죽입니다.
컨테이너 접속 명령어 입니다.
$ docker exec -it [컨테이너ID] /bin/bash
#외부에서 홈페이지 접속방법 #
홈페이지가 접속이 되셨다면 자기 집에 있는 통신사 공유기 포트를 포워딩 해주시고 고정 IP를 DNS합니다.
고정한 IP로 vm에 포워딩을 해주시면 친구들이나 외부에서도 서버가 꺼지지 않으면 접속할 수 있습니다.
지금 까지 간단한 배포 방법이었습니다.
다음에는 Jenkins 로 자동배포와 무중단배포로 개발환경 서버 구축을 작성하겠습니다.
감사합니다.
'CI CD & VM' 카테고리의 다른 글
| jenkins ssh remote 에러 해결 (0) | 2023.05.12 |
|---|---|
| Cannot find module 'react/jsx-runtime' (0) | 2022.12.15 |
| 우분투 20.04 고정IP 설정 (0) | 2022.12.04 |
| Oracle VM VirtualBox 관리자 설치 - 01 (0) | 2022.10.11 |