AWS
- 인스턴스 생성
- 배포를 위해서 git 설치
- sudo yum install git (ubuntu는 다름)
- git rsa key 생성
- ssh-keygen -t rsa -C [git 이메일]
- rsa key 복사
- cat id_rsa.pub
- Git hub에 등록하기
- setting ⇒ SSH keys ⇒ 복사해온 키 등록
- git clone으로 개발된 프로젝트 가져오기
도메인 설정하기
- 도메인 구매(ex)sodamsodam.site)
- rs5 에서 구매한 링크 주소 넣고 생성
- 가비아에 rs5에서 생성된 주소 값들 복사해서 저장
- ec2 인스턴스 주소 rs5에 추가
https설정하기
- 인증서 발급 받기
- nginx를 통해서 443 포트로 들어온 것 인증서 인증 받고 서버, 프론트롤 구분해서 넘어갈 수 있도록 설정
server { listen 80; server_name i11b105.p.ssafy.io; location / { return 301 https://$host$request_uri; } } server { listen 443 ssl; server_name i11b105.p.ssafy.io; location / { proxy_pass http://react:3000$request_uri; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; } location /api { proxy_pass <http://spring:8080>; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; } ssl_certificate /etc/letsencrypt/live/i11b105.p.ssafy.io/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/i11b105.p.ssafy.io/privkey.pem; }
- server { listen 443 ssl; server_name ddubam.site; location / { proxy_pass http://127.0.0.1:3000$request_uri; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; } location /api { proxy_pass http://127.0.0.1:8080$request_uri; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; } ssl_certificate /etc/letsencrypt/live/ddubam.site/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/ddubam.site/privkey.pem; include /etc/letsencrypt/options-ssl-nginx.conf; ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; } server { listen 80; location / { return 301 https://ddubam.site$request_uri; } }
프로젝트 실행시키기
백엔드
- 처음이면 build 권한 주기
- sudo chmod +x gradlew
- 혹시 필요한 파일인데 gitignore해놓은 경우 vim으로 코드 복사 ⇒ 가장 편한듯(아니면 다른 프로그램 사용)
- vim 파일명
- 프로젝트 빌드 시키기
- 기존에 켜놓은거 끄기
- ps -ef | grep jar => 백 돌아가는거 확인 ps -ef | grep js => 프론트 돌아가는거 확인 kill로 죽이면 됨
- 빌드 파일에서 snapshot nohup으로 고정시켜서 실행시키기
프론트
- 계속 해보니 cpu 용량이 1g가라 계속 터짐
- build 까지한 프로젝트를 pull 땡기기
- server.js 생성
- const http = require("http"); const express = require("express"); const path = require("path"); const app = express(); const port = 3000; //인스턴스 생성시 만들었던 포트번호 기입 app.get("/ping", (req, res) => { res.send("pong"); }); app.use(express.static(path.join(__dirname, "build"))); app.get("/*", (req, res) => { res.set({ "Cache-Control": "no-cache, no-store, must-revalidate", Pragma: "no-cache", Date: Date.now() }); res.sendFile(path.join(__dirname, "build", "index.html")); }); http.createServer(app).listen(port, () => { console.log(`app listening at ${port}`); });
- 해당 server.js를 nohup으로 고정시켜서 실행
도커
0번
- nginx를 위해서 미리 네트워크 생성
- docker network create app-network
- 젠킨슨 연결하기
- 서버에 젠킨슨 설치(docker container 생성)
docker run -d --name jenkins \\ -p 9090:8080 -p 50000:50000 \\ -v /var/jenkins_home:/var/jenkins_home \\ -v /var/run/docker.sock:/var/run/docker.sock \\ --privileged \\ --user root \\ jenkins/jenkins:lts
- 포트 9090으로 연결
- volume을 통해서 데이터 저장
- sock를 통해서 인증 처리
- git lab과 연결 시키기
- gitlab에서 acess 토큰 발급
- 해당 acess 토큰 jenkins credentials에 등록
- 이때 Username with password로 생성하여 자기 아이디 토큰 입력
- jenkins에 item생성
- git lab build trigger 설정
- push
- merge request
- git lab과 훅 걸기
- project hook에서 jenkins project의 url 넣기(build trigger 설정하는 곳에 존재)
- token 넣어주기 (build trigger 설정하는 곳에 존재)
- push event에 Regular expression에 ^test$ 이런식으로 입력해서 특정 branch 선택 가능
백엔드 파이프 라인
pipeline {
agent any
environment {
SPRING_IMAGE = 'spring-app' // Spring Boot 애플리케이션의 Docker 이미지 이름
COMPOSE_FILE = 'docker-compose.yml' // 사용될 docker-compose 파일 이름
}
tools {
gradle 'gradle' // Jenkins에서 설정한 Gradle 도구
}
stages {
stage('Checkout') {
steps {
// Git 리포지토리에서 'deploy' 브랜치를 체크아웃
git branch: 'server-main',
url: '<https://lab.ssafy.com/s11-webmobile1-sub2/S11P12B105.git>',
credentialsId: 'gitlab-access-token'
}
}
stage('Add Env') {
steps {
dir('./Backend/BITAMIN') {
withCredentials([file(credentialsId: 'secret-properties', variable: 'key')]) {
sh 'chmod 755 src/main/resources'
sh 'cp ${key} src/main/resources/application-key.properties'
}
}
}
}
stage('Build Spring Backend') {
steps {
script {
dir('./Backend/BITAMIN') {
sh 'chmod +x gradlew'
sh './gradlew build -x test'
}
}
}
}
stage('Stop and Remove Existing Containers') {
steps {
script {
// 기존 컨테이너 중지 및 제거
sh 'sudo docker-compose -f ${COMPOSE_FILE} down'
}
}
}
stage('Remove Existing Docker Images') {
steps {
script {
// 기존 Spring 이미지를 삭제
sh "docker rmi -f \\$(docker images -q ${SPRING_IMAGE}) || true"
}
}
}
stage('Build Docker Image Spring') {
steps {
script {
dir('./Backend/BITAMIN'){
sh 'docker build -t ${SPRING_IMAGE} .'
}
}
}
}
stage('docker-compose up') {
steps {
script {
sh 'docker-compose -f ${COMPOSE_FILE} down' // 기존 컨테이너 중지 및 제거
sh 'docker-compose -f ${COMPOSE_FILE} up -d' // 새로운 컨테이너 시작
}
}
}
}
post {
always {
// 빌드 후 정리 작업을 수행합니다.
cleanWs()
}
}
}
- 파이프 라인 구축
- push, merge가 들어옴
- branch 이동
- config 파일 가져오기
- config 파일 생성
- credential에 파일 등록 및 이름 설정 ⇒ 해당 이름을 key로 파일 찾기 가능
- build
- 생성된 build파일의 jar파일을 image화
- docker file을 미리 설정 (이때 directory 시작은 git clone을 했을때 바로 있는 폴더)
- docker file 코드
# Dokerfile FROM openjdk:17-alpine // 사용할 버전 ARG JAR_FILE=/build/libs/BITAMIN-0.0.1-SNAPSHOT.jar // build된 jar 파일로 이동 COPY ${JAR_FILE} app.jar //jar 파일을 app.jar 파일로 복사 ENTRYPOINT ["java","-jar","/app.jar"] // java -jar app.jar로 실행
- 해당 image를 Build ⇒ 이미지 생성
- docker-compose를 내리고 생성된 image를 다시 실행
- image를 실행 시켜 container 생성
- 여기에서 network 까지 같이 연결해서 하나의 network에 넣어서 해당 container에 접근 가능하도록 만듬
# docker-compse.yml 파일
version: '3.8'
services:
spring:
container_name: spring
image: spring-app
networks:
- app-network
networks:
app-network:
external: true
프론트 파이프라인
pipeline {
agent any
environment {
REACT_IMAGE = 'react-app' // React 애플리케이션을 위한 이미지 이름
COMPOSE_FILE = 'docker-compose.yml' // 사용할 Docker Compose 파일
}
stages {
stage('Checkout') {
steps {
// Git 리포지토리 체크아웃
git branch: 'client-main', // 사용할 브랜치
url: '<https://lab.ssafy.com/s11-webmobile1-sub2/S11P12B105.git>',
credentialsId: 'gitlab-access-token' // Jenkins에 설정된 Credential ID
}
}
stage('Build Docker Image for React') {
steps {
script {
dir('./bitamin'){
// Docker 이미지 빌드
sh 'docker build -t ${REACT_IMAGE} -f dockerfile .'
}
}
}
}
stage('Docker Compose Up') {
steps {
script {
// Docker Compose를 사용해 서비스 시작
sh 'docker-compose -f ${COMPOSE_FILE} down' // 기존 서비스 중지
sh 'docker-compose -f ${COMPOSE_FILE} up -d' // 새 서비스 시작
}
}
}
}
}
- 파이프라인 구축
- push,merge가 들어옴
- 사용할 branch로 checkout
- doker file을 실행시켜 image 생성
- node:20.15.0 이미지 선택 하여 build환경 설정
- 디렉토리 선택
- 사용할 패키지를 담은 파일 복사
- 의존성 설치
- react 애플리케이션 빌드
- nginx를 활용하여 해당 애플리케이션 실행
- 기본 제공 html 코드를 복사
- 80번 포트 오픈
- 해당 포트로 nginx서버 실행
- compose 파일을 통해서 container들 생성
- react 컨테이너 생성
- network 연결
# docker-compse.yml 파일
version: '3.8'
services:
react:
container_name: react
image: react-app
networks:
- app-network
networks:
app-network:
external: true
# Dockerfile
# 1단계: React 애플리케이션 빌드
FROM node:20.15.0 AS build
# 작업 디렉토리 설정
WORKDIR /app
# package.json 및 package-lock.json 복사
COPY package*.json ./
# 의존성 설치
RUN npm install
# 애플리케이션 코드 복사
COPY . .
# 애플리케이션 빌드
RUN npm run build
# 2단계: Nginx로 React 애플리케이션 제공
FROM nginx:alpine
# 빌드된 파일을 Nginx의 HTML 디렉토리로 복사
COPY --from=build /app/dist /usr/share/nginx/html
# 80번 포트 오픈
EXPOSE 80
# Nginx 서버 시작
CMD ["nginx", "-g", "daemon off;"]
nginx 설정
- docker에서 nginx 이미지 제공하는 것이 존재
- 설정 파일만 생성해주면 실행 가능
- 생성 위치 (임의로 만듬 : /etc/nginx/templates)
server { listen 80; server_name i11b105.p.ssafy.io; location / { return 301 https://$host$request_uri; } } server { listen 443 ssl; server_name i11b105.p.ssafy.io; resolver 127.0.0.11; location / { proxy_pass http://react:80$request_uri; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; } location /api { proxy_pass <http://spring:8080>; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; } ssl_certificate /etc/letsencrypt/live/i11b105.p.ssafy.io/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/i11b105.p.ssafy.io/privkey.pem; }
- 443 포트로 들어오면 url을 바탕으로 proxy
- /api가 붙어 있는 경우 spring container의 8080 포트로 이동
- 아무것도 없는 경우 react container의 80 포트로 이동
- 이때 react를 같은 network에 넣어 주었는데도 찾지 못해서 docker내의 dns서버 활용
- resolver 127.0.0.11; ⇒ docker내의 dns 서버를 활용하여 react 컨테이너 찾아주기
- https://medium.com/dtevangelist/docker-기본-8-8-docker의-network-c75f3077335d
- dns 서버 : docker에 모든 container를 관리 ⇒ 같은 네트워크에 있는 컨테이너의 주소를 보내줌
- Docker는 사용자가 정의한 Bridge, Overlay 및 MACVLAN Network들에게 Host 내의 모든 Container의 위치를 제공하는 내부 DNS Server를 갖고 있습니다. 각 Docker Container(또는 Docker Swarm의 Task)에 존재하는 DNS Resolver가, DNS 쿼리를 DNS Server 역할을 하는 Docker Engine으로 전달합니다. 그런 다음 Docker Engine은 DNS 쿼리가 요청한 Container가 Network 내에 포함되어있는지 확인합니다. Docker Engine은 key-value 저장소에서 Container, Task 또는 Service 이름과 일치하는 IP주소를 조회하고, 해당 IP 또는 Service Virtual IP(VIP)를 요청자에게 반환합니다. 이렇게 Docker는 내장 DNS를 사용하여, Single Docker Engine에서 실행되는 Container 및 Docker Swarm에서 실행되는 Task에 대한 Service Discovery기능을 제공합니다.
- resolver 127.0.0.11; ⇒ docker내의 dns 서버를 활용하여 react 컨테이너 찾아주기
- 이때 인증서를 사용하여 https 설정
- 80포트로 들어온 경우
- 443 포트(https://domain.com)으로 보냄
- nginx 컨테이너 생성 코드
1. 외부와 연결을 위해서 80, 443 포트 연결 2. nginx의 인증서와 설정 파일을 위해서 볼륨 설정 1. /etc/nginx/templates:/etc/nginx/templates \\ ⇒ 설정 2. /etc/letsencrypt:/etc/letsencrypt \\ ⇒ 인증서 저장 위치
- 외부와 연결을 위해서 80, 443 포트 연결
- nginx의 인증서와 설정 파일을 위해서 볼륨 설정
- /etc/nginx/templates:/etc/nginx/templates \ ⇒ 설정
- /etc/letsencrypt:/etc/letsencrypt \ ⇒ 인증서 저장 위치