diff --git a/.github/workflows/develop.yml b/.github/workflows/develop.yml new file mode 100644 index 0000000..78e273a --- /dev/null +++ b/.github/workflows/develop.yml @@ -0,0 +1,106 @@ +name: CI/CD using github actions & docker + +on: + pull_request: + branches: [ "develop" ] + push: + branches: [ "develop" ] + workflow_dispatch: + +jobs: + CI-CD: + # Operating system - ubuntu-latest + runs-on: ubuntu-latest + permissions: + contents: read + + steps: + # Checkout - 가상 머신에 체크아웃(저장소 코드 체크아웃) + - name: Checkout code + uses: actions/checkout@v3 + + # JDK setting - JDK 17 설정 + - name: Set up JDK 17 + uses: actions/setup-java@v3 + with: + java-version: '17' + distribution: 'corretto' + + # gradle caching - 빌드 시간 향상 + - name: Gradle Caching + uses: actions/cache@v3 + with: + path: | + ~/.gradle/caches + ~/.gradle/wrapper + key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} + restore-keys: | + ${{ runner.os }}-gradle- + + # gradle build - 테스트 없이 gradle 빌드 + - name: Build with Gradle + run: | + chmod +x gradlew + ./gradlew clean build -x test + shell: bash + + # Set up Docker Buildx - Docker Buildx 설치 + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v2.9.1 + + - name: Docker Image Build + uses: docker/build-push-action@v5 + with: + context: . + dockerfile: Dockerfile + push: false + tags: ${{ secrets.DOCKER_USERNAME }}/dearnote:latest + + # Log in to Docker Hub - Docker Hub 로그인 + - name: Log in to Docker Hub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_TOKEN }} + + # Docker image 푸시 + - name: Docker Push + uses: docker/build-push-action@v5 + with: + context: . + dockerfile: Dockerfile + push: true + tags: ${{ secrets.DOCKER_USERNAME }}/dearnote:latest + + ## deploy to develop + - name: Deploy to dev + uses: appleboy/ssh-action@master + with: + host: ${{ secrets.EC2_HOST }} # EC2 퍼블릭 IPv4 DNS + username: ${{ secrets.EC2_USERNAME }} # ec-user + key: ${{ secrets.EC2_PRIVATE_KEY }} + port: 22 + script: | + # Docker 네트워크가 존재하지 않으면 생성 + if [ -z "$(sudo docker network ls --filter name=${{ secrets.DOCKER_NETWORK }} -q)" ]; then + sudo docker network create ${{ secrets.DOCKER_NETWORK }} + fi + + sudo docker pull ${{ secrets.DOCKER_USERNAME }}/dearnote:latest + + # 기존 컨테이너 중지 및 제거 + EXISTING_CONTAINER_ID=$(sudo docker ps -q -f "publish=8080" -f "status=running") # 현재 실행 중이며 8080 포트를 사용하는 컨테이너의 ID + if [ ! -z "$EXISTING_CONTAINER_ID" ]; then + sudo docker stop $EXISTING_CONTAINER_ID + sudo docker rm $EXISTING_CONTAINER_ID + fi + + EXISTING_CONTAINER_ID=$(sudo docker ps -q -f "publish=8080" -f "status=exited") # 8080 포트를 사용하지만 중지된 컨테이너의 ID + if [ ! -z "$EXISTING_CONTAINER_ID" ]; then + sudo docker rm $EXISTING_CONTAINER_ID + fi + + # 상태가 exited인 모든 컨테이너를 제거 + sudo docker rm $(sudo docker ps --filter 'status=exited' -a -q) + sudo docker run -d --env-file ~/.env --name dearnote -p 8080:8080 --net ${{secrets.DOCKER_NETWORK}} -e TZ=Asia/Seoul ${{ secrets.DOCKER_USERNAME }}/dearnote:latest + sudo docker image prune -a -f \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..a5344e8 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,9 @@ +FROM openjdk:17-jdk + +RUN ln -snf /usr/share/zoneinfo/Asia/Seoul /etc/localtime + +COPY ./build/libs/*.jar app.jar + +ENTRYPOINT ["java", "-jar", "-Dspring.profiles.active=prod", "app.jar"] + + diff --git a/build.gradle b/build.gradle index 20786ba..1d2cc67 100644 --- a/build.gradle +++ b/build.gradle @@ -30,6 +30,7 @@ dependencies { annotationProcessor 'org.projectlombok:lombok' testImplementation 'org.springframework.boot:spring-boot-starter-test' testRuntimeOnly 'org.junit.platform:junit-platform-launcher' + runtimeOnly 'com.mysql:mysql-connector-j' } tasks.named('test') { diff --git a/src/main/resources/application-local.yml b/src/main/resources/application-local.yml new file mode 100644 index 0000000..1e4e45f --- /dev/null +++ b/src/main/resources/application-local.yml @@ -0,0 +1,19 @@ +spring: + datasource: + url: jdbc:mysql://localhost:3306/mydb + username: ${LOCAL_DB_USERNAME} + password: ${LOCAL_DB_PASSWORD} + driver-class-name: com.mysql.cj.jdbc.Driver + sql: + init: + mode: never + jpa: + properties: + hibernate: + dialect: org.hibernate.dialect.MySQL8Dialect + show_sql: true + format_sql: true + use_sql_comments: true + hbm2ddl: + auto: create + default_batch_fetch_size: 1000 \ No newline at end of file diff --git a/src/main/resources/application-prod.yml b/src/main/resources/application-prod.yml new file mode 100644 index 0000000..2345a57 --- /dev/null +++ b/src/main/resources/application-prod.yml @@ -0,0 +1,13 @@ +spring: + datasource: + url: jdbc:mysql://${PROD_DB_HOST}:3306/mydb + username: ${PROD_DB_USERNAME} + password: ${PROD_DB_PASSWORD} + driver-class-name: com.mysql.cj.jdbc.Driver + jpa: + show-sql: true + properties: + hibernate: + dialect: org.hibernate.dialect.MySQLDialect + hibernate: + ddl-auto: create \ No newline at end of file diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties deleted file mode 100644 index 1b93141..0000000 --- a/src/main/resources/application.properties +++ /dev/null @@ -1 +0,0 @@ -spring.application.name=dearnote diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml new file mode 100644 index 0000000..ef46c2a --- /dev/null +++ b/src/main/resources/application.yml @@ -0,0 +1,3 @@ +spring: + profiles: + active: local \ No newline at end of file