From 06d609027406142544a057f64a4ae796fc076f85 Mon Sep 17 00:00:00 2001 From: solo5star Date: Mon, 8 Jan 2024 13:46:58 +0900 Subject: [PATCH 1/3] =?UTF-8?q?feat:=20prod=20=EB=94=94=EB=A0=89=ED=86=A0?= =?UTF-8?q?=EB=A6=AC,=20https=20=EC=84=A4=EC=A0=95,=20certbot=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C,=20=EB=B0=B1=EC=97=94=EB=93=9C=20docker=20=EC=BB=A8?= =?UTF-8?q?=ED=85=8C=EC=9D=B4=EB=84=88=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- infrastructure/docker-compose.yml | 56 +++++++++++++++++++++++++ infrastructure/nginx.conf.template | 10 +++++ infrastructure/prod/docker-compose.yml | 51 ---------------------- infrastructure/prod/nginx.conf.template | 23 ---------- 4 files changed, 66 insertions(+), 74 deletions(-) create mode 100644 infrastructure/docker-compose.yml create mode 100644 infrastructure/nginx.conf.template delete mode 100644 infrastructure/prod/docker-compose.yml delete mode 100644 infrastructure/prod/nginx.conf.template diff --git a/infrastructure/docker-compose.yml b/infrastructure/docker-compose.yml new file mode 100644 index 00000000..ddb557a1 --- /dev/null +++ b/infrastructure/docker-compose.yml @@ -0,0 +1,56 @@ +version: "3.8" +services: + web: + image: nginx + restart: unless-stopped + ports: + - 80:80 + volumes: + - ./nginx.conf.template:/etc/nginx/templates/default.conf.template + + mysql: + image: library/mysql:8.0.33 + restart: unless-stopped + ports: + - 20000:3306 + volumes: + - db-data:/var/lib/mysql + command: + - mysqld + - --character-set-server=utf8mb4 + - --collation-server=utf8mb4_general_ci + environment: + - MYSQL_DATABASE=yozm-cafe + - MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD:?} + - MYSQL_USER=${MYSQL_USER:?} + - MYSQL_PASSWORD=${MYSQL_PASSWORD:?} + - TZ=Asia/Seoul + + server: + build: + context: ../server + restart: unless-stopped + ports: + - 8080:8080 + environment: + - SPRING_DATASOURCE_URL=jdbc:mysql://mysql:3306/yozm-cafe?useSSL=false&allowPublicKeyRetrieval=true&characterEncoding=UTF-8&serverTimezone=UTC + - SPRING_DATASOURCE_USERNAME=${MYSQL_USER:?} + - SPRING_DATASOURCE_PASSWORD=${MYSQL_PASSWORD:?} + - SPRING_AUTH_KEY=${AUTH_KEY:?} + + - SPRING_AUTH_GOOGLE_TOKENURI=https://www.googleapis.com/oauth2/v4/token + - SPRING_AUTH_GOOGLE_AUTHURI=https://accounts.google.com/o/oauth2/v2/auth + - SPRING_AUTH_GOOGLE_REDIRECTURI=http://localhost:3000/auth/google + - SPRING_AUTH_GOOGLE_SCOPE=https%3A//www.googleapis.com/auth/userinfo.profile + - SPRING_AUTH_GOOGLE_CLIENTID=${AUTH_GOOGLE_CLIENTID:?} + - SPRING_AUTH_GOOGLE_CLIENTSECRET=${AUTH_GOOGLE_CLIENTSECRET:?} + + - SPRING_AUTH_KAKAO_TOKENURI=https://kauth.kakao.com/oauth/token + - SPRING_AUTH_KAKAO_AUTHURI=https://kauth.kakao.com/oauth/authorize + - SPRING_AUTH_KAKAO_REDIRECTURI=http://localhost:3000/auth/kakao + - SPRING_AUTH_KAKAO_SCOPE=openid,profile_nickname,profile_image + - SPRING_AUTH_KAKAO_CLIENTID=${AUTH_KAKAO_CLIENTID:?} + - SPRING_AUTH_KAKAO_CLIENTSECRET=${AUTH_KAKAO_CLIENTSECRET:?} + +volumes: + db-data: diff --git a/infrastructure/nginx.conf.template b/infrastructure/nginx.conf.template new file mode 100644 index 00000000..8edc1163 --- /dev/null +++ b/infrastructure/nginx.conf.template @@ -0,0 +1,10 @@ +server { + listen 80; + + client_max_body_size 0; + + location /api { + rewrite ^/api(.*)$ $1 break; + proxy_pass http://server:8080; + } +} diff --git a/infrastructure/prod/docker-compose.yml b/infrastructure/prod/docker-compose.yml deleted file mode 100644 index e9d802a6..00000000 --- a/infrastructure/prod/docker-compose.yml +++ /dev/null @@ -1,51 +0,0 @@ -version: "3.8" -services: - web: - image: nginx - restart: unless-stopped - ports: - - 80:80 - - 443:443 - volumes: - - ./nginx.conf.template:/etc/nginx/templates/nginx.conf.template - - letsencrypt:/etc/letsencrypt:ro - - /home/ubuntu/public:/usr/share/nginx/html:ro - environment: - - DOMAIN=${DOMAIN?:'DOMAIN required'} - - certbot: - image: certbot/certbot - ports: - - 80:80 - volumes: - - letsencrypt:/etc/letsencrypt - command: - - certonly - - --standalone - - -d ${DOMAIN:?'DOMAIN required'} - - -m ${EMAIL:?'EMAIL required'} - - --preferred-challenges=http - - --agree-tos - - --verbose - - mysql: - image: library/mysql:8.0.33 - restart: unless-stopped - ports: - - 20000:3306 - volumes: - - db-data:/var/lib/mysql - command: - - mysqld - - --character-set-server=utf8mb4 - - --collation-server=utf8mb4_general_ci - environment: - - MYSQL_DATABASE=yozm-cafe - - MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD:?'MYSQL_ROOT_PASSWORD required'} - - MYSQL_USER=${MYSQL_USER:?'MYSQL_USER required'} - - MYSQL_PASSWORD=${MYSQL_PASSWORD:?'MYSQL_PASSWORD required'} - - TZ=Asia/Seoul - -volumes: - letsencrypt: - db-data: diff --git a/infrastructure/prod/nginx.conf.template b/infrastructure/prod/nginx.conf.template deleted file mode 100644 index b5f5d57e..00000000 --- a/infrastructure/prod/nginx.conf.template +++ /dev/null @@ -1,23 +0,0 @@ -server { - listen 80; - return 301 https://$host$request_uri; -} - -server { - listen 443 ssl; - - client_max_body_size 0; - - ssl_certificate /etc/letsencrypt/live/${DOMAIN}/fullchain.pem; - ssl_certificate_key /etc/letsencrypt/live/${DOMAIN}/privkey.pem; - - location / { - root /usr/share/nginx/html; - include /etc/nginx/mime.types; - try_files $uri $uri/ /index.html; - } - - location /api { - proxy_pass http://172.17.0.1:8080; - } -} From ecc401bb7f480a70e041c832d9b5680ce84b50fa Mon Sep 17 00:00:00 2001 From: solo5star Date: Mon, 8 Jan 2024 13:47:52 +0900 Subject: [PATCH 2/3] =?UTF-8?q?refactor:=20DB=20=EB=A0=88=ED=94=8C?= =?UTF-8?q?=EB=A6=AC=EC=B9=B4=20=EC=84=A4=EC=A0=95=20=EC=A0=9C=EA=B1=B0=20?= =?UTF-8?q?=EB=B0=8F=20=EA=B8=B0=EC=A1=B4=20docker-compose.yml=20=EB=A6=AC?= =?UTF-8?q?=ED=8C=A9=ED=86=A0=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- infrastructure/ci/docker-compose.yml | 4 ++-- server/docker-compose.yml | 19 ++++++++----------- 2 files changed, 10 insertions(+), 13 deletions(-) diff --git a/infrastructure/ci/docker-compose.yml b/infrastructure/ci/docker-compose.yml index 99ff3e12..1966f74a 100644 --- a/infrastructure/ci/docker-compose.yml +++ b/infrastructure/ci/docker-compose.yml @@ -74,8 +74,8 @@ services: - ./webhook-broker:/app command: run --allow-net --allow-read --allow-env /app/app.js environment: - - SLACK_WEBHOOK_URL=${SLACK_WEBHOOK_URL:?'SLACK_WEBHOOK_URL required'} - - SLACK_CHANNEL=${SLACK_CHANNEL:?'SLACK_CHANNEL required'} + - SLACK_WEBHOOK_URL=${SLACK_WEBHOOK_URL:?} + - SLACK_CHANNEL=${SLACK_CHANNEL:?} - SLACK_USERNAME=TeamCity - 'SLACK_ICON_EMOJI=:teamcity:' diff --git a/server/docker-compose.yml b/server/docker-compose.yml index 453ab1e5..bf563be8 100644 --- a/server/docker-compose.yml +++ b/server/docker-compose.yml @@ -1,24 +1,21 @@ version: "3.8" services: mysql: - platform: linux/arm64/v8 image: library/mysql:8.0.33 ports: - 20000:3306 + volumes: + - db-data:/var/lib/mysql + command: + - mysqld + - --character-set-server=utf8mb4 + - --collation-server=utf8mb4_general_ci environment: MYSQL_ROOT_PASSWORD: root MYSQL_DATABASE: yozm-cafe - MYSQL_USER: user - MYSQL_PASSWORD: password + MYSQL_USER: ${DB_USERNAME:?} + MYSQL_PASSWORD: ${DB_PASSWORD:?} TZ: Asia/Seoul - command: [ "mysqld", "--character-set-server=utf8mb4", "--collation-server=utf8mb4_general_ci" ] - volumes: - - db-data:/var/lib/mysql - # my.cnf의 server_id 값은 복제에 참여한 MySQL 서버들이 고유하게 가지고 있는 식별 값이다. - # 이 값은 바이너리 로그에 이벤트별로 이벤트가 최초로 발생한 MySQL을 식별하기 위해 사용되며, 기본값이 모두 1이다. - # 이 때문에 Master 서버와 Slave 서버를 구별할 수 있도록 Slave 서버의 server_id를 바꾸어 주기 위해 volume 매핑을 진행해야한다. - # my.cnf 파일이 존재해야한다. - - ./my.cnf:/etc/my.cnf volumes: db-data: From 148f4d1060065db49d0da5c92a9a602353eb23fe Mon Sep 17 00:00:00 2001 From: solo5star Date: Mon, 8 Jan 2024 13:53:38 +0900 Subject: [PATCH 3/3] =?UTF-8?q?docs:=20=EC=9D=B8=ED=94=84=EB=9D=BC=20?= =?UTF-8?q?=EB=AC=B8=EC=84=9C=20=EC=97=85=EB=8D=B0=EC=9D=B4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- infrastructure/README.md | 63 +++++++++++++++++----------------------- 1 file changed, 27 insertions(+), 36 deletions(-) diff --git a/infrastructure/README.md b/infrastructure/README.md index 04bd09e3..d85a7a0e 100644 --- a/infrastructure/README.md +++ b/infrastructure/README.md @@ -7,72 +7,63 @@ ## Table of Contents -- [ci](#ci) +- [운영](#운영) - [주요 인스턴스 목록](#주요-인스턴스-목록) - [환경변수](#환경변수) - [설치 방법](#설치-방법) -- [prod](#prod) +- [CI](#ci) - [주요 인스턴스 목록](#주요-인스턴스-목록-1) - [환경변수](#환경변수-1) - [설치 방법](#설치-방법-1)

-## ci -CI/CD를 수행하는 인스턴스입니다. ci/ 폴더의 파일들 및 `docker-compose.yml` 에는 CI/CD 환경에 필요한 코드 및 서비스들이 있습니다. +## 운영 +`infrastructure` 폴더의 파일들 및 `infrastructure/docker-compose.yml` 에는 운영 환경에 필요한 코드 및 서비스들이 있습니다. ### 주요 인스턴스 목록 -* **TeamCity**: CI/CD 시스템입니다 -* **TeamCity Agent 1, 2, 3**: 빌드 및 배포를 수행하는 에이전트입니다. -* **Webhook Broker**: TeamCity Webhook 메세지를 Slack Webhook 으로 전달해주는 Webhook 브로커입니다. +* **nginx**: 프론트엔드 html, css, js 정적 리소스 서빙 및 백엔드 서버 리버스 프록시 역할을 수행합니다 +* **MySQL**: 백엔드에서 사용하는 DB입니다 +* **Spring**: API 요청 및 비즈니스 로직을 수행하는 Spring 서버 인스턴스입니다 ### 환경변수 |이름|설명|예시| |-|-|-| -|`SLACK_WEBHOOK_URL`|빌드 결과 알림을 받을 Slack Webhook URL 입니다|`https://hooks.slack.com/services/XXXXXXXXXXX/XXXXXXXXXXX/XXXXXXXXXXXXXXXXXXXXXXXX`| -|`SLACK_CHANNEL`|빌드 결과 알림 메세지가 전송될 Slack 채널입니다|`C05PNZ142H6S`| - +|`MYSQL_ROOT_PASSWORD`|MySQL DB root 계정의 패스워드입니다|`supersecretpassword`| +|`MYSQL_USER`|MySQL DB 사용자 계정 이름입니다|`myuser`| +|`MYSQL_PASSWORD`|MySQL DB 사용자 계정의 패스워드입니다|`supersecretpassword`| +|`AUTH_KEY`|JWT 발급에 사용될 Secret Key 입니다|`supersecretkey`| +|`AUTH_GOOGLE_CLIENTID`|Google OAuth 에서 제공하는 Client ID 값입니다|`780816631155-gbvyo1o7r2pn95qc4ei9d61io4uh48hl.apps.googleusercontent.com`| +|`AUTH_GOOGLE_CLIENTSECRET`|Google OAuth 에서 제공하는 Client Secret 값입니다|`GOCSPX-XXX`| +|`AUTH_KAKAO_CLIENTID`|Kakao OAuth 에서 제공하는 Client ID 값입니다|`ccd9ea 136632b1fe01c0e918381`| +|`AUTH_KAKAO_CLIENTSECRET`|Kakao OAuth 에서 제공하는 Client Secret 값입니다|`l7BpJ8YxvFotJYEu2WkH4NsvWM9qy47E`| ### 설치 방법 ```bash -cd ci docker compose up -d ``` -위의 명령으로 TeamCity 서버 및 에이전트, Webhook 브로커를 실행시킬 수 있습니다. -Agent Authorize는 Web UI에서 직접 해야 합니다. +nginx와 MySQL, Spring Server를 켜주면 됩니다.

-## prod -운영 환경에서 사용하는 인스턴스입니다. prod/ 폴더의 파일들 및 `docker-compose.yml` 에는 운영 환경에 필요한 코드 및 서비스들이 있습니다. +## CI +`infrastructure/ci/` 폴더의 파일들 및 `infrastructure/ci/docker-compose.yml` 에는 CI/CD 환경에 필요한 코드 및 서비스들이 있습니다. ### 주요 인스턴스 목록 -* **nginx**: 프론트엔드 html, css, js 정적 리소스 서빙 및 백엔드 서버 리버스 프록시 역할을 수행합니다 -* **MySQL**: 백엔드에서 사용하는 DB입니다 -* **certbot**: HTTPS 인증서 발급을 수행합니다 +* **TeamCity**: CI/CD 시스템입니다 +* **TeamCity Agent 1, 2, 3**: 빌드 및 배포를 수행하는 에이전트입니다. +* **Webhook Broker**: TeamCity Webhook 메세지를 Slack Webhook 으로 전달해주는 Webhook 브로커입니다. ### 환경변수 |이름|설명|예시| |-|-|-| -|`DOMAIN`|HTTPS 인증서를 발급받을 도메인 이름입니다|`www.example.com`| -|`EMAIL`|HTTPS 인증서를 발급받을 때 사용할 이메일입니다|`example@gmail.com`| -|`MYSQL_ROOT_PASSWORD`|MySQL DB root 계정의 패스워드입니다|`supersecretpassword`| -|`MYSQL_USER`|MySQL DB 사용자 계정 이름입니다|`myuser`| -|`MYSQL_PASSWORD`|MySQL DB 사용자 계정의 패스워드입니다|`supersecretpassword`| +|`SLACK_WEBHOOK_URL`|빌드 결과 알림을 받을 Slack Webhook URL 입니다|`https://hooks.slack.com/services/XXXXXXXXXXX/XXXXXXXXXXX/XXXXXXXXXXXXXXXXXXXXXXXX`| +|`SLACK_CHANNEL`|빌드 결과 알림 메세지가 전송될 Slack 채널입니다|`C05PNZ142H6S`| ### 설치 방법 ```bash -cd prod -docker compose up certbot -``` -먼저, certbot을 사용하여 HTTPS 인증서를 발급받아야 합니다. certbot은 [HTTP-01 challenge](https://letsencrypt.org/docs/challenge-types/#http-01-challenge) 방법을 사용하여 HTTPS 인증서 발급을 시도할 것입니다. 이 방법을 사용하기 위해 certbot은 80 포트를 점유하여 웹 서버를 열기 때문에 nginx와 함께 켜면 안됩니다. - -```bash -docker compose up -d web -``` -HTTPS 인증서 발급이 완료되면 nginx를 켜주세요. - -```bash -docker compose up -d mysql +cd ci +docker compose up -d ``` -MySQL은 위 과정과 상관없이 별도로 켜주면 됩니다. +위의 명령으로 TeamCity 서버 및 에이전트, Webhook 브로커를 실행시킬 수 있습니다. +Agent Authorize는 Web UI에서 직접 해야 합니다.