#!/bin/bash # script to run the dev guide's docker image. # creates a settings.sh file where the path of directory holding the persistent data # accepts --no-nis as first argument to not start nis in the container ################################################################################ # preamble: functions definitions, variable setting, etc ################################################################################ # we look for the config file in the same directory as the script, whose location # is stored in this variable script_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd -P )" # by default start nis with_nis=1 # by default, do not pass a user to run the command as # if we run in the tools container, this will be set to run the command as user nem. docker_user_flag="" pull=0 # tools_dir is the directory mounted in the tools container to /home/nem/code # currently hard-coded in this variable tools_dir="./code" usage() { cat <<-EOF Usage: $0 [options] [command] The command can be run without flags or commands. In that case it will: * if missing, create $script_dir/settings.sh, prompting the user for values * if missing, download the docker-compose.yml to $script_dir * if missing, create the directory where you store your code, also available in the tools container. By default it is '$tools_dir'. * start the containers The user running $0 needs to have the right to start and stop docker containers. Options are: -c name --container name apply command to container. name can be nis or tools -n --no-nis do not start NIS in the container. -p --pull pull new images from the Docker Hub and exit -s --shutdown shutdown containers. This flag has the highest priotity and will be handled befor all others. Note that **THIS DELETES ALL DATA IN THE CONTAINER**. -S --status display running containers before handling other flags Command is a command available in the container. Custom commands are also available: ts-node : opens a Typescript nodejs repl in which you can load nem-library repl.js : opens a nodejs repl with nem-sdk loaded and available under the variable 'nem' mitm : opens a mitmproxy console in your terminal, listening on port 7892 EOF exit } # function to handle arguments passed to the script handle_args() { while [[ $# -gt 0 ]]; do key="$1" case $key in -c|--container) container="$2" shift # passed argument shift ;; -n|--no-nis) with_nis=0 shift # no argument ;; -h|--help) usage shift ;; -p|--pull) pull=1 shift ;; -s|--shutdown) shutdown=1 shift ;; -S|--status) state=1 shift ;; # an unrecognised option is interpreted as the end of options # and sets the remaining value as the command to be run *) if [[ $key =~ ^-.* ]]; then echo "Unrecognised option, please run \"$0 --help\"" exit 1 else cmd="$@" return 0 fi ;; esac done } container_name() { container=$1 echo $(eval "echo \$${container}_container") } service_name() { container=$1 echo nemdev${container} } handle_config_file() { # we store the persistent data location for ease if [[ ! -f $script_dir/settings.sh ]]; then echo "It appears no saved settings have been detected. We will create one now, please answer the questions below" while [[ ! -d "$persistent_location" ]] ; do [[ -z $persistent_location ]] || echo "Directory not found: $persistent_location" echo "In which *existing* directory should the persistent data of the container be stored? (it should exist, no directory will be created)" read persistent_location done echo "#if you change this, change also tools/.env!" >> settings.sh echo "export persistent_location=\"$persistent_location\"" >> settings.sh echo "export tools_dir=\"$PWD/code\"" >> settings.sh fi . $script_dir/settings.sh } # makes sure we have consistent data with cmd handle_command() { case $1 in tsc) container="tools" ;; node) container="tools" ;; ts-node) container="tools" ;; repl.js) container="tools" ;; bash) [[ -z $container ]] && container="tools" ;; # by default, execute command in tools container *) [[ -z $container ]] && container="tools" ;; esac } check_running_containers() { containers=$(docker ps --format '{{.Names}}' | grep $(basename $script_dir)_nemdev) nis_container=$(echo "$containers" | grep nis) tools_container=$(echo "$containers" | grep tools) } check_compose_file() { cd $script_dir [[ -f docker-compose.yml ]] || { curl -q https://raw.githubusercontent.com/rb2nem/nem-dev-guide/master/docker/docker-compose.yml > docker-compose.yml ; echo "The required docker-compose.yml file has been downloaded and saved under $script_dir" ; } } start_containers() { # start docker containers if needed, possibly with nis if [[ -z "$nis_container" ]] ; then mkdir -p $persistent_location/nem mkdir -p $tools_dir docker-compose up -d [[ $with_nis -eq 1 ]] && sleep 1 && docker exec -it docker_nemdevnis_1 supervisorctl start nis ; # update running containers variable after starting containers check_running_containers cat <<-EOF ############################################################################### Welcome to the NEM developer's guide Docker containers. By default, two containers have been started, one running NIS ($nis_container), and the other ($tools_container) running mitmproxy. Only the tools container has ports mapped to your host: - http://localhost:7890 : to contact the NIS instance running in the nis container through mitmproxy - http://localhost:7778 : to contact the NIS instance' websocket port through mitmproxy - http://localhost:8081 : to view requests to NIS intercepted by mitmproxy - http://localhost:8082 : to view websocket requests to NIS intercepted by mitmproxy Run with --help to get an overview of flags and supported commands. ############################################################################### EOF fi } pull_images() { # no container specified, update both images if [[ -z $container ]] ; then docker pull rb2nem/nem-dev-guide:nis docker pull rb2nem/nem-dev-guide:tools else # container specified, only update its images docker pull rb2nem/nem-dev-guide:$container fi } set_docker_user_flag() { if [[ $container = "tools" ]]; then docker_user_flag="-u nem" fi } # go to script directory to have Dockerfile available cd $script_dir handle_args "$@" handle_config_file check_compose_file check_running_containers if [[ $pull -eq 1 ]] ; then pull_images exit fi if [[ $state -eq 1 ]] ; then echo "running containers are:" echo "$containers" exit fi if [[ $shutdown -eq 1 ]] ; then # if we pass a container, check if it is running, and set action accordingly if [[ -n $container ]]; then check_running_containers set -x if [[ $(eval "echo \$${container}_container") == "" ]]; then action="up -d" else action="stop" fi docker-compose $action $(service_name $container) # if we stop the container, also remove it [[ $action == "stop" ]] && docker-compose rm -f $(service_name $container) else docker-compose down fi exit fi # make args consistent with command handle_command $cmd set_docker_user_flag start_containers if [[ -n "$cmd" ]]; then set -x docker exec ${docker_user_flag} -it $(container_name $container) bash -i -c "$cmd" fi