553 lines
18 KiB
Bash
Executable File
553 lines
18 KiB
Bash
Executable File
#!/bin/bash
|
||
############################################################
|
||
# Decription: Script to manage stack docker
|
||
#
|
||
# Author: Gilles Mouchet (gilles.mouchet@gmail.com)
|
||
# Creation Date: 12-06-2025
|
||
# Version: 1.0
|
||
# Usage: ./manage.sh
|
||
# Changelog:
|
||
# V1.0 - dd-Mmm-2025 - GMo
|
||
# Added
|
||
# - Creation of script from scratch
|
||
#
|
||
############################################################
|
||
|
||
#-----------------------------------------------------------------
|
||
# Doesn't change anything from here
|
||
#-----------------------------------------------------------------
|
||
version="1.0-rc1"
|
||
|
||
prog_name="./$(/bin/basename $0)"
|
||
|
||
containers_to_start=(init minio minio-cli grafana loki promtail prometheus node-exporter proxy)
|
||
containers_all=("${containers_to_start[@]}" log-generator dns-tools)
|
||
|
||
# Couleurs
|
||
VERT="\e[32m"
|
||
ROUGE="\e[31m"
|
||
NORMAL="\e[0m"
|
||
#-----------------------------------------------------------------
|
||
# Functions
|
||
#-----------------------------------------------------------------
|
||
# display help
|
||
function print_usage {
|
||
/bin/cat << EOF
|
||
|
||
Usage: $prog_name [options]
|
||
|
||
Options:
|
||
config Create folder for persit. vol. and copy conf files
|
||
param Display all vars defined in .env file
|
||
list Display container (servie) list define in docker compose file
|
||
create Create container
|
||
start-stack Start stack '${COMPOSE_PROJECT_NAME}'
|
||
stop Stop stack '${COMPOSE_PROJECT_NAME}'
|
||
down Stop stack '${COMPOSE_PROJECT_NAME}' and delete containers
|
||
restart Restart stack '${COMPOSE_PROJECT_NAME}'
|
||
version,-v,--version Display script version
|
||
help,-h,--help Display this help
|
||
|
||
Examples:
|
||
To start stack '${COMPOSE_PROJECT_NAME}'
|
||
$prog_name start
|
||
To stop stack '${COMPOSE_PROJECT_NAME}'
|
||
$prog_name stop
|
||
To start a specific container and his depend
|
||
docker compose up <container_name> -d
|
||
Ex:
|
||
docker compose up minio-cli -d
|
||
To create a new stack
|
||
$prog_name config
|
||
$prog_name create
|
||
$prog_name start
|
||
EOF
|
||
}
|
||
#-----------------------------------------------------------------
|
||
# create folders for persistent volume and config file
|
||
function create_folder {
|
||
for folder_item in "${folder_to_create[@]}"; do
|
||
echo -n "Create folder '${folder_item}': "
|
||
sudo mkdir -p ${folder_item}
|
||
rc=$?
|
||
if [ $rc -eq 0 ]; then
|
||
echo -e "${VERT}SUCCESS${NORMAL}"
|
||
else
|
||
echo -e "${ROUGE}ERROR${NORMAL}"
|
||
exit $rc
|
||
fi
|
||
done
|
||
}
|
||
#-----------------------------------------------------------------
|
||
# remove folders for persistent volume and config file
|
||
function remove_folder {
|
||
for folder_item in "${folder_to_create[@]}"; do
|
||
# we doesn't delete the certs folder.
|
||
# this folder is maybe shared with other container
|
||
if [ "${folder_item}" != "${PRX_CERTS_DIR}" ]; then
|
||
echo -n "Remove folder '${folder_item}': "
|
||
sudo rm -rf ${folder_item}
|
||
rc=$?
|
||
if [ $rc -eq 0 ]; then
|
||
echo -e "${VERT}SUCCESS${NORMAL}"
|
||
else
|
||
echo -e "${ROUGE}ERROR${NORMAL}"
|
||
exit $rc
|
||
fi
|
||
fi
|
||
done
|
||
}
|
||
#-----------------------------------------------------------------
|
||
# copy config file
|
||
function copy_conf_file {
|
||
echo -n "Copy loki config file into '${LOKI_CONF_DIR}/': "
|
||
envsubst < ./config/loki/local-config.yaml.tmpl | \
|
||
sudo tee ${LOKI_CONF_DIR}/local-config.yaml > /dev/null
|
||
rc=$?
|
||
if [ $rc -eq 0 ]; then
|
||
echo -e "${VERT}SUCCESS${NORMAL}"
|
||
else
|
||
echo -e "${ROUGE}ERROR ($rc)${NORMAL}"
|
||
exit $rc
|
||
fi
|
||
|
||
echo -n "Copy proxy (nginx) config file into '${PRX_NGINX_CONF_DIR}/': "
|
||
sudo cp ./config/nginx/default.conf ${PRX_NGINX_CONF_DIR}/. > /dev/null 2>&1
|
||
rc=$?
|
||
if [ $rc -eq 0 ]; then
|
||
echo -e "${VERT}SUCCESS${NORMAL}"
|
||
else
|
||
echo -e "${ROUGE}ERROR ($rc)${NORMAL}"
|
||
exit $rc
|
||
fi
|
||
|
||
echo -n "Copy the Prometheus configuration file into '${PROM_CONF_DIR}/': "
|
||
sudo cp ./config/prometheus/prometheus.yml ${PROM_CONF_DIR}/. > /dev/null 2>&1
|
||
rc=$?
|
||
if [ $rc -eq 0 ]; then
|
||
echo -e "${VERT}SUCCESS${NORMAL}"
|
||
else
|
||
echo -e "${ROUGE}ERROR ($rc)${NORMAL}"
|
||
exit $rc
|
||
fi
|
||
|
||
echo -n "Copy promtail config file into '${PROMTAIL_CONF_DIR}/': "
|
||
sudo cp ./config/promtail/config.yml ${PROMTAIL_CONF_DIR}/. > /dev/null 2>&1
|
||
rc=$?
|
||
if [ $rc -eq 0 ]; then
|
||
echo -e "${VERT}SUCCESS${NORMAL}"
|
||
else
|
||
echo -e "${ROUGE}ERROR ($rc)${NORMAL}"
|
||
exit $rc
|
||
fi
|
||
|
||
}
|
||
#-----------------------------------------------------------------
|
||
# create all containers
|
||
function create_container {
|
||
for cont_item in "${containers_all[@]}"; do
|
||
# check if container exist. If not create it
|
||
if [ $(docker ps -a | grep ${COMPOSE_PROJECT_NAME}-$cont_item | wc -l) -eq 0 ]; then
|
||
echo -n "Create container $cont_item: "
|
||
if docker compose create $cont_item > /dev/null 2>&1; then
|
||
echo -e "${VERT}SUCCESS${NORMAL}"
|
||
else
|
||
echo -e "${ROUGE}ERROR${NORMAL}"
|
||
fi
|
||
# else
|
||
# echo "Container $cont_item already exist"
|
||
fi
|
||
done
|
||
}
|
||
#-----------------------------------------------------------------
|
||
# start container
|
||
function start_container {
|
||
for cont_item in "${containers_to_start[@]}"; do
|
||
echo -n "Start container $cont_item: "
|
||
if docker compose up -d $cont_item > /dev/null 2>&1; then
|
||
echo -e "${VERT}SUCCESS${NORMAL}"
|
||
else
|
||
echo -e "${ROUGE}ERROR${NORMAL}"
|
||
fi
|
||
done
|
||
}
|
||
#-----------------------------------------------------------------
|
||
# create grafana ds
|
||
# $1 = ds name
|
||
# $2 = url
|
||
function add_gf_data_source {
|
||
curl -k -X POST "${GF_ROOT_URL}/api/datasources" \
|
||
-u "${GF_ADMIN_USER}:${GF_ADMIN_PASS}" \
|
||
-H "Content-Type: application/json" \
|
||
-d '{
|
||
"name": "'"${1^}"'",
|
||
"type": "'"$1"'",
|
||
"access": "proxy",
|
||
"url": "'"$2"'",
|
||
"basicAuth": false,
|
||
"isDefault": false,
|
||
"jsonData": {
|
||
"maxLines": 1000
|
||
}
|
||
}' > /dev/null 2>&1
|
||
}
|
||
#-----------------------------------------------------------------
|
||
# import grafana dashboard
|
||
# $1 = dashboard ID
|
||
# $2 = source
|
||
# $3 = dashboard title. Needed for check if already impoerted
|
||
function import_gf_dashboard {
|
||
db_file=/tmp/dashboard-$1.json
|
||
wr_file=/tmp/wrapped-dashboard.json
|
||
|
||
#download json
|
||
curl -s -k -o "$db_file" "https://grafana.com/api/dashboards/$1/revisions/latest/download"
|
||
if [ ! -s "$db_file" ]; then
|
||
exit 1
|
||
fi
|
||
|
||
# stage 2 - clean up and add datadource
|
||
sed -i 's/"id":[ ]*[0-9]\+/"id": null/g' "$db_file"
|
||
sed -i 's/"uid":[ ]*"[^"]*"/"uid": null/g' "$db_file"
|
||
sed -i 's/"datasource": ".*"/"datasource": "'"${2^}"'"/g' "$db_file"
|
||
|
||
# stage 3 - creating the final JSON file expected by the Grafana API
|
||
echo '{' > "$wr_file"
|
||
echo '"dashboard":' >> "$wr_file"
|
||
cat "$db_file" >> "$wr_file"
|
||
echo ',' >> "$wr_file"
|
||
echo '"overwrite": true' >> "$wr_file"
|
||
echo '}' >> "$wr_file"
|
||
|
||
# stage 4 - import dashboard into grafana
|
||
curl -s -k -X POST "$GF_ROOT_URL/api/dashboards/db" \
|
||
-u "$GF_ADMIN_USER:$GF_ADMIN_PASS" \
|
||
-H "Content-Type: application/json" \
|
||
--data-binary "@$wr_file" > /dev/null 2>&1
|
||
|
||
#rm -f $db_file $wr_file
|
||
}
|
||
#-----------------------------------------------------------------
|
||
# MAIN
|
||
#-----------------------------------------------------------------
|
||
|
||
# read .env if exist
|
||
if [ ! -f .env ]; then
|
||
echo "file '.env' doesn't exist!"
|
||
echo "See README.md"
|
||
exit
|
||
fi
|
||
set -a
|
||
source .env
|
||
set +a
|
||
|
||
# create array folder to create
|
||
folder_to_create=(${PRX_CERTS_DIR}
|
||
${PRX_NGINX_CONF_DIR}
|
||
${MINIO_DATA_ROOT_DIR}
|
||
${MINIO_CONF_CLI_DIR}
|
||
${GF_DATA_DIR}
|
||
${PROM_CONF_DIR}
|
||
${PROM_DATA_DIR}
|
||
${LOKI_CONF_DIR}
|
||
${LOKI_DATA_DIR}
|
||
${LOKI_GEN_LOG_DIR}
|
||
${PROMTAIL_CONF_DIR})
|
||
|
||
case "$1" in
|
||
param)
|
||
cat << EOF
|
||
COMPOSE_PROJECT_NAME = ${COMPOSE_PROJECT_NAME}
|
||
PRX_CERTS_DIR = ${PRX_CERTS_DIR}
|
||
PRX_NGINX_CONF_DIR = ${PRX_NGINX_CONF_DIR}
|
||
MINIO_DATA_ROOT_DIR = ${MINIO_DATA_ROOT_DIR}
|
||
MINIO_CONF_CLI_DIR = ${MINIO_CONF_CLI_DIR}
|
||
MINIO_ACCESS_KEY = ${MINIO_ACCESS_KEY}
|
||
MINIO_SECRET_KEY = ${MINIO_SECRET_KEY}
|
||
MINIO_BUCKET_NAME = ${MINIO_BUCKET_NAME}
|
||
MINIO_BUCKET_USER = ${MINIO_BUCKET_USER}
|
||
MINIO_BUCKET_PASS = ${MINIO_BUCKET_PASS}
|
||
MINIO_BUCKET_POL_NAME = ${MINIO_BUCKET_POL_NAME}
|
||
MINIO_REDIRECT_URL = ${MINIO_REDIRECT_URL}
|
||
MINIO_ALIAS = ${MINIO_ALIAS}
|
||
GF_ADMIN_USER = ${GF_ADMIN_USER}
|
||
GF_ADMIN_PASS = ${GF_ADMIN_PASS}
|
||
GF_DATA_DIR = ${GF_DATA_DIR}
|
||
GF_ROOT_URL = ${GF_ROOT_URL}
|
||
PROM_CONF_DIR = ${PROM_CONF_DIR}
|
||
PROM_DATA_DIR = ${PROM_DATA_DIR}
|
||
LOKI_CONF_DIR = ${LOKI_CONF_DIR}
|
||
LOKI_DATA_DIR = ${LOKI_DATA_DIR}
|
||
LOKI_GEN_LOG_DIR = ${LOKI_GEN_LOG_DIR}
|
||
PROMTAIL_CONF_DIR = ${PROMTAIL_CONF_DIR}
|
||
EOF
|
||
;;
|
||
start-stack)
|
||
echo -e "---- Create Folders ----"
|
||
create_folder
|
||
echo -e "\n---- Copy config file ----"
|
||
copy_conf_file
|
||
echo -e "\n---- Config minio ----"
|
||
#-----
|
||
echo -n "Start minio container: "
|
||
if docker compose up -d minio > /dev/null 2>&1; then
|
||
echo -e "${VERT}SUCCESS${NORMAL}"
|
||
else
|
||
echo -e "${ROUGE}ERROR${NORMAL}"
|
||
fi
|
||
#----
|
||
echo -n "Wait until minio container is started: "
|
||
while ! curl -s "http://$HOSTNAME:9000/minio/health/live" >/dev/null; do
|
||
sleep 1
|
||
done
|
||
echo -e "${VERT}STARTED${NORMAL}"
|
||
#-----
|
||
echo -n "Start minio-cli container: "
|
||
docker compose up -d minio-cli > /dev/null 2>&1
|
||
rc=$?
|
||
if [ $rc -eq 0 ]; then
|
||
echo -e "${VERT}SUCCESS${NORMAL}"
|
||
else
|
||
echo -e "${ROUGE}ERROR ($rc)${NORMAL}"
|
||
exit $rc
|
||
fi
|
||
#-----
|
||
echo -n "Create minios alias: "
|
||
docker exec ${COMPOSE_PROJECT_NAME}-minio-cli-1 mc alias set ${MINIO_ALIAS} http://minio:9000 \
|
||
${MINIO_ACCESS_KEY} ${MINIO_SECRET_KEY} > /dev/null 2>&1
|
||
rc=$?
|
||
if [ $rc -eq 0 ]; then
|
||
echo -e "${VERT}SUCCESS${NORMAL}"
|
||
else
|
||
echo -e "${ROUGE}ERROR ($rc)${NORMAL}"
|
||
exit $rc
|
||
fi
|
||
#-----
|
||
echo -n "Copy mino policy config file into ${MINIO_CONF_CLI_DIR}/: "
|
||
envsubst < ./config/minio/policy.json.tmpl |
|
||
sudo tee ${MINIO_CONF_CLI_DIR}/.mc/policy.json > /dev/null
|
||
rc=$?
|
||
if [ $rc -eq 0 ]; then
|
||
echo -e "${VERT}SUCCESS${NORMAL}"
|
||
else
|
||
echo -e "${ROUGE}ERROR ($rc)${NORMAL}"
|
||
exit $rc
|
||
fi
|
||
#-----
|
||
echo -n "Create user for bucket ${MINIO_BUCKET_NAME}: "
|
||
docker exec ${COMPOSE_PROJECT_NAME}-minio-cli-1 mc admin user add \
|
||
${MINIO_ALIAS} ${MINIO_BUCKET_USER} ${MINIO_BUCKET_PASS} >/dev/null 2>&1
|
||
rc=$?
|
||
if [ $rc -eq 0 ]; then
|
||
echo -e "${VERT}SUCCESS${NORMAL}"
|
||
else
|
||
echo -e "${ROUGE}ERROR ($rc)${NORMAL}"
|
||
exit $rc
|
||
fi
|
||
#-----
|
||
echo -n "Create policy for access to bucket ${MINIO_BUCKET_NAME}: "
|
||
docker exec ${COMPOSE_PROJECT_NAME}-minio-cli-1 mc admin policy create \
|
||
${MINIO_ALIAS} ${MINIO_BUCKET_POL_NAME} /root/.mc/policy.json >/dev/null 2>&1
|
||
rc=$?
|
||
if [ $rc -eq 0 ]; then
|
||
echo -e "${VERT}SUCCESS${NORMAL}"
|
||
else
|
||
echo -e "${ROUGE}ERROR ($rc)${NORMAL}"
|
||
exit $rc
|
||
fi
|
||
#-----
|
||
echo -n "Attach policy to user ${MINIO_BUCKET_USER}: "
|
||
docker exec ${COMPOSE_PROJECT_NAME}-minio-cli-1 mc admin policy attach \
|
||
${MINIO_ALIAS} ${MINIO_BUCKET_POL_NAME} --user=${MINIO_BUCKET_USER} >/dev/null 2>&1
|
||
rc=$?
|
||
if [ $rc -eq 0 ]; then
|
||
echo -e "${VERT}SUCCESS${NORMAL}"
|
||
else
|
||
echo -e "${ROUGE}ERROR ($rc)${NORMAL}"
|
||
exit $rc
|
||
fi
|
||
#-----
|
||
echo -n "Create bucket if not exist: "
|
||
docker exec ${COMPOSE_PROJECT_NAME}-minio-cli-1 mc ls "${MINIO_ALIAS}/$MINIO_BUCKET_NAME" >/dev/null 2>&1
|
||
rc=$?
|
||
if [ $rc -ne 0 ]; then
|
||
docker exec -it ${COMPOSE_PROJECT_NAME}-minio-cli-1 /bin/sh -c \
|
||
"mc mb ${MINIO_ALIAS}/${MINIO_BUCKET_NAME}" >/dev/null 2>&1
|
||
rc1=$?
|
||
if [ $rc1 -eq 0 ]; then
|
||
echo -e "${VERT}SUCCESSFULLY CREATED${NORMAL}"
|
||
else
|
||
echo -e "${ROUGE}ERROR ($rc1)${NORMAL}"
|
||
exit $rc1
|
||
fi
|
||
else
|
||
echo -e "${VERT}ALREADY EXISTING${NORMAL}"
|
||
fi
|
||
# ----
|
||
echo -e "\n---- Create container ----"
|
||
create_container
|
||
echo -e "\n---- Start container ----"
|
||
start_container
|
||
echo -e "\n---- Create Grafana DS ----"
|
||
# ----
|
||
# wait until grafan is up
|
||
echo -n "Wait until grafana is starting: "
|
||
timeout=60 # Max time to wait in seconds
|
||
interval=2 # Wait time between checks
|
||
elapsed=0
|
||
while true; do
|
||
status_code=$(curl -k -s -o /dev/null -w "%{http_code}" \
|
||
-u "$GF_ADMIN_USER:$GF_ADMIN_PASS" \
|
||
"$GF_ROOT_URL/api/health")
|
||
|
||
if [ "$status_code" -eq 200 ]; then
|
||
echo -e "${VERT}STARTED${NORMAL}"
|
||
break
|
||
fi
|
||
|
||
if [ "$elapsed" -ge "$timeout" ]; then
|
||
echo -e "${ROUGE}ERROR ($status_code)${NORMAL}"
|
||
exit 1
|
||
fi
|
||
|
||
sleep "$interval"
|
||
elapsed=$((elapsed + interval))
|
||
done
|
||
# ----
|
||
echo -n "Create Loki DS: "
|
||
add_gf_data_source loki http://loki:3100
|
||
rc1=$?
|
||
if [ $rc1 -eq 0 ]; then
|
||
echo -e "${VERT}SUCCESSFULLY CREATED${NORMAL}"
|
||
else
|
||
echo -e "${ROUGE}ERROR ($rc1)${NORMAL}"
|
||
exit $rc1
|
||
fi
|
||
# ----
|
||
echo -n "Create Prometheus DS: "
|
||
add_gf_data_source prometheus http://prometheus:9090 ""
|
||
rc1=$?
|
||
if [ $rc1 -eq 0 ]; then
|
||
echo -e "${VERT}SUCCESSFULLY CREATED${NORMAL}"
|
||
else
|
||
echo -e "${ROUGE}ERROR ($rc1)${NORMAL}"
|
||
exit $rc1
|
||
fi
|
||
echo -e "\n---- Install Grafana dashboard ----"
|
||
# ----
|
||
db_name="Node Exporter Full"
|
||
echo -n "Import '$db_name' dashboard: "
|
||
# check if already imported
|
||
response=$(curl -k -s -u "$GF_ADMIN_USER:$GF_ADMIN_PASS" "$GF_ROOT_URL/api/search?query=")
|
||
if echo "$response" | grep -iq "\"title\":\"$db_name\""; then
|
||
echo -e "${VERT}ALREADY IMPORTED${NORMAL}"
|
||
else
|
||
import_gf_dashboard 1860 prometheus
|
||
rc1=$?
|
||
if [ $rc1 -eq 0 ]; then
|
||
echo -e "${VERT}SUCCESSFULLY IMPORTED${NORMAL}"
|
||
else
|
||
echo -e "${ROUGE}ERROR ($rc1)${NORMAL}"
|
||
exit $rc1
|
||
fi
|
||
fi
|
||
# ----
|
||
db_name="Logs / App"
|
||
echo -n "Import '$db_name' dashboard: "
|
||
# check if already imported
|
||
response=$(curl -k -s -u "$GF_ADMIN_USER:$GF_ADMIN_PASS" "$GF_ROOT_URL/api/search?query=")
|
||
if echo "$response" | grep -iq "\"title\":\"$db_name\""; then
|
||
echo -e "${VERT}ALREADY IMPORTED${NORMAL}"
|
||
else
|
||
import_gf_dashboard 13639 loki
|
||
rc1=$?
|
||
if [ $rc1 -eq 0 ]; then
|
||
echo -e "${VERT}SUCCESSFULLY IMPORTED${NORMAL}"
|
||
else
|
||
echo -e "${ROUGE}ERROR ($rc1)${NORMAL}"
|
||
exit $rc1
|
||
fi
|
||
fi
|
||
# ----
|
||
#db_name="Prometheus 2.0 Overview"
|
||
db_name="Prometheus All Metrics"
|
||
echo -n "Import '$db_name' dashboard: "
|
||
# check if already imported
|
||
response=$(curl -k -s -u "$GF_ADMIN_USER:$GF_ADMIN_PASS" "$GF_ROOT_URL/api/search?query=")
|
||
if echo "$response" | grep -iq "\"title\":\"$db_name\""; then
|
||
echo -e "${VERT}ALREADY IMPORTED${NORMAL}"
|
||
else
|
||
#import_gf_dashboard 3662 prometheus
|
||
import_gf_dashboard 19268 prometheus
|
||
rc1=$?
|
||
if [ $rc1 -eq 0 ]; then
|
||
echo -e "${VERT}SUCCESSFULLY IMPORTED${NORMAL}"
|
||
else
|
||
echo -e "${ROUGE}ERROR ($rc1)${NORMAL}"
|
||
exit $rc1
|
||
fi
|
||
fi
|
||
# ----
|
||
db_name="MinIO Dashboard"
|
||
echo -n "Import '$db_name' dashboard: "
|
||
# check if already imported
|
||
response=$(curl -k -s -u "$GF_ADMIN_USER:$GF_ADMIN_PASS" "$GF_ROOT_URL/api/search?query=")
|
||
if echo "$response" | grep -iq "\"title\":\"$db_name\""; then
|
||
echo -e "${VERT}ALREADY IMPORTED${NORMAL}"
|
||
else
|
||
import_gf_dashboard 13502 prometheus
|
||
rc1=$?
|
||
if [ $rc1 -eq 0 ]; then
|
||
echo -e "${VERT}SUCCESSFULLY IMPORTED${NORMAL}"
|
||
else
|
||
echo -e "${ROUGE}ERROR ($rc1)${NORMAL}"
|
||
exit $rc1
|
||
fi
|
||
fi
|
||
;;
|
||
stop-stack)
|
||
docker compose stop
|
||
;;
|
||
down-down)
|
||
docker compose down
|
||
;;
|
||
del-stack)
|
||
# confirm installation
|
||
while true; do
|
||
read -p "Are you sure you want to permanently delete the stack '${COMPOSE_PROJECT_NAME}'? [y/n] ? " yn
|
||
case $yn in
|
||
[Yy]* ) break;;
|
||
* ) exit; #echo "Please answer yes or no.";;
|
||
esac
|
||
done
|
||
echo -e "\n---- Stop and remove all container ----"
|
||
docker compose down
|
||
echo -e "\n---- Delete all folder ----"
|
||
remove_folder
|
||
;;
|
||
list)
|
||
echo "-------------------------------------"
|
||
echo " Container list"
|
||
echo "-------------------------------------"
|
||
docker compose config --services | sort
|
||
#for cont_item in "${containers_all[@]}"; do
|
||
# echo "- $cont_item"
|
||
#done
|
||
;;
|
||
-h|--help|help)
|
||
print_usage
|
||
exit 0
|
||
;;
|
||
-v|--version|version)
|
||
cat << EOF
|
||
$(basename "$0") v$version (c) 1990 - $(date +%Y) by Gilles Mouchet
|
||
Non-Commercial Use License – See LICENSE for details
|
||
EOF
|
||
exit 0
|
||
;;
|
||
*)
|
||
print_usage
|
||
exit 0
|
||
;;
|
||
esac
|