简体   繁体   English

如何在 Docker 中检查卷是否存在且不为空,并根据此运行不同的 docker-compose.yml?

[英]How to check in Docker whether a volume exists and is not empty and run different docker-compose.yml depending on this?

I'm deploying an application with a Dockerfile and docker-compose.我正在部署一个带有 Dockerfile 和 docker-compose 的应用程序。 It loads a model from an AWS bucket to run the application.它从 AWS 存储桶加载模型以运行应用程序。 When the containers get restarted (not intentionally but because of the cloud provider), it loads again the model from AWS.当容器重新启动时(不是故意的,而是因为云提供商),它会再次从 AWS 加载模型。 What I would like to achive is storing the model on a persistent volume.我想要实现的是将模型存储在持久卷上。 In case of a restart, I would like to check whether the volume exists and is not empty and if so run a different docker-compose file which has a different bash command, not loading the model from AWS again.在重新启动的情况下,我想检查该卷是否存在且不为空,如果是,则运行具有不同 bash 命令的不同 docker-compose 文件,而不是再次从 AWS 加载模型。

This is part of my docker-compose.yml:这是我的 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" 

In case of a restart the command would look like this:如果重新启动,命令将如下所示:

    command: bash -c "rasa run --model model.tar.gz --endpoints endpoints.yml --credentials credentials.yml --enable-api --cors \"*\" --debug --port 5006" 

Note that this请注意,这

--remote-storage aws --remote-storage aws

was removed.去掉了。

This is my Dockerfile:这是我的 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 . .

I know that I can use this:我知道我可以使用这个:

docker volume ls

to list volumes.列出卷。 But I do not know how to wrap this in a if condition to check whether但我不知道如何将其包装在 if 条件中以检查是否

     - ./models /app/models

exists and is not empty and if it is not empty run a second docker-compose.yml which contains the second modified bash command.存在且不为空,如果不为空,则运行第二个 docker-compose.yml,其中包含第二个修改后的 bash 命令。

You could have an if statement in your bash command to use aws or not depending on the result you get from docker volume ls using -f name= you can filter based on the volume name and then you can check if its not null and run a different command.您可以在 bash 命令中使用 if 语句来使用 aws,具体取决于您使用 -f name= 从docker volume ls获得的结果,您可以根据卷名称进行过滤,然后您可以检查它是否不为空并运行不同的命令。
Note that this command is just an example and I have no idea if it works or not as I don't use bash day -to-day请注意,此命令只是一个示例,我不知道它是否有效,因为我每天都不使用 bash

command: bash -c "
    VOLUME = docker volume ls -f name=FOO
    if [ -z "$VOLUME" ]; 
    then
        rasa run --model model.tar.gz --remote-storage aws --endpoints endpoints.yml --credentials credentials.yml --enable-api --cors \"*\" --debug --port 5006
    else 
        rasa run --model model.tar.gz --endpoints endpoints.yml --credentials credentials.yml --enable-api --cors \"*\" --debug --port 5006
    fi
    " 

I would accomplish this by making the main container command actually be a script that looks to see if the file exists and optionally fills in the command line argument.我将通过使主容器命令实际上是一个脚本来实现这一点,该脚本查看文件是否存在并可选择填充命令行参数。

#!/bin/sh

MODEL_EXISTS=$(test -f /app/models/model.tar.gz && echo yes)

exec rasa run \
  --model model.tar.gz \
  ${MODEL_EXISTS:---remote-storage aws} \
  --endpoints endpoints.yml \
  ...

The first line uses the test (1) shell command to see if the file already exists, and sets the variable MODEL_EXISTS to yes if it exists and empty if it does not.第一行使用test (1)shell命令查看文件是否已经存在,存在则设置变量MODEL_EXISTSyes ,不存在则为空。 Then in the command, there is a shell parameter expansion: if the variable MODEL_EXISTS is unset or empty :- then expand and split the text --remote-storage aws .然后在命令中,有一个 shell 参数扩展:如果变量MODEL_EXISTS未设置或为空:-然后扩展并拆分文本--remote-storage aws (This approach inspired by BashFAQ/050 .) (这种方法受到BashFAQ/050的启发。)

In your Dockerfile, COPY this script into your image and make it be the default CMD .在您的 Dockerfile 中,将此脚本COPY到您的图像中,并使其成为默认的CMD It needs to be executable like any other script (run chmod +x on your host and commit that change to source control);它需要像任何其他脚本一样可执行(在您的主机上运行chmod +x并将更改提交到源代码管理); since it is executable and begins with a "shebang" line, you do not need to explicitly name the shell when you run it.因为它是可执行的并且以“shebang”行开头,所以在运行它时不需要明确命名 shell。

...
COPY rasa-run ./
CMD ["./rasa-run"]

In your Compose file, you do not need to override the command: , change the working_dir: from what the Dockerfile sets, or change from a couple of Compose-provided defaults.在您的 Compose 文件中,您不需要覆盖command: ,更改working_dir: Dockerfile 设置的内容,或更改 Compose 提供的几个默认值。 You should be able to reduce this to你应该能够将其减少到

version: '3.8'
services:
  rasa-server:
    build: .
    volumes:
      - ./models:/app/models

More generally for this class of question, I might suggest:更一般地,对于这类问题,我可能会建议:

  1. Prefer setting a Dockerfile default CMD to a Compose command: override;更喜欢将 Dockerfile 默认CMD设置为 Compose command:覆盖; and
  2. Write out non-trivial logic in a script and run that script as the main container command;在脚本中写出重要逻辑并将该脚本作为主容器命令运行; don't write complicated conditionals in an inline CMD or command: .不要在内联CMDcommand:

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM