[Docker] ๐ Spring ์๋ฒ๋ฅผ Docker๋ก ๋์ฐ๊ธฐ
๐ SpringBoot Server
์ฐ์ต์ ์ํ์ฌ ๊ฐ๋จํ๊ฒ demo/hello
API์ getํ์์ demo/demo
๋ฅผ ๊ฐ์ง๊ณ ์๋ Demo Server
๋ฅผ ์ฌ๋ ธ๋ค.
์คํ๋ง๋ถํธ๋ IntelliJ์์ ์งํํ ์์ ์ด๋ฉฐ, ์๋ฐ๋ JDK-17
/ ์คํ๋ง๋ถํธ ๋ฒ์ ์ 3.2.2
์ ์ฌ์ฉํ์๋ค.
์์ ๊ฐ์ด ํ๋ก์ ํธ๋ฅผ ๋ง๋ค์ด ์ฃผ์๋ค.
์๋๋ MVC๋ชจ๋ธ๋ก ๊ตฌํํ ์์ค์ฝ๋์ด๋ค.
๐ ์์ค ์ฝ๋
Controller
package com.example.demo.Controller;
import com.example.demo.Service.DemoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("demo")
public class DemoController {
private final DemoService demoService;
@Autowired
public DemoController(DemoService demoService) {
this.demoService = demoService;
}
@RequestMapping("/hello")
public String hello() {
return "hello";
}
@GetMapping()
public String getName(int index) {
System.out.println(index);
return demoService.DemoDTO(index);
}
}
DTO
package com.example.demo.DTO;
public class DemoDTO {
String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Entity
package com.example.demo.entity;
import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
@Entity
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "Demo")
public class Demo {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int index;
@Column(nullable = false)
private String name;
}
Repository
package com.example.demo.Repository;
import com.example.demo.DTO.DemoDTO;
import com.example.demo.entity.Demo;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface DemoRepository extends JpaRepository<Demo, Integer> {
}
Service
package com.example.demo.Service;
import com.example.demo.DTO.DemoDTO;
import com.example.demo.Repository.DemoRepository;
import com.example.demo.entity.Demo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.stereotype.Service;
@Service
public class DemoService {
private final DemoRepository demoRepository;
@Autowired
public DemoService(DemoRepository demoRepository) {
this.demoRepository = demoRepository;
}
public String DemoDTO(int index) {
Demo demo = demoRepository.findById(index).get();
return demo.getName();
}
}
Repository
package com.example.demo.Repository;
import com.example.demo.DTO.DemoDTO;
import com.example.demo.entity.Demo;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface DemoRepository extends JpaRepository<Demo, Integer> {
}
application.yml
๊ธฐ์กด์ ์๋ application.properties ํ์ผ์ ์ญ์ ํ๊ณ , application.yml๋ก ๋ณ๊ฒฝํด์ฃผ์๋ค.
์ด๋ local db
๋ฅผ ์ฌ์ฉํ์๋๋ฐ, ์ด๋ฅผ ์ํ์ฌ docker์์ ๊ธฐ๋ณธ์ ์ผ๋ก ์ค์ ๋์ด ์๋ host
network์ ์ ์ํ๊ธฐ ์ํ์ฌ host.docker.internal
๋ฅผ ์ง์ ํด์ฃผ์๋ค.
spring:
datasource:
url: jdbc:mariadb://host.docker.internal:3306/demo
driver-class-name: org.mariadb.jdbc.Driver
username: 'root'
password: '1234'
jpa:
open-in-view: false
generate-ddl: true
show-sql: true
hibernate:
ddl-auto: update
application:
name: demo
profiles:
active: dev
server:
port: 8080
์์กด์ฑ ์ฃผ์
build.gradle์ ์๋ dependencies
//swagger
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.0.2'
//Database
runtimeOnly 'org.mariadb.jdbc:mariadb-java-client' // MariaDB
๐ docker ์ด๋ฏธ์ง ๋ง๋ค๊ธฐ
์๋์ ๊ฐ์ด ์ค๋ฅธ์ชฝ์ Gradle ํญ๋ชฉ์์ build/bootJar
์ ํด๋ฆญํ์ฌ ํ์ผ ๋น๋๋ฅผ ํด์ค๋ค.
๊ทธ๋ฌ๋ฉด build/libs
์๋์ .jar
ํ์ผ์ด ์์ฑ๋๊ฒ ๋๋ค.
dockerfile
์ด๋ผ๋ ์ด๋ฆ์ ํ์ผ์ ํ๋ก์ ํธ rootํด๋ ์๋์ ๋ง๋ค์ด์ค๋ค.
์๋์ ๊ฐ์ด ๋ด์ฉ์ ์ ์ด์ค๋ค.
- dockerfile
FROM openjdk:11 ARG JAR_FILE=*.jar COPY ${JAR_FILE} app.jar ENTRYPOINT ["java","-jar","/app.jar"]
๐ ์ค์ต
์๋์ ๊ฐ์ด ํ๋ฉด ๋์ปค ์ด๋ฏธ์ง๋ฅผ ๋น๋ํด์ฃผ๊ณ , Docker Hub
์ ์ด๋ฅผ ์ฌ๋ฆฐ๋ค.
docker build -t [๋์ปคํ๋ธ ID]/[Repository ์ด๋ฆ] .
docker push [๋์ปคํ๋ธ ID]/[Repository ์ด๋ฆ]
์๋์ ๊ฐ์ด docker Hub
์์ ์ด๋ฏธ์ง๋ฅผ ๋ค์ด๋ฐ์์ ์คํ์์ผฐ๋ค.
docker run -d -i -p 8080:8080 [๋์ปค ํ๋ธ ID/์ด๋ฏธ์ง ์ด๋ฆ]
์๋๋ ์คํ ํ๋ฉด๋ค์ด๋ค.
๐ ๋ฉํฐ ์คํ ์ด์ง๋ฅผ ํตํด ์ด๋ฏธ์ง ๋ง๋ค๊ธฐ
๊ธฐ์กด๊ณผ ๋์ผํ ์ฝ๋์์ Dockerfile
์ ๋ณ๊ฒฝํด์ฃผ๋ฉด ๋๋ค.
# build
FROM gradle:8.5 AS builder
WORKDIR /build
COPY build.gradle settings.gradle /build/
RUN gradle build -x test --parallel --continue > /dev/null 2>&1 || true
COPY . /build
RUN gradle build -x test --parallel
# app
FROM openjdk:17
WORKDIR /app
COPY --from=builder /build/build/libs/*-SNAPSHOT.jar ./app.jar
ENTRYPOINT ["java","-jar","app.jar"]
EXPOSE 8080
์ด๋, builder์ ๋ฒ์ ์ ํ์ธํด ์ฃผ์ด์ผ ํ๋๋ฐ, ์ด๋ gradle/wrapper/gradle-wrapper.properties
ํ์ผ์ ์๋ distributionUrl
์์ ํ์ธํ ์ ์๋ค.
๐ ์ค์ต
docker build -t [๋์ปคํ๋ธ ID]/[Repository ์ด๋ฆ] .
docker push [๋์ปคํ๋ธ ID]/[Repository ์ด๋ฆ]
๊ธฐ์กด๊ณผ ๋๊ฐ์ด build ํ pushํด์ฃผ์๋ค.
๊ธฐ์กด๊ณผ ๋ฌ๋ผ์ง ์ ์ Dockerfile์์ ํ๊ฒฝ์ ๋ง๋ค์ด์ฃผ๊ธฐ ๋๋ฌธ์, bootJar
๋ฅผ ์คํ์์ผ์ค ํ์๋ ์๋ค.
docker run -d -i -p 8080:8080 [๋์ปค ํ๋ธ ID/์ด๋ฏธ์ง ์ด๋ฆ]
์ด์ ๊ณผ ๊ฐ์ด ์ ์๋ํ๋ ๊ฒ์ ๋ณผ ์ ์๋ค.
๊ฐ์ธ ๊ณต๋ถ ๊ธฐ๋ก์ฉ ๋ธ๋ก๊ทธ์
๋๋ค.
ํ๋ฆฌ๊ฑฐ๋ ์ค๋ฅ๊ฐ ์์ ๊ฒฝ์ฐ ์ ๋ณดํด์ฃผ์๋ฉด ๊ฐ์ฌํ๊ฒ ์ต๋๋ค.๐