diff --git a/README.md b/README.md index df1baf8..e299fad 100644 --- a/README.md +++ b/README.md @@ -26,6 +26,7 @@ Project started with passion by [AlgoTech](https://www.algotech.solutions)! - [Loopback aliases](doc/bash/loopback_aliases.md) - [Gulp aliases](doc/bash/gulp_aliases.md) - [Apache aliases](doc/bash/apache_aliases.md) + - [Docker aliases](doc/bash/docker_aliases.md) #### Git aliases: - You can find the documentation for git aliases [here](doc/git/git_aliases.md) diff --git a/bash/docker_aliases b/bash/docker_aliases new file mode 100644 index 0000000..1a8c5f6 --- /dev/null +++ b/bash/docker_aliases @@ -0,0 +1,401 @@ +alias drund="docker run -d -P" +alias drun="docker run -t -i -P" +alias dimg="di" +alias dexec='dx' +alias dc='docker-compose' + +# Build an image with the given name/tag using the Dockerfile in the +# current directory +function dbuild() { + docker build -t="$1" .; +} + +# +# Format output from the included functions. +# +function dockererror() { + unset containername; + # Detect whether output is piped or not. + if [[ -t 1 ]]; then + printf '%b\n' "\033[1;31m${@}\033[0m" + else + print $@ + fi + +} >&2 + +# +# List Docker images on the local system. +# +function di() { + if [[ -z "$1" ]]; then + dimagelike all | sed -e $'s# #\\\n#g' | grep -v "^REPOSITORY:TAG" + else + dimagelike $1 | sed -e $'s# #\\\n#g' | grep -v "^REPOSITORY:TAG" + fi +} + +# +# Display Docker image tags for images in the public repo +# +function ditags { + for Repo in $* ; do + if [[ -z $( echo "$Repo" | grep "/" ) ]]; then + fullRepo="library/$Repo" + else + fullRepo="$Repo" + fi + + curl -s -S "https://registry.hub.docker.com/v2/repositories/$fullRepo/tags/" | \ + python -mjson.tool | \ + sed -e 's#,#,\n#g' -e 's#\[#\[\n#g' | \ + grep '"name"' | \ + awk -F\" '{print $4;}' | \ + sort -fu | \ + sed -e "s#^#${Repo}:#" + done +} + +# Stop one or more running containers. If none are provided, you will +# be promped with a list of containers. +function dstop() { + # if the user does not provide a container, let them pick one + dwhich $1 + + if [[ -z "$containername" ]]; then + dockererror "Please specify one or more containers to stop."; return 1; + fi + + docker stop "$containername"; +} + +# +# Starts a persistent tail of the logs of a running container. The last +# 100 lines are printed to start. +# +function dtail() { + # if the user does not provide a container, let them pick one + dwhich $1 + + docker logs --tail=100 -f $containername +} + +# +# Stops, removes, and recreates one or more services defined by Docker Compose. +# This function will traverse the directory hierarchy upward to find a +# docker-compose.yml file if none exist in the current directory. +# +function dcbounce { + if [[ -z "$@" ]]; then + dc stop + dc rm -f + dc up -d + else + for i in "${@}"; do + dc stop "$i" + dc rm -f "$i" + dc up -d "$i" + done + fi +} + +# +# Restarts one or more named containers. +# +function dbounce { + docker restart "$@" +} + +# +# Lists all running containers. Adding the -a will will +# stopped containers as well. +# +function dps() { + if [[ -z "$1" ]] + then + dwhich all + elif [ "$#" -eq 1 ] && [ "$1" == "-a" ] + then + dwhich -a all + else + dwhich "$@" + fi +} + +# Remove one or more stopped containers. If none are provided, you will +# be promped with a list of containers. +function drm() { + # if the user does not provide a container, let them pick one + dwhich "$@" '-a' + + if [[ -z "$containername" ]]; then + dockererror "Please specify one or more containers to remove."; return 1; + fi + + docker rm "$containername"; +} + +# Remove one or more images. If none are provided, you will be promped +# with a list of images. Partial matches and regex are supported. +function drmi() { + # if the user does not provide an image, let them pick one + imagename=$(dimagelike "$@") + if [[ -z "$imagename" ]]; then + dockererror "Please specify one or more partial image names and/or versions to remove or all to remove all images"; return 1; + fi + + docker rmi "$imagename"; +} + +# +# Generic exec into a running container. If none are provided, you will be +# promped with a list of images. Partial matches and regex are supported. +# +function dx() { + # if the user does not provide a container, let them pick one + dwhich "$1" + + if [[ -z "$containername" ]]; then + dockererror "Please select a valid container to exec."; return 1; + # if the user does not provide a container, or argument, just run the default command + elif [[ -z "$1" ]]; then + docker exec -i -t $containername $2; + # pop the container name from the argument list and run the rest as the command + else + shift + docker exec -i -t $containername "$@"; + fi +} + +# Does a basic docker exec into a container's bash shell. If none are provided, +# you will be promped with a list of images. Partial matches and regex are +# supported. +function dbash() { + dwhich "$1" + + if [[ -z "$containername" ]]; then + dockererror "Please select a valid container to exec."; return 1; + else + dx "$containername" '/bin/bash'; + fi +} + +# +# Does a basic docker exec into a container's default shell. If none are +# provided, you will be promped with a list of images. Partial matches and +# regex are supported. +function dsh() { + dwhich "$1" + + if [[ -z "$containername" ]]; then + dockererror "Please select a valid container to exec."; return 1; + else + dx "$containername" 'sh'; + fi +} + +# Does a basic docker exec into an alpine container's shell. If none are provided, +# you will be promped with a list of images. Partial matches and regex are +# supported. +function dash() { + dwhich "$1" + + # if the user does not provide a container, let them pick one + dwhich "$1" + + if [[ -z "$containername" ]]; then + dockererror "Please select a valid container to exec."; return 1; + # if the user does not provide a container, or argument, just run the default command + elif [[ -z "$1" ]]; then + docker exec -i -t $containername $2; + # pop the container name from the argument list and run the rest as the command + else + shift + docker exec -i -t --entrypoint="/bin/ash" $containername "$@"; + fi +} + +# +# Display realtime info for one or more running containers. If none +# are provided, you will be promped with a list of images. Partial +# matches and regex are supported. +# +function dstats() { + # if the user does not provide an image, let them pick one + dwhich "$@" + + if [ -z "$containername" ]; then + dockererror "Please specify one or more containers for which to display realtime stats."; return 1; + fi + + docker stats "$containername" +} + +# +# Removes all untagged Docker image. This is probably the handiest command +# in this entire repo. Run this early and often to keep the zombie images +# at bay. +# +function dtidy() { + docker rmi $(docker images | grep "^" | awk '{print $3}') +} + +# +# Full cleanup of the local Docker install. Deletes every container and +# removes every untagged image +# +function dclean() { + docker stop $(docker ps -a -q); + docker rm $(docker ps -q -a); + docker rmi $(docker images | grep "^" | awk "{print $3}"); +} + +# Smokes every container and every tagged image +function dnuke() { + docker stop $(docker ps -a -q); + docker rm $(docker ps -q -a); + docker rmi $(docker images -q); +} + +# +# Looks up a user-supplied container name. If none is supplied, the user is +# prompted to select from a list of containers on the current system. +# +function dwhich() { + containername='' + INCLUDE_STOPPED='' + if [[ "$#" == "0" ]] + then + # nothing to do here + INCLUDE_STOPPED='' + else + iter=1 + for i in "$@" + do + if [[ '-a' == "$i" ]] + then + INCLUDE_STOPPED="-a" + shift + #else + # echo -e "leaving argument $i in place\n" + fi + iter="$[iter+1]" + done + fi + + containerids=( $(docker ps $INCLUDE_STOPPED | grep -v '^CONTAINER' | awk '{print $NF}') ) + if [[ -z "$1" ]]; then + for i in "${!containerids[@]}" + do + echo "[$i] ${containerids[$i]}" + done + + echo -n "Select container(s) []: " + eval "read containerresponse" + containerresponse=( $containerresponse ) + else + containerresponse=( "$@" ) + fi + + re='^[0-9]+$' + # if empty, none was provided and none was selected + if [[ -z "$containerresponse" ]]; then + dockererror "Unknown container name. Please select a valid number from 1-${#containerids[@]} or provide a valid container name."; return 1; + else + for i in "${!containerresponse[@]}" + do + # validate the numeric selection + if [[ "${containerresponse[$i]}" =~ $re ]] ; then + if [ ${containerresponse[$i]} -ge ${#containerids[@]} ]; then + dockererror "Invalid choice. Please select a valid number from 1-${#containerids[@]} or provide a valid container name."; return 1; + else + containername=$(echo -e "${containerids[${containerresponse[$i]}]}\n${containername}") + # echo "${containername}" + fi + # return all containers + elif [ "all" == "${containerresponse[$i]}" ] || [ "*" == "${containerresponse[$i]}" ]; then + containername="${containerids[@]}" + #echo "${containername}" + # validate the provided value + else + + containermatches=$(docker ps $INCLUDE_STOPPED | grep -v '^CONTAINER' | awk '{print $NF}' | grep "${containerresponse[$i]}") + if [[ -n "$containermatches" ]]; then + foundmatching=1 + containername=$(echo -e "${containermatches}\n$containername") + #echo "${containername}" + else + dockererror "Unknown container name ${containerresponse[$i]}. Please select a valid number from 1-${#containerids[@]} or provide a valid container name."; return 1; + fi + #for i in "${!containerids[@]}" + #do + # if [[ "$containername" == "${containerids[$i]}" ]]; then + # foundmatch=1 + # containername="${containerids[$i]}" + # break + # fi + #done + + #if [ -z "$foundmatch" ]; then + # dockererror "Unknown container name. Please select a valid number from 1-${#containerids[@]} or provide a valid container name."; return 1; + #fi + fi + done + + # print results | strip duplicates | reverse and delete empty newlines | replace spaces with newlines + echo "${containername}" | awk '!a[$0]++' | sed -ne '1!G;h;$p' | tr " " "\n" + fi + + #echo "$containername" +} +# +# Looks up a user-supplied image name and/or version based on partial match. +# If none is supplied the user is prompted to select from a list of images on +# the current system +# +function dimagelike() { + imagenames=( $(docker images | grep -v '^' | awk '{print $1,":",$2; }' | sed -e 's# ##g') ) + if [[ -z "$1" ]]; then + for i in "${!imagenames[@]}" + do + echo "[$i] ${imagenames[$i]}" + done + + echo -n "Select imag(e) []: " + eval "read selectedimage" + else + selectedimage="$1" + fi + + re='^[0-9]+$' + # if empty, none was provided and none was selected + if [[ -z "$selectedimage" ]]; then + dockererror "Please provide an image name and/or version or select a valid number from 1-${#imagenames[@]}. Partial names and wildcards are supported."; return 1; + # validate the numeric selection + elif [[ "$selectedimage" =~ $re ]] ; then + if [ $selectedimage -ge ${#imagenames[@]} ]; then + dockererror "Invalid choice. Please provide an image name and/or version or select a valid number from 1-${#imagenames[@]}. Partial names and wildcards are supported."; return 1; + else + echo "${imagenames[$selectedimage]}" + fi + # return all containers + elif [ "all" == "$selectedimage" ] || [ "*" == "$selectedimage" ]; then + echo "${imagenames[@]}" + # validate the provided value + else + # selectedimage=( "${selectedimage[@]}" ) + # for j in "${#selectedimage[@]}" + # do + # match the selected value against the existing image name and tag + imgmatches=$(docker images | grep -v '^' | awk '{print $1,":",$2; }' | sed -e 's# ##g' | grep "$selectedimage") + if [[ -n "$imgmatches" ]]; then + foundmatching=1 + echo "${imgmatches}" + fi + # done + + if [[ -z "$foundmatching" ]]; then + dockererror "Invalid image value. Please provide an image name and/or version or select a valid number from 1-${#imagenames[@]}. Partial names and wildcards are supported."; return 1; + fi + fi +} diff --git a/bash_aliases b/bash_aliases index b918bb7..3f0ac44 100644 --- a/bash_aliases +++ b/bash_aliases @@ -18,3 +18,4 @@ source $ALIASES_HOME/.aliases/bash/django_aliases source $ALIASES_HOME/.aliases/bash/npm_aliases source $ALIASES_HOME/.aliases/bash/loopback_aliases source $ALIASES_HOME/.aliases/bash/gulp_aliases +source $ALIASES_HOME/.aliases/bash/docker_aliases diff --git a/doc/bash/docker_aliases.md b/doc/bash/docker_aliases.md new file mode 100644 index 0000000..5f2daf2 --- /dev/null +++ b/doc/bash/docker_aliases.md @@ -0,0 +1,40 @@ +# Bash aliases for Django # + +- [Manage Docker images](#manage-docker-images) +- [Run Docker containers](#run-docker-containers) +- [Manage Docker containers](#manage-docker-containers) +- [Exec into Docker containers](#exec-into-docker-containers) +- [Manage Docker Compose services](#manage-docker-compose-services) +- [Back to main page](../../README.md) + +### Manage Docker images ### +- **di**: `dimagelike $1 | sed -e $'s# #\\\n#g' | grep -v "^REPOSITORY:TAG"` +- **dbuild**: `docker build -t="$1" .` +- **ditags**: Display Docker image tags for images in the public repo +- **drmi**: `docker rmi` +- **dnuke**: `docker stop $(docker ps -a -q) && docker rm $(docker ps -q -a) && docker rmi $(docker images -q)` + +### Run Docker containers ### +- **drund**: `docker run -d -P` +- **drun**: `docker run -t -i -P` +- **dbounce**: `docker restart` + +### Manage Docker containers ### +- **dps**: `docker ps` +- **dstop**: `docker stop` +- **dtail**: `docker logs --tail=100 -f` +- **drm**: `docker rm` +- **dtidy**: `docker rmi $(docker images | grep "^" | awk '{print $3}')` +- **dstats**: `docker stats` +- **dclean**: `docker stop $(docker ps -a -q) && docker rm $(docker ps -q -a) && docker rmi $(docker images | grep "^" | awk "{print $3}")` + +### Exec into Docker containers ### +- **dexec**: `dx` +- **dx**: `docker exec -i -t` +- **dbash**: `docker exec -i -t $1 bash` +- **dsh**: `docker exec -i -t $1 sh` +- **dash**: `docker exec -i -t --entrypoint="/bin/ash" $1` + +### Manage Docker Compose services ### +- **dc**: `docker-compose` +- **dcbounce**: `docker-compose stop "$@" || docker-compose rm -f "$@" || docker-compose up -d "$@" `