這是一個普通的docker-compose文件
version: '3'
services:
applymgr:
image: harbor.cloud.test/online/applymgr:b88b2301
networks:
- default
dns:
- 10.99.165.22
extra_hosts:
- "zk_hadoop_hbase_kafka:10.109.95.32"
environment:
CONFIG_SERVER_URI: http://10.09.65.43:8002
DEUREKA_URL: http://user:123@10.19.25.53:8001
JAVA_OPTS: -Xms1024m -Xmx1024m -XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=256m -XX:+UseConcMarkSweepGC -XX:+CMSParallelRemarkEnabled -XX:+UseCMSCompactAtFullCollection -XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=70
command: java -jar -Dspring.profiles.active=test3 manager.jar
ports:
- "18001:8080"
networks:
default:
driver: bridge
這里 environment 表示環境變量。我們這里設置了一些環境變量。數量不多,但是顯得很繁瑣。
command 表示我們使用什么命令啟動鏡像中的jar 文件,它會覆蓋Dockerfile中的CMD指令。
這里我們看到配置都是寫死的,怎么才能配置化呢?
docker-compose 其實支持文件環境變量
version: '3'
services:
applymgr:
image: harbor.cloud.test/online/applymgr:b88b2301
networks:
- default
dns:
- 10.99.165.22
extra_hosts:
- "zk_hadoop_hbase_kafka:10.109.95.32"
env_file:
- ./common.env
command: java -jar ${RUN_PROFILE} manager.jar
ports:
- "18001:8080"
networks:
default:
driver: bridge
這里可以看到我們把具體的環境變量換成了引用 當前目錄下的 common.env文件。同時command 指令也使用了占位符來獲取環境變量的值。看下環境變量文件中的內容:
CONFIG_SERVER_URI=http://10.88.75.83:8002
EUREKA_URL=http://user:123@10.88.75.83:8001
JAVA_OPTS=-Xms512m -Xmx512m -XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=256m -XX:+UseConcMarkSweepGC -XX:+CMSParallelRemarkEnabled -XX:+UseCMSCompactAtFullCollection -XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=70
RUN_PROFILE=-Dspring.profiles.active=test3
TZ="Asia/Shanghai"
這里需要注意的是,環境變量文件 最好使用 key=value的形式 不要使用 key:value的形式,否則會出現null的情況
之后怎么驗證呢,其實我們可以使用命令查看docker-compose.yml效果
docker-compose config
執行該命令,得到結果:
networks: default: driver: bridge services: applymgr: command: java -jar manager.jar dns: - 10.99.165.22 environment: CONFIG_SERVER_URI: http://10.88.75.83:8002 EUREKA_URL: http://user:123@10.88.75.83:8001 JAVA_OPTS: -Xms512m -Xmx512m -XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=256m -XX:+UseConcMarkSweepGC -XX:+CMSParallelRemarkEnabled -XX:+UseCMSCompactAtFullCollection -XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=70 RUN_PROFILE: -Dspring.profiles.active=test3 extra_hosts: - zk_hadoop_hbase_kafka:10.109.95.32 image: harbor.cloud.test/online/applymgr:b88b2301 networks: default: null ports: - 18001:8080/tcp version: '3.0'
發現環境變量都設置進去了,但是我們再commond 那里設置的占位符 卻變成了空格。那說名占位符並沒有取到環境變量的值。
那么這是什么原因了。如果我們把 common.env 重命名為 .env 。同時更改docker-compose.yml文件 env_file 中的文件名。此時可以看到
version: '3' services: applymgr: image: harbor.cloud.test/online/applymgr:b88b2301 networks: - default dns: - 10.99.165.22 extra_hosts: - "zk_hadoop_hbase_kafka:10.109.95.32" env_file: - ./.env command: java -jar ${RUN_PROFILE} manager.jar ports: - "18001:8080" networks: default: driver: bridge
結果:
networks: default: driver: bridge services: applymgr: command: java -jar -Dspring.profiles.active=test3 manager.jar dns: - 10.99.165.22 environment: CONFIG_SERVER_URI: http://10.88.75.83:8002 EUREKA_URL: http://user:123@10.88.75.83:8001 JAVA_OPTS: -Xms512m -Xmx512m -XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=256m -XX:+UseConcMarkSweepGC -XX:+CMSParallelRemarkEnabled -XX:+UseCMSCompactAtFullCollection -XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=70 RUN_PROFILE: -Dspring.profiles.active=test3 extra_hosts: - zk_hadoop_hbase_kafka:10.109.95.32 image: harbor.cloud.test/online/applymgr:b88b2301 networks: default: null ports: - 18001:8080/tcp version: '3.0'
可以看到command 獲取環境變量成功了。因為如果我們使用文件設置環境變量。那么文件名 盡量設置為 .env。
同時獲取 環境變量 可以使用 ${} 也可以直接使用 $
需要注意的是,當我們使用java docker時,如果要設置自定義參數時,盡量避免 使用 JAVA_OPTS 這個環境變量的Key。因為如果設置了這個環境變量,啟動后並不會按照你設置的參數來啟動java應用,而是會走默認的一個java參數,因此可以設置一個其他名稱來啟動(如:MY_JAVA_OPTS)。具體的其實可以 通過docker-compose cofig命令來看。
實際上我們還可以做一個實驗。就是 我們不設置 JAVA_OPTS 這個環境變量
但是在寫 command 的時候 加上 $JAVA_OPTS 環境變量 。如 java -jar $JAVA_OPTS xx.jar
這個時候使用 docker-compose config 來查看 會發現 command 命令已經加上了啟動參數(雖然我們並沒有設置這個環境變量)。
之所以會出現這個,是因為docker-compose 對各種情況下的環境變量有個優先級的概念!也就是我們構建的鏡像的基礎鏡像設置了這個環境變量,但是我們設置的環境變量並沒有覆蓋基礎鏡像設置的環境變量。
還有一點是需要注意的。如果我們在docker-compose.yml 的environment中添加了環境變量,同時在command中使用了這個變量,其實是並不生效的。
.......
environment:
JAVA_FILE: app.jar
# 這里 返回的實際是 java -jar 。只有使用env_file(且該值為.env)設置的環境變量占位符才會被替換
command: java -jar ${JAVA_FILE}
.......
那么如果 environment 中定義的環境變量 和 env_file中定義的變量重復了會怎么樣。
實際通過docker-compose config的測試發現。
例如。我們的 .env 文件中 定義了 JAVA_FILE: test.jar。我們的docker-compose.yml定義為。
.......
environment:
JAVA_FILE: app.jar
env_file:
- ./.env
# 這里 返回的實際是 java -jar 。只有使用env_file(且該值為.env)設置的環境變量占位符才會被替換
command: java -jar ${app.jar}
.......
實際結果卻是
.......
environment:
JAVA_FILE: app.jar
command: java -jar test.jar
.......
因此我們可以得到結論,environment跟env_file的作用范圍是有差別的,就單純從環境變量來看,environment的優先級更高,從占位符替換來看,卻只能使用env_file(.env)
有時候我們的服務不是一下子都寫好的,有可能是先啟動了幾個應用,然后過了幾天又要上線幾個應用,那么我們又得編輯docker-compose文件。把新添加的服務加上去,
然后使用
#停止服務,並刪除容器
docker-compose down
#后台啟動所有服務 docker-compose up -d
如果你的應用比較多,那么過程會很慢。其實如果我們在docker-compose.yml中新添加了幾個應用,這個時候是可以單獨啟動這幾個應用的。
docker-compose -f docker-compose.yml up -d [新添加的應用名]
這樣就可以單獨啟動新加的應用了,而且新加的應用也是可以訪問之前的應用的。之前的應用也可以訪問新添加的應用
