Skip to content

Commit fa5cc5d

Browse files
authored
Merge pull request #2 from S0ftwareC0ntest/develop
[FEAT/#1] CICD 구축
2 parents 73c1472 + f61f951 commit fa5cc5d

File tree

13 files changed

+173
-43
lines changed

13 files changed

+173
-43
lines changed

.github/workflows/cd.yml

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,38 @@ jobs:
1111
steps:
1212
- uses: actions/checkout@v4
1313

14+
- name: Create application-secret.yml
15+
run: |
16+
mkdir -p ./temp_secret
17+
echo "${{ secrets.APPLICATION_SECRET }}" > ./temp_secret/application-secret.yml
18+
shell: bash
19+
20+
- name: Copy application-secret.yml to EC2
21+
uses: appleboy/scp-action@v0.1.3
22+
with:
23+
username: ubuntu
24+
host: ${{ secrets.EC2_HOST }}
25+
key: ${{ secrets.EC2_SSH_KEY }}
26+
source: ./temp_secret/application-secret.yml
27+
target: /home/ubuntu/secret/
28+
29+
- name: Copy docker-compose.yml
30+
uses: appleboy/scp-action@v0.1.3
31+
with:
32+
username: ubuntu
33+
host: ${{ secrets.EC2_HOST }}
34+
key: ${{ secrets.EC2_SSH_KEY }}
35+
source: ./docker-compose.yml
36+
target: /home/ubuntu/app/
37+
1438
- name: Upload deploy.sh to EC2
1539
uses: appleboy/scp-action@v0.1.3
1640
with:
1741
host: ${{ secrets.EC2_HOST }}
1842
username: ${{ secrets.EC2_USER }}
1943
key: ${{ secrets.EC2_SSH_KEY }}
2044
source: ./deploy.sh
21-
target: /home/ubuntu/
45+
target: /home/ubuntu/app/
2246

2347
- name: SSH and Deploy
2448
uses: appleboy/ssh-action@v1.0.0
@@ -28,6 +52,6 @@ jobs:
2852
key: ${{ secrets.EC2_SSH_KEY }}
2953
script: |
3054
echo ${{ secrets.DOCKERHUB_TOKEN }} | docker login -u ${{ secrets.DOCKERHUB_USERNAME }} --password-stdin
31-
export DOCKERHUB_USERNAME=${{ secrets.DOCKERHUB_USERNAME }}
32-
chmod +x /home/ubuntu/deploy.sh
33-
/home/ubuntu/deploy.sh
55+
docker pull ${{ secrets.DOCKERHUB_USERNAME }}/assu-app:latest
56+
sudo chmod +x /home/ubuntu/app/deploy.sh
57+
sudo /home/ubuntu/app/deploy.sh

.github/workflows/ci.yml

Lines changed: 46 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ on:
99
jobs:
1010
ci:
1111
runs-on: ubuntu-latest
12+
permissions:
13+
contents: read
1214

1315
steps:
1416
- uses: actions/checkout@v4
@@ -19,16 +21,57 @@ jobs:
1921
java-version: '17'
2022
distribution: 'temurin'
2123

24+
- name: Gradle Cache
25+
uses: actions/cache@v4
26+
with:
27+
path: |
28+
~/.gradle/caches
29+
~/.gradle/wrapper
30+
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
31+
restore-keys: ${{ runner.os }}-gradle-
32+
33+
- name: Grant execute permission to gradlew
34+
run: chmod +x ./gradlew
35+
2236
- name: Build and Test
2337
run: ./gradlew clean build test
2438

39+
- name: Set up Docker Buildx
40+
uses: docker/setup-buildx-action@v3
41+
with:
42+
install: true
43+
44+
- name: Create buildx builder
45+
run: |
46+
docker buildx create --use --name mybuilder
47+
docker buildx inspect --bootstrap
48+
2549
- name: Login to DockerHub
2650
uses: docker/login-action@v2
2751
with:
2852
username: ${{ secrets.DOCKERHUB_USERNAME }}
2953
password: ${{ secrets.DOCKERHUB_TOKEN }}
3054

31-
- name: Build and Push Docker Image
55+
- name: Build & Push Dependency Cache
56+
run: |
57+
docker buildx build \
58+
--builder mybuilder \
59+
--platform linux/amd64 \
60+
--push \
61+
--file Dockerfile \
62+
--tag ${{ secrets.DOCKERHUB_USERNAME }}/assu-app:dependency-cache \
63+
--target dependencies \
64+
--cache-to type=registry,ref=${{ secrets.DOCKERHUB_USERNAME }}/assu-app:dependency-cache,mode=max \
65+
.
66+
67+
- name: Build & Push Final App Image
3268
run: |
33-
docker build -t ${{ secrets.DOCKERHUB_USERNAME }}/assu-app:latest .
34-
docker push ${{ secrets.DOCKERHUB_USERNAME }}/assu-app:latest
69+
docker buildx build \
70+
--builder mybuilder \
71+
--platform linux/amd64 \
72+
--push \
73+
--file Dockerfile \
74+
--tag ${{ secrets.DOCKERHUB_USERNAME }}/assu-app:latest \
75+
--build-arg DEPENDENCY_IMAGE=${{ secrets.DOCKERHUB_USERNAME }}/assu-app:dependency-cache \
76+
--cache-from type=registry,ref=${{ secrets.DOCKERHUB_USERNAME }}/assu-app:dependency-cache \
77+
.

.gitignore

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
### build ###
2+
*.jar
3+
*.tar
4+
*.tar.gz
5+
*.zip
6+
17
HELP.md
28
.gradle
39
build/
@@ -38,9 +44,5 @@ out/
3844

3945
### Secret ###
4046
src/main/resources/application-secret.yml
41-
42-
### build ###
43-
*.jar
44-
*.tar
45-
*.tar.gz
46-
*.zip
47+
src/test/resources/application-test.yml
48+
src/test/resources/application-secret.yml

.test-develop.txt

42 Bytes
Binary file not shown.

Dockerfile

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,32 @@
1+
# Stage 1: Dependencies
2+
FROM gradle:8.4.0-jdk17 AS dependencies
3+
WORKDIR /build
4+
5+
COPY gradlew .
6+
# COPY gradle.properties /root/.gradle/gradle.properties
7+
COPY gradle/wrapper/gradle-wrapper.jar gradle/wrapper/
8+
COPY gradle/wrapper/gradle-wrapper.properties gradle/wrapper/
9+
COPY build.gradle settings.gradle ./
10+
11+
RUN ./gradlew dependencies --no-daemon
12+
13+
# Stage 2: Build
14+
FROM gradle:8.4.0-jdk17 AS builder
15+
WORKDIR /build
16+
17+
COPY --from=dependencies /build /build
18+
COPY src src
19+
20+
RUN ./gradlew bootJar -x test --build-cache --no-daemon
21+
22+
# Stage 3: Final Image
123
FROM openjdk:17-jdk-slim
2-
COPY server-0.0.1-SNAPSHOT.jar app.jar
3-
ENTRYPOINT ["java", "-jar", "/app.jar"]
24+
25+
ENV TZ=Asia/Seoul
26+
RUN ln -sf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ >/etc/timezone
27+
28+
WORKDIR /app
29+
30+
COPY --from=builder /build/build/libs/*.jar app.jar
31+
32+
ENTRYPOINT ["java", "-jar", "/app/app.jar"]

build.gradle

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ dependencies {
4141
testImplementation 'org.springframework.batch:spring-batch-test'
4242
testImplementation 'org.springframework.security:spring-security-test'
4343
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
44+
45+
runtimeOnly 'com.h2database:h2'
4446
}
4547

4648
tasks.named('test') {

compose.yaml

Lines changed: 0 additions & 17 deletions
This file was deleted.

deploy.sh

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,39 @@
11
#!/bin/bash
22

3+
4+
DOCKER_USERNAME=${DOCKERHUB_USERNAME}
35
APP_NAME=assu-app
46
TAG=latest
5-
DOCKER_USERNAME=${DOCKERHUB_USERNAME:-your_dockerhub_username}
67

78
BLUE_CONTAINER="assu-blue"
89
GREEN_CONTAINER="assu-green"
10+
COMPOSE_FILE="/home/ubuntu/app/docker-compose.yml"
11+
COMPOSE_PATH="/home/ubuntu/app"
912

1013
echo "[1] Determine currently running container"
1114
ACTIVE_CONTAINER=$(docker ps --filter "name=assu-" --format "{{.Names}}" | grep assu- | head -n 1)
1215

1316
if [ "$ACTIVE_CONTAINER" == "$BLUE_CONTAINER" ]; then
1417
NEW_CONTAINER=$GREEN_CONTAINER
1518
OLD_CONTAINER=$BLUE_CONTAINER
19+
NEW_PORT=8081
1620
else
1721
NEW_CONTAINER=$BLUE_CONTAINER
1822
OLD_CONTAINER=$GREEN_CONTAINER
23+
NEW_PORT=8080
1924
fi
2025

21-
echo "[2] Pull latest image"
26+
echo "[2] Pull latest Docker image"
2227
docker pull $DOCKER_USERNAME/$APP_NAME:$TAG
2328

24-
echo "[3] Run new container: $NEW_CONTAINER"
25-
docker run -d --name $NEW_CONTAINER -p 8080:8080 $DOCKER_USERNAME/$APP_NAME:$TAG
26-
27-
echo "[4] Wait for new container to start (basic health delay)"
28-
sleep 10
29-
30-
echo "[5] Stop and remove old container: $OLD_CONTAINER"
29+
echo "[3] Stop and remove old container if exists: $OLD_CONTAINER"
3130
docker stop $OLD_CONTAINER || true
3231
docker rm $OLD_CONTAINER || true
3332

34-
echo "[✅] Switched to $NEW_CONTAINER"
33+
echo "[4] Start new container: $NEW_CONTAINER"
34+
docker compose -f $COMPOSE_FILE up -d $NEW_CONTAINER
35+
36+
echo "[5] Wait for container to start (basic health delay)"
37+
sleep 10
38+
39+
echo "[✅] $NEW_CONTAINER deployed on port $NEW_PORT"

docker-compose.yml

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
version: "3.8"
2+
3+
services:
4+
assu-blue:
5+
build:
6+
context: .
7+
dockerfile: Dockerfile
8+
image: andylee259/assu-app:latest
9+
container_name: assu-blue
10+
ports:
11+
- "8080:8080"
12+
environment:
13+
- SPRING_PROFILES_ACTIVE=blue
14+
- SPRING_CONFIG_ADDITIONAL_LOCATION=file:/app/config/
15+
volumes:
16+
- /home/ubuntu/app/config/application-secret.yml:/app/config/application-secret.yml:ro
17+
networks:
18+
- assu-network
19+
20+
assu-green:
21+
build:
22+
context: .
23+
dockerfile: Dockerfile
24+
image: andylee259/assu-app:latest
25+
container_name: assu-green
26+
ports:
27+
- "8081:8080"
28+
environment:
29+
- SPRING_PROFILES_ACTIVE=green
30+
- SPRING_CONFIG_ADDITIONAL_LOCATION=file:/app/config/
31+
volumes:
32+
- /home/ubuntu/app/config/application-secret.yml:/app/config/application-secret.yml:ro
33+
networks:
34+
- assu-network
35+
36+
networks:
37+
assu-network:
38+
driver: bridge

gradle/wrapper/gradle-wrapper.jar

42.7 KB
Binary file not shown.

0 commit comments

Comments
 (0)