1. 프로젝트 구조
/project-root
--/database
---/config
---/init
---Dockerfile
--/redis
---Dockerfile
--/src
---/main
----/java
----/resources
-----application.yaml
---/test
--.env
--docker-compose.yml
--docker-compose-local.yml
--Dockerfile
--build.gradle
2. application.yaml
spring:
profiles:
active: local
group:
local:
- common
prod:
- common
---
spring:
config:
activate:
on-profile: common
kakao:
rest:
api:
key: ${KAKAO_REST_API_KEY}
---
spring:
config:
activate:
on-profile: local
datasource:
driver-class-name: org.mariadb.jdbc.Driver
url: jdbc:mariadb://localhost:3307/pharmacy-recommendation
username: ${SPRING_DATASOURCE_USERNAME}
password: ${SPRING_DATASOURCE_PASSWORD}
redis:
host: localhost
port: 6379
jpa:
hibernate:
ddl-auto: validate
show-sql: true
pharmacy:
recommendation:
base:
url: http://localhost:8080/dir/
---
spring:
config:
activate:
on-profile: prod
datasource:
driver-class-name: org.mariadb.jdbc.Driver
url: jdbc:mariadb://pharmacy-recommendation-database:3306/pharmacy-recommendation
username: ${SPRING_DATASOURCE_USERNAME}
password: ${SPRING_DATASOURCE_PASSWORD}
redis:
host: pharmacy-recommendation-redis
port: 6379
jpa:
hibernate:
ddl-auto: validate
show-sql: true
pharmacy:
recommendation:
base:
url: http://13.124.200.5/dir/
2.1 테스트용 yaml
spring:
datasource:
driver-class-name: org.testcontainers.jdbc.ContainerDatabaseDriver
url: jdbc:tc:mariadb:10:///
jpa:
hibernate:
ddl-auto: create
show-sql: true
kakao:
rest:
api:
key: ${KAKAO_REST_API_KEY}
pharmacy:
recommendation:
base:
url: http://localhost:8080/dir/
3. docker-compose.yml
version: "3.8"
services:
pharmacy-recommendation-redis:
container_name: pharmacy-recommendation-redis
build:
dockerfile: Dockerfile
context: ./redis
image: sun/pharmacy-recommendation-redis
ports:
- "6379:6379"
pharmacy-recommendation-database:
container_name: pharmacy-recommendation-database
build:
dockerfile: Dockerfile
context: ./database
image: sun/pharmacy-recommendation-database
environment:
- MARIADB_DATABASE=pharmacy-recommendation
- MARIADB_ROOT_PASSWORD=${SPRING_DATASOURCE_PASSWORD}
volumes:
- ./database/config:/etc/mysql/conf.d
- ./database/init:/docker-entrypoint-initdb.d
ports:
- "3306:3306"
healthcheck:
test: "/usr/bin/mysql --user=${SPRING_DATASOURCE_USERNAME} --password=${SPRING_DATASOURCE_PASSWORD} --execute \"SHOW DATABASES;\""
interval: 2s
timeout: 20s
retries: 10
pharmacy-recommendation-app:
container_name: pharmacy-recommendation-app
build: .
depends_on:
pharmacy-recommendation-database:
condition: service_healthy
pharmacy-recommendation-redis:
condition: service_started
image: sun/pharmacy-recommendation-app
environment:
- SPRING_DATASOURCE_USERNAME=${SPRING_DATASOURCE_USERNAME}
- SPRING_DATASOURCE_PASSWORD=${SPRING_DATASOURCE_PASSWORD}
- SPRING_PROFILES_ACTIVE=${SPRING_PROFILES_ACTIVE}
- KAKAO_REST_API_KEY=${KAKAO_REST_API_KEY}
ports:
- "80:8080"
restart: always
4. Dockerfile
FROM openjdk:17
ARG JAR_FILE=build/libs/app.jar
COPY ${JAR_FILE} ./app.jar
ENV TZ=Asia/Seoul
ENTRYPOINT ["java", "-jar", "./app.jar"]
5. build.gradle
plugins {
id 'java'
id 'org.springframework.boot' version '2.7.13'
id 'io.spring.dependency-management' version '1.1.0'
id 'groovy'
}
group = 'com.example'
version = '0.0.1-SNAPSHOT'
java {
sourceCompatibility = '17'
}
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.retry:spring-retry:'
//implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
implementation 'org.springframework.boot:spring-boot-starter-data-redis'
implementation 'pl.allegro.tech.boot:handlebars-spring-boot-starter:0.3.4'
compileOnly 'org.projectlombok:lombok'
runtimeOnly 'org.mariadb.jdbc:mariadb-java-client'
annotationProcessor 'org.springframework.boot:spring-boot-configuration-processor'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation('org.spockframework:spock-core:2.1-groovy-3.0')
//testImplementation('org.spockframework:spock-core:2.4-M1-groovy-4.0')
testImplementation('org.spockframework:spock-spring:2.1-groovy-3.0')
//testImplementation('org.spockframework:spock-spring:2.4-M1-groovy-4.0')
testImplementation('net.bytebuddy:byte-buddy:1.12.10')
//testcontainer
testImplementation('org.testcontainers:spock:1.17.1')
//testImplementation('org.testcontainers:spock:1.17.6')
testImplementation('org.testcontainers:mariadb:1.17.1')
//testImplementation('org.testcontainers:mariadb:1.17.6')
testImplementation('com.squareup.okhttp3:okhttp:4.10.0')
testImplementation('com.squareup.okhttp3:mockwebserver:4.10.0')
// https://github.com/seruco/base62
implementation 'io.seruco.encoding:base62:0.1.3'
}
tasks.named('test') {
useJUnitPlatform()
}
bootJar{
archiveFileName = 'app.jar'
}
//./gradlew clean build -PKAKAO_REST_API_KEY={api key 값}
processTestResources{
boolean hasProperty = project.hasProperty("KAKAO_REST_API_KEY")
System.out.println("Set kakao rest api key : $hasProperty")
filesMatching('**/application.yaml'){
expand(project.properties)
}
}
6. EC2 세팅(서버에서 직접 빌드)
- EC2 인스턴스 생성(AWS linux)
- Elastic IP 할당
- 보안그룹 설정
- 초기세팅
- sudo yum update -y
- sudo yum install java-17-amazon-corretto
- sudo yum install git -y
- sudo yum install docker
- sudo curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
- sudo systemctl start docker
- sudo chmod +x /usr/local/bin/docker-compose
- sudo chmod 666 /var/run/docker.sock
- (필요시)sudo dnf install libxcrypt-compat
- (필요시) swap 메모리 설정
- git clone project
- .env파일 세팅 -> docker-compose config 명령어로 최종 세팅된 파일을 볼 수 있음
- docker-compose build #프리티어 인스턴스 부하를 줄이기 위해 build와 up을 별도로 진행
- docker-compose up