diff --git a/.github/workflows/deploys.yml b/.github/workflows/deploys.yml index bc2daf01..5f76c4bf 100644 --- a/.github/workflows/deploys.yml +++ b/.github/workflows/deploys.yml @@ -27,6 +27,7 @@ jobs: uses: aws-actions/amazon-ecr-login@v2 - name: Build, tag, and push image to ECR + id: build-image env: ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }} ECR_REPOSITORY: ${{ secrets.AWS_ECR_REPOSITORY }} @@ -35,77 +36,24 @@ jobs: docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG -t $ECR_REGISTRY/$ECR_REPOSITORY:latest . docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG docker push $ECR_REGISTRY/$ECR_REPOSITORY:latest + echo "image=$ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG" >> $GITHUB_OUTPUT - - name: Deploy to EC2 Instance - uses: appleboy/ssh-action@v1.0.3 - env: - ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }} - ECR_REPOSITORY: ${{ secrets.AWS_ECR_REPOSITORY }} - AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} - AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} - AWS_REGION_CODE: ${{ secrets.AWS_REGION_CODE }} - AWS_S3_BUCKET_NAME: ${{ secrets.AWS_S3_BUCKET_NAME }} - DB_HOST: ${{ secrets.DB_HOST }} - DB_PORT: ${{ secrets.DB_PORT }} - DB_NAME: ${{ secrets.DB_NAME }} - DB_USER: ${{ secrets.DB_USER }} - REDIS_HOST: ${{ secrets.REDIS_HOST }} - REDIS_PORT: ${{ secrets.REDIS_PORT }} - DB_PASSWORD: ${{ secrets.DB_PASSWORD }} - JWT_SECRET: ${{ secrets.JWT_SECRET }} - GOOGLE_EMAIL: ${{ secrets.GOOGLE_EMAIL }} - GOOGLE_APP_PASSWORD: ${{ secrets.GOOGLE_APP_PASSWORD }} + - name: Download ECS Task Definition + run: | + aws ecs describe-task-definition --task-definition ${{ vars.AWS_ECS_TASK_DEFINITION_FAMILY }} --query taskDefinition > task-definition.json + + - name: Fill in the new image ID in task definition + id: task-def + uses: aws-actions/amazon-ecs-render-task-definition@v1 with: - host: ${{ secrets.EC2_HOST }} - username: ${{ secrets.EC2_USERNAME }} - key: ${{ secrets.EC2_SSH_PRIVATE_KEY }} - port: ${{ secrets.EC2_SSH_PORT }} - envs: ECR_REGISTRY, ECR_REPOSITORY, AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_REGION_CODE, AWS_S3_BUCKET_NAME, DB_HOST, DB_PORT, DB_NAME, DB_USER, DB_PASSWORD, REDIS_HOST, REDIS_PORT, JWT_SECRET, GOOGLE_EMAIL, GOOGLE_APP_PASSWORD - script: | - sudo rm -rf .aws - aws configure set aws_access_key_id $AWS_ACCESS_KEY_ID - aws configure set aws_secret_access_key $AWS_SECRET_ACCESS_KEY - aws configure set default.region $AWS_REGION_CODE - aws configure set default.ouput json - - rm env.prod - touch env.prod - echo "ECR_REGISTRY=$ECR_REGISTRY" >> env.prod - echo "ECR_REPOSITORY=$ECR_REPOSITORY" >> env.prod - echo "AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID" >> env.prod - echo "AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY" >> env.prod - echo "AWS_REGION_CODE=$AWS_REGION_CODE" >> env.prod - echo "AWS_S3_BUCKET_NAME=$AWS_S3_BUCKET_NAME" >> env.prod - echo "DB_HOST=$DB_HOST" >> env.prod - echo "DB_PORT=$DB_PORT" >> env.prod - echo "DB_NAME=$DB_NAME" >> env.prod - echo "DB_USER=$DB_USER" >> env.prod - echo "REDIS_HOST=$REDIS_HOST" >> env.prod - echo "REDIS_PORT=$REDIS_PORT" >> env.prod - echo "DB_PASSWORD=$DB_PASSWORD" >> env.prod - echo "JWT_SECRET=$JWT_SECRET" >> env.prod - echo "GOOGLE_EMAIL=$GOOGLE_EMAIL" >> env.prod - echo "GOOGLE_APP_PASSWORD=$GOOGLE_APP_PASSWORD" >> env.prod - - docker stop myapp || true - docker rm myapp || true - docker rmi -f $(docker images -aq) - aws ecr get-login-password --region $AWS_REGION_CODE | docker login --username AWS --password-stdin $ECR_REGISTRY - docker pull $ECR_REGISTRY/$ECR_REPOSITORY:latest - docker run -d --env-file ./env.prod -p 80:8080 --name myapp $ECR_REGISTRY/$ECR_REPOSITORY:latest - - - name: Check Container Status - uses: appleboy/ssh-action@v1.0.3 + task-definition: task-definition.json + container-name: ${{vars.AWS_ECS_CONTAINER_NAME}} + image: ${{ steps.build-image.outputs.image }} + + - name: Deploy to ECS + uses: aws-actions/amazon-ecs-deploy-task-definition@v1 with: - host: ${{ secrets.EC2_HOST }} - username: ${{ secrets.EC2_USERNAME }} - key: ${{ secrets.EC2_SSH_PRIVATE_KEY }} - port: ${{ secrets.EC2_SSH_PORT }} - script: | - if docker ps | grep -w "myapp"; then - echo "Container 'myapp' is running." - else - echo "Server check: Container 'myapp' is not running." - docker logs myapp - exit 1 - fi + cluster: ${{vars.AWS_ECS_CLUSTER_NAME}} + service: ${{vars.AWS_ECS_SERVICE_NAME}} + task-definition: ${{ steps.task-def.outputs.task-definition }} + wait-for-service-stability: true diff --git a/build.gradle b/build.gradle index 8317247e..bd66a645 100644 --- a/build.gradle +++ b/build.gradle @@ -46,6 +46,7 @@ dependencies { implementation 'org.springframework.boot:spring-boot-starter-validation' implementation 'org.springframework.boot:spring-boot-starter-mail' implementation 'org.springframework.boot:spring-boot-starter-websocket' + implementation 'org.springframework.boot:spring-boot-starter-actuator' compileOnly 'org.projectlombok:lombok' developmentOnly 'org.springframework.boot:spring-boot-devtools' runtimeOnly 'com.mysql:mysql-connector-j' diff --git a/src/main/java/com/dife/api/config/AWSConfig.java b/src/main/java/com/dife/api/config/AWSConfig.java index 36380161..900a6f12 100644 --- a/src/main/java/com/dife/api/config/AWSConfig.java +++ b/src/main/java/com/dife/api/config/AWSConfig.java @@ -4,8 +4,8 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Profile; -import software.amazon.awssdk.auth.credentials.AwsBasicCredentials; import software.amazon.awssdk.auth.credentials.AwsSessionCredentials; +import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider; import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider; import software.amazon.awssdk.regions.Region; import software.amazon.awssdk.services.s3.S3Client; @@ -15,10 +15,10 @@ @Profile("!test") public class AWSConfig { - @Value("${spring.aws.access-key}") + @Value("${spring.aws.access-key:#{null}") private String accessKey; - @Value("${spring.aws.secret-key}") + @Value("${spring.aws.secret-key:#{null}") private String secretKey; @Value("${spring.aws.session-token:#{null}}") @@ -42,14 +42,14 @@ public S3Client S3BucketWithSessionToken() { @Profile("!local") public S3Client S3BucketWithoutSessionToken() { return S3Client.builder() - .credentialsProvider( - StaticCredentialsProvider.create(AwsBasicCredentials.create(accessKey, secretKey))) + .credentialsProvider(DefaultCredentialsProvider.create()) .region(Region.of(awsRegion)) .build(); } @Bean - public S3Presigner presigner() { + @Profile("local") + public S3Presigner presignerWithSessionToken() { return S3Presigner.builder() .credentialsProvider( StaticCredentialsProvider.create( @@ -57,4 +57,13 @@ public S3Presigner presigner() { .region(Region.of(awsRegion)) .build(); } + + @Bean + @Profile("!local") + public S3Presigner presigner() { + return S3Presigner.builder() + .credentialsProvider(DefaultCredentialsProvider.create()) + .region(Region.of(awsRegion)) + .build(); + } } diff --git a/src/main/java/com/dife/api/config/SecurityConfig.java b/src/main/java/com/dife/api/config/SecurityConfig.java index 3d1bb4c6..9fbab93f 100644 --- a/src/main/java/com/dife/api/config/SecurityConfig.java +++ b/src/main/java/com/dife/api/config/SecurityConfig.java @@ -51,6 +51,7 @@ public SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Excepti "/api/members/refresh-token", "/api/members/change-password", "/api/members/login", + "/health", "/ws/**") .permitAll(); requests.requestMatchers("/api/**").authenticated(); diff --git a/src/main/java/com/dife/api/jwt/JWTFilter.java b/src/main/java/com/dife/api/jwt/JWTFilter.java index c5c28eb7..798db233 100644 --- a/src/main/java/com/dife/api/jwt/JWTFilter.java +++ b/src/main/java/com/dife/api/jwt/JWTFilter.java @@ -78,6 +78,7 @@ private boolean isExemptPath(String servletPath) { return servletPath.startsWith("/api/members/register") || servletPath.equals("/api/members/change-password") || servletPath.equals("/api/members/login") + || servletPath.equals("/health") || servletPath.startsWith("/swagger-ui/") || servletPath.startsWith("/api/v1/api-docs") || servletPath.startsWith("/ws") diff --git a/src/main/resources/application-local.yml b/src/main/resources/application-local.yml index 7bfd4c3f..1a231c5f 100644 --- a/src/main/resources/application-local.yml +++ b/src/main/resources/application-local.yml @@ -8,4 +8,6 @@ spring: ddl-auto: create aws: + access-key: ${AWS_ACCESS_KEY_ID} + secret-key: ${AWS_SECRET_ACCESS_KEY} session-token: ${AWS_SESSION_TOKEN} \ No newline at end of file diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index f9fd017c..5af7c820 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -25,8 +25,6 @@ spring: auth: true aws: - access-key: ${AWS_ACCESS_KEY_ID} - secret-key: ${AWS_SECRET_ACCESS_KEY} region: ${AWS_REGION_CODE} bucket-name: ${AWS_S3_BUCKET_NAME} @@ -38,6 +36,13 @@ spring: jwt: secret: ${JWT_SECRET} +management: + health: + mail: + enabled: false + endpoints: + web: + base-path: / springdoc: swagger-ui: