A Simple Bash Script for Docker Compose Management

If you’re like me and love running your own homelab, Docker has likely become an essential part of your workflow. It provides an efficient and convenient way to manage various services, applications, and environments.

Now, there are plenty of graphical tools available such as Portainer or Cockpit which offer a nice user interface for managing Docker containers. However, if you prefer a leaner approach like I do, you might find these tools somewhat bloated and less functional than the good old command line.

That’s why I want to share with you a simple bash script I use to manage my Docker containers. The script uses Docker’s new integrated compose command, a part of Docker 1.27.0 and later. It helps me manually start, stop, and update containers through Docker Compose, and all I need to do is place it at the root of the directory containing my various projects, and execute.

Here is the script.
You can also find it on Github and contributions are welcome!

#!/bin/bash

function prompt_command() {
  clear
  echo "Which command do you want to execute?"
  echo "1. up -d"
  echo "2. down"
  echo "3. pull"
  echo "4. pull && down && up -d"
  echo "5. restart"
  echo "6. down all projects"
  echo "7. exit"
  read command
}

prompt_command

while [[ $command -ne 7 ]]; do
  # Decide on the command to run
  case $command in
    1)
      cmd="up -d"
      ;;
    2)
      cmd="down"
      ;;
    3)
      cmd="pull"
      ;;
    4)
      cmd="pull"
      cmd2="down"
      cmd3="up -d"
      ;;
    5)
      cmd="restart"
      ;;
    6)
      cmd="down"
      downAllProjects="true"
      ;;
    *)
      echo "Invalid option"
      prompt_command
      continue
      ;;
  esac

  function prompt_mode() {
  clear
    # Prompt for how to proceed
    if [ "$downAllProjects" != "true" ]; then
      echo "How do you want to proceed?"
      echo "1. List mode"
      echo "2. Prompt mode"
      echo "3. back"
      read mode
    else
      mode=1
    fi
  }

  prompt_mode

  while [[ $mode -ne 3 ]]; do
    # Iterate through each directory in the current location
    dirs=(*/)
    case $mode in
      1)
        # List mode
        if [ "$downAllProjects" = "true" ]; then
          eval "docker compose -f swag/docker-compose.yml $cmd"
          for dir in "${dirs[@]}"; do
            if [ "$dir" != "swag/" ]; then
              eval "docker compose -f ${dir}docker-compose.yml $cmd"
              if [ "$command" -eq 4 ]; then
                eval "docker compose -f ${dir}docker-compose.yml $cmd2"
                eval "docker compose -f ${dir}docker-compose.yml $cmd3"
              fi
            fi
          done
        else
          while true; do
            echo "Select a project to execute:"
            select dir in "${dirs[@]}" "Back" "Quit"; do
              if [[ "${dir}" == "Back" ]]; then
                break 2
              elif [[ $REPLY = $(( ${#dirs[@]}+2 )) ]] || [[ "${dir}" == "Quit" ]]; then
                clear
                echo "Exiting."
                exit
              elif ((REPLY > 0 && REPLY <= ${#dirs[@]})); then
                eval "docker compose -f ${dir}docker-compose.yml $cmd"
                if [ "$command" -eq 4 ]; then
                  eval "docker compose -f ${dir}docker-compose.yml $cmd2"
                  eval "docker compose -f ${dir}docker-compose.yml $cmd3"
                fi
                break
              else
                echo "Invalid option"
              fi
            done
          done
        fi
        break
        ;;
      2)
        # Prompt mode
        for dir in "${dirs[@]}"; do
          if [ "$cmd" == "up -d" ] && [ "$dir" == "swag/" ]; then
            continue
          fi
          if [ "$cmd" == "down" ] && [ "$dir" == "swag/" ]; then
            eval "docker compose -f ${dir}docker-compose.yml $cmd"
            break
          fi
          echo "Do you want to execute the project $dir? (Y/n/back)"
          read answer
          # Default to "Yes" if no answer is given
          if [ -z "$answer" ]; then
            answer="y"
          fi
          if [ "$answer" = "back" ]; then
            break 2
          elif [ "$answer" = "y" ]; then
            # Run docker compose on the yml file within the directory
            eval "docker compose -f ${dir}docker-compose.yml $cmd"
            if [ "$command" -eq 4 ]; then
              eval "docker compose -f ${dir}docker-compose.yml $cmd2"
              eval "docker compose -f ${dir}docker-compose.yml $cmd3"
            fi
          fi
        done
        if [ "$answer" != "back" ] && [ "$cmd" == "up -d" ]; then
          eval "docker compose -f swag/docker-compose.yml $cmd"
        fi
        break
        ;;
      *)
        echo "Invalid option"
        prompt_mode
        continue
        ;;
    esac
  done
  prompt_command
done

This bash script will prompt you to choose which command you want to execute (up, down, pull, etc.), and how you want to proceed (select mode or list mode). In List mode, it will display a numbered list of directories and allow you to choose which project to execute the command on. In Prompt mode, it will iterate over each directory one by one, asking if you want to execute the command for each project.

I hope you find this script as useful as I do.

Happy Docker Composing!