實戰Spring Boot 2.0系列(一) - 使用Gradle構建Docker鏡像

前言

一般咱們使用 Dockerfile 來構建項目的 Docker 鏡像。可是也有使用 gradle 在編譯項目的時候一塊兒把鏡像給 構建上傳 的需求。本文將會講解如何使用 gradle 編寫並配置 Dockerfile 並生成 鏡像java

本系列文章

  1. 實戰Spring Boot 2.0系列(一) - 使用Gradle構建Docker鏡像
  2. 實戰Spring Boot 2.0系列(二) - 全局異常處理和測試
  3. 實戰Spring Boot 2.0系列(三) - 使用@Async進行異步調用詳解
  4. 實戰Spring Boot 2.0系列(四) - 使用WebAsyncTask處理異步任務
  5. 實戰Spring Boot 2.0系列(五) - Listener, Servlet, Filter和Interceptor
  6. 實戰Spring Boot 2.0系列(六) - 單機定時任務的幾種實現

正文

1. 建立項目

利用 Spring Initializer 建立一個 gradle 項目 spring-boot-gradle-for-docker,建立時添加一個 web 依賴。獲得的初始 build.gradle 以下:git

buildscript {
    ext {
        springBootVersion = '2.0.2.RELEASE'
    }
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
    }
}

apply plugin: 'java'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'


group = 'io.ostenant.springboot.sample'
version = '1.0'
sourceCompatibility = 1.8

repositories {
    mavenCentral()
    jcenter()
}

dependencies {
    compile('org.springframework.boot:spring-boot-starter-web')
    testCompile('org.springframework.boot:spring-boot-starter-test')
}
複製代碼

2. 配置入口類

爲了方便容器部署的測試,在 Spring Boot 啓動類上配置一個控制器,響應當前的系統時間。github

@RestController
@SpringBootApplication
public class Application {

    private ThreadLocal<SimpleDateFormat> threadLocal = ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyy/MM/dd hh:mm:ss"));

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

    @GetMapping("/")
    public String retrieveTime() {
        return threadLocal.get().format(new Date());
    }
}
複製代碼

3. 添加插件

這裏使用 gradle-docker 插件 來實現 docker 鏡像構建。這樣,咱們就能夠直接在 Gradle 的腳本里配置 Dockerfile 達到 構建鏡像 功能的目的。web

gradle-docker 插件已經被上傳到 jCenterMavenCentral 上。因此只須要在 dependencies 添加依賴 se.transmode.gradle:gradle-docker:1.2 就能使用 docker 插件。spring

buildscript {
    ext {
        springBootVersion = '2.0.2.RELEASE'
    }
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
        classpath("se.transmode.gradle:gradle-docker:1.2")
    }
}
複製代碼

4. 應用插件

添加如下代碼到 build.gradledocker

apply plugin: 'application'
apply plugin: 'docker'
複製代碼

若是添加了 application 插件的話,默認 gradle-docker 插件會添加一個 distDockergradle task,用來構建一個 包含全部程序文件docker 鏡像。編程

5. 配置鏡像構建信息

5.1. 配置group

group = 'io.ostenant.springboot.sample'
複製代碼

5.2. 配置鏡像名稱和版本號

jar {
    baseName = "spring-boot-gradle-for-docker"
    version = 1.0
}
複製代碼

其中鏡像的 tag 默認的構成爲:項目組/應用名稱:版本號後端

tag = "${project.group}/${applicationName}:${tagVersion}"
複製代碼
  • project.group:標準的 gradle 屬性,若是不進行定義,插件默認會 省略 ${project.group} 這個屬性。api

  • applicationName:應用被容器化時的 名稱緩存

  • tagVersion:可選屬性,會做爲鏡像的 標籤。默認值爲 project.version,若是未指定 project.version,則使用 latest 做爲標記。

5.3. 配置docker構建基礎信息

distDocker {
    baseImage = "openjdk"
    maintainer = "harrison"
}
複製代碼

其中,baseImage 至關於 Dockerfile 中聲明的 FROM。聲明瞭在 構建鏡像 是基於的 Imagemaintainer 至關於 MAINTAINER ,聲明瞭 鏡像做者。若是聲明瞭 registry 地址,插件在 鏡像射生成後 能夠自動 push 到該地址。其餘的配置還包括 docker hub地址用戶名密碼

更詳細的配置案例以下:

docker {
    baseImage 'openjdk'
    maintainer 'harrison'
    useApi true
    hostUrl 'http://myserver:4243'
    apiUsername 'user'
    apiPassword 'password'
    apiEmail 'me@mycompany.com'
}
複製代碼

6. 添加task任務

完成了基本的配置,咱們還須要添加一個 task 用來在 gradle 編譯的時候 執行鏡像構建

插件提供了一些 轉換方法,用來指代 Dockerfile 中的 關鍵詞語法,以下表,能夠按照需求對照着來:

Dockerfile關鍵詞 gradle task方法
ADD addFile(Closure copySpec)
addFile(String source, String dest)
addFile(File source, String dest)
CMD defaultCommand(List cmd)
ENTRYPOINT entryPoint(List entryPoint)
ENV setEnvironment(String key, String val)
EXPOSE exposePort(Integer port)
exposePort(String port)
RUN runCommand(String cmd)
USER switchUser(String userNameOrUid)
VOLUME volume(String... paths)
WORKDIR workingDir(String dir)

下面是本項目的 taskBuilder 的任務配置

task dockerBuilder(type: Docker) {
    applicationName = jar.baseName
    tagVersion = jar.version
    volume('/tmp')
    addFile("${jar.baseName}-${jar.version}.jar", "app.jar")
    entryPoint(["java", "-Djava.security.egd=file:/dev/./urandom", "-jar", 'app.jar'])
    exposePort(8080)
    doFirst {
        copy {
            from jar
            into stageDir
        }
    }
}
複製代碼

構建完成y之後,項目根目錄的 build/docker 文件夾下面會出現 Dockerfilespring-boot-gradle-for-docker-1.0.jar 文件。其中,以上的 task 等同於如下的 Dockerfile

FROM aglover/java8-pier
VOLUME ["/tmp"] ADD spring-boot-gradle-for-docker-1.0.jar app.jar ENTRYPOINT ["java", "-Djava.security.egd=file:/dev/./urandom", "-jar", "app.jar"] EXPOSE 8080
複製代碼

若是覺的在 task 中編寫 Dockerfile 替換腳本 很是彆扭,也能夠直接在 task 中指定 Dockfile文件路徑,直接使用已有的文件來生成鏡像:

task buildDocker(type: Docker) {
    applicationName = jar.baseName
    tagVersion = jar.version
    dockerfile = file('Dockerfile')
    doFirst {
        copy {             from jar
            into stageDir
        }
    }
}
複製代碼

經過 file() 指定 task 使用位於 項目根目錄Dockerfile 來生產鏡像。

7. 編譯並構建Docker鏡像

進入項目根目錄,運行 gradle 命令進行打包構建。

$ ./gradlew clean build dockerBuilder --info
複製代碼

gradle 首先會運行 本地測試,而後進行 項目打包,進一步根據 docker-gradle 插件進行 鏡像構建

等待出現 BUILD SUCCESSFUL 就代表任務運行成功。能夠觀察到鏡像的名稱爲

io.ostenant.springboot.sample/spring-boot-gradle-for-docker:1.0
複製代碼

運行 docker images 查看本地鏡像,進一步驗證鏡像構建成功。

下面給出 build.gradle 完整的 配置文件

buildscript {
    ext {
        springBootVersion = '2.0.2.RELEASE'
    }
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
        classpath("se.transmode.gradle:gradle-docker:1.2")
    }
}

apply plugin: 'java'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'
apply plugin: 'application'
apply plugin: 'docker'


group = 'io.ostenant.springboot.sample'
version = '1.0'
sourceCompatibility = 1.8
targetCompatibility = 1.8
mainClassName = "io.ostenant.springboot.sample.Application"

repositories {
    mavenCentral()
    jcenter()
}

dependencies {
    compile('org.springframework.boot:spring-boot-starter-web')
    testCompile('org.springframework.boot:spring-boot-starter-test')
}

jar {
    baseName 'spring-boot-gradle-for-docker'
    version '1.0'
}

distDocker {
    baseImage 'openjdk'
    maintainer 'harrison'
}

task dockerBuilder(type: Docker) {
    applicationName = jar.baseName
    tagVersion = jar.version
    volume('/tmp')
    addFile("${jar.baseName}-${jar.version}.jar", "app.jar")
    entryPoint(["java", "-Djava.security.egd=file:/dev/./urandom", "-jar", 'app.jar'])
    exposePort(8080)
    doFirst {
        copy {
            from jar
            into stageDir
        }
    }
}
複製代碼

8. 使用鏡像啓動容器

運行以下命令,根據鏡像啓動容器,對外暴露 8080 訪問端口。

$ docker run -d --name gradle-boot -p 8080:8080 io.ostenant.springboot.sample/spring-boot-gradle-for-docker:1.0
複製代碼

訪問 http://127.0.0.1:8080/ ,頁面會輸出當前系統時間,如圖所示:

小結

gradle-docker 插件還提供了配置 鏡像倉庫地址、配置使用 Docker Remote ApiDocker Hub 等用法,能夠參考該項目的 GitHub 地址來進行配置使用: github.com/Transmode/g…


歡迎關注技術公衆號: 零壹技術棧

零壹技術棧

本賬號將持續分享後端技術乾貨,包括虛擬機基礎,多線程編程,高性能框架,異步、緩存和消息中間件,分佈式和微服務,架構學習和進階等學習資料和文章。

相關文章
相關標籤/搜索