상황
사이드 프로젝트에서 서버 한대에서 front, back을 컨테이너 기반으로 돌리는 중
비용 문제로 서버는 한대로 유지한 채, 운영 중인 서비스에는 영향이 없도록 테스트용 dev환경을 구축하고 싶음
아키텍처
reverse proxy로 nginx를 구동
spring boot, react, docker-compose 사용
db 사용
서버 환경 분리
1. spring boot 환경 분리
- src/main/resource/application.yml를 분리
1) 기존 application.yml에 local, dev, prd 추가
- default는 가장 하단에 기입된 환경 (여기서는 local)
... // 기존 application
---
spring:
profiles:
active: prd
---
spring:
profiles:
active: dev
---
spring:
profiles:
active: local
2) 환경 별 application.yml 추가
application-prd.yaml
spring:
datasource:
url: jdbc:mysql://....... // prd환경의 db url
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver
application-dev.yaml
spring:
datasource:
url: jdbc:mysql://....... // dev환경의 db url
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver
application-local.yaml
spring:
datasource:
url: jdbc:mysql://....... // local환경의 db url
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver
3) 환경 지정해서 실행
java -jar -Dspring.profiles.active=$ENV *.jar 명령어 실행
- dockerfile 분리해서 실행
Dockerfile.dev
FROM adoptopenjdk:11-jdk-hotspot AS builder
COPY gradlew .
COPY gradle gradle
COPY build.gradle .
COPY settings.gradle .
COPY src src
RUN chmod +X ./gradlew
RUN ./gradlew bootJar
FROM adoptopenjdk:11-jdk-hotspot
COPY --from=builder build/libs/*.jar a.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "-Dspring.profiles.active=dev", "/a.jar"]
Dockerfile.prd
FROM adoptopenjdk:11-jdk-hotspot AS builder
COPY gradlew .
COPY gradle gradle
COPY build.gradle .
COPY settings.gradle .
COPY src src
RUN chmod +X ./gradlew
RUN ./gradlew bootJar
FROM adoptopenjdk:11-jdk-hotspot
COPY --from=builder build/libs/*.jar a.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "-Dspring.profiles.active=prd", "/a.jar"]
2. react 환경 분리
환경변수를 이용한 분리
환경변수로 LOCAL / DEV / PRD를 구분해서 주입하면서 실행시킴
1) npm install cross-env
2) package.json에 scripts 추가
.env파일에 추가할 환경변수를 script에서 다이나믹하게 설정할 수 있음
REACT_APP_ENV 변수에 LOCAL/DEV/PRD를 넣음
ex)
npm run start 를 실행하면 기본값으로 실행됨
npm run start:dev 를 실행하면 REACT_APP_ENV가 DEV로 설정되어서 실행됨
npm run start:prd 를 실행하면 REACT_APP_ENV가 PRD로 설정되어서 실행됨
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject",
"start:dev": "cross-env REACT_APP_ENV=DEV react-scripts start", // dev환경 추가
"start:prd": "cross-env REACT_APP_ENV=PRD react-scripts start" // prd환경 추가
},
3) .env 설정
필요한 내용들을 기입함
.env파일을 환경별로 나눠서 사용할 수 도 있음
현재는 관리할 변수가 backend url 하나밖에 없어서 한 파일에서 관리함
REACT_APP_ENV=LOCAL
REACT_APP_BACK_URL_LOCAL=http://localhost:8080
REACT_APP_BACK_URL_DEV=http://dev.back.abc.co.kr
REACT_APP_BACK_URL_PRD=http://back.abc.co.kr
4) 환경 별 env 가져오기
function getBackURL() {
if (process.env.REACT_APP_ENV === "DEV")
return process.env.REACT_APP_BACK_URL_DEV;
if (process.env.REACT_APP_ENV === "PRD")
return process.env.REACT_APP_BACK_URL_PRD;
return process.env.REACT_APP_BACK_URL_LOCAL;
}
export const BACK_URL = getBackURL();
5) dockerfile 설정
npm run start:dev
npm run start:prd
명령어로 실행
Dockerfile.dev
FROM node:alpine
WORKDIR '/app'
COPY package.json .
RUN npm install
COPY . .
CMD ["npm", "run", "start:dev"]
Dockerfile.prd
FROM node:alpine
WORKDIR '/app'
COPY package.json .
RUN npm install
COPY . .
CMD ["npm", "run", "start:prd"]
3. docker-compose 설정
docker-compose-dev.yml, docker-compose-prd.yml 분리
nginx는 dev, prd 공동으로 사용함
docker-compose-dev.yml
version: "3"
services:
proxy:
container_name: abc-proxy
restart: always
build: ./proxy
ports:
- "80:80"
extra_hosts:
- host.docker.internal:host-gateway
dev-frontend:
container_name: dev-abc-frontend
restart: always
build:
context: ./frontend
dockerfile: Dockerfile.dev
ports:
- "3001:3000"
dev-backend:
container_name: dev-abc-backend
restart: always
build:
context: ./backend
dockerfile: Dockerfile.dev
ports:
- "8081:8080"
extra_hosts:
- host.docker.internal:host-gateway
docker-compose-prd.yml
version: "3"
services:
proxy:
container_name: abc-proxy
restart: always
build: ./proxy
ports:
- "80:80"
extra_hosts:
- host.docker.internal:host-gateway
frontend:
container_name: abc-frontend
restart: always
build:
context: ./frontend
dockerfile: Dockerfile.prd
ports:
- "3000:3000"
backend:
container_name: abc-backend
restart: always
build:
context: ./backend
dockerfile: Dockerfile.prd
ports:
- "8080:8080"
extra_hosts:
- host.docker.internal:host-gateway
필요한 docker-compose를 구동시켜서 배포
ex) dev 환경
echo killing old docker processes
docker-compose -f docker-compose-dev.yml rm -fs
echo building docker containers
docker-compose -f docker-compose-dev.yml up --build -d
4. nginx.conf 설정
dev와 prd가 공동으로 nginx.conf를 사용함
upstream으로 서버를 구분해서 연결
upstream front-server {
server host.docker.internal:3000;
}
upstream back-server {
server host.docker.internal:8080;
}
upstream dev-front-server {
server host.docker.internal:3001;
}
upstream dev-back-server {
server host.docker.internal:8081;
}
server {
server_name abc.co.kr;
listen 80;
location / {
proxy_pass http://front-server;
}
location /ws {
proxy_pass http://front-server;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header Origin "";
}
}
server {
server_name back.abc.co.kr;
listen 80;
location / {
proxy_pass http://back-server;
}
}
server {
server_name dev.abc.co.kr;
listen 80;
location / {
proxy_pass http://dev-front-server;
}
location /ws {
proxy_pass http://dev-front-server;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header Origin "";
}
}
server {
server_name dev.back.abc.co.kr;
listen 80;
location / {
proxy_pass http://dev-back-server;
}
}
배포 완료!
- reverse-proxy
- dev-front
- dev-back
- prd-front
- prd-back
(proxy는 한번 배포해놓고 docker-compose에서 주석처리해놓아서 dev와 prd가 서로서로 배포될 때 영향이 없게함)
'web' 카테고리의 다른 글
[nginx + docker + react] websocket connection to ws failed (0) | 2023.01.03 |
---|---|
[express, res.cookie] subdomain의 쿠키 공유 (0) | 2022.01.17 |