
๐งฉ SpringBoot
โ๏ธ SpringBoot jar ํ์ผ ์์ฑํ๊ธฐ
๐ง jar file์ด ๋ญ์ฃ ?
Java ARchive Files๋ฅผ ์๋ฏธํ๋ฉฐ, ์ผ์ข ์ ์๋ฐ ํ๋ก์ ํธ ์์ถ ํ์ผ์ ๋ปํ๊ธฐ ๋๋ฌธ์, zip๊ณผ ์ ์ฌํ๋ค๊ณ ์ดํดํ์๋ฉด ์ข์ต๋๋ค..jar์ ํ์ฅ์๋ฅผ ๊ฐ์ง ํ์ผ์ ํ๋ก์ ํธ์์ ๊ฐ์ฅ ์ค์ํ ์ปดํ์ผ๋.classํ์ผ์ ๊ฐ์ง๊ณ ์๊ฒ ๋ฉ๋๋ค.- ์ฐ๋ฆฌ๊ฐ ์คํ๋ง๋ถํธ๋ก ๊ฐ๋ฐ์ ํ๊ฒ ๋๋ฉด,
build.gradle๋ฑ์ ํ์ผ์ ์ฌ๋ฌ๊ฐ์ง ์์กด์ฑ์ ์ค์ ํ๊ฒ ๋ฉ๋๋ค.- ์ด๋ jar ํ์ผ ๋ด๋ถ์ ์ด ์์กด์ฑ์ ๋ชจ๋ ํฌํจ์ํค๊ธฐ ๋๋ฌธ์ ์ฝ๊ฒ ๋ฐฐํฌ์ ์ฌ์ฉํ ์ ์๋ ๊ฒ์ ๋๋ค.
- ์ถ์ฒ : [java] jar ํ์ผ์ด๋?
1. IntelliJ์ ์ค๋ฅธ์ชฝ ๋ > gradle > bulid ํด๋ ์ ๊ทผ
2. BootJar ๋๋ธ ํด๋ฆญ์ผ๋ก jar ํ์ผ ์์ฑ

3. Project > {ํ๋ก์ ํธ ์ต์์ ํด๋} > bulid > libs ํด๋ ๋ด๋ถ์ jar ํ์ผ์ ์์ฑ๋์๋์ง ํ์ธ

๐ ๋ง์ฝ jar ํ์ผ์ด
....jar์ ํจ๊ป...plain.jar๊ฐ ์ ์ฅ๋์์ ๊ฒฝ์ฐ์๋ ๋น๋ ์์ ์๋ฌ๊ฐ ๋ฐ์ํ ์ ์์ด์!
- ํด๊ฒฐ ๋ฐฉ๋ฒ : ์ฐ์ ์์ฑํ jar ํ์ผ 2๊ฐ๋ฅผ ์ญ์ ํ๊ณ ,
build.gradle์ ๋ค์์ ํฌํจํด์ค๋ค์ ๋ค์ jar ํ์ผ์ ๋ง๋ค์ด์ฃผ๊ธฐ- ์ถ์ฒ : Plain jar vs Executable jar(feat. plain jar ์์ฑ ๋ฐฉ์ง)
...
jar {
enabled = false
}
...
{ํจํค์ง๋ช
}-0.0.1-SNAPSHOT.jar ํํ์ jar ํ์ผ์ ์์ฑํ ์ ์์ต๋๋ค.๐ณ Docker
โ๏ธ Mac์ Docker ์ค์นํ๊ธฐ
1. Docker ํํ์ด์ง์์ dmg ๋ค์ด๋ก๋
Docker Desktop Mac With Apple sillicon ํด๋ฆญํด ๋ค์ด๋ก๋ ํ์ต๋๋ค.
2. ๋ค์ด๋ฐ์ dmg ์ด์ด์ Applications์ ์ถ๊ฐํ๊ธฐ

3. Terminal์์ Docker ๋ฒ์ ํ์ธ
docker -v
๐๏ธ Dockerfile
- Dockerfile์ ํตํด์ jar ํ์ผ์ ์ฌ๋ฆฌ๊ณ ์คํํ ์์
IntelliJ > {ํ๋ก์ ํธ ์ต์์ ํด๋}์ Dockerfile ๋ง๋ค๊ธฐ

๋ค์ ๋ด์ฉ ์์ฑํ๊ณ ์ ์ฅํ๊ธฐ

๋ค์ ๋ด์ฉ์ ๊ฐ์ธ ์ค์ ์ด๋ฏ๋ก 4๋ฒ์ผ๋ก ๋์ด๊ฐ์ฃผ์ธ์!
(3. ํ๊ฒฝ๋ณ์ ํธ์งํ๊ธฐ)
- jar ํ์ผ์ด ํ๊ฒฝ๋ณ์๋ฅผ ์ฝ์ด๋ค์ด์ง ๋ชปํ๋ ๋ฌธ์
error: unable to access jarfile /build/libs/parking-0.0.1-snapshot.jar
-> ํด๊ฒฐ ๋ฐฉ๋ฒ : ๋ชจ๋ ํ๊ฒฝ๋ณ์๋ฅผ ํ๋์ฝ๋ฉํจ.
Docker์ฉ ParkingServer ํ๊ฒฝ๋ณ์ ํธ์ง(๋น๊ณต๊ฐ)
โ๏ธ BootJar ํ๋ฒ ๋ ๋๋ธํด๋ฆญํด์ ๋น๋ํด์ฃผ๊ธฐ
IntellJ์ ํฐ๋ฏธ๋์์ ๋ค์ ์คํ
๋์ปค๋ฅผ ๋น๋(์ด๋ฏธ์ง ์์ฑ)
docker build -t hayannn/parking_server:1 ./
๋์ปค ์ปจํ
์ด๋ ์คํ
docker run -it -p8080:8080 hayannn/parking_server:1
์ด๋ฏธ์ง ํ์ธ

์ปจํ
์ด๋ ํ์ธ

๋น๋ ์ฑ๊ณต!


ํฌ๋กฌ์์ ํ์ธ(ํ์ํ ๊ฒฝ์ฐ)

-> ์ ๋ฆฌ๋ค์ด๋ ํ
๋จ ํ์ธ!



docker-compose.yml
version: '3'
services:
web:
container_name: web
image: {docker username}/{docker ์ด๋ฏธ์ง ์ด๋ฆ}
expose:
- "8080"
ports:
- "3000:8080"
ํ์ฌ ์ ํฌ๋ 3000๋ฒ ํฌํธ๋ฅผ ํตํด ์ธ๋ถ์์ ์๋ฒ API์ ์ ๊ทผํ๊ธฐ ๋๋ฌธ์ expose ์ค์ ์ ํด์ฃผ์์ต๋๋ค.
์ฐธ๊ณ ๋ ํผ๋ฐ์ค : ์ฝ๋ Push๋ก ๋ฐฐํฌ๊น์ง! Spring Boot + Github Actions + Docker
๊ทธ ๋ค์ Github Actions๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํด ์๋ก์ด ํจํค์ง๋ฅผ ๋ง๋ค์ด์ฃผ์ด์ผ ํฉ๋๋ค.
์ธํ
๋ฆฌ์ ์ด์์ ๋ฃจํธ ํด๋์ .github ํด๋๋ฅผ ๋ง๋ค๊ณ , ๊ทธ ์์ workflows ํด๋๋ฅผ ๋ง๋ค์ด ์ค๋๋ค.

๊ทธ ๋ค์ ~~~.yml ํ์ผ์ ๋ง๋ค์ด์ค ๋ค์, ๋ค์ ๋ด์ฉ์ ์์ฑํฉ๋๋ค.
์์ง commit ํ์ง ๋ง์ธ์!
์์) deploy.yml
name: CD with Gradle
on:
push:
branches: [ "์ฌ์ฉํ๊ณ ์ ํ๋ ๋ธ๋์น ์ด๋ฆ" ]
permissions:
contents: read
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: checkout
uses: actions/checkout@v3
- name: Set up JDK 17
uses: actions/setup-java@v3
with:
java-version: '17'
distribution: "adopt"
- name: Make application.yml
run: |
cd ./src/main/resources
touch ./application.yml
echo "${{ secrets.PROPERTIES }}" > ./application.yml
shell: bash
- name: Build with Gradle
run: |
chmod +x ./gradlew
./gradlew clean build -x test
- name: Docker build & push to docker repo
run: |
docker login -u ${{ secrets.DOCKER_USERNAME }} -p ${{ secrets.DOCKER_PASSWORD }}
docker build -f Dockerfile -t ${{ secrets.DOCKER_REPO }} .
docker push ${{ secrets.DOCKER_REPO }}
- name: Deploy to server
uses: appleboy/ssh-action@master
id: deploy
with:
host: ${{ secrets.HOST }}
username: ec2-user
key: ${{ secrets.KEY }}
envs: GITHUB_SHA
script: |
sudo docker rm -f $(docker ps -qa)
sudo docker pull ${{ secrets.DOCKER_REPO }}
docker-compose up -d
docker image prune -f
ํ๊ฒฝ๋ณ์๋ก ์ง์ ํ ๊ฐ๋ค์ ๋ค์ด๋ ํ
ํด์ฃผ๊ธฐ ์ํด ๊นํ๋ธ ๋ ํฌ์งํฐ๋ฆฌ > settings > Security > Actions์์ ๊ฐ ๊ฐ์ ๋ฃ์ด์ค๋๋ค.

DOCKER_PASSWORD : ๋์ปค ๋ก๊ทธ์ธ ์ ๋น๋ฐ๋ฒํธ
DOCKER_REPO : ๋์ปค์ ๋ ํฌ์งํฐ๋ฆฌ ์ด๋ฆ
DOCKER_USERNAME : ๋์ปค ๋ก๊ทธ์ธ ์ ์ด๋ฆ ๋๋ ์ด๋ฉ์ผ
HOST : AWS EC2 IP
KEY : AWS EC2 ์์ฑ ์ ์ฌ์ฉํ pem ํค
(pem ํค๋ฅผ ๋ฉ๋ชจ์ฅ ๋ฑ์ผ๋ก ์ด์ด ๋ด์ฉ์ ๋ชจ๋ ๋ณต์ฌ-๋ถ์ฌ๋ฃ๊ธฐ ํด์ฃผ์ด์ผ ํจ)
์ด์ ์์ ์์ฑํ ~~~.yml๋ฅผ commit&push ํด์ค๋๋ค.
on:
push:
branches: [ "์ฌ์ฉํ๊ณ ์ ํ๋ ๋ธ๋์น ์ด๋ฆ" ]
๋ค์๊ณผ ๊ฐ์ด ์ค์ ํด์ฃผ์๊ธฐ ๋๋ฌธ์, push ์์ Github Actions์์ ๊ฐ์งํ๊ณ ๋ฐฐํฌ๋ฅผ ์งํํ๊ฒ ๋ฉ๋๋ค!
๊นํ๋ธ ๋ ํฌ์งํฐ๋ฆฌ > Actions > All workflows์์ ์ํ๋ ์ปค๋ฐ ๊ธฐ๋ก์ ํด๋ฆญํด ํ์ธํฉ๋๋ค.
์์ธํ ๋ด์ฉ์ ์๋์ 2๊ฐ์ง ํธ๋ฌ๋ธ์ํ ์ผ๋ก ์๊ฐํ๋๋ก ํ๊ฒ ์ต๋๋ค.
๐ ์ฒซ๋ฒ์งธ ํธ๋ฌ๋ธ ์ํ
- ERROR: invalid tag "***/์ด๋ฏธ์ง์ด๋ฆ:ํ๊ทธ": invalid reference format

-> Docker์ ๋ก๊ทธ์ธ์ ์ฑ๊ณต์ ์ผ๋ก ๋์์ง๋ง, ์ค์ image:ํ๊ทธ๋ฅผ ํ์ธํ์ง ๋ชปํ๋ ๊ฒ์ผ๋ก ๋ณด๊ณ ํด๊ฒฐ์ ์ ์ฐพ์๋ณด์์ต๋๋ค.
์ด์ ์ deploy.yml ํ์ผ ์ผ๋ถ
- name: Docker build & push to docker repo
run: |
docker login -u ${{ secrets.DOCKER_USERNAME }} -p ${{ secrets.DOCKER_PASSWORD }}
docker build -f Dockerfile -t ${{ secrets.DOCKER_USERNAME }}/์ด๋ฏธ์ง์ด๋ฆ:ํ๊ทธ .
docker push ${{ secrets.DOCKER_USERNAME }}/์ด๋ฏธ์ง์ด๋ฆ:ํ๊ทธ
...
script: |
sudo docker rm -f $(docker ps -qa)
sudo docker pull ${{ secrets.DOCKER_USERNAME }}/์ด๋ฏธ์ง์ด๋ฆ:ํ๊ทธ
docker-compose up -d
docker image prune -f
๐ํด๊ฒฐ
/์ด๋ฏธ์ง์ด๋ฆ:ํ๊ทธ๋ถ๋ถ์ ๋ณด๋ฉด, ํ์ฌ ์ ํฌ๊ฐ ๋ถ๋ฌ์ค๊ณ ์ ํ๋ docker image์์ ๋งค์นญ์ด ์๋๋ ๋ฌธ์ ๊ฐ ๋ฐ์ํ ๊ฒ์ผ๋ก ํ๋จํ์ต๋๋ค.
๋ํ, ๊ทธ ์์ ${{ secrets.DOCKER_USERNAME }}์ ${{ secrets.DOCKER_REPO }}๋ก ์์ ํด์ฃผ์์ต๋๋ค.
๋ณ๊ฒฝ ํ deploy.yml
- name: Docker build & push to docker repo
run: |
docker login -u ${{ secrets.DOCKER_USERNAME }} -p ${{ secrets.DOCKER_PASSWORD }}
docker build -f Dockerfile -t ${{ secrets.DOCKER_REPO }} .
docker push ${{ secrets.DOCKER_REPO }}
- name: Deploy to server
uses: appleboy/ssh-action@master
id: deploy
with:
host: ${{ secrets.HOST }}
username: ec2-user
key: ${{ secrets.KEY }}
envs: GITHUB_SHA
script: |
sudo docker rm -f $(docker ps -qa)
sudo docker pull ${{ secrets.DOCKER_REPO }}
docker-compose up -d
docker image prune -f
๐ ๋๋ฒ์งธ ํธ๋ฌ๋ธ ์ํ
- ssh: handshake failed: ssh: unable to authenticate, attempted methods [none publickey], no supported methods remain
์ด์ ์ฑ๊ณต์ ์ผ๋ก Docker๋ฅผ ๋ถ๋ฌ์ค์ง๋ง, ์ด๋ฒ์๋ ์๋ฒ ์ ๋ณด๋ฅผ ๋ถ๋ฌ์ค๋๋ฐ์ ๋ฌธ์ ๊ฐ ๋ฐ์ํ์ต๋๋ค๐
์ด ๋ถ๋ถ์ ํด๊ฒฐ์ ์์ฃผ ๊ฐ๋จํ๋๋ฐ์!
์ ํฌ๋ ํ์ฌ ์
๋ฌด๋ฅผ ์ํด ๋ถ์ฌ๋ฐ์ EC2 ์๋ฒ์์ ์์
์ ํด์ผ ํ๋๋ฐ, ์ด EC2 ์๋ฒ๊ฐ Ubuntu๊ฐ ์๋ Amazon Linux 2์์ต๋๋ค.
๊ทธ๋ ๊ธฐ ๋๋ฌธ์ ๋ค์ ํ๋ฒ deploy.yml ํ์ผ์์ ์์ ์ด ํ์ํ์ต๋๋ค..!!
๋ณ๊ฒฝ ์ด์ deploy.yml ์ค ์๋ฒ์ ์ฐ๊ฒฐํ๋ "Deploy to server" ๋ถ๋ถ
- name: Deploy to server
uses: appleboy/ssh-action@master
id: deploy
with:
host: ${{ secrets.HOST }}
username: ubuntu
key: ${{ secrets.KEY }}
envs: GITHUB_SHA
script: |
sudo docker rm -f $(docker ps -qa)
sudo docker pull ${{ secrets.DOCKER_REPO }}
docker-compose up -d
docker image prune -f
๋ณ๊ฒฝ ์ด์ ์ yml์ ๋ณด๋ฉด, ๋ค์๊ณผ ๊ฐ์ด username์ด ubuntu๋ก ๋์ด์๋ ๊ฒ์ ํ์ธํ์ค ์ ์์ต๋๋ค.
์ด๊ฒ์ด ๋ฌธ์ ๊ฐ ๋๋ ์ด์ ๋ ubuntu๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ํ ์๋ฒ์ ๋ฌ๋ฆฌ amazon linux 2๋ ๊ธฐ๋ณธ ์ ์ ์ด๋ฆ์ด ec2-user์ด๊ธฐ ๋๋ฌธ์
๋๋ค.
๋ฐ๋ผ์, yml์ ํตํด AWS EC2 ์๋ฒ๊ฐ ์ฌ์ฉ์๋ฅผ ์ธ์ํ๊ธฐ ์ํด ์ด ๋ถ๋ถ์ ec2-user๋ก ๋ฐ๊ฟ์ฃผ์ด์ผ ํฉ๋๋ค!
์๋ฒ์ ๋ฐ๋ฅธ ์ ์ ์ ๋ํดํธ ์ด๋ฆ ์ฐพ๊ธฐ
๋ณ๊ฒฝ ํ
- name: Deploy to server
uses: appleboy/ssh-action@master
id: deploy
with:
host: ${{ secrets.HOST }}
username: ec2-user
key: ${{ secrets.KEY }}
envs: GITHUB_SHA
script: |
sudo docker rm -f $(docker ps -qa)
sudo docker pull ${{ secrets.DOCKER_REPO }}
docker-compose up -d
docker image prune -f

์ ์งํ๋์์ต๋๋ค!
์ค์ ๋ก ๋ถ์ฌ๋ฐ์ ip๋ฅผ ํตํด ์ ์ํด๋ดค์ต๋๋ค.
์ฑ๊ณต์ ์ผ๋ก ์ ๋ค์ด๊ฐ์ง๋ค์!
Github Actions๋ฅผ ํตํ ๋ฐฐํฌ๊ฐ ๋์๋์ง ํ์ธ

ip๋ฅผ ํตํ API ์ ์
ํ์ฌ ํ๋ก์ ํธ๋ ์นด์นด์ค ์์
๋ก๊ทธ์ธ์ ์ฌ์ฉํ๊ธฐ ๋๋ฌธ์, ์นด์นด์ค ์์
๋ก๊ทธ์ธ์ด ์ ์งํ๋๋์ง ํ
์คํธํด๋ณด์์ต๋๋ค.
ํฌ๋กฌ ์ฐฝ์์ {ip์ฃผ์}/kakao/login ์
๋ ฅ
ํฌํธ 3000๋ฒ์ ์ด์ด์ฃผ์ง ์์ ๋ฌธ์ ๊ฐ ์๊ฒผ๊ณ , AWS EC2์์ ํฌํธ ์ ๊ทผ์ ํ์ฉํด์ค ๋ค์ ๋ค์ ์๋ํ๋ ์ ์ด๋ ธ์ต๋๋ค.
์ ์ฉ ์ด์

3000 ํฌํธ ์ ์ฉ ํ

๋ก๊ทธ์ธ์ ์ํ ํ๋ฉด ์ถ๋ ฅ ์๋ฃ!

์ค์ ๋ฐ์ดํฐ๊ฐ ๋ณด์ด๋ API ์ ๊ทผ ์, ์๋ฌ์์ด ๋ฐ์ดํฐ๊ฐ ๋ณด์ฌ์ง๋ ๊ฒ์ ํ์ธ!
(๋ด์ฉ ๋ชจ๋๋ฅผ ๋ณด์ฌ๋๋ฆด ์ ์๋ ์ ์ํด ๋ถํ๋๋ ค์!)

์ฐธ๊ณ ํ ๋ ํผ๋ฐ์ค
๐ ์ฝ๋ Push๋ก ๋ฐฐํฌ๊น์ง! Spring Boot + Github Actions + Docker
๐ [ํ๋ก ํธ ์๋ฒ ๋ฐฐํฌ] ์ฌ์ดํธ ์ฐ๊ฒฐ ๊ฑฐ๋ถ
๐ ๋ฆฌ๋ ์ค ํฌํธ ์ํ ํ์ธ ๋ฐ ์ด๊ธฐ