如何检查Docker卷是否存在且非空,按需运行不同docker-compose.yml
我通过Dockerfile和docker-compose部署Rasa应用,应用启动时会从AWS存储桶加载模型运行。但容器因云服务商故障意外重启时,会重复执行从AWS加载模型的操作。我希望将模型存储在持久卷中,重启时检查该卷是否存在且非空,若满足条件则使用不带--remote-storage aws参数的命令启动,避免重复加载模型。
现有docker-compose.yml部分配置:
rasa-server: image: rasa-bot:latest working_dir: /app build: context: ./ dockerfile: Dockerfile volumes: - ./models:/app/models command: bash -c "rasa run --model model.tar.gz --remote-storage aws --endpoints endpoints.yml --credentials credentials.yml --enable-api --cors \"*\" --debug --port 5006"
重启时需要的启动命令(移除了--remote-storage aws):
command: bash -c "rasa run --model model.tar.gz --endpoints endpoints.yml --credentials credentials.yml --enable-api --cors \"*\" --debug --port 5006"
Dockerfile内容:
FROM python:3.7.7-stretch AS BASE RUN apt-get update \ && apt-get --assume-yes --no-install-recommends install \ build-essential \ curl \ git \ jq \ libgomp1 \ vim WORKDIR /app RUN pip install --no-cache-dir --upgrade pip RUN pip install rasa==3.1 RUN pip3 install boto3 ADD . .
我知道可以用docker volume ls查看卷列表,但不清楚如何通过if条件检查./models:/app/models对应的存储是否存在且非空,再据此执行对应的启动逻辑。
推荐两种实现方式,优先选择容器内判断的方案,逻辑更贴合容器化部署的设计:
方法1:容器内启动脚本判断(推荐)
不需要拆分docker-compose配置,将判断逻辑封装成启动脚本,让容器自行决定启动方式。
步骤1:创建启动脚本
在项目根目录创建start_rasa.sh,内容如下:
#!/bin/bash # 检查容器内模型目录是否存在目标模型文件 if [ -f "/app/models/model.tar.gz" ]; then echo "检测到本地模型,使用本地模型启动服务" rasa run --model model.tar.gz --endpoints endpoints.yml --credentials credentials.yml --enable-api --cors "*" --debug --port 5006 else echo "未检测到本地模型,从AWS存储桶加载启动" rasa run --model model.tar.gz --remote-storage aws --endpoints endpoints.yml --credentials credentials.yml --enable-api --cors "*" --debug --port 5006 fi
给脚本添加执行权限:
chmod +x start_rasa.sh
步骤2:修改docker-compose配置
将原command替换为执行启动脚本:
rasa-server: image: rasa-bot:latest working_dir: /app build: context: ./ dockerfile: Dockerfile volumes: - ./models:/app/models command: ./start_rasa.sh
步骤3:更新Dockerfile(可选)
如果项目根目录的ADD . .已经包含start_rasa.sh,则无需修改;若未包含,需添加一行拷贝脚本的指令:
COPY start_rasa.sh /app/
方法2:宿主机脚本控制docker-compose
在宿主机层面判断存储状态,选择对应的docker-compose配置启动。
步骤1:创建本地启动配置文件
复制原docker-compose.yml为docker-compose.local.yml,修改其中的command为不带AWS参数的版本:
rasa-server: image: rasa-bot:latest working_dir: /app build: context: ./ dockerfile: Dockerfile volumes: - ./models:/app/models command: bash -c "rasa run --model model.tar.gz --endpoints endpoints.yml --credentials credentials.yml --enable-api --cors \"*\" --debug --port 5006"
步骤2:写宿主机启动脚本
创建run_app.sh,内容如下:
#!/bin/bash # 检查宿主机上的模型目录是否非空(当前使用的是绑定挂载,而非Docker命名卷) if [ "$(ls -A ./models)" ]; then echo "本地模型目录非空,使用本地配置启动" docker-compose -f docker-compose.local.yml up -d else echo "本地模型目录为空,使用AWS加载配置启动" docker-compose up -d fi
添加执行权限并运行:
chmod +x run_app.sh ./run_app.sh
注意事项
- 当前你使用的是绑定挂载(
./models:/app/models),判断的是宿主机本地./models目录的状态;如果改用Docker命名卷(比如- rasa-models:/app/models),则需要通过临时容器挂载卷来检查内容,示例判断逻辑:if docker run --rm -v rasa-models:/tmp/models alpine ls -A /tmp/models | grep -q .; then docker-compose -f docker-compose.local.yml up -d else docker-compose up -d fi
内容的提问来源于stack exchange,提问作者Bananachip

