簡體   English   中英

有條件地在 docker-compose 中掛載卷以適應多種情況

[英]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 文件。 由於以下幾個原因,這對於我的案例來說並不是一個真正可行的解決方案:

  • 這個工具是為那些不一定了解 docker、docker-compose 或相關實用程序的人設計的,所以期望他們編寫/編輯自己的 docker-compose.yml 文件是一個問題
  • 這些目錄不止兩個(我以兩個為例),實際上我無法為這些路徑的每個可能組合創建一個 docker-compose 文件,這些路徑被聲明或未聲明
  • 老實說,考慮到所需的信息就在 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

docker-compose.yml

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"]

.env

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.ymldocker-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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM