SpringBoot之jar構建docker容器(Maven外掛)-yellowcong
將springboot的服務,都做成了容器的,老爽了,這樣就可以直接將war包或者是jar包,都封裝到容器裡面,然後可以直接執行服務了,一次構建,到處運行了,說實話,俺還是踩了不少的坑啊,這個地方,我們要確認自己的docker伺服器開啟了遠端埠,不然就不能打包到目標伺服器上了。
實驗準備
#先確保有映象在docker上,不然會在編譯的時候pull容器
docker pull docker.io/relateiq/oracle-java8
1、建立軟連線
ln -s /usr/libexec/docker/docker-proxy-current /usr/bin/docker-proxy
ln -s /usr/libexec/docker/docker-runc-current docker-runc
2、配置Dockerfile
一定要確保映象存在,不然就會報錯,說映象不存在的問題。
FROM daocloud.io/library/java:openjdk-8u40
VOLUME /tmp
ADD datav-eureka-0.0.1-SNAPSHOT.jar app.jar
#RUN bash -c 'touch /app.jar'
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar" ]
EXPOSE 8761
引數說明
引數 | 解釋 |
---|---|
FROM | 表示用的哪個映象 |
ENTRYPOINT | 表示容器複製完後執行的名利 |
VOLUME /tmp | 建立/tmp目錄並持久化到Docker資料資料夾,因為Spring Boot使用的內嵌Tomcat容器預設使用/tmp作為工作目錄。 |
ADD docker-springboot-0.0.1-SNAPSHOT.jar app.jar | 將應用jar包複製到/app.jar |
ENTRYPOINT [“java”,”-Djava.security.egd=file:/dev/./urandom”,”-jar”,”/app.jar”] | 執行java -Djava.security.egd=file:/dev/./urandom -jar /aap.jar 命令 |
EXPOSE 8761 | 開放8761埠 |
#/dev/urandom則是一個非阻塞的發生器
java -Djava.security.egd=file:/dev/./urandom -jar /aap.jar
關於執行命令的說法
dev/random的一個副本是/dev/urandom(”unlocked”,非阻塞的隨機數發生器),它會重複使用熵池中的資料以產生偽隨機資料。這表示對/dev/urandom的讀取操作不會產生阻塞,但其輸出的熵可能小於/dev/random的。它可以作為生成較低強度密碼的偽隨機數生成器,不建議用於生成高強度長期密碼。
另外wiki裡也提到了為什麼linux核心裡的隨機數生成器採用SHA1雜湊演算法而非加密演算法,是為了避開法律風險(密碼出口限制)。
回到tomcat文件裡的建議,採用非阻塞的熵源(entropy source),通過java系統屬性來設定:
-Djava.security.egd=file:/dev/./urandom
這個系統屬性egd表示熵收集守護程序(entropy gathering daemon),但這裡值為何要在dev和random之間加一個點呢?是因為一個jdk的bug,在這個bug的連線裡有人反饋及時對 securerandom.source 設定為/dev/urandom它也仍然使用的/dev/random,有人提供了變通的解決方法,其中一個變通的做法是對securerandom.source設定為/dev/./urandom才行。也有人評論說這個不是bug,是有意為之。
3、配置pom.xml
docker.image.prefix
這個需要我們自己手動指定。
<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>yellowcong.com</groupId>
<artifactId>datav-eureka</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>cas-client-springboot</name>
<url>http://maven.apache.org</url>
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
<!-- 引用父類依賴 -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.10.RELEASE</version>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<docker.image.prefix>springboot</docker.image.prefix>
</properties>
<dependencies>
<!--eureka server -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka-server</artifactId>
<version>1.3.0.RELEASE</version><!--$NO-MVN-MAN-VER$-->
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<!-- 新增spring的外掛, 就可以直接通過 mvn spring-boot:run 運行了 -->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>springloaded</artifactId>
<version>1.2.4.RELEASE</version>
</dependency>
</dependencies>
</plugin>
<plugin>
<groupId>com.spotify</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>0.4.13</version>
<configuration>
<!-- 映象地址 -->
<imageName>${docker.image.prefix}/${project.artifactId}</imageName>
<!-- docker的DockerFile配置檔案路徑 -->
<dockerDirectory>src/main/docker</dockerDirectory>
<!-- 遠端docker容器的地址 -->
<dockerHost>http://192.168.100.10:2375</dockerHost>
<resources>
<resource>
<targetPath>/</targetPath>
<directory>${project.build.directory}</directory>
<include>${project.build.finalName}.jar</include>
</resource>
</resources>
</configuration>
</plugin>
</plugins>
</build>
</project>
4、配置application.yml
這個與我們的docker打包,沒有半毛錢關係,可以忽略掉。
# 註冊服務的埠
server:
port: 8761
#配置eureka
eureka:
instance:
#主機名稱
hostname: localhost
client:
#registerWithEureka 和fetchRegistry 都設定為 false 表示是 服務端
registerWithEureka: false
fetchRegistry: false
serviceUrl:
#伺服器地址,${} 表示引用
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
5、編譯容器
#執行命令構建docker容器
mvn clean package docker:build
6、執行容器
#執行容器
docker run -d -p 9000:8761 springboot/datav-eureka
#檢視當前執行的容器
docker ps
#檢視端口占用(3756f54bc69b 為容器的id)
docker port 3756f54bc69b
7、訪問容器裡面的服務
可以看到,我直接訪問宿主機的域名,直接就指向了目標的9000埠,直接訪問到了容器的資訊了。
常見問題
1、/usr/bin/docker-current: Error response from daemon: shim error: docker-runc not installed on system.
打包完成後,執行容器,就找不到docker-runc 了
#到docker的lib目錄
cd /usr/libexec/docker/
#執行軟連線
ln -s /usr/libexec/docker/docker-runc-current docker-runc
軟連線一個docker-runc
啟動容器,發現一切ok了
2、/usr/bin/docker-current: Error response from daemon: driver failed programming external connectivity on endpoint flamboyant_knuth exec: “docker-proxy”: executable file not found in $PATH.
這個異常的原因是docker啟動後將會執行docker-proxy指令,但是在shell中載入的$PATH中無法找到對應的指令。與之類似是docker-runc無法找到,這個原因是在/usr/libexec/docker下面,在安裝的時候可能因為沒有完全安裝導致的兩個link沒有安裝上,用如下方法進行修補:
ln -s /usr/libexec/docker/docker-proxy-current /usr/bin/docker-proxy