1. 簡介
Docker 是一個開源的應用容器引擎,讓開發人員可以將應用打包部署到一個可移植的容器中,然后發布到任何流行的Linux服務器上,容器是完全使用沙箱機制,相互之間不會有任何接口。
一個完整的Docker有以下幾個部分組成:
- Docker Client 客戶端
- Docker Daemon 守護進程
- Docker Image 鏡像
- Docker Container 容器
2. 準備工作
為了通過Docker來構建與部署Spring Boot應用, 我們需要有一個安裝過 Docker 環境的服務器來打包 Spring Boot 項目, 因此在進行項目構建時, 需要安裝Java、Maven和Docker的應用環境,建議使用Linux系統來構建Docker鏡像。 Java與Maven環境安裝與配置在這就不詳細介紹了,Docker環境安裝與配置可以參考之前寫過的文章《Docker容器安裝與部署》。
環境配置
- Java版本: JDK1.8+
- Maven版本: Maven3.0+
- Docker版本: Docker 17.06+
3. 構建Spring Boot項目
1. 配置Maven項目依賴文件pom.xml
- 添加Spring Boot項目依賴
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.0</version>
<relativePath/>
</parent>
- 添加Spring Boot項目相關的依賴包
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- Java Mail -->
<dependency>
<groupId>com.sun.mail</groupId>
<artifactId>javax.mail</artifactId>
<version>1.6.1</version>
</dependency>
</dependencies>
- 創建Controller, 提供服務接口, 此處提供一個測試接口
@RestController
public class HelloController {
@RequestMapping("/sayHello")
public String sayHello() {
return "Hello Spring Boot!";
}
}
- 創建Spring Boot啟動類
@SpringBootApplication
public class HelloApplication {
public static void main(String[] args) {
SpringApplication.run(HelloApplication.class, args);
}
}
添加完畢后啟動項目,啟動成功后瀏覽器訪問:http://localhost:8080/sayHello,調用接口頁面返回:Hello Spring Boot!,說明 Spring Boot 項目工作正常。
4. Spring Boot項目中添加Docker構建組件
支持Spring Boot項目Docker容器構建的組件有許多個, 此處選擇com.spotify:docker-maven-plugin
組件進行構建。
- 修改pom.xml文件, 添加Docker編譯支持組件
<properties>
<docker.image.prefix>myProject</docker.image.prefix>
</properties>
<build>
<plugins>
<!-- Spring Boot Build Plugin -->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<!-- Docker maven plugin -->
<plugin>
<groupId>com.spotify</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>1.2.0</version>
<configuration>
<imageName>${docker.image.prefix}/${project.artifactId}:${project.version}</imageName>
<dockerDirectory>src/main/docker</dockerDirectory>
<resources>
<resource>
<targetPath>/</targetPath>
<directory>${project.build.directory}</directory>
<include>${project.build.finalName}.jar</include>
</resource>
</resources>
</configuration>
</plugin>
<!-- Docker maven plugin -->
</plugins>
</build>
說明 :
- ${docker.image.prefix}為pom文件中properties中添加的配置;
- ${project.artifactId}為pom文件中的artifactId屬性,${project.version}為pom文件中的version屬性;
- dockerDirectory屬性配置dockerfile文件的存放路徑
/src/main/docker
;- resources屬性中配置復制 jar 包到 docker 容器指定目錄配置,將target下編譯的Jar包復制到docker目錄下。
我們也可以通過spotify的docker-maven-plugin組件配置, 自動創建Docker鏡像,繞過下面創建Dockerfile的步驟, 直接生成Docker鏡像:
<properties>
<docker.image.prefix>myProject</docker.image.prefix>
</properties>
<build>
<plugins>
<!-- Spring Boot Build Plugin -->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<!-- Docker maven plugin -->
<plugin>
<groupId>com.spotify</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>1.2.0</version>
<configuration>
<imageName>${docker.image.prefix}/${project.artifactId}:${project.version}</imageName>
<baseImage>docker.io/cemmersb/centos-jdk8:latest</baseImage>
<entryPoint>["java", "-jar", "/${project.build.finalName}.jar"]</entryPoint>
<resources>
<resource>
<targetPath>/</targetPath>
<directory>${project.build.directory}</directory>
<include>${project.build.finalName}.jar</include>
</resource>
</resources>
</configuration>
</plugin>
<!-- Docker maven plugin -->
</plugins>
</build>
說明:
- 使用baseImage屬性配置Docker容器依賴的基礎鏡像信息;
- 使用entryPoint屬性配置Docker容器的入口命令。
- 在
src/main/docker
下創建Dockerfile
FROM docker.io/cemmersb/centos-jdk8:latest
MAINTAINER garyond
VOLUME /tmp
ADD hello-service:0.0.1-SNAPSHOT.jar app.jar
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]
關于Dockerfile的相關命令可以參考我的文章《使用Dockerfile構建Docker鏡像》, 這里我就不詳細講解了。
- 編譯項目, 進行Docker鏡像打包, 執行命令
mvn clean package docker:build
$ mvn clean package docker:build
...
Step 1/5 : FROM docker.io/cemmersb/centos-jdk8:latest
---> ccba23a213f2
Step 2/5 : MAINTAINER zhangjiayang <zhangjiayang@sczq.com.cn>
---> 0de52ae244d4
Step 3/5 : VOLUME /tmp
---> 3d25b5f60bb8
Step 4/5 : ADD hello-service-0.0.1-SNAPSHOT.jar app.jar
---> a02fcec9904c
Step 5/5 : ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]
---> Running in a5cf7c699a3f
Removing intermediate container a5cf7c699a3f
---> 2177684b649d
ProgressMessage{id=null, status=null, stream=null, error=null, progress=null, progressDetail=null}
Successfully built 2177684b649d
Successfully tagged hello-service:0.0.1-SNAPSHOT
...
由于Docker構建時需要下載基礎鏡像信息, 所以過程會比較長, 所以我只粘貼了最后一部分編譯的信息。編譯完成后, 查看主機的鏡像信息。
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-service 0.0.1-SNAPSHOT 2177684b649d 13 minutes ago 875MB
rabbitmq 3-management 75472a5c510b 2 months ago 149MB
cemmersb/centos-jdk8 latest ccba23a213f2 3 years ago 858MB
- Docker鏡像生成后, 運行Docker容器
$ docker run -d -p 8080:8080 hello-service:0.0.1-SNAPSHOT
通過docker ps
命令查詢Docker容器是否正常啟動
$ docker ps
容器成功啟動后,打開瀏覽器訪問:http://localhost:8080/sayHello,調用接口頁面返回:Hello Spring Boot!,說明 Spring Boot 項目Docker容器工作正常。
5. 構建Spring Boot多模塊依賴工程
由于Spring Boot項目開發中經常會遇見多模塊的應用, 比如下面有一個應用sword
, 應用中包含以下幾個模塊, 其中需要部署三個應用sword-api、sword-job、sword-admin
:
- sword-common 公共模塊(基礎依賴)
- sword-util 常用工具模塊(基礎依賴)
- sword-api 接口模塊(獨立部署)
- sword-job 應用采集模塊(獨立部署)
- sword-admin 管理后臺模塊(獨立部署)
5.1 準備工作
- 配置總體項目POM
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.garyond</groupId>
<artifactId>sword</artifactId>
<version>2.0.0</version>
<packaging>pom</packaging>
<modules>
<module>sword-common</module> <!--核心業務 -->
<module>sword-admin</module><!-- 后臺 -->
<module>sword-api</module><!-- API -->
<module>sword-job</module><!-- 定時采集程序 -->
<module>sword-util</module><!-- 常用工具 -->
</modules>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.4.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
</project>
- 配置sword-common等基礎依賴模塊
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>sword-common</artifactId>
<packaging>jar</packaging>
<parent>
<groupId>com.garyod</groupId>
<artifactId>sword</artifactId>
<version>2.0.0</version>
<relativePath>../pom.xml</relativePath> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<relativePath/>
</properties>
<dependencies>
......
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<classifier>exec</classifier>
</configuration>
</plugin>
</plugins>
</build>
</project>
- 配置sword-api、sword-admin等應用模塊
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>sword-api</artifactId>
<packaging>jar</packaging>
<parent>
<groupId>com.garyond</groupId>
<artifactId>sword</artifactId>
<version>2.0.0</version>
<relativePath>../pom.xml</relativePath>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
......
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<executable>true</executable>
</configuration>
</plugin>
<!-- Docker maven plugin -->
<plugin>
<groupId>com.spotify</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>1.2.0</version>
<configuration>
<imageName>${project.groupId}/${project.artifactId}:${project.version}</imageName>
<baseImage>java:8</baseImage>
<maintainer>garyond</maintainer>
<entryPoint>["java", "-jar", "/${project.build.finalName}.jar"]</entryPoint>
<resources>
<resource>
<targetPath>/</targetPath>
<directory>${project.build.directory}</directory>
<include>${project.build.finalName}.jar</include>
</resource>
</resources>
</configuration>
</plugin>
<!-- Docker maven plugin -->
</plugins>
</build>
</project>
5.2 應用部署
- 進入父工程(sword)pom文件所在目錄,打包編譯,將依賴包放至本地倉庫
mvn clean install package -Dmaven.test.skip
- 分別進入各模塊(sword-api/sword-admin/sword-job)目錄,使用 Docker構建鏡像
mvn package docker:build -Dmaven.test.skip
- 運行Docker容器
docker run -d -p 8080:8080 --name=sword-admin sword-admin:2.0.0