Code Monkey home page Code Monkey logo

be-java-cafe-max's Introduction

Spring Cafe

목차

  1. 프로젝트 설명
  2. cafe 기능
  3. 아키텍처
  4. 데모 영상
  5. 문서 링크
  6. Docker
  7. Wiki

1. 프로젝트 설명

1.1 프로젝트 기획

질문 게시글을 올리기 위한 게시판

1.2 프로젝트 목적

  • 스프링 프레임워크 원리 이해
  • 로그인 및 회원가입 구현으로 인한 세션 이해
  • JDBC를 이용한 데이터베이스 연결
  • 게시판 및 댓글에 대한 이해
  • 페이지네이션 구현으로 인한 원리 이해

2. cafe 기능

  • 회원가입 및 로그인
  • 회원 정보 관리
  • 게시글 글쓰기
  • 게시글 관리
  • 댓글 관리

3. 아키텍처

img.png

기술스택

  • Spring Boot
  • Thymeleaf
  • MySQL

4. 데모 영상

img.png

5. 문서 링크

6. Docker

be-java-cafe-max $ ./gradlew clean build
be-java-cafe-max $ docker-compose up -d --build

7. Wiki

be-java-cafe-max's People

Contributors

yonghwankim-dev avatar honux77 avatar kimnayeon0108 avatar naneun avatar

be-java-cafe-max's Issues

[BE] env 파일 시크릿으로 넣기

  • Github Action 수행시 시크릿 값으로 넣은 env 값을 CI 수행시 파일을 만들어 넣습니다.
  • env 파일의 값은 로컬에서 gitignore 되어 있습니다.

[BE] CI/CD permission denied 문제 해결

문제 배경

Run appleboy/ssh-action@master
  with:
    host: ***
    username: ec[2](https://github.com/yonghwankim-dev/be-java-cafe-max/actions/runs/5430382845/jobs/9877274493#step:9:2)-user
    key: ***
    script: docker pull ***/be-java-cafe-max:latest
  docker stop $(docker ps -a -q)
  docker run -d --log-driver=syslog -p 8080:8080 ***/be-java-cafe-max:latest
  docker rm $(docker ps --filter 'status=exited' -a -q)
  docker image prune -a -f
  
    port: 22
    timeout: [3](https://github.com/yonghwankim-dev/be-java-cafe-max/actions/runs/5430382845/jobs/9877274493#step:9:3)0s
    command_timeout: 10m
    proxy_port: 22
    proxy_timeout: 30s
  env:
    JAVA_HOME: /opt/hostedtoolcache/Java_Temurin-Hotspot_jdk/11.0.19-7/x6[4](https://github.com/yonghwankim-dev/be-java-cafe-max/actions/runs/5430382845/jobs/9877274493#step:9:4)
    JAVA_HOME_11_X64: /opt/hostedtoolcache/Java_Temurin-Hotspot_jdk/11.0.19-7/x64
/usr/bin/docker run --name a6c8c84478a17774940f4b[5](https://github.com/yonghwankim-dev/be-java-cafe-max/actions/runs/5430382845/jobs/9877274493#step:9:5)2138cfde0[6](https://github.com/yonghwankim-dev/be-java-cafe-max/actions/runs/5430382845/jobs/9877274493#step:9:6)88e0_9b54[7](https://github.com/yonghwankim-dev/be-java-cafe-max/actions/runs/5430382845/jobs/9877274493#step:9:7)6 --label 2a6c[8](https://github.com/yonghwankim-dev/be-java-cafe-max/actions/runs/5430382845/jobs/9877274493#step:9:8)c --workdir /github/workspace --rm -e "JAVA_HOME" -e "JAVA_HOME_11_X64" -e "INPUT_HOST" -e "INPUT_USERNAME" -e "INPUT_KEY" -e "INPUT_SCRIPT" -e "INPUT_PORT" -e "INPUT_PASSPHRASE" -e "INPUT_PASSWORD" -e "INPUT_SYNC" -e "INPUT_USE_INSECURE_CIPHER" -e "INPUT_CIPHER" -e "INPUT_TIMEOUT" -e "INPUT_COMMAND_TIMEOUT" -e "INPUT_KEY_PATH" -e "INPUT_FINGERPRINT" -e "INPUT_PROXY_HOST" -e "INPUT_PROXY_PORT" -e "INPUT_PROXY_USERNAME" -e "INPUT_PROXY_PASSWORD" -e "INPUT_PROXY_PASSPHRASE" -e "INPUT_PROXY_TIMEOUT" -e "INPUT_PROXY_KEY" -e "INPUT_PROXY_KEY_PATH" -e "INPUT_PROXY_FINGERPRINT" -e "INPUT_PROXY_CIPHER" -e "INPUT_PROXY_USE_INSECURE_CIPHER" -e "INPUT_SCRIPT_STOP" -e "INPUT_ENVS" -e "INPUT_ENVS_FORMAT" -e "INPUT_DEBUG" -e "HOME" -e "GITHUB_JOB" -e "GITHUB_REF" -e "GITHUB_SHA" -e "GITHUB_REPOSITORY" -e "GITHUB_REPOSITORY_OWNER" -e "GITHUB_REPOSITORY_OWNER_ID" -e "GITHUB_RUN_ID" -e "GITHUB_RUN_NUMBER" -e "GITHUB_RETENTION_DAYS" -e "GITHUB_RUN_ATTEMPT" -e "GITHUB_REPOSITORY_ID" -e "GITHUB_ACTOR_ID" -e "GITHUB_ACTOR" -e "GITHUB_TRIGGERING_ACTOR" -e "GITHUB_WORKFLOW" -e "GITHUB_HEAD_REF" -e "GITHUB_BASE_REF" -e "GITHUB_EVENT_NAME" -e "GITHUB_SERVER_URL" -e "GITHUB_API_URL" -e "GITHUB_GRAPHQL_URL" -e "GITHUB_REF_NAME" -e "GITHUB_REF_PROTECTED" -e "GITHUB_REF_TYPE" -e "GITHUB_WORKFLOW_REF" -e "GITHUB_WORKFLOW_SHA" -e "GITHUB_WORKSPACE" -e "GITHUB_ACTION" -e "GITHUB_EVENT_PATH" -e "GITHUB_ACTION_REPOSITORY" -e "GITHUB_ACTION_REF" -e "GITHUB_PATH" -e "GITHUB_ENV" -e "GITHUB_STEP_SUMMARY" -e "GITHUB_STATE" -e "GITHUB_OUTPUT" -e "RUNNER_OS" -e "RUNNER_ARCH" -e "RUNNER_NAME" -e "RUNNER_ENVIRONMENT" -e "RUNNER_TOOL_CACHE" -e "RUNNER_TEMP" -e "RUNNER_WORKSPACE" -e "ACTIONS_RUNTIME_URL" -e "ACTIONS_RUNTIME_TOKEN" -e "ACTIONS_CACHE_URL" -e GITHUB_ACTIONS=true -e CI=true -v "/var/run/docker.sock":"/var/run/docker.sock" -v "/home/runner/work/_temp/_github_home":"/github/home" -v "/home/runner/work/_temp/_github_workflow":"/github/workflow" -v "/home/runner/work/_temp/_runner_file_commands":"/github/file_commands" -v "/home/runner/work/be-java-cafe-max/be-java-cafe-max":"/github/workspace" 2a6c8c:84478a17774[9](https://github.com/yonghwankim-dev/be-java-cafe-max/actions/runs/5430382845/jobs/9877274493#step:9:9)40f4b52138cfde0688e0
======CMD======
docker pull ***/be-java-cafe-max:latest
docker stop $(docker ps -a -q)
docker run -d --log-driver=syslog -p 8080:8080 ***/be-java-cafe-max:latest
docker rm $(docker ps --filter 'status=exited' -a -q)
docker image prune -a -f

======END======
err: Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Post "http://%2Fvar%2Frun%2Fdocker.sock/v1.24/images/create?fromImage=***%2Fbe-java-cafe-max&tag=latest": dial unix /var/run/docker.sock: connect: permission denied
err: Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Get "http://%2Fvar%2Frun%2Fdocker.sock/v1.24/containers/json?all=1": dial unix /var/run/docker.sock: connect: permission denied
err: "docker stop" requires at least 1 argument.
err: See 'docker stop --help'.
err: Usage:  docker stop [OPTIONS] CONTAINER [CONTAINER...]
err: Stop one or more running containers
err: docker: Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Post "http://%2Fvar%2Frun%2Fdocker.sock/v1.24/containers/create": dial unix /var/run/docker.sock: connect: permission denied.
err: See 'docker run --help'.
err: Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Get "http://%2Fvar%2Frun%2Fdocker.sock/v1.24/containers/json?all=1&filters=%7B%22status%22%3A%7B%22exited%22%3Atrue%7D%7D": dial unix /var/run/docker.sock: connect: permission denied
err: "docker rm" requires at least 1 argument.
err: See 'docker rm --help'.
err: Usage:  docker rm [OPTIONS] CONTAINER [CONTAINER...]
err: Remove one or more containers
err: Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Post "http://%2Fvar%2Frun%2Fdocker.sock/v1.24/images/prune?filters=%7B%22dangling%22%3A%7B%22false%22%3Atrue%7D%7D": dial unix /var/run/docker.sock: connect: permission denied
2023/07/01 [12](https://github.com/yonghwankim-dev/be-java-cafe-max/actions/runs/5430382845/jobs/9877274493#step:9:12):49:12 Process exited with status 1

문제 원인

  • docker 명령어 실행시 권한이 없어서 입니다.

해결 방법

  • /var/run/docker.sock 파일의 권한을 666으로 변경하여 그룹 내 다른 사용자도 접근 가능하게 변경합니다.

workflow.yml 파일의 내용중 도커 작업에서 SSH 접속한 EC2에서 docker 명령어를 호출하기 전에 /var/run/docker.sock의 실행권한을 666으로 변경합니다.

sudo chmod 666 /var/run/docker.sock
    # 배포
    - name: Deploy
      uses: appleboy/ssh-action@master
      with:
        host: ${{ secrets.HOST }} # EC2 인스턴스 퍼블릭 DNS
        username: ec2-user
        key: ${{ secrets.PRIVATE_KEY }} # pem 키
        # 도커 작업
        script: |
          sudo chmod 666 /var/run/docker.sock
          docker pull ${{ secrets.DOCKER_USERNAME }}/be-java-cafe-max:latest
          docker stop $(docker ps -a -q)
          docker run -d --log-driver=syslog -p 8080:8080 ${{ secrets.DOCKER_USERNAME }}/be-java-cafe-max:latest
          docker rm $(docker ps --filter 'status=exited' -a -q)
          docker image prune -a -f

[BE] docker-compose에 mysql 컨테이너 정보 추가

  • docker-compsoe에 mysql 컨테이너 정보를 추가
  • mysql 컨테이너 추가가 성공하면 mysql 컨테이너 정보를 기반으로 스프링부트 앱의 application-prod.properties에 삽입할 MYSQL 정보 추가해야 합니다. HOST, USERNAME, PASSWORD, 데이터베이스 스키마명

현재문제

  • 스프링 부트 앱이 mysql에 데이터소스가 연결되지 않은 상태인것 같습니다.

[BE] EC2 인스턴스 시간 출력 형식 설정 문제

배경

EC2 인스턴스에서 시간을 출력할때 다음과 같이 출력됩니다.

$ date
Wed Jul  5 17:23:05 KST 2023

원인

EC2 인스턴스에서 설정된 시간 형식이 별도로 설정되어 있지 않기 때문입니다.

해결

date "+%Y-%m-%d %H:%M:%S"

[BE] 스프링 부트 서버 시간 UTC 문제

상황

  • EC2에서 서버 실행시 UTC 기준으로 시간이 출력됩니다.

원인

  • EC2 시간이 UTC 기준이기 때문입니다.

해결

# 루트로 로그인
$ sudo su - root

# 기존 타임존 삭제
$ sudo rm /etc/localtime

# 타임존 변경
$ sudo ln -s /usr/share/zoneinfo/Asia/Seoul /etc/localtime

# clock 파일 수정하여 영구 반영
$ sudo vim /etc/sysconfig/clock
ZONE="Asia/Seoul"
UTC=true

# 시간 변경 확인
$ date

[BE] aappleboy/scp-action@master 복사 문제

배경

스프링부트 앱을 서버 배포하기 위해서 Github Actions, EC2 인스턴스를 이용하여 CI/CD 파이프 라인을 구축하려고 했습니다.

Github Actions를 수행하기 위해서 .github/workflows/cicd.yml 파일에 CI를 수행하기 위한 작업들을 정의하였습니다.

이 작업들 중에서 외부에 노출시키고 싶지 않은 설정 파일(데이터베이스 정보 등)들을 CI 과정에서 파일을 생성하여 시크릿 값으로 넣는 작업들이 있습니다.

다음은 문제가 발생한 워크플로우 파일 내용입니다.

# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.
# This workflow will build a Java project with Gradle and cache/restore any dependencies to improve the workflow execution time
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-java-with-gradle

name: Java CI with Gradle

on:
  push:
    branches: [ "네모네모", "main", "infra/cicd" ]
  pull_request:
    branches: [ "네모네모", "main", "infra/cicd" ]

permissions:
  contents: read

jobs:
  build-image:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      ## JDK 설정
      - name: Set up JDK 11
        uses: actions/setup-java@v3
        with:
          java-version: '11'
          distribution: 'temurin'
      # application-prod.properties 파일을 생성하여 설정
      - name: make application-prod.properties
        run: |
          cd ./src/main/resources
          touch ./application-prod.properties
          echo "${{ secrets.APPLICATION_PROD }}" > ./application-prod.properties
          ls -l
      # .env 파일을 생성하여 설정
      - name: make .env
        run: |
          touch ./.env
          echo "${{ secrets.DATASOURCE_ENV }}" > ./.env
          ls -l
      - name: make mysql config file
        run: |
          cd ./src/main/resources
          mkdir -p ./db/mysql/conf.d
          mkdir -p ./db/mysql/initdb.d
          touch ./db/mysql/conf.d/my.cnf
          touch ./db/mysql/initdb.d/init.sql
          echo "${{ secrets.MYSQL_CNF }}" > ./db/mysql/conf.d/my.cnf
          echo "${{ secrets.MYSQL_INIT }}" > ./db/mysql/initdb.d/init.sql
          ls -l ./db/mysql/conf.d/
          ls -l ./db/mysql/initdb.d/
      # gradlew 실행을 위해서 실행 권한을 부여
      - name: Grant execute permission for gradlew
        run: chmod +x gradlew
      # Gradle을 이용하여 빌드 수행
      - name: Build with Gradle
        run: ./gradlew build -x test
      # 도커 이미지 빌드하여 도커 허브에 푸시하기
      - name: Docker build
        run: |
          docker login -u ${{ secrets.DOCKER_USERNAME }} -p ${{ secrets.DOCKER_PASSWORD }}
          docker build -t app .
          docker tag app ${{ secrets.DOCKER_USERNAME}}/be-java-cafe-max:latest
          docker push ${{ secrets.DOCKER_USERNAME }}/be-java-cafe-max:latest
  cd-pipeline:
    needs: build-image
    name: continuos deploy
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@master
      - name: print pwd, ls
        run: |
          pwd
          ls -l
      - name: copy datasource env file via ssh password
        uses: appleboy/scp-action@master
        with:
          host: ${{ secrets.HOST }}
          username: ec2-user
          key: ${{ secrets.PRIVATE_KEY }}
          port: 22
          source: ".env"
          target: "/home/ec2-user/"
      - name: copy file via ssh password
        uses: appleboy/scp-action@master
        with:
          host: ${{ secrets.HOST }}
          username: ec2-user
          key: ${{ secrets.PRIVATE_KEY }}
          port: 22
          source: "docker-compose.yml"
          target: "/home/ec2-user/"
      - name: executing remote ssh commands using password
        uses: appleboy/ssh-action@master
        with:
          host: ${{ secrets.HOST }} # EC2 인스턴스 퍼블릭 DNS
          username: ec2-user
          key: ${{ secrets.PRIVATE_KEY }} # pem 키
          port: 22
          script: |
            sudo chmod 666 /var/run/docker.sock
            docker stop $(docker ps -a -q) 2>/dev/null
            docker-compose pull && docker-compose up -d

문제가 발생한 부분은 다음 부분이었습니다.

  cd-pipeline:
    needs: build-image
    name: continuos deploy
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@master
      # ...
      - name: copy datasource env file via ssh password
        uses: appleboy/scp-action@master
        with:
          host: ${{ secrets.HOST }}
          username: ec2-user
          key: ${{ secrets.PRIVATE_KEY }}
          port: 22
          source: ".env"
          target: "/home/ec2-user/"

에러 내용은 다음과 같았습니다.

Run appleboy/scp-action@master
  with:
    host: ***
    username: ec[2](https://github.com/yonghwankim-dev/be-java-cafe-max/actions/runs/5461538057/jobs/9939705852#step:6:2)-user
    key: ***
    port: 22
    source: .env
    target: /home/ec2-user/
    timeout: [3](https://github.com/yonghwankim-dev/be-java-cafe-max/actions/runs/5461538057/jobs/9939705852#step:6:3)0s
    command_timeout: 10m
    use_insecure_cipher: false
    rm: false
    debug: false
    strip_components: 0
    overwrite: false
    tar_dereference: false
    tar_exec: tar
    proxy_port: 22
    proxy_timeout: 30s
    proxy_use_insecure_cipher: false
# ...
tar: empty archive
tar all files into /tmp/oKKbSiNQNq.tar.gz
exit status 1

에러의 내용은 EC2에 업로드할 대상 파일이 없다는 것이었습니다.

원인

  • 본인은 Github Actions에서 워크플로우 단계를 2단계로 구분하였습니다. 첫번째 단계는 build-image, 두번째 단계는 continous deploy였습니다.
  • 그런데 첫번째 단계 build-image에서 명령어로 생성한 시크릿 파일들은 continous deploy 단계에서는 공유가 되지 않는 것이었습니다. 왜냐하면 첫번째 단계에서 이어지는 것이 아닌 푸시한 커밋을 기준으로 새로운 브랜치를 생성하여 수행하기 때문입니다.

image

  • 실제로 continous deploy 단계에서 에러가 발생하기 이전 스텝에서 ls 명령어로 .env 파일이 있는지 확인해봤지만 없는 것을 확인할 수 있었습니다.

해결

  • build-image, continous deploy 단계를 하나의 단계로 통합하여 해결하였습니다.

해결한 워크플로우 링크를 참고해주세요.

개선점

  • build-image, continous deploy 단계를 하나의 단계로 통합하여 해결할 수도 있지만 기존대로 각각의 단계로 나누고 continous deploy 단계에서 파일을 생성하는 스텝을 정의하여 EC2에 .env 파일을 복사하여 업로드하는 방법도 있습니다.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.