skip to Main Content

I’m deploying an application with a Dockerfile and docker-compose. It loads a model from an AWS bucket to run the application. When the containers get restarted (not intentionally but because of the cloud provider), it loads again the model from 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.

This is part of my 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

was removed.

This is my 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

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

2

Answers


  1. 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 it’s not null and run a different command.

    Note that this command is just an example and I have no idea if it works or not as I don’t use bash everyday.

    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
        " 
    
    Login or Signup to reply.
  2. 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. 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. (This approach inspired by BashFAQ/050.)

    In your Dockerfile, COPY this script into your image and make it be the default CMD. It needs to be executable like any other script (run chmod +x on your host and commit that change to source control); since it is executable and begins with a "shebang" line, you do not need to explicitly name the shell when you run it.

    ...
    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. 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; 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:.
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search