Skip to content

Commit

Permalink
Feat(*): 개발 서버 배포 스크립트 마이그레이션 준비 (#78)
Browse files Browse the repository at this point in the history
* Feat(*): develop readme 초안 작성

* Feat(*): NotFound 예외처리 추가

* Fix(*): 시큐리티 필터 예외 버그 수정

* Feat(*): 개발 서버 compose file 저장

* Feat(*): Readme 오타 수정

* Fix(*): 누락된 환경 설정 파일 변경 적용

* Fix(*): 파일 마지막 개행문자 수정
  • Loading branch information
InHyeok-J authored Sep 24, 2024
1 parent b03fd49 commit b51b34e
Show file tree
Hide file tree
Showing 15 changed files with 412 additions and 2 deletions.
1 change: 1 addition & 0 deletions jabiseo-api/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.boot:spring-boot-starter-actuator'
implementation 'io.micrometer:micrometer-registry-prometheus'

implementation project(":jabiseo-domain")
implementation project(":jabiseo-infrastructure")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,8 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
.map(RegexRequestMatcher::regexMatcher)
.toArray(RegexRequestMatcher[]::new)
).permitAll()
.requestMatchers("/**").authenticated()
.requestMatchers("/api/**").authenticated()
.requestMatchers("/**").permitAll()
);

http.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,15 @@
import com.jabiseo.common.exception.ErrorCode;
import com.jabiseo.database.exception.PersistenceException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.method.annotation.HandlerMethodValidationException;
import org.springframework.web.servlet.NoHandlerFoundException;

@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {
Expand Down Expand Up @@ -82,4 +85,9 @@ public ResponseEntity<?> handleException(Exception e) {
.body(new ErrorResponse(errorMessage, CommonErrorCode.INTERNAL_SERVER_ERROR.getErrorCode()));
}

@ExceptionHandler(NoHandlerFoundException.class)
public ResponseEntity<?> handleNotFound(NoHandlerFoundException e) {
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(new ErrorResponse("URL에 해당하는 요청을 찾을 수 없습니다", CommonErrorCode.NOT_FOUND.getErrorCode()));
}

}
2 changes: 2 additions & 0 deletions jabiseo-api/src/main/resources/api.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ jabiseo:
default-image-url: ${DEFAULT_IMAGE_URL}

management:
server:
port: 9292
endpoints:
web:
base-path: "/manage"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ public enum CommonErrorCode implements ErrorCode {
INVALID_REQUEST_BODY("요청의 body가 올바르지 않습니다.", "COM_001", ErrorCode.BAD_REQUEST),
INTERNAL_SERVER_ERROR("internal server error", "COM_002", ErrorCode.INTERNAL_SERVER_ERROR),
INVALID_REQUEST_PARAMETER("요청의 parameter가 올바르지 않습니다.", "COM_003", ErrorCode.BAD_REQUEST),
FORBIDDEN("권한이 없거나 금지된 요청입니다.", "COM_004", ErrorCode.FORBIDDEN);
FORBIDDEN("권한이 없거나 금지된 요청입니다.", "COM_004", ErrorCode.FORBIDDEN),
NOT_FOUND("리소스를 찾을 수 없습니다", "COM_005", ErrorCode.NOT_FOUND);

private final String message;
private final String errorCode;
Expand Down
13 changes: 13 additions & 0 deletions script/developcompose/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Database configuration
MYSQL_PORT=
MYSQL_ROOT_PASSWORD=
MYSQL_DATABASE=

# Redis configuration
REDIS_PASSWORD=

# Prometheus configuration
PROMETHEUS_PORT=

# grafana configuration
GRAFANA_PORT=
1 change: 1 addition & 0 deletions script/developcompose/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.env
145 changes: 145 additions & 0 deletions script/developcompose/Readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@


## 개발 환경 배포 정보



## 고려사항
- 단일 EC2 환경 고려 : SW 마에스트로 활동이 끝나도 유지보수가 가능하기 위해 단일 EC2 환경의 Docker 기반으로 구성 되어야 함.
- 개인 랩탑 개발 시 활용 가능
- 추후 시스템 구성 요소가 추가되도 문서만 보고 적용 및 실행이 가능하도록 Readme에 잘 적혀있어야 함
- 개인 랩탑에서 원활하게 실행하기 위해 주입되는 환경 값들의 변수적용이 되어야 함

## 시스템 구성도

<img src="./images/devserver.png" width="900">


### 도커 Service Name / Port(default) 현황
- service name이 static으로 compose에 적용됐기 때문에 따로 Readme에 테이블로 명시
- port 같은 경우 컨테이너 내부 포트는 기본 시스템 포트(ex, MySQL -> 3306, Spring Boot-> 8080) 사용
- 컨테이너 외부 포트의 경우 env 값으로 명시 없으면 default 값을 compose에 static 명시, **아래 표에 표시함**
- 외부 포트를 받거나 명시하는 이유는 로컬에 실행시 기존의 시스템과 충돌을 방지하기 위함
- 해당 부분은 추후 서비스명:포트가 아닌 다른 표현 방식이 사용될 경우 없어질 예정

<table>
<tr>
<th>서비스 종류</th>
<th>docker service 이름</th>
<th>docker 컨테이너 외부 포트 </th>
</tr>
<tr>
<td>
스프링 WAS
</td>
<td>
jabiseo-was
</td>
<td>
8081
</td>
</tr>
<tr>
<td>
MySQL DB
</td>
<td>
jabiseo-mysql
</td>
<td>
3307
</td>
</tr>
<tr>
<td>
Redis
</td>
<td>
jabiseo-redis
</td>
<td>
7380
</td>
</tr>
<tr>
<td>
Nginx
</td>
<td>
webserver-nginx
</td>
<td>
80
</td>
</tr>
<tr>
<td>
프로메테우스
</td>
<td>
jabiseo-prometheus
</td>
<td>
9090
</td>
</tr>
<tr>
<td>
그라파나
</td>
<td>
jabiseo-grafana
</td>
<td>
4000
</td>
</tr>
</table>

---

## 실행
- 주의 : nginx의 경우 로컬을 고려하지 않음 사용 x

1. 사전 준비(1) - docker network 생성
```shell
docker network create jabiseo-dev
```

2. 사전 준비(2) - .env 환경변수 파일 생성
- .env.example 파일 카피 후 .env파일을 /developcompose/.env 위치에 생성
- 적절한 값 셋팅

3. 각 파일 별로 실행

```shell
docker compose -f ./{종류별}/docker-compose.yml up -d

# or

cd ./{종류별} # 디렉토리 이동
docker compose up -d
```

4. 종료
```shell
docker compose -f ./{종류별}/docker-compose.yml down

# or

cd ./{종류별} # 디렉토리 이동
docker compose down
```

## 폴더별 설명

### 데이터베이스
- MySQL, Redis 간단 셋팅

### Nginx
- default.conf : 환경 설정 파일
- init-letsencrpyt.sh ssh 키 파일 생성 스크립트 파일(nginx 공식 깃헙 제공, 서비스 명 수정됨)

### 모니터링
- 프로메테우스, 그라파나 설정
- 현재 Local(인텔리제이) WAS를 host.docker.internal:9292 경로로 직접 가져옴.(수정 예정)
39 changes: 39 additions & 0 deletions script/developcompose/database/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@

services:
jabiseo-mysql:
container_name: jabiseo-mysql
image: mysql:8
ports:
- "${MYSQL_PORT:-3307}:3306"
command:
- --character-set-server=utf8mb4
- --collation-server=utf8mb4_unicode_ci
env_file:
- ../.env
environment:
- TZ=Asia/Seoul
restart: always
volumes:
- mysqlvolume:/var/lib/mysql
networks:
- jabiseo-dev

jabiseo-redis:
container_name: jabiseo-redis
image: redis
ports:
- "${REDIS_PORT:-6380}:6379"
command: redis-server --requirepass ${REDIS_PASSWORD} --port 6379
env_file:
- ../.env
networks:
- jabiseo-dev
restart: on-failure

volumes:
mysqlvolume:

networks:
jabiseo-dev:
external: true
name: jabiseo-dev
Binary file added script/developcompose/images/devserver.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
32 changes: 32 additions & 0 deletions script/developcompose/monitoring/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@

services:
grafana:
image: grafana/grafana:latest
container_name: jabiseo-grafana
restart: always
ports:
- "${GRAFANA_PORT:-4000}:3000"
volumes:
- grafana-data:/var/lib/grafana
env_file:
- ../.env
depends_on:
- prometheus
prometheus:
image: prom/prometheus:latest
container_name: jabiseo-prometheus
restart: always
env_file:
- ../.env
ports:
- "${PROMETHEUS_PORT:-9090}:9090"
volumes:
- ./prometheus/config:/etc/prometheus/
- prometheus-data:/prometheus
command:
- '--config.file=/etc/prometheus/prometheus.yml'
- '--storage.tsdb.path=/prometheus'

volumes:
grafana-data:
prometheus-data:
20 changes: 20 additions & 0 deletions script/developcompose/monitoring/prometheus/config/prometheus.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
global:
scrape_interval: 15s
evaluation_interval: 15s
alerting:
alertmanagers:
- static_configs:
- targets:

rule_files:

scrape_configs:
- job_name: "prometheus"
static_configs:
- targets: [ "localhost:9090" ]

- job_name: "spring-actuator"
metrics_path: '/manage/prometheus' # 프로메테우스에서 동적 주입 방식 미지원 추후 변수 처리
scrape_interval: 1s
static_configs:
- targets: [ "host.docker.internal:9292" ] # 프로메테우스에서 동적 주입 방식 미지원 추후 변수 처리
39 changes: 39 additions & 0 deletions script/developcompose/nginx/default.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
server {
listen 80;
server_name devserver.jabiseo.com;
server_tokens off;

location /.well-known/acme-challenge/ {
allow all;
root /var/www/certbot;
}

location / {
return 301 https://$host$request_uri;
}
}

upstream was {
server jabiseo-was:8080;
}

server {

listen 443 ssl;
server_name devserver.jabiseo.com;
server_tokens off;

ssl_certificate /etc/letsencrypt/live/devserver.jabiseo.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/devserver.jabiseo.com/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

client_max_body_size 10M;
location /api {
proxy_pass http://was/api;
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;
}
}
33 changes: 33 additions & 0 deletions script/developcompose/nginx/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
services:
webserver:
container_name: webserver-nginx
image: nginx:latest
restart: always
ports:
- "80:80"
- "443:443"
volumes:
- ./default.conf:/etc/nginx/conf.d/default.conf
- ./data/certbot/conf:/etc/letsencrypt
- ./data/certbot/www:/var/www/certbot
environment:
- TZ=Asia/Seoul
command: "/bin/sh -c 'while :; do sleep 6h & wait $${!}; nginx -s reload; done & nginx -g \"daemon off;\"'"
networks:
- jabiseo-dev

certbot:
container_name: webserver-certbot
image: certbot/certbot
restart: unless-stopped
volumes:
- ./data/certbot/conf:/etc/letsencrypt
- ./data/certbot/www:/var/www/certbot
entrypoint: "/bin/sh -c 'trap exit TERM; while :; do certbot renew; sleep 12h & wait $${!}; done;'"
networks:
- jabiseo-dev

networks:
jabiseo-dev:
external: true
name: jabiseo-dev
Loading

0 comments on commit b51b34e

Please sign in to comment.