Spring Boot應用Docker打包成映象
本教程將引導你通過建立一個Docker映象來執行Spring Boot應用。
你將構建什麼
Docker是一個具有社群性的Linux容器管理工具集,它允許使用者釋出映象或者使用其他開發者釋出的映象。Docker映象本質上是一個程序的執行環境。在這篇guide中,我們將構建一個執行Spring Boot應用程式的映象。
構建之前你要準備的東西
如果你當前使用的系統不是Linux,那麼你需要一個虛擬機器。通過安裝VirtualBox或者像mac的boot2docker等其他工具都可以滿足你的使用。
訪問VirtualBox下載地址選擇你的系統版本來下載VirtualBox,並且安裝執行起來。
當然你也需要安裝Docker(只能在64位機器上執行),有關詳細資訊請參閱https://docs.docker.com/installation/#installation來安裝Docker到你的系統上。開始下一步之前,你要確認在你的shell上是否可以執行docker
命令,如果你使用的是boot2docker,在執行docker
命令之前你需要先啟動boot2docker。
如何完成這篇教程
像大多數的Spring系列教程 Getting Started guides,你可以從頭開始,完成每一步,也可以跳過已經熟悉的基本構建步驟。 無論哪種方式,你都可以成功。
使用maven構建
首先你得安裝構建指令碼. 你可以使用你喜歡的構建系統去構建Spring應用,你可以前往
建立目錄結構
在你當前專案工作目錄中,建立如下子目錄:
1234 | └── src └── main └── java └── hello |
如在Linux系統下使用mkdir -p src/main/java/hello
來建立。
pom.xml
<?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>org.springframework</groupId> <artifactId>gs-spring-boot-docker</artifactId> <version>0.1.0</version> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.4.RELEASE</version> </parent> <properties> <java.version>1.8</java.version> </properties> <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> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
- 它集中了
classpath
下的所有jar,並構建一個可執行的“uber-jar”,這樣可以更方便地執行和釋出服務。 - 它查詢
public static void main()
方法並標記該類為可執行類。 - 它提供了一個內建的依賴解析器,將應用與Spring Boot依賴的版本號進行匹配。你可以修改(override)成你希望的版本,但它預設為Spring Boot選擇的版本。
使用你的IDE構建
建立一個Spring Boot應用程式
現在你可以建立一個簡單的Spring Boot應用程式。
src/main/java/hello/Application.java
package hello;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@SpringBootApplication
@RestController
public class Application {
@RequestMapping("/")
public String home() {
return "Hello Docker World";
}
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
這個類使用@SpringBootApplication
註解和@RestController
註解標記,表示這個類已經準備好使用Spring
MVC來處理web請求。@RequestMapping
對映/
在home()
方法上,這個方法返回Hello
Docker World
的響應。main()
方法調SpringApplication.run()
方法來啟動應用程式。
現在你可以在沒有Docker的情況下執行該應用程式。
如果你使用gradle構建的Spring Boot應用程式,執行:
./gradlew build && java -jar build/libs/gs-spring-boot-docker-0.1.0.jar
如果你使用maven構建的,執行:
./mvnw package && java -jar target/gs-spring-boot-docker-0.1.0.jar
然後訪問localhost:8080就可以看見Hello
Docker World
字樣。
使你的應用程式容器化
Docker有一個Dockerfile檔案格式的檔案,並且使用指定的映象作為基礎映象。接下來我們去建立一個Dockerfile在Spring Boot應用程式中。
Dockerfile
12345 | FROM openjdk:8-jdk-alpineVOLUME /tmpADD target/gs-spring-boot-docker-0.1.0.jar app.jarENV JAVA_OPTS=""ENTRYPOINT exec java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -jar /app.jar |
這個Dockerfile很簡單,但是已經包含了你執行這個Spring Boot應用程式的所有東西並且沒有多餘的東西:僅僅只有Java和一個Jar檔案。應用程式的jar檔案(檔名為app.jar)被新增到容器中,執行 ENTRYPOINT
我們增加了一個
VOLUME
指向”/tmp”,因為那是Spring Boot應用程式為Tomcat建立的預設工作目錄。作用是在你的主機”/var/lib/docker”目錄下建立一個臨時的檔案,並且連結到容器中的”/tmp”目錄。對於簡單程式這一步是可選的,但是對於其他想要真實寫入檔案系統的Spring Boot應用程式又是必選的。我們增加了一個指向”/dev/urandom”的Tomcat系統屬性來縮小Tomcat的啟動時間。
如果你使用的是boot2docker,在你使用Docker命令或者使用構建工具構建(它執行在守護程序,在虛擬機器上為你工作)之前,你必須先啟動它。
構建Docker映象,你可以使用一些諸如Gradle或Maven的工具或者藉助社群(強烈感謝Transmode和Spotify提供這些工具)。
使用Maven構建Docker映象
在Maven的pom.xml
中,你應該增加一個外掛,如下。(參閱the
plugin documentation獲取更多資訊)。
pom.xml
123456789101112131415 | <properties> <docker.image.prefix>springio</docker.image.prefix></properties><build> <plugins> <plugin> <groupId>com.spotify</groupId> <artifactId>dockerfile-maven-plugin</artifactId> <version>1.3.4</version> <configuration> <repository>${docker.image.prefix}/${project.artifactId}</repository> </configuration> </plugin> </plugins></build> |
配置指定了兩個東西:
- 映象名字,最終會在
springio/gs-spring-boot-docker
- 可選,映象的標籤,未指定預設為
latest
,如果有需要的話,也可以指定artifact id
。
繼續下面的步驟之前(使用Docker CLI工具),輸入
docker ps
確保正常執行,如果有錯誤資訊,大概因為沒有設定其他什麼資訊。如果使用的Mac,在.bash_profile
(或者是類似env-setting配置檔案)最後增加$(boot2docker shellinit 2> /dev/null)
並重新整理你的shell,確保更改生效。
你可以使用下面的命令來構建Docker的映象:
1 | $ ./mvnw install dockerfile:build |
你可以使用./mvnw dockerfile:push
命令釋出映象到Docker
映象中心去。
你不用著急釋出你剛剛製作的映象,如果你不是”springio”組織的成員
push
命令會失敗。改變構建的配置和命令列中的使用者名稱為自己的而不是”springio”就可以正常工作。你可以讓
dockerfile:push
自動執行在安裝或部署生命週期階段,通過將其新增到外掛配置中。
pom.xml
12345678910 | <executions> <execution> <id>default</id> <phase>install</phase> <goals> <goal>build</goal> <goal>push</goal> </goals> </execution></executions> |
釋出之後
對你來說”Docker映象釋出”會失敗(除非你在Dockerhub中是”springio”組織的一員),但是如果你修改配置符合你自己的docker ID之後同樣會成功,你會有一個新的標籤,並且部署映象。
如果你沒有註冊docker,或者沒有釋出任何docker映象。但是你有一個本地的映象,你可以像這樣讓它執行起來:
1234 $ docker run -p 8080:8080 -t springio/gs-spring-boot-docker....2015-03-31 13:25:48.035 INFO 1 --- [ main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 8080 (http)2015-03-31 13:25:48.037 INFO 1 --- [ main] hello.Application : Started Application in 5.613 seconds (JVM running for 7.293)
然後應用程式可以在http://localhost:8080/訪問(訪問可以看到”Hello Docker World”)。確保它是真的在工作,把”springio”字首改成其他(比如${env.USER}
並且重新構建執行)。
如果你使用mac的boot2docker,你通常在啟動時可以看到這樣的事情:
1234 Docker client to the Docker daemon, please set: export DOCKER_CERT_PATH=/Users/gturnquist/.boot2docker/certs/boot2docker-vm export DOCKER_TLS_VERIFY=1 export DOCKER_HOST=tcp://192.168.59.103:2376 檢視應用程式,你必須訪問Docker主機而不是本地主機的ip(localhost),在這種情況下,http://192.168.59.103:8080/,對於VM來說就是開發的ip。
當它正在執行,你可以在容器列表中看到:
123 | $ docker psCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES81c723d22865 springio/gs-spring-boot-docker:latest "java -jar /app.jar" 34 seconds ago Up 33 seconds 0.0.0.0:8080->8080/tcp goofy_brown |
你可以使用docker stop
加上容器的id來關閉它。
12 | $ docker stop 81c723d2286581c723d22865 |
當然你喜歡你也可以刪除容器(它們都儲存在/var/lib/docker
檔案目錄下)。
1 | $ docker rm 81c723d22865 |
使用Spring Profiles
執行你新制作的映象使用Spring Profiles,和執行docker命令傳入一個環境變數一樣簡單。
1 | $ docker run -e "SPRING_PROFILES_ACTIVE=prod" -p 8080:8080 -t springio/gs-spring-boot-docker |
或
1 | $ docker run -e "SPRING_PROFILES_ACTIVE=dev" -p 8080:8080 -t springio/gs-spring-boot-docker |
在Docker容器中除錯應用程式
使用JPDA Transport可以除錯應用程式,所以我們可以視容器為一個伺服器,啟用此功能通過java設定JAVA_OPTS變數和代理的埠對映到本地主機在一個容器中執行。對於Docker for Mac由於有限制,我們不能通過IP訪問容器因為沒有black magic usage.。
1 | $ docker run -e "JAVA_OPTS=-agentlib:jdwp=transport=dt_socket,address=5005,server=y,suspend=n" -p 8080:8080 -p 5005:5005 -t springio/gs-spring-boot-docker |
總結
恭喜你!剛剛為Spring Boot應用程式建立了Docker容器!Spring Boot應用程式在容器中執行預設埠8080對映到相同的宿主機埠使用”-p”引數。
另請參閱
以下教程也可能是有用的: