Docker In-container execution from anywhere in your FS
UPDATE: I've published this script as a configurable CLI under github.com/philsupertramp/docr
Sometimes one wants to execute several commands in a docker container.
To fix the issue with searching for the right container name, proper paths and to prevent running several instances of a container on a single machine. I created a workflow to solve this issue.
The idea is simple, we create a bash script which handles 3 things for us
- verify that docker is running
- search for container name
- run a provided command in an interactive tty
To use this approach company-wide one needs to introduce fixed structure or adjust the script on each machine.
Disclaimer: tested under arch linux, no clue how to handle situations without systemctl
as well as absence of commands like awk
or docker-compose
might cause trouble.
#!/usr/bin/env bash
set -e;
ROOT_DIR=/path/to/application/root
COMPOSE_DIR=${ROOT_DIR}/path/to/docker/compose/file
cur_dir=$CWD
CONTAINER_ID=""
CONTAINER_NAME="my-app"
COMPOSE_CONTAINER_NAME="compose-${CONTAINER_NAME}"
COMPOSE_COMMAND="docker-compose -f docker-compose.override.yml -f docker-compose.yml"
export CURRENT_UID=$(id -u):$(id -g)
help() {
echo -e "
==============================================================================
backend.sh [COMMAND]
Help:
--logs -l : get logs from the main app
--status -i : environment status
--start -s : starts the container
--stop -q : stops the container
--restart : restarts the container
--remove -rm : stops the container and removes associated volumes
--recreate : recreates the container environment
--rebuild : rebuilds the container environment
--help -h : this help
==============================================================================
"
}
refresh_CONTAINER_ID() {
CONTAINER_ID="$(docker ps | grep -v "run" | grep "${COMPOSE_CONTAINER_NAME}" | awk '{print $1}')"
}
start_container() {
cd ${COMPOSE_DIR};
$(${COMPOSE_COMMAND} up -d);
cd ${cur_dir};
refresh_CONTAINER_ID
}
ensure_docker_running() {
if [ -z "$(docker version | grep "Server")" ]
then
echo "Docker not running. Starting now...";
# currently only supports systemctl/MacOS' open command
if command -v systemctl &> /dev/null
then
sudo systemctl start docker;
else
open --background -a Docker;
fi
fi
}
logs() {
docker logs -f ${CONTAINER_ID}
}
remove() {
cd ${COMPOSE_DIR};
$($COMPOSE_COMMAND down -v --remove-orphans);
cd ${cur_dir};
}
create() {
cd ${ROOT_DIR};
bash develop.sh;
start_container
echo "Container started and available as ${CONTAINER_ID}"
}
recreate() {
remove @> /dev/null;
create;
}
rebuild() {
remove @> /dev/null;
current_dir=$(pwd)
cd ${COMPOSE_DIR};
docker-compose build
cd "${current_dir}"
start_container
}
restart() {
docker stop ${CONTAINER_ID};
start_container;
}
ensure_container() {
if [ "${CONTAINER_ID}" = "" ]
then
start_container
fi
}
start() {
ensure_container
echo "Container started and available as ${CONTAINER_ID}"
}
stop() {
docker stop ${CONTAINER_ID};
}
down() {
cd ${COMPOSE_DIR};
$($COMPOSE_COMMAND down);
cd ${ROOT_DIR};
}
run() {
ensure_container
docker exec -ti ${CONTAINER_ID} $@
}
attach() {
docker attach ${CONTAINER_ID}
}
status() {
if [ -z "$(docker version | grep "Server")" ]
then
echo "Docker not running."
echo "Container(s) not running."
else
refresh_CONTAINER_ID
echo "Docker running."
if [ "${CONTAINER_ID}" = "" ]
then
echo "Container(s) not running."
else
echo "Container(s) running."
fi
fi
}
ensure_docker_running
refresh_CONTAINER_ID
case $1 in
--logs|-l)
logs
;;
--attach|-a)
attach
;;
--remove|-rm)
remove
;;
--recreate)
recreate
;;
--rebuild)
rebuild
;;
--restart)
restart
;;
--stop|-q)
down
;;
--start|-s)
start
;;
--status|-i)
status
;;
--create)
create
;;
--help|-h)
help
;;
*)
run $@
;;
esac
Afterwards allow execution of your script chmod +x backend.sh
, drop it into your home directory, and append your .zshrc
or .bashrc
with an alias for example:
echo 'alias backend="/home/user/backend.sh"' >> .zshrc
Now you can use your script to run commands within your container, like
backend ./manage.py test -v 2