# 構建以及執行Springboot Docker映象時的變數傳遞
Docker可以把我們的執行環境打包,然後我們只要run就可以了。大部分hello world都是這麼寫的。但都缺少了實際應用環節。以springboot為例,hello world的Dockerfile是這樣的:
FROM openjdk:8-jdk-alpine
VOLUME /tmp
ARG JAR_FILE
COPY ${JAR_FILE} app.jar
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]
我們實際使用的時候通常是
java -jar app.jar --spring.profiles.active=prod
也就是說,需要分環境。那直接
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar", "--spring.profiles.active=prod"]
這樣確實可以直接打出prod的執行包。直接run就可以了。
當同時需要打test環境的時候,我重新寫一個新的Dockerfile,改成test, 然後構建,就可以了。
docker build -t demo -f Dockerfile.test .
寫兩個Dockerfile看起來太傻逼了,構建時替換好了。
暴力替換 -- shell替換
準備好我們的Dockerfile
FROM openjdk:8-jdk-alpine VOLUME /tmp ARG JAR_FILE COPY ${JAR_FILE} app.jar ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar", "--spring.profiles.active=<active-profile>"]
然後我們的構建指令碼:
function build(){
local env=$1
sed -i 's/<active-profile>/${env}/g' Dockerfile
docker build -t demo --build-arg JAR_FILE=demo.jar .
}
# 構建測試環境的包
build test
# 構建生產環境的包
build prod
# 執行
docker run -d demo
使用執行時指定引數
我們可以打一份映象,在執行的時候傳遞profile來確定啟用哪個配置檔案,就和springboot原生一樣。
ENTRYPOINT裡是Docker容器的執行命令, CMD則是追加的引數,也就是說可以在後面加引數的。
docker run -d demo --spring.profiles.active=prod
執行時還可以傳遞環境變數,就是系統的環境變數。
$ docker run -e "SPRING_PROFILES_ACTIVE=prod" -p 8080:8080 -t springio/gs-spring-boot-docker
按照Springboot屬性覆蓋優先順序,命令列優先順序超過系統環境變數的,所以還是選擇其中一種方式就好了。
構建時傳遞引數
如果我們開發模式是master模式,即所有的分發部署都是同一個分支master, 先將master部署到test環境,沒問題後直接釋出到prod。同樣的映象,只是執行時指定配置檔案。那麼,我們是可以走執行時配置的。這樣,不同環境的K8s配置檔案要修改對應的cmd命令。
我現在開發模式類似gitflow. dev分支開發結束後,merge到test分支,test分支釋出到測試環境,測試環境ready後,再merge到master分支,master分支釋出到生產環境。即,test環境和prod環境是不同的分支打出的映象。這就使得在打映象的時候就指定配置檔案。可以選擇上文的暴力方式,文字替換。
也可以使用Docker引數。
Dockerfile
FROM openjdk:8-jdk-alpine
VOLUME /tmp
ARG JAR_FILE
ARG profile=prod
ENV SPRING_PROFILES_ACTIVE ${profile}
COPY ${JAR_FILE} app.jar
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]
構建
docker build -t demo --build-arg JAR_FILE=demo.jar --build-arg profile=test .
ARG
允許通過--build-arg
傳遞引數ENV
等同於docker run -e來設定系統環境變數,但優先順序弱於-e
上述幾種方案差不多解決了我的springboot容器化部署方式。在構建其他docker映象也可以通過類似的方案去傳遞引數。
大部分Dockerfile都是有docker-entrypoint.sh
, 將啟動邏輯都放在一個腳本里,然後
ENTRYPOINT ["/docker-entrypoint.sh"]
這樣,我們也可以在啟動的時候傳遞引數到腳本里,指令碼按照shell接受引數就可以了。
參考
- https://spring.io/guides/gs/spring-boot-docker/
- https://docs.spring.io/spring-boot/docs/2.1.6.RELEASE/reference/html/boot-features-external-config.html