[英]Conditionally mount volumes in docker-compose for several conditions
我使用 docker 和 docker compose 將科學工具打包成易於/通用的可執行模塊。 一個例子是一個 docker,它將一個相當復雜的 python 庫打包到一個運行 jupyter notebook 服務器的容器中; 這個想法是,其他不太精通技術的科學家可以克隆一個 github 存儲庫,運行docker-compose up
然后進行分析,而無需安裝庫、配置各種插件和其他依賴項等。
我讓這一切工作正常,只是我在讓卷安裝以連貫的方式工作時遇到問題。 這樣做的原因是 docker 容器內的庫處理多種數據集,用戶將這些數據集存儲在幾個單獨的目錄中,這些目錄通常通過 shell 環境變量進行跟蹤。 (請不要告訴我這是一個糟糕的方法——這是在現場做事的方式,而不是我選擇的做事方式。)因此,例如,如果用戶存儲 FreeSurfer 數據,它們將有一個名為 SUBJECTS_DIR 的環境變量,指向包含數據的目錄; 如果他們存儲 HCP 數據,他們將有一個環境變量 HCP_SUBJECTS_DIR。 但是,他們可能同時擁有這些集合,或者兩者都沒有(以及其他一些)。
我希望能夠在我的 docker-compose.yml 文件中放置類似的內容以處理這些情況:
version: '3'
services:
my_fancy_library:
build: .
ports:
- "8080:8888"
environment:
- HCP_SUBJECTS_DIR="/hcp_subjects"
- SUBJECTS_DIR="/freesurfer_subjects"
volumes:
- "$SUBJECTS_DIR:/freesurfer_subjects"
- "$HCP_SUBJECTS_DIR:/hcp_subjects"
在對此進行測試時,如果用戶設置了兩個環境變量,則一切正常。 但是,如果他們沒有這些設置中的一個,我會收到關於未安裝長度少於 2 個字符的目錄的錯誤(我認為這是對安裝由“:/hcp_subjects”指定的卷的抱怨)。
這個問題問的基本相同,答案指向這里,如果我理解正確的話,它基本上解釋了如何以某種方式解決多個 docker-compose 文件。 由於以下幾個原因,這對於我的案例來說並不是一個真正可行的解決方案:
我能夠想出的唯一體面的解決方案是要求用戶運行腳本./run.sh
而不是docker-compose up
; 該腳本檢查環境變量,用適當的卷寫出自己docker-compose.yml
文件,並運行docker-compose.yml
docker-compose up
本身。 這看起來也有點笨拙,但它有效。
有沒有人知道在運行docker-compose up
時根據環境變量的狀態有條件地掛載一組卷的方法?
您可以在與.env
docker-compose.yml
[1]一起提供的.env
文件中設置環境變量的默認值。
通過默認將環境變量設置為/dev/null
,然后在容器化應用程序中處理這種情況,您應該能夠實現您所需要的。
$ tree -a
.
├── docker-compose.yml
├── Dockerfile
├── .env
└── run.sh
version: "3"
services:
test:
build: .
environment:
- VOL_DST=${VOL_DST}
volumes:
- "${VOL_SRC}:${VOL_DST}"
FROM alpine
COPY run.sh /run.sh
ENTRYPOINT ["/run.sh"]
VOL_SRC=/dev/null
VOL_DST=/volume
#!/usr/bin/env sh
set -euo pipefail
if [ ! -d ${VOL_DST} ]; then
echo "${VOL_DST} not mounted"
else
echo "${VOL_DST} mounted"
fi
未定義環境變量VOL_SRC
:
$ docker-compose up
Starting test_test_1 ... done
Attaching to test_test_1
test_1 | /volume not mounted
test_test_1 exited with code 0
環境變量VOL_SRC
定義:
$ VOL_SRC="./" docker-compose up
Recreating test_test_1 ... done
Attaching to test_test_1
test_1 | /volume mounted
[1] https://docs.docker.com/compose/environment-variables/#the-env-file
雖然@Ente 的回答解決了這個問題,但當您在環境之間有更復雜的差異時,這里有一個替代解決方案。
Docker compose 支持多個 docker-compose 文件,用於在不同環境中進行配置覆蓋。
這很有用,例如,如果您有不同的命名卷,您可能需要根據環境將其安裝在同一路徑上。
您可以修改現有服務,甚至添加新服務,例如:
# docker-compose.yml
version: '3.3'
services:
service-a:
image: "image-name"
volumes:
- type: volume
source: vprod
target: /data
ports:
- "80:8080"
volumes:
vprod:
vdev:
然后你有覆蓋文件來更改卷映射:
# docker-compose.override.yml
services:
service-a:
volumes:
- type: volume
source: vdev
target: /data
運行docker-compose up -d
兩個配置都將與優先的覆蓋文件合並。
Docker compose 默認選取docker-compose.yml
和docker-compose.yml
docker-compose.override.yml
,如果文件較多,或者文件名不同,需要按順序指定:
docker-compose -f docker-compose.yml -f docker-compose.custon.yml -f docker-compose.dev.yml up -d
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.