Building the docker-compose.yaml to run or init Rasa bot

Stephen Cow Chau
3 min readDec 3, 2021

--

To run the rasa bot locally, it would need to initialize a project, update the file, train and then run the bot (using shell or API)

docker-compose.yaml

version: '3.8'
services:
rasa:
image: rasa/rasa:3.0.0-full
container_name: rasa
ports:
- 5005:5005
user: "$UID:$GID"
volumes:
#- ./rasa_data:/app
- "${BIND_FOLDER}:/app"
command:
# - "run" # original hard code value as array entry
# - "--enable-api"
# - "${COMMAND}" # tried to mimic the array approach
# - "${COMMAND_ARG}" # but init command not allow this switch, even it's empty string
"${COMMAND}" # this is string, allow command as string like 'run --enable-api' or 'init'

Volume mapping

I plan to have multiple model to run with the same docker container, so it’s easiest to bind a host folder to the container’s /app path

And it’s planned to use an environment variable BIND_FOLDER to configure which folder contains the model config.

User mapping

Because rasa init would try to create files to the container’s /app folder, which in turn map to the host’s specific folder, it would have a operation not allowed (permission denied) when the container’s user account user id and group id not matching the host folder owner / user with permission.

So the docker-compose file would use another set of environment variable UID and GID to control what user id / group id to run the container

Command

The command in my use case could be “run”, “init” or “run --enable-api”, I used to use an yaml array to work with “run --enable-api”, but that might not work with “init’ which does not expect a switch, so instead I use a string (no leading dash, compare to an YAML array entry which start each line with leading dash)

Script to execute the docker-compose

#!/bin/bash# Check if folder path exist
if [ -z "$1" ]; then
echo "ERROR: Missing argument volume"
echo "Usage: $0 <rasa folder> <command> <command arg>"
echo "example 1: $0 ./rasa_data run --enable-api"
echo "example 2: $0 ./rasa_data init"
exit 1
fi
echo "Volume expected to be $1"# Arg after folder
ARGS="${@:2}"
echo "Arguments are $ARGS"
if [ -d "$1" ]; then
if [ "$2" = "run" ]; then
echo "Run 'docker-compose up -d' ..."
eval "env UID=$(id -u) GID=$(id -g) BIND_FOLDER=$1 COMMAND=$ARGS docker-compose up -d"
echo "Running 'docker-compose logs -f' ..."
eval "docker-compose logs -f"
fi
if [ "$2" = "init" ]; then
echo "Run 'docker-compose run' ..."
eval "env UID=$(id -u) GID=$(id -g) BIND_FOLDER=$1 docker-compose run rasa $ARGS"
#echo "Running 'docker-compose logs -f' ..."
#eval "docker-compose logs -f"
fi
else
echo "ERROR: the folder '$1' does not exist"
exit 1
fi

The first if block check if there are any argument and exit if not, with message telling user what to input

The following 2 if block handle “run” and “init” respectively.

Note that for run we can use “docker-compose up -d” with setting environment variables defined for UID, GID and BIND_FOLDER and COMMAND

While we use “docker-compose run” to perform “init”, that’s because the init would call python prompt and it would throw error if we perform a “docker-compose up” as it is not expecting interactivity, while docker-compose run would send a --tty (allocate a virtual terminal session) so one can interact with the rasa “init”.

running the script with “bash rasa_script.sh ./product_selling_bot init”

Reference:

--

--