這個問題是筆者在運行docker-blog-example這個repo時發生的。
這個repo本來是不會造成這個問題的,筆者為了配置方便,選擇自行另外建立一個.env檔案,與docker-compose.yml配合使用。
.env檔裡面儲存了建立docker集群及部署服務時需要用到的環境變量。
在使用docker-compose up
這個指令時,會參考docker-compose.yml這個配置檔。
而docker-compose.yml這個檔案會接著調用在.env檔案裡面定義的$HOSTIP
這個環境變量。
筆者發現在.env檔裡定環境變量這個方法對docker-compose
管用,但是對docker stack deploy
來說卻不管用。
後來在GitHub尋找原因,才看到原來是因為docker stack deploy
本來就不支持這種用法。
因此在後面我們會採用一些補丁來解決這個問題。
首先看到docker stack deploy in 1.13 doesn’t load .env file as docker-compose up does,這個討論串中dnephin的回答說明了docker stack deploy確實無法從.env檔案中載入環境變量。
討論串中有不少人提出他們自己的解決方案,筆者親測了whoan的回答,做了一些修改,使它成為一個可以運行的腳本:
dsd() {
stack=${1:-${PWD##*/}} # by default, the name of the cointaining folder
compose_file=${2:-docker-compose.yml}
if [ ! -f $compose_file ]; then
echo "Misses compose file: $compose_file" >&2
return 1
fi
# execute as a subcommand in order to avoid the variables remain set
(
# export variables excluding comments
[ -f .env ] && export $(sed '/^#/d' .env)
# Use dsd your_stack your_compose_file to override the defaults
docker stack deploy --compose-file $compose_file $stack
)
}
dsd
這個腳本運行的原理如下:
雖然docker stack deploy
無法從.env檔裡載入環境變量,但是它卻可以從當前環境中找出它需要的環境變量。
他的做法就是在呼叫docker stack deploy
之前,先在當前環境中設定所需的環境變量,以此來繞過它無法從.env檔中抓出環境變量的限制。
而"設定環境變量+docker stack deploy
"這兩個指令是以subcommand的角色被執行的,所以在整段bash檔執行結束後,環境變量會自動消失。
我們將以上內容寫進secrets.sh
,接著將secrets.sh
變成可以執行的檔案:
chmod +x secrets.sh
然後運行:
./secrets.sh
就會發現.env檔中定義的環境變量是可以被成功載入的。
kinghuang的回答更簡單,只要在docker stack deploy後面加上-c <(docker-compose config)這個參數,在建置時就可以自動將.env檔內的環境變量載入。
docker stack deploy -c <(docker-compose config) <stack-name>
docker stack deploy in 1.13 doesn’t load .env file as docker-compose up does
How to Get Environment Variables Passed Through docker-compose to the Containers