一般咱們使用 Dockerfile
來構建項目的 Docker
鏡像。可是也有使用 gradle
在編譯項目的時候一塊兒把鏡像給 構建 並 上傳 的需求。本文將會講解如何使用 gradle
編寫並配置 Dockerfile
並生成 鏡像。java
利用 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')
}
複製代碼
爲了方便容器部署的測試,在 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());
}
}
複製代碼
這裏使用 gradle-docker
插件 來實現 docker
鏡像構建。這樣,咱們就能夠直接在 Gradle
的腳本里配置 Dockerfile
達到 構建鏡像 功能的目的。web
gradle-docker
插件已經被上傳到 jCenter
和 MavenCentral
上。因此只須要在 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")
}
}
複製代碼
添加如下代碼到 build.gradle
中docker
apply plugin: 'application'
apply plugin: 'docker'
複製代碼
若是添加了 application
插件的話,默認 gradle-docker
插件會添加一個 distDocker
的 gradle task
,用來構建一個 包含全部程序文件 的 docker
鏡像。編程
group = 'io.ostenant.springboot.sample'
複製代碼
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
做爲標記。
distDocker {
baseImage = "openjdk"
maintainer = "harrison"
}
複製代碼
其中,baseImage
至關於 Dockerfile
中聲明的 FROM
。聲明瞭在 構建鏡像 是基於的 Image
,maintainer
至關於 MAINTAINER
,聲明瞭 鏡像做者。若是聲明瞭 registry
地址,插件在 鏡像射生成後 能夠自動 push
到該地址。其餘的配置還包括 docker hub
的 地址、用戶名 和 密碼。
更詳細的配置案例以下:
docker {
baseImage 'openjdk'
maintainer 'harrison'
useApi true
hostUrl 'http://myserver:4243'
apiUsername 'user'
apiPassword 'password'
apiEmail 'me@mycompany.com'
}
複製代碼
完成了基本的配置,咱們還須要添加一個 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
文件夾下面會出現 Dockerfile
和 spring-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
來生產鏡像。
進入項目根目錄,運行 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
}
}
}
複製代碼
運行以下命令,根據鏡像啓動容器,對外暴露 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 Api
和 Docker Hub
等用法,能夠參考該項目的 GitHub
地址來進行配置使用: github.com/Transmode/g…。
歡迎關注技術公衆號: 零壹技術棧
本賬號將持續分享後端技術乾貨,包括虛擬機基礎,多線程編程,高性能框架,異步、緩存和消息中間件,分佈式和微服務,架構學習和進階等學習資料和文章。