diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..43b604a --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,44 @@ +name: Daybook - BackEnd - CI + +on: + pull_request: + branches: [ "main" ] + +permissions: + contents: read + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Set up JDK 17 + uses: actions/setup-java@v3 + with: + java-version: '17' + distribution: 'temurin' + + ## gradle caching + - name: Setup Gradle + uses: gradle/gradle-build-action@v2 + with: + arguments: check + cache-read-only: ${{ github.ref != 'refs/heads/main' && github.ref != 'refs/heads/develop' }} + + # 프로젝트 저장소에 업로드하면 안되는 설정 파일들을 만들어줍니다. + - name: Make application.yml + run: | + # src/main/resources 으로 경로를 이동합니다. + cd ./src/main/resources + # 필요한 yml 파일들을 만들어줍니다. + touch ./application.yml + echo "$APPLICATION" > ./application.yml + env: + APPLICATION: ${{ secrets.APPLICATION }} + shell: bash + + - name: Gradle 권한 부여 + run: chmod +x gradlew + + - name: Gradle로 빌드 실행 + run: ./gradlew bootjar diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml new file mode 100644 index 0000000..0df6636 --- /dev/null +++ b/.github/workflows/deploy.yml @@ -0,0 +1,82 @@ +# Workflow의 이름을 지정합니다. +name: Daybook - BackEnd - CD + +on: + push: + # main branch에 push(merge)될 경우 실행됩니다. + branches: [ "main" ] + +permissions: + contents: read + +jobs: + build: + environment: DEV + # build를 진행할 운영체제를 선택합니다. + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + # JDK를 11 버전으로 셋팅합니다. + - name: Set up JDK 17 + uses: actions/setup-java@v3 + with: + java-version: '17' + distribution: 'temurin' + + - name: Setup Gradle + uses: gradle/gradle-build-action@v2 + with: + arguments: check + cache-read-only: ${{ github.ref != 'refs/heads/main' && github.ref != 'refs/heads/develop' }} + + # 프로젝트 저장소에 업로드하면 안되는 설정 파일들을 만들어줍니다. + - name: Make application.yml + run: | + # 필요한 yml 파일들을 만들어줍니다. + mkdir -p ./src/main/resources + echo "$APPLICATION" > ./src/main/resources/application.yml + env: + APPLICATION: ${{ secrets.APPLICATION }} + shell: bash + + - name: Gradle 권한 부여 + run: chmod +x gradlew + + - name: Gradle로 빌드 실행 + run: ./gradlew bootjar + + # 배포에 필요한 여러 설정 파일과 프로젝트 빌드파일을 zip 파일로 모아줍니다. + - name: zip file 생성 + run: | + mkdir deploy + cp ./docker/docker-compose.blue.yml ./deploy/ + cp ./docker/docker-compose.green.yml ./deploy/ + cp ./appspec.yml ./deploy/ + cp ./docker/Dockerfile ./deploy/ + cp ./scripts/*.sh ./deploy/ + cp ./build/libs/*.jar ./deploy/ + chmod +x ./deploy/deploy.sh + zip -r -qq -j ./daybook-app.zip ./deploy + + # AWS에 연결해줍니다. + - name: AWS 연결 + uses: aws-actions/configure-aws-credentials@v1 + with: + aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} + aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + aws-region: ${{ secrets.AWS_REGION }} + + # S3에 프로젝트를 업로드 합니다. + - name: S3에 프로젝트 업로드 + run: | + aws s3 cp \ + --region ap-northeast-2 \ + ./daybook-app.zip s3://daybook-server + + # CodeDelploy에 배포를 요청합니다. + - name: Code Deploy 배포 요청 + run: aws deploy create-deployment --application-name daybook-code-deploy-app + --deployment-config-name CodeDeployDefault.AllAtOnce + --deployment-group-name daybook-code-deploy-app + --s3-location bucket=daybook-server,bundleType=zip,key=daybook-app.zip diff --git a/appspec.yml b/appspec.yml new file mode 100644 index 0000000..8dedd0c --- /dev/null +++ b/appspec.yml @@ -0,0 +1,34 @@ +version: 0.0 +# Deploy 대상 서버의 운영체제를 표시 +os: linux + +# 코드 파일 전송과 관련된 설정 +files: + # 코드 파일의 소스 경로 + - source: / + # 코드 파일의 대상 경로 -> /home/ec2-user/app 디렉토리로 파일을 복사한다. + destination: /home/ec2-user/app + # 대상 경로에 이미 파일이 존재하는 경우, 덮어쓰기를 허용할지 여부 + overwrite: yes + +# 파일 및 디렉토리 권한에 관련된 설정 +permissions: + # 권한을 설정할 대상 경로 + - object: / + # 모든 파일 및 디렉토리를 의미 + pattern: "**" + # 파일 및 디렉토리의 소유자를 ec2-user로 설정 + owner: ec2-user + # 파일 및 디렉토리의 그룹을 ec2-user로 설정 + group: ec2-user + +# Deploy 전후에 실행할 스크립트 또는 명령에 관련된 설정 +hooks: + # 애플리케이션 시작시 실행할 스크립트 또는 명령에 관련된 설정 + ApplicationStart: + # 실행할 스크립트 또는 명령의 위치 + - location: deploy.sh + # 스크립트 또는 명령 실행의 제한 시간을 설정 + timeout: 60 + # CodeDeploy 중 실행되는 스크립트 또는 명령을 실행할 사용자를 지정 + runas: ec2-user diff --git a/docker/Dockerfile b/docker/Dockerfile new file mode 100644 index 0000000..e9476e4 --- /dev/null +++ b/docker/Dockerfile @@ -0,0 +1,8 @@ +### Docker 이미지를 생성할 때 기반이 되는 베이스 이미지를 설정한다. +FROM openjdk:17 +### Dockerfile 내에서 사용할 변수 JAR_FILE을 정의한다. +ARG JAR_FILE=/*.jar +### JAR_FILE 경로에 해당하는 파일을 Docker 이미지 내부로 복사한다. +COPY ${JAR_FILE} daybook-app.jar +### Docker 컨테이너가 시작될 때 실행할 명령을 지정한다. +ENTRYPOINT ["java","-jar","/daybook-app.jar"] diff --git a/docker/docker-compose.blue.yml b/docker/docker-compose.blue.yml new file mode 100644 index 0000000..6a7ae58 --- /dev/null +++ b/docker/docker-compose.blue.yml @@ -0,0 +1,12 @@ +#blue +version: '3' +services: + # 서비스의 이름 + backend: + # 현재 디렉토리에서의 Dockerfile을 사용하여 Docker 이미지를 빌드 + build: . + ports: + - "8080:8080" + container_name: daybook-blue + environment: + - TZ=Asia/Seoul \ No newline at end of file diff --git a/docker/docker-compose.green.yml b/docker/docker-compose.green.yml new file mode 100644 index 0000000..ccb2f24 --- /dev/null +++ b/docker/docker-compose.green.yml @@ -0,0 +1,12 @@ +#green +version: '3' +services: + backend: + build: . + ports: + - "8080:8080" + container_name: daybook-green + environment: + - TZ=Asia/Seoul + env_file: + - .env diff --git a/scripts/deploy.sh b/scripts/deploy.sh new file mode 100644 index 0000000..2613684 --- /dev/null +++ b/scripts/deploy.sh @@ -0,0 +1,33 @@ +#!/bin/bash + +# 작업 디렉토리를 /home/ec2-user/app으로 변경 +cd /home/ec2-user/app + +# 환경변수 DOCKER_APP_NAME을 spring으로 설정 +DOCKER_APP_NAME=daybook + +# 배포 시작한 날짜와 시간을 기록 +echo "배포 시작일자 : $(date +%Y)-$(date +%m)-$(date +%d) $(date +%H):$(date +%M):$(date +%S)" >> /home/ec2-user/deploy.log + +# 현재 실행중인 컨테이너가 있는지 확인 +EXIST_BLUE=$(sudo docker-compose -p ${DOCKER_APP_NAME}-blue -f docker-compose.blue.yml ps | grep Up) +EXIST_GREEN=$(sudo docker-compose -p ${DOCKER_APP_NAME}-green -f docker-compose.green.yml ps | grep Up) + +# 기존에 실행중인 도커 컨테이너를 중지하고 삭제 +if [ -n "$EXIST_BLUE" ]; then + sudo docker-compose -p ${DOCKER_APP_NAME}-blue -f docker-compose.blue.yml down +fi + +if [ -n "$EXIST_GREEN" ]; then + sudo docker-compose -p ${DOCKER_APP_NAME}-green -f docker-compose.green.yml down +fi + +# 사용하지 않는 이미지 삭제 +sudo docker image prune -af + +# 블루 배포 시작 +echo "블루 배포 시작 : $(date +%Y)-$(date +%m)-$(date +%d) $(date +%H):$(date +%M):$(date +%S)" >> /home/ec2-user/deploy.log +sudo docker-compose -p ${DOCKER_APP_NAME}-blue -f docker-compose.blue.yml up -d --build + +echo "배포 종료 : $(date +%Y)-$(date +%m)-$(date +%d) $(date +%H):$(date +%M):$(date +%S)" >> /home/ec2-user/deploy.log +echo "===================== 배포 완료 =====================" >> /home/ec2-user/deploy.log diff --git a/src/main/java/com/unit/daybook/domain/auth/service/TokenFilter.java b/src/main/java/com/unit/daybook/domain/auth/service/TokenFilter.java index 36fa160..a70d7ad 100644 --- a/src/main/java/com/unit/daybook/domain/auth/service/TokenFilter.java +++ b/src/main/java/com/unit/daybook/domain/auth/service/TokenFilter.java @@ -18,6 +18,7 @@ @Slf4j @RequiredArgsConstructor +@Component public class TokenFilter extends OncePerRequestFilter { private final SecurityService securityService; diff --git a/src/main/java/com/unit/daybook/global/config/security/WebSecurityConfig.java b/src/main/java/com/unit/daybook/global/config/security/WebSecurityConfig.java index 5122760..be446db 100644 --- a/src/main/java/com/unit/daybook/global/config/security/WebSecurityConfig.java +++ b/src/main/java/com/unit/daybook/global/config/security/WebSecurityConfig.java @@ -44,6 +44,7 @@ public class WebSecurityConfig { private static final String[] permitAllUrl = { "/", + "/auth/**", "/index.html", "/favicon.ico", "/robots.txt", @@ -81,8 +82,9 @@ public WebSecurityCustomizer configure() { public CorsConfigurationSource corsConfigurationSource() { CorsConfiguration configuration = new CorsConfiguration(); - configuration.addAllowedOriginPattern(UrlConstants.PROD_DOMAIN_URL.getValue()); - configuration.addAllowedOriginPattern(UrlConstants.LOCAL_DOMAIN_URL.getValue()); + // configuration.addAllowedOriginPattern(UrlConstants.PROD_DOMAIN_URL.getValue()); + // configuration.addAllowedOriginPattern(UrlConstants.LOCAL_DOMAIN_URL.getValue()); + configuration.addAllowedOriginPattern("*"); configuration.addAllowedMethod("*"); configuration.addAllowedHeader("*"); configuration.setAllowCredentials(true);