【Kotlin】【Spring Boot】Dockerにデプロイしてリモートデバッグする

環境の準備

実行環境

  • Intellij IDEA Community 2021.3
  • open JDK 17.0.1
  • Kotlin 1.6
  • Docker Desktop 4.3.2

SpringBootの準備

依存関係

  • spring initializrでプロジェクト作成したあと、下記コードで上書きしてください。
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile

plugins {
    id("org.springframework.boot") version "2.6.1"
    id("io.spring.dependency-management") version "1.0.11.RELEASE"
    war
    kotlin("jvm") version "1.6.0"
    kotlin("plugin.spring") version "1.6.0"
    kotlin("plugin.jpa") version "1.6.0"
}

group = "com.example"
version = "0.0.1-SNAPSHOT"
java.sourceCompatibility = JavaVersion.VERSION_11

repositories {
    mavenCentral()
}

dependencies {
    implementation("org.springframework.boot:spring-boot-starter-data-jpa")
    implementation("org.springframework.boot:spring-boot-starter-web")
    implementation("com.fasterxml.jackson.module:jackson-module-kotlin")
    implementation("org.jetbrains.kotlin:kotlin-reflect")
    implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
    developmentOnly("org.springframework.boot:spring-boot-devtools")
    runtimeOnly("org.postgresql:postgresql")
    providedRuntime("org.springframework.boot:spring-boot-starter-tomcat")
    testImplementation("org.springframework.boot:spring-boot-starter-test")
}

tasks.withType<KotlinCompile> {
    kotlinOptions {
        freeCompilerArgs = listOf("-Xjsr305=strict")
        jvmTarget = "11"
    }
}

tasks.withType<Test> {
    useJUnitPlatform()
}

Kotlin配下のソース

package com.example.demo.controller

import com.example.demo.repository.entity.DemoTbl
import com.example.demo.service.DemoService
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RequestMethod
import org.springframework.web.bind.annotation.RestController

@RestController
class DemoController
    (private val service: DemoService) {

    @RequestMapping(path = ["/"], method = [RequestMethod.GET])
    fun search(): List<DemoTbl> {
        return service.demoTblSearch()
    }
}
package com.example.demo.service

import com.example.demo.repository.DemoTblRepository
import com.example.demo.repository.entity.DemoTbl
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Transactional

@Service
@Transactional
class DemoService
    @Autowired
    constructor(private val repository: DemoTblRepository) {

    fun demoTblSearch(): List<DemoTbl> {
        return repository.findAll()
    }
}
package com.example.demo.repository;

import com.example.demo.repository.entity.DemoTbl
import org.springframework.data.jpa.repository.JpaRepository
import org.springframework.stereotype.Repository

@Repository
interface DemoTblRepository : JpaRepository<DemoTbl, Int> {
}
package com.example.demo.repository.entity

import javax.persistence.*

@Entity
@Table(name = "demo_tbl")
data class DemoTbl(
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    var id: Int? = 0,

    @Column(name = "demo_name")
    var name: String)

application.propertiesの設定

spring.datasource.driver-class-name=org.postgresql.Driver
spring.datasource.url=jdbc:postgresql://localhost:5432/testdb
spring.datasource.username=postgres
spring.datasource.password=postgres
spring.datasource.sql-script-encoding=UTF-8
spring.h2.console.enabled=true
spring.jpa.show-sql=true

docker-composeの準備(プロジェクト配下に作成)

Java実行環境(docker-compose-springboot.yml)

version: '3.8'
services:
  springboot:
    container_name: demo_springboot
    image: amazoncorretto:11
    ports:
      - "18080:8080"
      - "80:80"
      - "443:443"
      - "5005:5005"
    volumes:
      - ./:/var/tmp
    working_dir: /var/tmp
    environment:
      spring.datasource.driver-class-name: "org.postgresql.Driver"
      spring.datasource.url: "jdbc:postgresql://demo_db:5432/testdb"
      spring.datasource.username: "postgres"
      spring.datasource.password: "postgres"
      spring.datasource.sql-script-encoding: "UTF-8"
      spring.jpa.show-sql: true
      TZ: "Asia/Tokyo"
    command: bash -c "java -agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=*:5005 -jar build/libs/demo-0.0.1-SNAPSHOT.jar"

DB実行環境(docker-compose-db.yml)

version: '3.8'
services:
  db:
    container_name: demo_db
    image: postgres:14.1-alpine
    ports:
      - "5432:5432"
    volumes:
      - ./dbdata:/var/lib/postgresql/data
    environment:
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: postgres
      POSTGRES_DB: testdb
      TZ: "Asia/Tokyo"

Jarファイル作成からDockerにデプロイ

Jarファイルの作成

  • GradleのTaskを実行(./build/libs配下にdemo-0.0.1-SNAPSHOT.jarが作成される)

Dockerでコンテナ作成

  • ターミナルから実行すると、Docker上にコンテナが作成される
docker compose -f docker-compose-db.yml -f docker-compose-springboot.yml up -d
  • コンテナを削除したい場合はこちら
docker compose -f docker-compose-db.yml -f docker-compose-springboot.yml down

テストデータの用意

  • SQLクライアントツールでDBに接続する(接続情報はdocker-compose-db.yml参照)
DROP TABLE IF EXISTS DEMO_TBL;

CREATE TABLE DEMO_TBL (
    ID int PRIMARY KEY,
    DEMO_NAME VARCHAR(100) NOT NULL
);
INSERT INTO DEMO_TBL(ID, DEMO_NAME) VALUES (1,'demo01');
INSERT INTO DEMO_TBL(ID, DEMO_NAME) VALUES (2,'demo02');
INSERT INTO DEMO_TBL(ID, DEMO_NAME) VALUES (3,'demo03');

SpringBootアプリケーションの起動からリモートデバッグ

Intellijでの操作

  • 「実行」メニュー > 「実行構成の編集」を選択
  • 「+」ボタン > 「リモートJVMデバッグ」を選択
  • 下記情報を入力してOKボタン押下
デバッグモード:リモートJVMに接続
トランスポート:Socket
ホスト:localhost
ポート:5005
使用するモジュールのクラスパス:demo.main
  • 作成した構成情報を選択してデバッグボタン押下

Dockerでの操作

  • 特になし
  • リモートデバッグで接続すると、SpringBootアプリケーションのmainクラスが実行され、起動状態になります。

ブレークポイントの設定

  • ブレークポイントで止まれば、成功です。

あとがき

初めてDockerで開発環境を作ってみました。
意外と簡単に構築できることがわかりました。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です