Docker สำหรับ Java 8 Development

หลังๆนี้ลง Java JDK ใหม่ๆมาใช้งาน อย่าง Jdk17 Jdk21

แต่พอมี project ที่ต้องใช้ Jdk8 แล้วไม่อยากลง Jdk8 ทับลงไปอีกรอบ กลัวมีปัญหาต้องมานั่งแก้

เลยอยากจะลองดูว่าถ้าเราเอา docker มา load environment เก่าๆมาใช้ มันจะเป็นอย่างไร

ตัวแรก Docker-compose.yml

services:
  java-dev:
    build: .
    container_name: java8-gradle-dev
    volumes:
      # แมปโค้ดจากเครื่อง Host เข้าไปใน Container
      - .:/app
      # สร้าง Volume สำหรับ Gradle Cache เพื่อไม่ต้องโหลดไลบรารีใหม่ทุกครั้งที่รัน
      - gradle-cache:/home/gradle/.gradle
    ports:
      - "8080:8080"  # พอร์ตสำหรับ Web Application (ปรับเปลี่ยนได้ตามใจชอบ)
      - "5005:5005"  # พอร์ตสำหรับ NetBeans Remote Debugger
    environment:
      - GRADLE_USER_HOME=/home/gradle/.gradle

volumes:
  gradle-cache:

ต่อไป Dockerfile

FROM gradle:4.10.3-jdk8

# ตั้งค่า Working Directory ใน Container
WORKDIR /app

# คัดลอกไฟล์คอนฟิกของ Gradle เข้ามาก่อนเพื่อทำ Caching (ช่วยให้บิวด์เร็วขึ้น)
COPY build.gradle settings.gradle* /app/

# เปิดพอร์ตสำหรับ Java Remote Debugging
EXPOSE 5005

# คำสั่งเริ่มต้น: ให้ Gradle รันแอปพลิเคชันในโหมดเดบักและรอการเชื่อมต่อ
CMD ["gradle", "run", "--no-daemon", "--debug-jvm"]

เพิ่ม build.gradle สำหรับ start project ว่างๆ

plugins {
    id 'java'
    id 'application'
}

group = 'com.example'
version = '1.0-SNAPSHOT'

//sourceCompatibility = 1.8
//targetCompatibility = 1.8


java {
    sourceCompatibility = JavaVersion.VERSION_1_8
    targetCompatibility = JavaVersion.VERSION_1_8
}


repositories {
    mavenCentral()
}

dependencies {

    testImplementation 'junit:junit:4.12'

    compileOnly 'org.projectlombok:lombok:1.18.46'
    annotationProcessor 'org.projectlombok:lombok:1.18.46'
    testCompileOnly 'org.projectlombok:lombok:1.18.46'
    testAnnotationProcessor 'org.projectlombok:lombok:1.18.46'

    implementation 'com.fasterxml.jackson.core:jackson-databind:2.17.0'
    implementation 'com.fasterxml.jackson.core:jackson-core:2.17.0'
    implementation 'com.fasterxml.jackson.core:jackson-annotations:2.17.0'
    implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.17.0'

    implementation 'com.formdev:flatlaf:1.0'
    implementation 'com.google.code.gson:gson:2.8.6'
    implementation 'org.apache.httpcomponents:httpclient:4.5.13'
    implementation 'commons-io:commons-io:2.8.0'
    implementation 'org.apache.commons:commons-collections4:4.4'
    implementation 'org.apache.poi:poi:4.1.2'
    implementation 'org.apache.poi:poi-ooxml:4.1.2'
    implementation 'org.apache.poi:poi-ooxml-schemas:4.1.2'

    implementation 'mysql:mysql-connector-java:8.0.29'

    implementation 'org.apache.pdfbox:pdfbox:2.0.9'
    implementation 'org.apache.pdfbox:pdfbox-tools:2.0.24'
}

application {
    if (GradleVersion.current() >= GradleVersion.version("6.0")) {
        mainClass.set('com.example.App')
    } else {
        mainClassName = 'com.example.App'
    }
}

เพิ่ม nb-configuration.xml เอาไว้ให้ netbeans มัน load แล้วตอน build มันจะได้ run ด้วย docker command เพื่อเข้าไป run gradle ภายใน docker

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <actions>
        <!-- เมื่อกดปุ่ม Build (F11) -->
        <action name="build">
            <target>exec</target>
            <property name="exec.executable">docker</property>
            <property name="exec.args">compose exec -T java-dev gradle build</property>
        </action>

        <!-- เมื่อกดปุ่ม Clean & Build -->
        <action name="rebuild">
            <target>exec</target>
            <property name="exec.executable">docker</property>
            <property name="exec.args">compose exec -T java-dev gradle clean build</property>
        </action>

        <!-- เมื่อกดปุ่ม Run (F6) -->
        <action name="run">
            <target>exec</target>
            <property name="exec.executable">docker</property>
            <property name="exec.args">compose exec -T java-dev gradle run</property>
        </action>

        <!-- เมื่อกดปุ่ม Test (Ctrl+F6) -->
        <action name="test">
            <target>exec</target>
            <property name="exec.executable">docker</property>
            <property name="exec.args">compose exec -T java-dev gradle test</property>
        </action>
    </actions>
</configuration>

จากนั้นก็สั่ง docker compose up –build
เพื่อ build Dockerfile

ถ้าไม่มีปัญหาอะไร เราก็ควรจะเข้าไปใน bash แล้ว check version ของ gradle กับ java ได้

สามารถ run คำสั่ง gradle จากภายใน container ได้เลย

พอมี build.gradle เวลาใช้ netbeans เปิด มันก็รู้จักเลย

พอเปิด netbeans ก็จะ resolve problem โดยการทำ priming build รอบแรกก่อน

แปลกตรงที่ ตอน build ใน netbeans เหมือนมันใช้ local gradle เลย เพราะอย่างนั้นมันเลย run ด้วย version ใหม่
ตามจริงมันน่าจะใช้ gradle ใน docker มากกว่า
แต่ ณ จุดนี้ถือว่ายังใช้ได้

แต่พอสั่ง javap เพื่อดู major version ของ compile file ก็เห็นว่า major version เป็น 52 ซึ่งก็ตรงกับ Java 8 อยู่ ก็แปลกดี

ลองสั่ง gradle run จากภายใน container มันใช้เวลา compile ครั้งแรกไป 26s ซึ่งนานผิดปรกติ แต่ก็ทำงานได้ แต่พอ run อีกรอบก็เร็วแล้ว

โดยรวม ก็ถือว่าใช้ได้แล้วล่ะนะ