├── .color_codes.conf ├── .gitattributes ├── .gitignore ├── .vars_docker.example ├── README.md ├── docker_commands_list.sh ├── docker_compose_bounce.sh ├── docker_compose_folders.sh ├── docker_compose_function.sh ├── docker_compose_logs.sh ├── docker_compose_networks.sh ├── docker_compose_start.sh ├── docker_compose_stop.sh ├── docker_compose_test.sh ├── docker_folders_create.sh ├── docker_functions.sh ├── docker_list_configs.sh ├── docker_list_container.sh ├── docker_list_stack.sh ├── docker_scripts_setup.sh ├── docker_service_error.sh ├── docker_service_logs.sh ├── docker_stack_bounce.sh ├── docker_stack_folders.sh ├── docker_stack_start.sh ├── docker_stack_stop.sh ├── docker_swarm_init.sh ├── docker_swarm_leave.sh ├── docker_system_backup.sh ├── docker_system_clean.sh ├── docker_system_image.sh ├── docker_system_network.sh ├── docker_system_prune.sh ├── docker_system_stats.sh └── docker_system_volume.sh /.color_codes.conf: -------------------------------------------------------------------------------- 1 | ## Color picker, syntax: echo $BLD$CUR$RED$BBLU'Hello World!'$DEF 2 | # 3 | ## to display a grid of colors in your specific terminal, run this function: 4 | # for x in 0 1 4 5 7 8; do for i in {30..37}; do for a in {40..47}; do echo -ne "\e[$x;$i;$a""m\\\e[$x;$i;$a""m\e[0;37;40m "; done; echo; done; done; echo ""; 5 | # 6 | ## or this function: 7 | # for colour in {1..225}; do echo -en "\033[38;5;${colour}m38;5;${colour} \n"; done | column -x; 8 | # 9 | red=$'\033[38;2;255;000;000m' 10 | orn=$'\033[38;2;255;075;075m' 11 | ylw=$'\033[38;2;255;255;000m' 12 | grn=$'\033[38;2;000;170;000m' 13 | cyn=$'\033[38;2;085;255;255m' 14 | blu=$'\033[38;2;000;120;255m' 15 | prp=$'\033[38;2;085;085;255m' 16 | mgn=$'\033[38;2;255;085;255m' 17 | wht=$'\033[38;2;255;255;255m' 18 | blk=$'\033[38;2;025;025;025m' 19 | def=$'\033[m' 20 | # ## Text color 21 | # BLK=$'\e[30m' # Black 22 | # blk=$'\e[90m' # 23 | # RED=$'\e[31m' # Red 24 | # red=$'\e[91m' # 25 | # GRN=$'\e[32m' # Green 26 | # grn=$'\e[92m' # 27 | # YLW=$'\e[33m' # Yellow 28 | # ylw=$'\e[93m' # 29 | # BLU=$'\e[34m' # Blue 30 | # blu=$'\e[94m' # 31 | # MGN=$'\e[35m' # Magenta 32 | # mgn=$'\e[95m' # 33 | # CYN=$'\e[36m' # Cyan 34 | # cyn=$'\e[96m' # 35 | # WHT=$'\e[37m' # White 36 | # wht=$'\e[97m' # 37 | # 38 | ## Background color 39 | BBLK=$'\e[40m' # Black background 40 | bblk=$'\e[100m' # 41 | BRED=$'\e[41m' # Red background 42 | bred=$'\e[101m' # 43 | BGRN=$'\e[42m' # Green background 44 | bgrn=$'\e[102m' # 45 | BYLW=$'\e[43m' # Yellow background 46 | bylw=$'\e[103m' # 47 | BBLU=$'\e[44m' # Blue background 48 | bblu=$'\e[104m' # 49 | BMGN=$'\e[45m' # Magenta background 50 | bmgn=$'\e[105m' # 51 | BCYN=$'\e[46m' # Cyan background 52 | bcyn=$'\e[106m' # 53 | BWHT=$'\e[47m' # White background 54 | bwht=$'\e[107m' # 55 | # 56 | # Text Effect 57 | DEF=$'\e[0m' # Default color (reset) 58 | def=$'\e[0m' # 59 | BLD=$'\e[1m' # Bold\brighter 60 | bld=$'\e[1m' # 61 | DIM=$'\e[2m' # Dim\darker 62 | dim=$'\e[2m' # 63 | CUR=$'\e[3m' # Italic font 64 | cur=$'\e[3m' # 65 | UND=$'\e[4m' # Underline 66 | und=$'\e[4m' # 67 | INV=$'\e[7m' # Inverted 68 | inv=$'\e[7m' # 69 | STK=$'\e[9m' # Strikethrough 70 | stk=$'\e[9m' # 71 | COF=$'\e[?25l' # Cursor OFF 72 | cof=$'\e[?25l' # 73 | CON=$'\e[?25h' # Cursor ON 74 | con=$'\e[?25h' # 75 | # -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto eol=lf 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.env 2 | *profile* 3 | *shellcheck* 4 | *template* -------------------------------------------------------------------------------- /.vars_docker.example: -------------------------------------------------------------------------------- 1 | #### Variables list for Docker helper-scripts by Drauku. 2 | # 3 | #### These variables must be filled in with your network, architecture, etc. 4 | # Search for "REDACTED" and insert your own information for each variable found. 5 | # 6 | ## IMPORTANT! -- DO NOT LEAVE EMPTY LINES IN THIS CONFIG FILE, OR THE '.env' REDIRECT WILL BREAK 7 | ## NOTE: values inside '' (single quotes) are not expanded, use "" (double quotes) to include variable expansion 8 | # 9 | ## UserID and GroupID for the 'docker' username on the NAS 10 | # TIP: UID/GID are obtained from the terminal by executing the command: 'id docker' 11 | var_uid=1000 12 | var_gid=1000 13 | ## Timezone Region and City, according to 'TZ database name' column here: 14 | # https://en.wikipedia.org/wiki/List_of_tz_database_time_zones 15 | var_tz="America/Chicago" 16 | # 17 | var_email="redacted" 18 | # 19 | ## Internal network and docker system variables 20 | var_host_name="redacted" # NOTE: This variable cannot be used to create a 'service' name in traefik-dynamic.yml 21 | var_host_ip="192.168.1.redacted" # change to your NAS local area network IP 22 | var_public_ip="" # OPTIONAL. Be careful using this unless you have a static ip, if it changes it could break routing. 23 | # 24 | ## SUPER secret squirrel "admin:password" htpasswd basic auth (just kidding, make sure you change this) 25 | # TIP: make your own with the command: 'htpasswd -n username_changeme password_changeme' 26 | # NOTE: after using the `htpasswd` command, add a 2nd `$` for each generated `$` as shown in the below example: 27 | var_basic_auth="admin:$$apr1$$a0m8c2x6$$NoASfJAKF6lVquLYx0Urh/" 28 | # 29 | ## Media storage directory 30 | data_dir=/mnt/data 31 | media_folder="/share/Multimedia" # the `/share` prefix is QTS specific for all Shared Folders 32 | media_audio_books="${media_folder}/audio/books" 33 | media_audio_music="${media_folder}/audio/music" 34 | media_print_books="${media_folder}/print/books" 35 | media_video_series="${media_folder}/video/series" 36 | media_video_movies="${media_folder}/video/movies" 37 | # 38 | ## These entries must be domains at which you have dns nameserver permissions 39 | var_domain1="redacted" 40 | var_domain2="redacted" 41 | var_domain3="redacted" 42 | # 43 | ## External network resolution and access variables (cloudflare, namecheap, afraid.org, etc.) 44 | # If your 'certresolver' and 'dns' services are not through cloudflare, check this link for setup requirements: 45 | # https://docs.traefik.io/v2.0/https/acme/#providers 46 | var_certresolver="cloudflare" 47 | # 48 | ## DNS provider information 49 | var_dns_provider="cloudflare" 50 | var_dns1="9.9.9.9:53" # quad9 DNS 51 | var_dns2="1.1.1.1:53" # cloudflare DNS1 52 | var_dns3="1.0.0.1:53" # cloudflare DNS2 53 | var_dns4="208.67.222.222:53" # OpenDNS 54 | # 55 | #################################################################################################### 56 | #################### VARIABLES AFTER THIS LINE PROBABLY SHOULD NOT BE CHANGED #################### 57 | #################################################################################################### 58 | # 59 | ## This is the internal docker socket network, powered by "tecnativa/docker-socket-network" 60 | var_net_socket="docker_socket" 61 | var_subnet_socket="172.20.0.0/" 62 | var_gateway_socket="172.20.0.254" 63 | ## This is the edge network for connections outside of docker 64 | var_net_exedge="external_edge" 65 | var_subnet_exedge="172.21.0.0/16" 66 | var_gateway_exedge="172.21.0.254" 67 | ## This is the internal only bridge network 68 | var_net_rproxy="internal_only" 69 | var_subnet_rproxy="172.22.0.0/16" 70 | var_gateway_rproxy="172.22.0.254" 71 | ## This is the external bridge reverse proxy network 72 | var_net_rproxy="reverse_proxy" 73 | var_subnet_rproxy="172.23.0.0/16" 74 | var_gateway_rproxy="172.23.0.254" 75 | ## This is the docker-swarm only 'overlay' network for external pointing swarm traffic 76 | var_net_overlay="overlay" 77 | var_subnet_overlay="10.20.0.0/16" 78 | var_gateway_overlay="10.20.0.254" 79 | ## This is the docker-swarm only 'ingress' network for swarm management traffic 80 | var_net_ingress="ingress" 81 | var_subnet_ingress="10.21.0.0/16" 82 | var_gateway_ingress="10.21.0.254" 83 | # 84 | ## Folder heirarchy for Drauku's folder structure, modified from gkoerk's famously awesome folder structure for stacks. 85 | docker_dir=/opt/docker 86 | docker_folder="$HOME/docker" 87 | docker_appdata="${docker_folder}/appdata" 88 | docker_compose="${docker_folder}/compose" 89 | docker_secrets="${docker_folder}/secrets" 90 | docker_dkswarm="${docker_folder}/dkswarm" 91 | # these last two folders can be mapped to a different location, update accordingly 92 | docker_runtime="${docker_folder}/runtime" # map this to fast storage on your NAS, such as an SSD cache volume 93 | docker_scripts="${docker_folder}/scripts" # map this to wherever you store the qnaphomelab-docker-scripts repository 94 | # 95 | ## Ensure the 'var_script_vars' variable contents exactly references the copy of '.vars_docker.example' file. Default: '.vars_docker.env' 96 | var_script_vars="${docker_scripts}/.vars_docker.env" 97 | # 98 | ## This is the common name for all your docker compose config files. Default: 'compose.yml' 99 | ## WARNING: Do not change this unless you also change all your docker compose config file names. 100 | var_configs_file="compose.yml" 101 | # -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | # QNAP HomeLAB Using Docker Containers 4 | 5 | #### A Guide for Docker Container management via SSH Terminal 6 | 7 |
WARNING: Unfinished Project

8 | 9 |
10 | 11 | Getting this HomeLAB enviornment working in your QNAP will probably require tweaking and troubleshooting. 12 | 13 | Consider joining and contributing to the [QNAP Unofficial Discord](https://discord.gg/NaxEB4sz7G), a community built around advice on everything QNAP. We have helpful members, FAQs, community Docker images, and cookies (well, maybe not cookies). 14 | 15 | I am quite active in the Discord, and will help when and if I can, but I can not be held responsible for issues created while following this guide or performing any suggestions I make. 16 | 17 | **WARNING:** This guide is incomplete, and as such **will *probably*** contain errors. 18 | 19 | Please read the [disclaimer](#disclaimer) at the end of this document. 20 | 21 | ##### PRE-REQUISITES 22 | 23 | A desire to learn Docker and some basic Terminal commands. 24 | 25 | A desktop with a Terminal application (e.g. Termius), and a text editor (e.g. VSCodium) 26 | 27 | A QNAP device that supports the Container Station application and therefore Docker. 28 | 29 | A Debian based Linux distribution with Docker installed via https://get.docker.com 30 | 31 | Thanks for checking out this guide. If it ends up being useful for your setup, please consider donating! 32 | 33 | 34 | 35 |
36 | 37 | --- 38 | --- 39 | 40 | ### Contents 41 | [QNAP HomeLAB Using Docker Containers](#qnap-homelab-using-docker-containers) 42 | 43 | - [I. QNAP GUI Steps](#i-qnap-gui-steps) 44 | - [1. Network Port Configuration](#1-network-port-configuration) 45 | - [2. Docker user account](#2-docker-user-account) 46 | - [3. Entware-std installation](#3-entware-std-installation) 47 | - [4. Container Station Setup](#4-container-station-setup) 48 | - [5. Docker Shared Folder](#5-docker-shared-folder) 49 | - [II. Terminal Steps](#ii-terminal-steps) 50 | - [1. SSH Terminal Connection](#1-ssh-terminal-connection) 51 | - [2. Docker folder creation](#2-docker-folder-creation) 52 | - [3. Entware-std profile setup](#3-entware-std-profile-setup) 53 | - [4. Docker Scripts Reference](#4-docker-scripts-reference) 54 | - [III. Docker general config steps](#iii-docker-general-config-steps) 55 | - [1. Environment Variables](#1-environment-variables) 56 | - [2. Docker Container Creation](#2-docker-container-creation) 57 | - [Contributors](#contributors) 58 | - [DISCLAIMER](#disclaimer) 59 | 60 | --- 61 | --- 62 |
63 | 64 | ## QNAP GUI Steps 65 |
66 | 67 | All actions in this section will be performed in the QNAP QTS Web UI. 68 | 69 | If following this guide on a Debian based OS, QNAP specific steps are unnecessary. 70 | 71 | ### 1. Network Port Configuration 72 | 73 | ##### New Ports Settings Overview 74 | 75 | **QTS System UI** 76 | `HTTP: 8480 | HTTPS: 8443` 77 | 78 | **Web Server** 79 | `HTTP: 9480 | HTTPS: 9443` 80 | 81 | **SSH Terminal** 82 | `example: 54545` 83 | 84 | 1. For ease of configuration, ports 80, 443, and 8080 **must be _unused_ by your NAS.** 85 | - ***NOTE:*** This step may be unnecessary if you can get 'chained' port-forwards to work when configuring Traefik to recognize your domain and register a certificate. YMMV. 86 | - **EXPLANATION:** QTS assigns ports 8080 and 443 as the default HTTP and HTTPS ports for the QNAP Web UI, and assigns 80 as the default HTTP port for the native "Web Server" application. A reverse proxy requires 80 and 443 in order to obtain certificates and properly route traffic. Unless you decide not to use a reverse proxy, these must be changed to successfully complete this guide. 87 | - **RECOMMENDATION:** Even if you do not use a reverse proxy, I ***HIGHLY*** recommend that you change the default ports for the Web UI, Web Server, and SSH connections to increase the security of your NAS. Also disable UPnP. 88 | 89 | 1. Modify the default ports as follows to ensure there will be no port conflicts with docker stacks: 90 | - **Change default *System* ports:** In QNAP Web GUI 91 | - `Control Panel >> System >> General Settings` 92 | - Change the default HTTP port to `8480`, and the default HTTPS port to `8443`. 93 | - **NOTE:** This *will* change the LAN address from which you access your QTS web-gui, requiring you to add the port at the end of your NAS LAN IP (e.g. https://192.168.1.100:8443) 94 | - **Change default *Web Application* ports:** In QNAP Web GUI 95 | - `Control Panel >> Applications >> Web Server` 96 | - Change the default HTTP port to `9480`, and the default HTTPS port to `9443`. 97 | - **TIP:** Unless currently in use, consider disabling the MySQL application in the QNAP GUI Settings. 98 | - **NOTE:** Prior to version 5.x it is required to keep the **Web Server** application enabled with the modified ports, otherwise the QTS Web Server would re-acquire the default port when disabled. 99 | - **Change default *SSH* port:** In QNAP Web UI 100 | - `Control Panel >> Network & File Services >> Telent / SSH` 101 | - Change the default to a random number somewhere between `49152 - 65535`. 102 | - See this [list of port numbers](https://en.wikipedia.org/wiki/List_of_TCP_and_UDP_port_numbers#Dynamic,_private_or_ephemeral_ports) to make sure the one you choose is not already assigned. 103 | 104 | 1. In order to use a reverse proxy, ports 80 and 443 must be forwarded from your router to your NAS. 105 | - **WARNING:** Only configure this port forward if you are using a reverse proxy such as [Traefik](https://traefik.io/traefik/), [Caddy](https://caddyserver.com/docs/quick-starts/reverse-proxy), or [NXPM](https://nginxproxymanager.com/setup/). 106 | - *Disable UPnP on you router and manually forward ports 80 and 443 to your NAS.* 107 | - **NOTE:** There are too many possible routers to cover how to forward ports on each, but there are some good guides here if you don't know how to do it for your router: 108 | 109 | - https://www.howtogeek.com/66214/how-to-forward-ports-on-your-router 110 | 111 | - https://portforward.com/router.htm 112 | - **WARNING:** Do not purchase the port-forwarding program offered from this website, it will not work for this and is a waste of money. 113 | 114 | ### 2. Docker User Account Creation 115 | 116 | - **TIP:** During QTS initialization, if the first user created is the `dockeruser` user account, all the container configs shared here will be pre-configured to use the correct `UID: 1000` and `GID: 1000`. 117 | 118 | - **NOTE:** If you do not create the `docker` user as the first user account, you will need to update each container config to reflect your particular `UID` and `GID`, obtained by the terminal command: `id dockeruser`. 119 | 120 | 1. Ensure the `docker` user account is created. 121 | - `Control Panel >> Privilege >> Users` 122 | - Click the `Create` dropdown button and select `Create User`. 123 | **TIP:** Create the user with all lowercase letters so Linux case sensitivity is never an issue. 124 | 125 | 1. Create a new group called `docker`. 126 | **NOTE:** This step can be performed after creation of the `/docker` Shared Folder below in the `5. Docker Folder Creation` section. 127 | - `Control Panel >> Privilege >> User Groups` 128 | - Click the `Create` button and type in the `docker` name. 129 | **TIP:** Create the user with all lowercase letters so Linux case sensitivity is never an issue. 130 | - Assign the `docker` user account to this group by clicking the `Edit` button on the right. 131 | - If the `/docker` Shared Folder has been created, assign `read/write` folder permissions for this group to the folder. 132 | 133 | ### 3. Entware-std Installation 134 | 135 | 1. Install the `entware-std` package from the third-party QNAP Club repository appstore. This is necessary in order to set up the shortcuts/aliases used when controlling docker via command line by editing a permanent profile. 136 | 137 | - The preferred way to do this is to add the My QNAP (formerly QNAP Club) Repository to the App Center. Follow the [walkthrough instructions here](https://www.myqnap.org/install-the-repo/). 138 | 139 | Note, I use the English translation of the My QNAP website, but you may change languages (and urls) in the upper right language dropdown. 140 | 141 | - If you don't need the walkthrough, add the repository. 142 | For English, go to App Center, Settings, App Repository, paste in 143 | `https://www.myqnap.org/repo.xml`. 144 | 145 | - If you **cannot** add the QNAP Club store to the App Center, you may manually download the qpkg file from that link and use it to manually install via the App Center, "Install Manually" button. This is **not preferred** as QNAP cannot check for and notify you of updates to the package. 146 | 147 | - Search for `entware-std` and install the package. 148 | 149 | **TIP:** If you have trouble locating the correct package, the description begins with 150 | `entware-3x and entware-ng merged to become entware.` 151 | The working link (as of publication) is here: https://www.myqnap.org/product/entware-std/ 152 | 153 | - **IMPORTANT:** ***DO NOT*** install the `entware-ng` or `entware-3x-std` packages. These have merged and been superceded by `entware-std`. 154 | 155 | ### 4. Container Station Setup 156 | 157 | 1. Backup what you have running now (if you don't have anything running yet, skip to Step 3. If you have also never used Container Station, skip to Step 5). 158 | 159 | 1. Shutdown and remove all docker containers and networks. This can be accomplished using Container Station, but connecting via SSH terminal allows you to complete this quickly with only three commands. 160 | 161 | - Stop all running containers: 162 | ```bash 163 | docker stop $(docker container ls --all --quiet) 164 | ``` 165 | 166 | - Remove all stopped containers, unused networks, images, and build cache: 167 | ```bash 168 | docker system prune 169 | ``` 170 | 171 | - Ensure you are not a part of a Docker Swarm: 172 | ```bash 173 | docker swarm leave --force 174 | ``` 175 | 176 | 1. Remove Container Station: 177 | - In App Center, click the dropdown for Container Station and choose `Remove`. 178 | - In `Control Panel >> Shared Folders`, check the box next to the `container` shared folder and click "Remove" 179 |

180 | - In the pop-up box, check "Also delete the data" and click "Yes" 181 |


182 | 183 | 1. Reboot the NAS 184 |


185 | 186 | 1. Once the reboot is complete, install Container Station from the QNAP Appstore. 187 | - Launch CS after installed. 188 | - Create the `container/` folder when prompted during the first launch of CS. 189 | 190 | ### 5. Docker Shared Folder 191 | 192 | 1. Create the `docker/` folder share **using the QTS Web UI** 193 | 194 | - `ControlPanel >> Privilege >> Shared Folders` 195 | 196 | - Click the 'Create' dropdown button and select `Shared Folder`. 197 | 198 | - Name the folder `docker` using **all lowercase letters**. 199 | 200 | ***WARNING:*** An all lowercase `docker` folder is required so the helper scripts work correctly. 201 | 202 | - Give `dockeruser` Read/Write permissions for the newly created `/docker` shared folder: 203 | 204 | - **INFO:** This is the main "docker" folder inside which we will place swarm and compose config files in their own subfolders, as well as helper scripts and secrets. The remaining folders listed below should be created using the Terminal while logged in using the default QTS `admin` account. 205 | 206 | - **NOTE:** The `appdata`, `compose`, `secrets`, and `swarm` sub-folders can be created using QTS File Station, but that is entirely unnecessary considering you can create them all with a single terminal command shown below. They should *not* be created as Shared Folders in the same way as the parent `docker/` folder. 207 | 208 | --- 209 |
210 | 211 | ## Terminal Steps 212 |
213 | 214 | All actions in this section will be accomplished via SSH terminal connection to your QNAP NAS. 215 | 216 | ### 1. SSH Terminal Connection 217 | 218 | 1. Open/Connect an SSH terminal session to your QNAP NAS. 219 | * You can use [PuTTY](https://putty.org/), the `Windows Subsystem for Linux`, [Cmder](https://cmder.net/) or any terminal utility with SSH. 220 | - **NOTE:** Alternatively you can use [BitVise](https://www.bitvise.com/ssh-client-download) because this also has an SFTP remote file browser interface. 221 | - **TIP:** I switched to using [WinSCP](https://winscp.net/eng/download.php) and [Cmder](https://cmder.net/) because they have dark themes. [Windows Terminal Preview](https://docs.microsoft.com/en-us/windows/terminal/get-started) is turning out to be a good Terminal as well. 222 | - **TIP:** Connecting to the NAS using SFTP allows me to edit the docker config files using `Notepad++` or `VSCodium` (open source Visual Studio Code clone). 223 | - **TIP:** I also map the `/share/docker/` folder as a Network drive on my Windows desktop, which makes viewing and editing Docker config files very easy. 224 | 225 | 2. Install `nano` so you can edit text files in the terminal: 226 | ***NOTE:*** You must have installed `entware-std` as detailed in [Section 1.4](#4-container-station-setup) and rebooted to be able to use the "opkg" installer command. 227 | - **RUN:** `opkg install nano` 228 | 229 | ### 2. Docker folder creation 230 | 231 | 1. This section is a continuation of the QNAP QTS folder creation steps from the previous section. Here we will create required sub-folders in the `docker/` Shared Folder. 232 | 233 | 1. Before creating the folders, these descriptions will familiarize you with the structure. 234 | 235 | `/share/docker/appdata` 236 | - This is where `application` data and internal config files will reside. 237 | - Each docker `container` will have its own named subfolder. 238 | 239 | `/share/docker/compose` 240 | - This is where `Docker stack` files will be stored using the docker compose format. 241 | - Each `compose` file can have multiple apps or containers included in the stack. 242 | - A git repository can provide versioning and backup for this folder. 243 | - **Do not save sensitive data** in compose.yml files if this is a git repository. 244 | 245 | `/share/docker/runtime` 246 | - OPTIONAL. `Temporary` DB files and `transcode` files will go here. 247 | - This folder should reside on a volume that does not get backed up. 248 | - Link this folder to a fast storage volume or Qtier cache if possible. 249 | - If used, create with `ln -s /target/volume/path /share/docker/runtime` 250 | 251 | `/share/docker/scripts` 252 | - Docker helper scripts for convenient container management are stored here. 253 | - Read and update the `.vars_docker.env` file with your configuration info. 254 | - These scripts are why folder paths and compose files have strict naming requirements. 255 | 256 | `/share/docker/secrets` 257 | - This folder contains `secret` or `sensitive` configuration data such as passwords. 258 | - Do **not** store this folder in a public git repository. 259 | - Non-sensitive, `common` configuration settings can also be stored here. 260 | 261 | `/share/docker/swarm` 262 | - This is where `Swarm stack` files will be stored using the docker compose format. 263 | - Each `compose` file can have *multiple* apps or containers included in the stack. 264 | - A git repository can provide versioning and backup for this folder. 265 | - **Do not save sensitive data** in compose.yml files if this is a git repository. 266 | 267 | 1. The required subfolders should be created using this terminal command: 268 | - QNAP ONLY: A link from `/opt/docker` to `/share/docker` is required for script operations. 269 | ```bash 270 | ln -s /share/docker /opt/docker 271 | ``` 272 | 273 | **TIP:** Change `-o 1000` to your docker user `UID` and `-g 1000` to your docker group `GUID`. 274 | ```bash 275 | install -o 1000 -g 1000 -m 755 -d /share/docker/{appdata,compose,scripts,secrets,swarm} 276 | ``` 277 | 278 | - Once required folders are created, make sure all files and sub-folders inside `docker/` are owned by the `dockeruser` and have the proper permissions: 279 | ```bash 280 | chown dockeruser:dockergroup -cR /opt/docker && chmod 755 -cR /opt/docker 281 | ``` 282 | 283 | - This is what your folder heirarchy should show after creating the required folders: 284 | ```bash 285 | # Docker folder heirarchy 286 | /share 287 | └── docker 288 | ├── appdata 289 | │ ├── appname 290 | │ └── ... 291 | ├── compose 292 | │ ├── appname 293 | │ └── ... 294 | ├── runtime 295 | ├── scripts 296 | ├── secrets 297 | └── swarm 298 | ├── appname 299 | └── ... 300 | ``` 301 | - Viewed through WinSCP, which shows the volume designation: 302 |
303 |
The `CECACHEDEV2_DATA` volume tag may be different on your NAS.

304 | 305 | 1. Next you need to download the `docker helper scripts` from this [QNAP HomeLAB Docker Scripts](https://gitlab.com/qnap-homelab/docker-scripts) repository to your `/share/docker/scripts/` directory. 306 | 307 |
308 | 309 | **WARNING:** 310 | The automatic install script is not working, please download and install the scripts manually. 311 | 312 |
313 | 314 | - ~~Alternatively, if you trust my installation script to run as root on your system, you can run this `curl` command that will automatically download and install the scripts for you:~~ 315 | 316 | - ***TIP:*** Read through and understand what a script does before executing possibly malicious code on any device. 317 | 318 | ```bash 319 | # install the docker_scripts_setup.sh using wget without downloading the file 320 | wget -qO - https://raw.githubusercontent.com/qnap-homelab/docker-scripts/master/docker_scripts_setup.sh | sh 321 | ``` 322 | 323 | ***OR*** 324 | ```bash 325 | # download and install the docker_scripts_setup.sh using cURL 326 | curl -fs https://gitlab.com/qnap-homelab/docker-scripts/docker_scripts_setup.sh | sh 327 | ``` 328 | 329 | ### 3. Entware-std profile setup 330 | 331 | 1. Type the below lines into the QNAP command line. These commands will add a shortcut to reload the `profile` and make the docker scripts load each time you connect via SSH terminal. 332 | ```bash 333 | printf "\nalias profile='source /opt/etc/profile'" >> /opt/etc/profile 334 | ``` 335 | ```bash 336 | printf "\nsource /opt/docker/scripts/docker_commands_list.sh -c" >> /opt/etc/profile 337 | ``` 338 | - ***NOTE:*** If you prefer to enter the text manually, these are the lines that need to go at the bottom of the `profile` file: 339 | ```bash 340 | alias profile='source /opt/etc/profile' 341 | source /opt/docker/scripts/docker_commands_list.sh -c 342 | ``` 343 | 344 | - ***OPTIONAL:*** The below steps accomplish the same thing as above, but add notification messages whenever you reload or log into the qnap cli. 345 | 346 | - **EDIT** the `profile` file via `nano /opt/etc/profile` or `vi /opt/etc/profile` 347 | - **NOTE:** I prefer to use VSCodium to edit this file as it provides syntax highlighting. 348 | ```bash 349 | source /opt/docker/scripts/docker_commands_list.sh -c && echo " >> '.../docker_commands_list.sh' successfully loaded" || echo " -- ERROR: could not import '.../docker_commands_list.sh'" 350 | ``` 351 | - ***NOTE:*** You will need to restart your ssh terminal session, or execute the `profile` alias (a shortcut to reload `profile`), in order to make the changes effective. 352 |
353 | 354 |
355 | 356 | **WARNING:** 357 | If you use a Windows client to save the profile (or the scripts below), 358 | by default the files will be saved with the `CR LF` end of line sequence, 359 | and will error when executed. 360 | 361 | **You MUST set the end of line sequence to UNIX `LF`.** 362 | **Windows `CR LF` style EoL will result in failed scripts with no error.** 363 | 364 |
VSCodium EoL Settings
365 | 366 |
(click on the "CRLF" text on the right of the bottom status bar)
367 | 368 |
369 | 370 | ### 4. Docker Scripts Reference 371 | 372 | 1. Once the `profile` and `/share/docker/scripts` are set up, use the below section as a reference for Docker shortcut commands. 373 | 374 | - In general, this is the scheme for how the shortcut acronyms are composed: 375 | 376 | - `dc...` refers to "**D**ocker **C**ompose" commands, for use outside of a swarm setup 377 | - `dl...` refers to "**D**ocker **L**ist" commands (i.e. docker processes, docker networks, etc) 378 | - `ds...` refers to "**D**ocker **S**tack" commands (groups of containers in a swarm setup) 379 | - `dv...` refers to "**D**ocker ser**V**ice" commands (mostly error and logs related) 380 | - `dw...` refers to "**D**ocker s**W**arm" initialization/removal commands (the whole swarm) 381 | - `dy...` refers to "**D**ocker s**Y**stem" commands for showing info and cleaning remnants 382 |
383 | 384 | - ***NOTE:*** Individual script descriptions have been removed from this `readme.md`. Please refer to the [docker_commands_list.sh](https://github.com/QNAP-HomeLAB/Docker-Scripts/blob/master/docker_commands_list.sh) file for an updated list with descriptions. 385 | 386 | --- 387 |
388 | 389 | ## Docker general config steps 390 |
391 | 392 | All instructions in this section will apply to your chosen Docker environment. 393 | 394 | ### 1. Environment Variables 395 | 396 | 1. The Docker helper scripts require several environment variable to be properly configured. 397 | 398 | - The `.vars_docker.env` file has variables used by both Swarm and Compose containers. 399 | 400 | - Ensure this file is located here: `/share/docker/scripts/.vars_docker.env` 401 | 402 | - Read through this file, and fill in ***YOUR* NETWORK, NAS, OR PERSONAL INFORMATION**. 403 | 404 | - Pay special attention to these variables, as they are ***REQUIRED:*** 405 | 406 | - `var_host_ip` - this is the Local Area Network IP address of your QNAP 407 | 408 | - `var_uid` - userid from command `id dockeruser` 409 | 410 | - `var_gid` - groupid from command `id dockeruser` 411 | 412 | - `var_tz` - time zone in standard `Region/City` format 413 | 414 | - `var_domain0` - main, or only, domain name used by Traefik 415 | 416 | - `var_dns_provider` - DNS provider (e.g. Cloudflare, Namecheap, etc) 417 | 418 | - `var_certresolver` - Certificate Resolver (e.g. Cloudflare, Namecheap, etc) 419 | 420 | - There are many more variables, but not all will be used for each new container created. 421 | 422 | ### 2. Docker Container Creation 423 | 424 | 1. The basic setup is now complete. Continue in one of the two (or a combination of both!) linked repositories below to further customize your Docker environment. 425 | 426 | I recommend the `Docker Swarm` setup, as it is considered a production environment. Docker Compose files can still be used in a Docker Swarm, but not all features of a Swarm can be used in the basic Compose setup. 427 | 428 | Once these environment specific steps are completed, you will be ready to customize `Traefik` and other Docker container configuration files also found in the repositories below. 429 | 430 | Download and modify the desired Docker container config files, or write your own. 431 |
432 | 433 | 2. Final required steps and example application configuration files from QNAP HomeLAB: 434 | - [QNAP HomeLAB Docker Compose Configs](https://www.github.com/QNAP-HomeLAB/Docker-Compose) - No further system configuration required. `docker-compose.yml` files can be used to immediately run containerized applications. 435 | - [QNAP HomeLAB Docker Swarm Configs](https://www.github.com/QNAP-HomeLAB/Docker-Swarm) - Several more system configuration steps are required before you can run containerized applications using a Swarm setup. 436 | 437 | If you have questions or issues, please join the community here: [QNAP Unofficial Discord](https://discord.gg/NaxEB4sz7G). 438 | 439 | --- 440 | --- 441 | 442 | # Contributors 443 | 444 | * Thanks to the late `gkoerk` (RIP) for starting this community and project. Without his efforts, none of this would have been possible. 445 | * Funky Penguin at funkypenguin.co.nz provided a lot of the inspiration and docker config examples which started this QNAP specific project. 446 | * Several articles from smarthomebeginner.com were used as reference for the Traefik and Cloudflare configuration steps contained in the next two sections of this guide. 447 | * The many helpers and members in the [QNAP Unofficial Discord](https://discord.gg/NaxEB4sz7G) community. 448 | 449 | --- 450 | 451 | # DISCLAIMER 452 | 453 | - **WARNING:** This guide is incomplete, and as such ***will probably contain errors***. 454 | 455 | * **NOTE:** Effort has been made to provide accurate instructions tailored for QNAP NAS devices, but no guarantee can be made that this guide will work on your specific device. 456 | 457 | - I find it unfortunate that I have to say this, but you must accept all liability for any loss or damage or inconvenience resulting from your use of the information contained in these guides. 458 | 459 | - All responsibility and risk for properly verifying the validity of anything written in this guide lies with the user. 460 | 461 | - Contributors have composed the steps contained herin to the best of their ability, but nobody is infallible nor can all situations be accounted for. 462 | 463 | - If you have questions or concerns, please join us on the [QNAP Unofficial Discord](https://discord.gg/NaxEB4sz7G) community and request help. 464 | -------------------------------------------------------------------------------- /docker_commands_list.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ## Folder hierarchy for Drauku's directory structure, modified from gkoerk's famously awesome folder structure for stacks. 4 | export docker_folder="/opt/docker" 5 | export docker_appdata="${docker_folder}/appdata" 6 | export docker_compose="${docker_folder}/compose" 7 | export docker_runtime="${docker_folder}/runtime" 8 | export docker_scripts="${docker_folder}/scripts" 9 | export docker_secrets="${docker_folder}/secrets" 10 | export docker_swarm="${docker_folder}/swarm" 11 | 12 | ## external variable sources 13 | source /opt/docker/scripts/.color_codes.conf 14 | source /opt/docker/scripts/.vars_docker.env 15 | 16 | # function definitions 17 | fnc_help_docker_commands() { 18 | echo -e " ┌────────────────────────────────────────────────────────────────────────" 19 | echo -e " │ ${blu:?}Bash scripts and Docker aliases created to increase Docker command execution speed.${def:?}" 20 | echo -e " │ " 21 | echo -e " │ SYNTAX: # dlist | dlist ${cyn:?}-option${def:?}" 22 | echo -e " │ VALID OPTIONS:" 23 | echo -e " │ ${cyn:?} -a ${def:?}│${cyn:?} --aliases ${def:?}│ Displays the list of Docker Aliases." 24 | echo -e " │ ${cyn:?} -s ${def:?}│${cyn:?} --scripts ${def:?}│ Displays the list of Docker Scripts." 25 | echo -e " │ ${cyn:?} -f ${def:?}│${cyn:?} --functions ${def:?}│ Displays both the list of Docker Scripts and Aliases." 26 | echo -e " │ ${cyn:?} -c ${def:?}│${cyn:?} --create ${def:?}│ Register and create docker aliases and custom commands." 27 | echo -e " │ ${cyn:?} -h ${def:?}│${cyn:?} --help ${def:?}│ Displays this help message." 28 | echo -e " └────────────────────────────────────────────────────────────────────────" 29 | echo 30 | exit 1 # Exit script after printing help 31 | } 32 | case "${1}" in ("-h"|*"help"*) fnc_help_docker_commands ;; esac 33 | 34 | # echo -e " ┌────────────────────────────────────────────────────────────────────────" 35 | # echo -e " │ " 36 | # echo -e " └────────────────────────────────────────────────────────────────────────" 37 | # echo -e " ┌─────────┬──────────────────┬───────────────────────────────────────────" 38 | # echo -e " ├─────────┼──────────────────┼───────────────────────────────────────────" 39 | # echo -e " └─────────┴──────────────────┴───────────────────────────────────────────" 40 | # ┌ ─ ┬ ─ ┐ 41 | # │ │ │ 42 | # ├ ─ ┼ ─ ┤ 43 | # │ │ │ 44 | # └ ─ ┴ ─ ┘ 45 | 46 | # docker_commands_list -- function and alias for this script file 47 | fnc_docker_commands(){ sh "${docker_scripts}/docker_commands_list.sh" "${@}"; } 48 | alias dcmd="fnc_docker_commands" 49 | alias dlist="fnc_docker_commands -f"; 50 | # alias dscripts='source /opt/docker/scripts/docker_commands_list.sh --create' 51 | 52 | fnc_invalid_syntax(){ echo -e "${ylw:?} >> INVALID OPTION SYNTAX, USE THE ${cyn:?}-help${ylw:?} OPTION TO DISPLAY PROPER SYNTAX <<${def:?}"; } 53 | 54 | ## docker script definitions 55 | # src="/opt/docker/scripts/docker_commands_list.sh" 56 | # . $src && echo " >> '$src' successfully loaded" || echo " -- ERROR: could not import '$src'" 57 | # [ -e $src ] && . $src || echo " -- ERROR: '$src' does not exist" 58 | 59 | fnc_list_aliases() { 60 | echo -e " ┌─────────┬──────────────────┬───────────────────────────────────────────" 61 | echo -e " │ ${blu:?}ALIAS${def:?} │ ${blu:?}TARGET COMMAND${def:?} │ ${blu:?}ALIAS DESCRIPTION${def:?}" 62 | echo -e " ├─────────┼──────────────────┼───────────────────────────────────────────" 63 | echo -e " │${cyn:?} dk ${def:?}│${ylw:?} docker ${def:?}│ '${cyn:?}docker${def:?}' command alias" 64 | echo -e " │${cyn:?} dki ${def:?}│${ylw:?} docker images ${def:?}│ '${cyn:?}docker ${grn:?}images${def:?}' command alias" 65 | echo -e " │${cyn:?} dkn ${def:?}│${ylw:?} docker network ${def:?}│ '${cyn:?}docker ${grn:?}network${def:?}' command alias" 66 | echo -e " │${cyn:?} dkv ${def:?}│${ylw:?} docker service ${def:?}│ '${cyn:?}docker ${grn:?}service${def:?}' command alias" 67 | echo -e " │${cyn:?} dkl ${def:?}│${ylw:?} docker logs ${def:?}│ '${cyn:?}docker ${grn:?}logs${def:?}' command alias" 68 | echo -e " │${cyn:?} dklf ${def:?}│${ylw:?} docker logs -f ${def:?}│ '${cyn:?}docker ${grn:?}logs -f${def:?}' command alias" 69 | echo -e " │${cyn:?} dkrm ${def:?}│${ylw:?} docker rm ${def:?}│ '${cyn:?}docker ${grn:?}rm${def:?}' (removes no-trunc list) shortcut" 70 | echo -e " │${cyn:?} dkrmi ${def:?}│${ylw:?} docker rmi ... ${def:?}│ '${cyn:?}docker ${grn:?}rmi${def:?}' (removes dangling images) shortcut" 71 | echo -e " │${cyn:?} dkt ${def:?}│${ylw:?} docker stats ... ${def:?}│ '${cyn:?}docker ${grn:?}stats${def:?}' (lists stats using custom columns) shortcut" 72 | echo -e " │${cyn:?} dkps ${def:?}│${ylw:?} docker ps ... ${def:?}│ '${cyn:?}docker ${grn:?}ps${def:?}' (lists processes using custom columns) shortcut" 73 | echo -e " │${cyn:?} dc ${def:?}│${ylw:?} docker compose ${def:?}│ '${cyn:?}docker compose${def:?}' command alias" 74 | # echo -e " │${cyn:?} dm ${def:?}│${ylw:?} docker-machine ${def:?}│ '${cyn:?}docker-machine${def:?}' command alias" 75 | echo -e " │${cyn:?} dccfg ${def:?}│${ylw:?} dlg --compose ${def:?}│ '${cyn:?}docker ${grn:?}logs${def:?}' custom command alias" 76 | echo -e " │${cyn:?} dwcfg ${def:?}│${ylw:?} dlg --swarm ${def:?}│ '${cyn:?}docker ${grn:?}logs${def:?}' custom command alias" 77 | echo -e " │${cyn:?} bounce ${def:?}│${ylw:?} dsb --all ${def:?}│ ${cyn:?}stop${def:?} and ${cyn:?}restart${def:?} swarm stacks custom command alias" 78 | echo -e " │${cyn:?} dsup ${def:?}│${ylw:?} dsd --all ${def:?}│ ${cyn:?}start${def:?} ${grn:?}swarm stack${def:?} custom command alias" 79 | echo -e " │${cyn:?} dsrm ${def:?}│${ylw:?} dsr --all ${def:?}│ ${cyn:?}remove${def:?} ${grn:?}swarm stack${def:?} custom command alias" 80 | echo -e " │${cyn:?} dverror ${def:?}│${ylw:?} dve ${def:?}│ ${cyn:?}display${def:?} ${grn:?}container${def:?} errors custom command alias" 81 | echo -e " │${cyn:?} dvlogs ${def:?}│${ylw:?} dvl ${def:?}│ ${cyn:?}display${def:?} ${grn:?}container${def:?} logs custom command alias" 82 | echo -e " │${cyn:?} dwinit ${def:?}│${ylw:?} dwin traefik ${def:?}│ ${cyn:?}initialize${def:?} ${grn:?}swarm${def:?} custom command alias" 83 | echo -e " │${cyn:?} dwclr ${def:?}│${ylw:?} dwlv --all ${def:?}│ ${cyn:?}leave${def:?} and ${cyn:?}remove${def:?} ${grn:?}swarm${def:?} custom command alias" 84 | echo -e " │${cyn:?} dcmd ${def:?}│${ylw:?} dlist ${def:?}│ ${cyn:?}list${def:?} available custom Docker function aliases for use in terminal." 85 | echo -e " └─────────┴──────────────────┴───────────────────────────────────────────" 86 | echo -e " NOTE: Aliases do not have options, and are only shortcuts for the target command." 87 | echo 88 | } 89 | fnc_list_scripts() { 90 | echo -e " ┌────────────────────┬─────────────────────────┬──────────────────────────" 91 | echo -e " │ ${blu:?}COMMAND${def:?} │ ${blu:?}SCRIPT FILE NAME${def:?} │ ${blu:?}COMMAND DESCRIPTION${def:?}" 92 | echo -e " ├────────────────────┼─────────────────────────┼──────────────────────────" 93 | echo -e " │${cyn:?} dcmd / dlist ${def:?}│ ${ylw:?}docker_commands_list ${def:?}│ ${cyn:?}lists${def:?} available custom Docker function aliases for use in terminal." 94 | echo -e " ├──${blu:?} docker list ${def:?}─────┼─────────────────────────┼──────────────────────────" 95 | echo -e " │${cyn:?} dlc ${def:?}│ ${ylw:?}docker_list_container ${def:?}│ ${cyn:?}lists${def:?} currently deployed ${grn:?}docker containers${def:?} and/or services" 96 | echo -e " │${cyn:?} dlg / dcg / dsg ${def:?}│ ${ylw:?}docker_list_configs ${def:?}│ ${cyn:?}lists${def:?} ${grn:?}config files${def:?} in the custom QNAP Docker folder structure" 97 | echo -e " │${cyn:?} dli / dlimg ${def:?}│ ${ylw:?}docker_system_image ${def:?}│ ${cyn:?}lists${def:?} ${grn:?}docker images${def:?} currently stored on this system" 98 | echo -e " │${cyn:?} dln ${def:?}│ ${ylw:?}docker_system_network ${def:?}│ ${cyn:?}lists${def:?} currently created docker ${grn:?}networks${def:?}" 99 | echo -e " │${cyn:?} dls ${def:?}│ ${ylw:?}docker_list_stack ${def:?}│ ${cyn:?}lists${def:?} currently deployed ${grn:?}docker swarm stacks${def:?} and services" 100 | echo -e " │${cyn:?} dlv ${def:?}│ ${ylw:?}docker_system_volume ${def:?}│ ${cyn:?}lists${def:?} currently created docker ${grn:?}volumes${def:?}" 101 | echo -e " ├──${blu:?} docker compose ${def:?}──┼─────────────────────────┼──────────────────────────" 102 | echo -e " │${cyn:?} dcf / dcfolders ${def:?}│ ${ylw:?}docker_compose_folders ${def:?}│ ${cyn:?}creates ${grn:?}compose folder structure${def:?}" # for (1 - 9 listed) stacks" 103 | echo -e " │${cyn:?} dcb / dcbounce ${def:?}│ ${ylw:?}docker_compose_bounce ${def:?}│ ${cyn:?}removes${def:?} then ${cyn:?}recreates${def:?} a docker compose container " 104 | echo -e " │${cyn:?} dcl / dclogs ${def:?}│ ${ylw:?}docker_compose_logs ${def:?}│ ${cyn:?}lists${def:?} docker compose ${grn:?}logs${def:?}" 105 | echo -e " │${cyn:?} dcn / dcnet ${def:?}│ ${ylw:?}docker_compose_networks ${def:?}│ ${cyn:?}creates${def:?} docker compose ${grn:?}networks${def:?}" 106 | echo -e " │${cyn:?} dcs / dcstart ${def:?}│ ${ylw:?}docker_compose_start ${def:?}│ ${cyn:?}starts${def:?} (brings 'up') a docker compose container" 107 | echo -e " │${cyn:?} dcp / dcstop ${def:?}│ ${ylw:?}docker_compose_stop ${def:?}│ ${cyn:?}stops${def:?} (brings 'down') a docker compose container" 108 | echo -e " │${cyn:?} dct / dctest ${def:?}│ ${ylw:?}docker_compose_test ${def:?}│ ${cyn:?}tests${def:?} a docker compose file config by displaying all variables villed in" 109 | echo -e " ├──${blu:?} docker service ${def:?}──┼─────────────────────────┼──────────────────────────" 110 | echo -e " │${cyn:?} dve / dverror ${def:?}│ ${ylw:?}docker_service_error ${def:?}│ ${cyn:?}lists${def:?} docker services with ${grn:?}last error${def:?}" 111 | echo -e " │${cyn:?} dvl / dvlogs ${def:?}│ ${ylw:?}docker_service_logs ${def:?}│ ${cyn:?}lists${def:?} docker service and container ${grn:?}logs${def:?}" 112 | echo -e " ├──${blu:?} docker stack ${def:?}────┼─────────────────────────┼──────────────────────────" 113 | echo -e " │${cyn:?} dsf / dwfolder ${def:?}│ ${ylw:?}docker_stack_folders ${def:?}│ ${cyn:?}creates ${grn:?}stack folder structure${def:?}" # for (1 - 9 listed) stacks" 114 | echo -e " │${cyn:?} dsb / dsbounce ${def:?}│ ${ylw:?}docker_stack_bounce ${def:?}│ ${cyn:?}removes${def:?} then ${cyn:?}recreates${def:?} a docker stack container" 115 | echo -e " │${cyn:?} dss / dsstart ${def:?}│ ${ylw:?}docker_stack_start ${def:?}│ ${cyn:?}deploys ${grn:?}stack${def:?}, or a list of stacks in '${ylw:?}.../${cyn:?}swarm_stacks.conf${def:?}'" 116 | echo -e " │${cyn:?} dsp / dsstop ${def:?}│ ${ylw:?}docker_stack_stop ${def:?}│ ${cyn:?}removes ${grn:?}stack${def:?}, or ${cyn:?}-all${def:?} stacks listed via 'docker stack ls'" 117 | echo -e " ├──${blu:?} docker swarm ${def:?}────┼─────────────────────────┼──────────────────────────" 118 | echo -e " │${cyn:?} dwin / dwinit ${def:?}│ ${ylw:?}docker_swarm_init ${def:?}│ ${grn:?}swarm initialization script${def:?}, does ${ylw:?}NOT${def:?} download new scripts" 119 | echo -e " │${cyn:?} dwup / dwsup ${def:?}│ ${ylw:?}docker_swarm_setup ${def:?}│ ${grn:?}swarm setup script${def:?}, ${ylw:?}DOES${def:?} download new install scripts" 120 | echo -e " │${cyn:?} dwlv / dwclr ${def:?}│ ${ylw:?}docker_swarm_leave ${def:?}│ ${red:?}USE WITH CAUTION!${def:?} prunes & clears all docker stacks, ${grn:?}leaves swarm${def:?}" 121 | echo -e " ├──${blu:?} docker system ${def:?}───┼─────────────────────────┼──────────────────────────" 122 | echo -e " │${cyn:?} dcln / dclean ${def:?}│ ${ylw:?}docker_system_clean ${def:?}│ ${cyn:?}stops${def:?} and ${cyn:?}removes ${grn:?}ALL containers${def:?}, images, networks, and volumes" 123 | echo -e " │${cyn:?} dprn / dprune ${def:?}│ ${ylw:?}docker_system_prune ${def:?}│ ${cyn:?}prunes${def:?} ${grn:?}UNUSED containers${def:?}, images, networks, and volumes" 124 | echo -e " └────────────────────┴─────────────────────────┴──────────────────────────" 125 | echo -e " NOTE: Commands accept '${cyn:?}options${def:?}' which can be listed using the '${cyn:?}--help${def:?}' flag after the command, e.g. ${cyn:?}dls --${cyn:?}help${def:?} " 126 | echo 127 | } 128 | fnc_create_aliases(){ 129 | # docker alias list 130 | alias dk='docker' 131 | alias dki='docker images' 132 | alias dkn='docker network' 133 | alias dkv='docker service' 134 | alias dkrm='docker rm' 135 | alias dkl='docker logs' 136 | alias dklf='docker logs -f' 137 | alias dkrm='docker rm `docker ps --no-trunc -aq`' 138 | alias dkrmi='docker rmi $(docker images --filter "dangling=true" -q --no-trunc)' 139 | alias dkt='docker stats --format "table {{.Name}}\t{{.CPUPerc}} {{.MemPerc}}\t{{.MemUsage}}\t{{.NetIO}}"' 140 | alias dkps='docker ps --format "table {{.ID}}\t{{.Names}}\t{{.Status}}\t{{.Image}}"' 141 | alias dkc='docker compose' 142 | # alias dkm='docker-machine' 143 | # alias dkmssh='docker-machine ssh' 144 | 145 | docker_version(){ docker --version && docker compose version; } 146 | alias dkver="docker_version" 147 | 148 | docker_compose_info(){ docker ps -f name="${1}"; } 149 | alias dcinfo="docker_compose_info" 150 | 151 | docker_exec(){ docker exec -it "$(docker ps -f name="${1}" --format "{{.ID}}")" /bin/sh; } 152 | alias dkex="docker_exec" 153 | alias dkx="docker_exec" 154 | 155 | ipcheck(){ echo "Container IP: $(docker container exec -it "${*}" curl ipinfo.io)"; } 156 | alias checkip='ipcheck' 157 | # portcheck(){ curl -sq -b cookies.txt "http://${QIP}:${QPORT}/container-station/api/v1/system/port/tcp/${1}"; } 158 | # alias checkport='portcheck' 159 | vpncheck(){ echo " Host IP: $(wget -qO- ifconfig.me)" && echo "Container IP: $(docker container exec -it "${*}" wget -qO- ipinfo.io/ip)"; } 160 | alias checkvpn='vpncheck' 161 | 162 | ## folder and file permissions 163 | export perms_cert="a-rwx,u=rwX,g=,o=" # 600 # -rw-rw---- 164 | export perms_conf="a-rwx,u+rwX,g=rwX,o=rX" # 664 # -rw-rw-r-- 165 | export perms_data="a-rwx,u+rwX,g=rwX,o=" # 660 # -rw-rw---- 166 | # export docker_dir="a=rwx,o-w" # 775 # -rwxrwxr-x 167 | 168 | docker_file_permissions(){ 169 | case "${1}" in 170 | ("-a"|"--all") files_dir="${docker_folder}" ;; 171 | ("-l"|"--local") files_dir="${docker_compose}/${1}" ;; 172 | ("-w"|"--swarm") files_dir="${docker_swarm}/${1}" ;; 173 | (*) 174 | echo "invalid syntax" 175 | esac 176 | # update restricted access file permissions to 600 177 | files_restricted=("acme.json" "*.crt" "*.key" "*.pub" "*.ppk" "*.pem"); 178 | for file in "${files_restricted[@]}"; do 179 | ${var_sudo:-} find "$files_dir" -iname "$file" -type f -exec chmod "$perms_cert" {} + 180 | done 181 | # update limited access file permissions to 660 182 | files_limited=(".conf" "*.env" ".log" "*.secret"); 183 | for file in "${files_limited[@]}"; do 184 | ${var_sudo:-} find "$files_dir" -iname "$file" -type f -exec chmod "$perms_data" {} + 185 | done 186 | # # update general access file permissions to 664 187 | # files_general=("*.yml" "*.yaml" "*.toml"); 188 | # for file in "${files_general[@]}"; do 189 | # ${var_sudo}find "$docker_dir" -iname "$file" -type f -exec chmod "$perms_conf" {} + 190 | # done 191 | } 192 | 193 | 194 | appdata(){ cd "${docker_appdata}/${1}" || return; } 195 | compose(){ cd "${docker_compose}/${1}" || return; } 196 | secrets(){ cd "${docker_secrets}/${1}" || return; } 197 | swarm(){ cd "${docker_swarm}/${1}" || return; } 198 | 199 | # docker_compose_bounce -- stops then re-creates the listed containers or '-all' container-stacks with config files in the folder structure 200 | docker_compose_bounce(){ sh "${docker_scripts}/docker_compose_bounce.sh" "${@}"; } 201 | alias dcb="docker_compose_bounce"; 202 | # alias dcbounce="docker_compose_bounce --all"; 203 | 204 | # docker_compose_folders -- creates the folder structure required for each listed compose stack name (up to 9 per command) 205 | docker_compose_folders(){ sh "${docker_scripts}/docker_compose_folders.sh" "${@}"; } 206 | alias dcf="docker_compose_folders"; 207 | 208 | # docker_compose_edit -- opens a ../compose.yml file in nano text editor 209 | docker_compose_edit(){ nano "${docker_compose}/$1/compose.yml"; } 210 | alias dce="docker_compose_edit" 211 | 212 | # docker_compose_start -- starts the entered container using preconfigured docker_compose files 213 | docker_compose_start(){ sh "${docker_scripts}/docker_compose_start.sh" "${@}"; } 214 | alias dcu="docker_compose_start"; # "Up" 215 | alias dcs="docker_compose_start"; # "Start" 216 | 217 | # docker_compose_stop -- stops the entered container 218 | docker_compose_stop(){ sh "${docker_scripts}/docker_compose_stop.sh" "${@}"; } 219 | alias dcd="docker_compose_stop"; # "Down" 220 | alias dcp="docker_compose_stop -p"; # "stoP" 221 | alias dcr="docker_compose_stop -r"; # "Remove" 222 | 223 | # docker_compose_test -- displays the indicated compose file with variables/secrets filled in 224 | docker_compose_test(){ sh "${docker_scripts}/docker_compose_test.sh" "${@}"; } 225 | alias dcc="docker_compose_test"; 226 | alias dct="docker_compose_test"; 227 | alias dctest="docker_compose_test"; 228 | 229 | # docker_compose_logs -- displays 50 log entries for the indicated docker compose container 230 | docker_compose_logs(){ sh "${docker_scripts}/docker_compose_logs.sh" "${@}"; } 231 | alias dcl="docker_compose_logs"; 232 | 233 | # docker_compose_networks -- creates required networks for docker compose container manipulation via scripts 234 | docker_compose_networks(){ sh "${docker_scripts}/docker_compose_networks.sh" "${@}"; } 235 | alias dcn="docker_compose_networks"; 236 | 237 | # # docker_folders_create -- creates the folder structure required for each listed docker container 238 | # dkfolders(){ sh "${docker_scripts}/docker_folders_create.sh" "${@}"; } 239 | # alias dcf="dkfolders -c"; 240 | # alias dsf="dkfolders -w"; 241 | # alias dwf="dkfolders -w"; 242 | # # alias dcf='dkfolders -c "$1"'; 243 | # # alias dsf='dkfolders -w "$1"'; 244 | # # alias dwf='dkfolders -w "$1"'; 245 | 246 | # docker_list_configs -- lists existing stack config files for either swarm or compose filepaths 247 | docker_list_configs(){ sh "${docker_scripts}/docker_list_configs.sh" "${1}"; } 248 | alias dlg="docker_list_configs"; 249 | alias dccfg="docker_list_configs --compose"; 250 | alias dcg="docker_list_configs --compose"; 251 | alias dscfg="docker_list_configs --swarm"; 252 | alias dsg="docker_list_configs --swarm"; 253 | alias dwcfg="docker_list_configs --swarm"; 254 | alias dwg="docker_list_configs --swarm"; 255 | 256 | # docker_list_container -- lists all currently deployed containers and/or services 257 | docker_list_container(){ sh "${docker_scripts}/docker_list_container.sh" "${1}" "${2}"; } 258 | alias dlc="docker_list_container"; 259 | 260 | # docker_list_stack -- lists all stacks and number of services inside each stack 261 | docker_list_stack(){ sh "${docker_scripts}/docker_list_stack.sh" "${1}" "${2}"; } 262 | alias dls="docker_list_stack"; 263 | alias dlw="docker_list_stack"; 264 | 265 | bounce(){ 266 | if [[ $1 = "-all" ]]; then 267 | IFS=$'\n'; 268 | list=( "$(docker stack ls --format '{{.Name}}')" ); 269 | else 270 | list=("$*") 271 | fi 272 | for i in "${list[@]}"; do 273 | docker stack rm "$i" 274 | done 275 | for i in "${list[@]}"; do 276 | while [ "$(docker service ls --filter label=com.docker.stack.namespace="$i" -q)" ] || [ "$(docker network ls --filter label=com.docker.stack.namespace="$i" -q)" ]; do sleep 1; done 277 | done 278 | for i in "${list[@]}"; do 279 | docker stack deploy "$i" -c /share/docker/swarm/"$i"/compose.yml 280 | done 281 | unset list IFS 282 | } 283 | # docker_stack_bounce -- removes then re-deploys the listed stacks or '-all' stacks with config files in the folder structure 284 | # docker_stack_bounce(){ sh "${docker_scripts}/docker_stack_bounce.sh" "${@}"; } 285 | docker_stack_bounce(){ 286 | limit=15 287 | docker stack rm "${1}" 288 | until [ -z "$(docker service ls --filter label=com.docker.stack.namespace="$1" -q)" ] || [ "$limit" -lt 0 ]; do 289 | sleep 1; 290 | ((limit--)) 291 | done 292 | limit=15 293 | until [ -z "$(docker network ls --filter label=com.docker.stack.namespace="$1" -q)" ] || [ "$limit" -lt 0 ]; do 294 | sleep 1; 295 | ((limit--)) 296 | done 297 | docker stack deploy "${1}" -c "${docker_swarm}/${1}/compose.yml" 298 | } 299 | alias dsb="docker_stack_bounce"; 300 | alias dwb="docker_stack_bounce"; 301 | # alias dwbounce="docker_stack_bounce --all"; 302 | 303 | # # docker_stack_folders -- creates the folder structure required for each listed stack name (up to 9 per command) 304 | # docker_stack_folders(){ sh "${docker_scripts}/docker_stack_folders.sh" "$1" "$2" "$3" "$4" "$5" "$6" "$7" "$8" "$9"; } 305 | # docker_stack_folders -- creates the folder structure required for each listed stack name 306 | docker_stack_folders(){ sh "${docker_scripts}/docker_stack_folders.sh" "${@}"; } 307 | alias dsf="docker_stack_folders"; 308 | alias dwf="docker_stack_folders"; 309 | alias dwdir="docker_stack_folders"; 310 | alias dwfolder="docker_stack_folders"; 311 | 312 | # docker_stack_deploy -- deploys a single stack as defind in the configs folder structure 313 | # docker_stack_start(){ sh "${docker_scripts}/docker_stack_start.sh" "${@}"; } 314 | # docker_stack_start(){ docker stack deploy "${1}" -c "${docker_swarm}/${1}/compose.yml"; } 315 | docker_stack_start(){ docker stack deploy "${1}" -c "${docker_swarm}/${1}/compose.yml"; } 316 | alias dsd="docker_stack_start"; # "Deploy" 317 | alias dss="docker_stack_start"; # "Start" 318 | alias dsu="docker_stack_start"; # "Up" 319 | alias dsup="docker_stack_start --all"; 320 | alias dwd="docker_stack_start"; # "Deploy" 321 | alias dws="docker_stack_start"; # "Start" 322 | alias dwu="docker_stack_start"; # "Up" 323 | alias dwup="docker_stack_start --all"; 324 | 325 | # docker_stack_remove -- removes a single stack 326 | # docker_stack_stop(){ sh "${docker_scripts}/docker_stack_stop.sh" "${@}"; } 327 | docker_stack_stop(){ docker stack rm "${1}"; } 328 | alias dsr="docker_stack_stop"; # "Remove" 329 | alias dsp="docker_stack_stop"; # "stoP" 330 | alias dsrm="docker_stack_stop --all"; 331 | alias dwr="docker_stack_stop"; # "Remove" 332 | alias dwp="docker_stack_stop"; # "stoP" 333 | alias dwrm="docker_stack_stop --all"; 334 | 335 | # docker_service_errors -- displays 'docker ps --no-trunk ' command output 336 | docker_service_error(){ sh "${docker_scripts}/docker_service_error.sh" "${1}" "${2}"; } 337 | alias dse="docker_service_error"; 338 | alias dwe="docker_service_error"; 339 | alias dve="docker_service_error"; 340 | alias dverror="docker_service_error"; 341 | 342 | # docker_service_logs -- displays 'docker service logs ' command output 343 | docker_service_logs(){ sh "${docker_scripts}/docker_service_logs.sh" "${1}" "${2}"; } 344 | alias dsl="docker_service_logs"; 345 | alias dwl="docker_service_logs"; 346 | alias dvl="docker_service_logs"; 347 | alias dvlogs="docker_service_logs"; 348 | 349 | # docker_swarm_init -- Initializes a Docker Swarm using the docker_swarm_init.sh script 350 | docker_swarm_init(){ sh "${docker_scripts}/docker_swarm_init.sh" "${1}"; } 351 | alias dsin="docker_swarm_init traefik"; 352 | alias dwin="docker_swarm_init traefik"; 353 | alias dwinit="docker_swarm_init traefik"; 354 | # alias docker_swarm_setup="docker_swarm_init -setup"; # Downloads and executes the docker_swarm_setup.sh script (NOT YET WORKING) 355 | 356 | # docker_swarm_setup -- Downloads and executes the docker_swarm_setup.sh script (NOT YET WORKING) 357 | docker_swarm_setup(){ sh "${docker_scripts}/docker_swarm_setup.sh" "${@}"; } 358 | alias dssup="docker_swarm_setup traefik"; 359 | alias dwsup="docker_swarm_setup traefik"; 360 | # sh mkdir -pm 766 ${docker_scripts} && curl -fsSL https://raw.githubusercontent.com/Drauku/QNAP-Docker-Swarm-Setup/master/scripts/docker_swarm_setup.sh > "${docker_scripts}/docker_swarm_setup.sh" && . "${docker_scripts}/docker_swarm_setup.sh"; 361 | 362 | # docker_swarm_leave -- LEAVES the docker swarm. USE WITH CAUTION! 363 | docker_swarm_leave(){ sh "${docker_scripts}/docker_swarm_leave.sh" "${@}"; } 364 | alias dslv="docker_swarm_leave" 365 | alias dwlv="docker_swarm_leave" 366 | alias dsclr="docker_swarm_leave --all"; 367 | alias dwclr="docker_swarm_leave --all"; 368 | 369 | docker_backup(){ sh "${docker_scripts}/docker_system_backup.sh"; } 370 | alias dbk="docker_backup"; 371 | alias dkbk="docker_backup"; 372 | alias dback="docker_backup"; 373 | 374 | # docker_system_clean -- similar to prune, but performs more in-depth removal functions 375 | docker_system_clean(){ sh "${docker_scripts}/docker_system_clean.sh" "${1}"; } 376 | alias dkc="docker_system_clean"; 377 | alias dyc="docker_system_clean"; 378 | alias dclean="docker_system_clean"; 379 | 380 | # docker_system_image -- manage docker container images from the docker repository 381 | docker_system_images(){ sh "${docker_scripts}/docker_system_image.sh" "${1}"; } 382 | alias dli="docker_system_images -l"; 383 | alias dki="docker_system_images"; 384 | alias dyi="docker_system_images"; 385 | alias dimage="docker_system_images"; 386 | 387 | # docker_system_network -- lists current docker networks 388 | docker_system_network(){ sh "${docker_scripts}/docker_system_network.sh" "${1}" "${2}"; } 389 | alias dln="docker_system_network"; 390 | alias dyn="docker_system_network"; 391 | 392 | # docker_system_prune -- prunes the docker system (removes unused images and containers and networks and volumes) 393 | docker_system_prune(){ sh "${docker_scripts}/docker_system_prune.sh" "${1}"; } 394 | alias dprn="docker_system_prune"; 395 | alias dyp="docker_system_prune"; 396 | 397 | # docker_system_stats -- displays resources used by current docker stacks/containers 398 | docker_system_stats(){ sh "${docker_scripts}/docker_system_stats.sh" "${1}"; } 399 | alias dks="docker_system_stats"; 400 | alias dys="docker_system_stats"; 401 | alias dtop="docker_system_stats --live"; 402 | alias dstat="docker_system_stats --live"; 403 | 404 | # docker_system_volume -- lists unused docker volumes 405 | docker_system_volume(){ sh "${docker_scripts}/docker_system_volume.sh" "${1}" "${2}"; } 406 | alias dlv="docker_system_volume"; 407 | alias dyv="docker_system_volume"; 408 | 409 | echo -e "${blu:?} >> Docker terminal aliases and functions ${grn:?}created${blu:?}. Type 'dlist' to display defined commands.${def:?}\n"; 410 | } 411 | 412 | # logical action check 413 | case "${1}" in 414 | ("-a"|"--aliases") 415 | fnc_list_aliases; 416 | ;; 417 | ("-s"|"--scripts") 418 | fnc_list_scripts; 419 | ;; 420 | ("-f"|"--functions") 421 | fnc_list_aliases; 422 | fnc_list_scripts; 423 | ;; 424 | (""|"-c"|"--create") 425 | fnc_create_aliases ""; # register docker aliases and custom commands 426 | # [ ! -e "${docker_scripts}/.profile" ] && ln -s /opt/etc/profile "${docker_scripts}/.profile" # create link to 'entware-std' profile 427 | ;; 428 | (*) 429 | fnc_invalid_syntax; 430 | ;; 431 | esac 432 | -------------------------------------------------------------------------------- /docker_compose_bounce.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # external variable sources 4 | source /opt/docker/scripts/.color_codes.conf 5 | source /opt/docker/scripts/.vars_docker.env 6 | # source /opt/docker/compose/stackslist-compose.conf 7 | 8 | # script variable definitions 9 | unset bounce_list IFS 10 | 11 | # function definitions 12 | fnc_help_compose_bounce(){ 13 | echo -e "${blu:?}[-> This script bounces (removes then re-deploys) a single or pre-defined list of Docker Swarm stack <-]${def:?}" 14 | echo -e " -" 15 | echo -e " - SYNTAX: # dsb ${cyn:?}stack_name${def:?}" 16 | echo -e " - SYNTAX: # dsb ${cyn:?}-option${def:?}" 17 | echo -e " - VALID OPTIONS:" 18 | echo -e " - ${cyn:?}-a | --all ${def:?}│ Bounces all containers with a corresponding folder inside the '${ylw:?}${docker_compose}/${def:?}' path." 19 | echo -e " - ${cyn:?}-p | --preset ${def:?}│ Bounces the 'preset' array of containers defined in '${ylw:?}${docker_vars}/${cyn:?}compose_stacks.env${def:?}'" 20 | echo -e " - ${cyn:?}-d | --default ${def:?}│ Bounces the 'default' array of containers defined in '${ylw:?}${docker_vars}/${cyn:?}compose_stacks.env${def:?}'" 21 | echo -e " - ${cyn:?}-h │ --help ${def:?}│ Displays this help message." 22 | echo 23 | exit 1 # Exit script after printing help 24 | } 25 | case "$1" in ("-h"|*"help"*) fnc_help_compose_bounce ;; esac 26 | 27 | fnc_intro_compose_bounce(){ echo -e "${blu:?}[-> STOPS THEN RESTARTS LISTED CONTAINERS <-]${def:?}"; echo -e "${cyn:?} -> ${bounce_list[*]} ${def:?}"; echo; } 28 | fnc_outro_compose_bounce(){ echo -e "[-- ${grn:?}BOUNCE (REMOVE & REDEPLOY) STACK SCRIPT COMPLETE${def:?} --]"; echo; } 29 | fnc_nothing_to_do(){ echo -e "${ylw:?} -> no containers exist to bounce${def:?}"; } 30 | fnc_invalid_syntax(){ echo -e "${ylw:?} >> INVALID OPTION SYNTAX, USE THE -${cyn:?}help${ylw:?} OPTION TO DISPLAY PROPER SYNTAX <<${def:?}"; exit 1; } 31 | fnc_list_all(){ IFS=$'\n'; bounce_list=( "$(docker container list --format "{{.Names}}")" ); } 32 | fnc_list_default(){ IFS=$'\n'; bounce_list=( "${stacks_default[@]}" ); } 33 | fnc_list_preset(){ IFS=$'\n'; bounce_list=( "${stacks_preset[@]}" ); } 34 | fnc_docker_compose_stop(){ bash "${docker_scripts}/docker_compose_stop.sh" "${bounce_list[@]}"; } 35 | fnc_docker_compose_start(){ bash "${docker_scripts}/docker_compose_start.sh" "${bounce_list[@]}"; } 36 | 37 | # determine script output according to option entered 38 | case "${1}" in 39 | (-*) 40 | case "${1}" in 41 | ("-a"|"--all") fnc_list_all ;; 42 | ("-d"|"--default") fnc_list_default ;; 43 | ("-p"|"--preset") fnc_list_preset ;; 44 | (*) fnc_invalid_syntax ;; 45 | esac 46 | ;; 47 | (*) 48 | # container_list=("$(docker container list --format {{.Names}})") 49 | # for name in ${!container_list}; do 50 | 51 | # # case "${bounce_list[@]}" in 52 | # # (*${name}*) 53 | # # echo "present" 54 | # # ;; 55 | # # (*) 56 | # # echo "not present" 57 | # # ;; 58 | # # esac 59 | 60 | # if [[ " ${bounce_list[*]} " == *"${name}"* ]]; then 61 | # break 62 | # fi 63 | 64 | # done 65 | IFS=' '; bounce_list=("$@") 66 | ;; 67 | esac 68 | 69 | # # display script intro 70 | # fnc_intro_compose_bounce 71 | # remove all stacks in list defined above 72 | fnc_docker_compose_stop "${bounce_list[@]}" 73 | # (re)deploy all stacks in list defined above 74 | fnc_docker_compose_start "${bounce_list[@]}" 75 | # # display script outro 76 | # fnc_outro_compose_bounce -------------------------------------------------------------------------------- /docker_compose_folders.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # external variable sources 3 | source /opt/docker/scripts/.color_codes.conf 4 | source /opt/docker/scripts/.vars_docker.env 5 | 6 | # script variable definitions 7 | unset folder_list IFS; folder_list=("${@}"); 8 | # unset args_list IFS; args_list=("${@}"); 9 | ## chmod -R a-rwx,u=rwX,g+rX,o=rX # drwxr-x--- 10 | appdata_permissions="660" # a-x,ug=rwX,o-rwx # -rw-rw---- 11 | compose_permissions="664" # a-x,ug=rwX,o=rX # -rw-rw-r-- 12 | folders_permissions="775" # a-x,ug=rwX,o=rX # drwxrwxr-x 13 | cert_permissions="600" # a-rwx,u=rw # -rw------- 14 | 15 | # install -o 1000 -g 1000 -m 775 -d /share/docker/{appdata,compose,secrets}/${1} 16 | # install -o 1000 -g 1000 -m 664 /dev/null /share/docker/compose/${1}/compose.yml 17 | # install -o 1000 -g 1000 -m 664 /dev/null /opt/docker/compose/$1/.env 18 | # ln -sf /share/docker/compose/${1}/.env /share/docker/.docker.env 19 | 20 | # find /opt/docker -type d -exec chmod 0755 {} \; 21 | # find /opt/docker/compose -type f -exec chmod 0644 {} \; 22 | 23 | # function definitions 24 | fnc_help_compose_folders(){ 25 | echo -e "${blu:?}[-> This script creates Docker configuration folders using the schema created by ${cyn:?}Drauku${blu:?} <-]${def:?}" 26 | echo -e " - ${blu:?}(modified from ${cyn:?}gkoerk's (RIP)${blu:?} famously awesome folder structure for stacks)${def:?}" 27 | echo -e " -" 28 | echo -e " - Enter up to nine(9) container_names in a single command, separated by a 'space' character: " 29 | echo -e " - SYNTAX: dcf ${cyn:?}appname1${def:?} ${cyn:?}appname2${def:?} ... ${cyn:?}appname9${def:?}" 30 | echo -e " - SYNTAX: dcf ${cyn:?}-option${def:?}" 31 | echo -e " - VALID OPTIONS:" 32 | echo -e " - ${cyn:?}-c │ --create ${def:?}│ ${grn:?}Creates${def:?} ${cyn:?}{docker_appdata,docker_compose}/${mgn:?}appname${def:?}" 33 | echo -e " - ${cyn:?}-d │ --delete ${def:?}│ ${red:?}Deletes${def:?} all sub-folders and files in ${cyn:?}{docker_appdata,docker_compose}/${mgn:?}appname${def:?}" 34 | # echo -e " - ${cyn:?}-r │ --replace ${def:?}│ ${ylw:?}Replace${def:?} all folders and files in ${cyn:?}{docker_appdata,docker_compose}/${mgn:?}appname${def:?}" 35 | echo -e " - ${cyn:?}-p │ --permissions ${def:?}│ ${blu:?}Updates${def:?} all folder permissions for listed ${mgn:?}appname(s)${def:?}" 36 | echo -e " - ${cyn:?}-h │ --help ${def:?}| Displays this help message." 37 | echo -e " -" 38 | echo -e " - NOTE: The below folder structure is created for each 'appname' entered with this command:" 39 | echo -e " - ${cyn:?}${docker_appdata:?}/${mgn:?}appname${def:?}" 40 | echo -e " - ${cyn:?}${docker_compose:?}/${mgn:?}appname${def:?}" 41 | # echo -e " - ${mgn:?}${compose_runtime}/${cyn:?}appname${def:?}" 42 | # echo -e " - ${mgn:?}/share/compose/secrets/${cyn:?}appname${def:?}" 43 | echo 44 | exit 1 # Exit script after printing help 45 | } 46 | case "$1" in ("-h"|*"help"*) fnc_help_compose_folders ;; esac 47 | 48 | fnc_script_intro(){ echo; } # echo -e "${blu:?}[- CREATE DOCKER COMPOSE FOLDER STRUCTURE FOR LISTED STACKS -]${def:?}"; } 49 | fnc_script_outro(){ echo; exit 1; } 50 | fnc_nothing_to_do(){ echo -e "${ylw:?} >> A valid option and container name must be entered for this command to work (use ${cyn:?}--help ${ylw:?}for info) <<${def:?}"; } 51 | fnc_invalid_input(){ echo -e "${ylw:?} >> INVALID INPUT${def:?}: Must be any case-insensitive variation of '(Y)es' or '(N)o'."; } 52 | fnc_invalid_syntax(){ echo -e "${ylw:?} >> INVALID OPTION SYNTAX, USE THE ${cyn:?}-help${ylw:?} OPTION TO DISPLAY PROPER SYNTAX <<${def:?}" && fnc_script_outro; } 53 | # fnc_compose_comment(){ echo "# '${stack}' docker config file created for a homelab environment - https://github.com/qnap-homelab\n\n"; } 54 | fnc_compose_comment(){ printf "# '%s' docker config file created for a homelab environment - https://github.com/qnap-homelab\n\n" "${stack}"; } 55 | fnc_confirm_remove(){ echo -e "${ylw:?}Are you sure you want to ${red:?}DELETE / REMOVE${ylw:?} files and folders for the ${blu:?}\"${1}\"${ylw:?} container?\n ${mgn:?}WARNING: ${red:?}THIS ACTION CANNOT BE UNDONE!${def:?}"; } 56 | # fnc_array_cleanup(){ folder_list=( $(for index in "${!args_list[@]}"; do echo -e "${args_list[$index + 1]}"; done) ); } 57 | # fnc_array_cleanup(){ while IFS=$'\n' read -r line; do folder_list+=("${line}"); done < <(for index in "${!args_list[@]}"; do echo -e "${args_list[${index} + 1]}"; done); } 58 | # fnc_file_search() { [[ $(find ./"${@}" -type f) ]]; } 59 | fnc_action_message(){ # call syntax: fnc_action_message "action" "color" 60 | echo -e " -> ${blu:?}${docker_appdata:?}/${mgn:?}${stack}${def:?} AND ${blu:?}${docker_compose:?}/${mgn:?}${stack}${def:?} FOLDERS AND FILES ${2:?} ${1:?}${def:?}"; 61 | } 62 | fnc_check_env(){ 63 | if [[ ! -f "${docker_scripts}/.vars_docker.env" ]]; 64 | then install -o $var_uid -g $var_gid -m $appdata_permissions "${docker_scripts}/.vars_docker.example" "${docker_scripts}/.vars_docker.env"; 65 | fi; 66 | } 67 | fnc_check_sudo(){ 68 | if [[ $(id -u) -ne 0 ]]; 69 | then var_sudo="$(command -v sudo 2>/dev/null) "; 70 | else unset var_sudo; 71 | fi; } 72 | fnc_permissions_update(){ 73 | fnc_check_sudo; 74 | for stack in "${folder_list[@]}"; do 75 | if [[ "${1}" = "--all" ]]; then 76 | # ${var_sudo}find "${docker_appdata}" -type f -exec chmod ${appdata_permissions} {} + -o -type d -exec chmod ${folders_permissions} {} + 77 | # ${var_sudo}find "${docker_compose}" -type f -exec chmod ${compose_permissions} {} + -o -type d -exec chmod ${folders_permissions} {} + 78 | ${var_sudo}chmod -R a-rwx,ug=rwX "${docker_appdata:?}/${stack}"; 79 | ${var_sudo}chmod -R a-rwx,ug=rwX,o=rX "${docker_compose:?}/${stack}"; 80 | else 81 | ## appdata folder and file permissions 82 | # ${var_sudo}chmod -R "${appdata_permissions}" "${docker_appdata:?}/${stack}"; 83 | # ${var_sudo}chmod "${folders_permissions}" "${docker_appdata:?}/${stack}"; 84 | ${var_sudo}chown -R "${var_uid:-1000}:${var_gid:-1000}" "${docker_appdata:?}/${stack}"; 85 | ${var_sudo}chmod -R a-x,ug=rwX,o= "${docker_appdata:?}/${stack}"; 86 | 87 | ## compose folder and file permissions 88 | # ${var_sudo}chmod -R "${compose_permissions}" "${docker_compose:?}/${stack}"; 89 | # ${var_sudo}chmod "${folders_permissions}" "${docker_compose:?}/${stack}"; 90 | ${var_sudo}chown -R "${var_uid:-1000}:${var_gid:-1000}" "${docker_compose:?}/${stack}"; 91 | ${var_sudo}chmod -R a-x,ug=rwX,o=rX "${docker_compose:?}/${stack}"; 92 | fi 93 | if [[ "${stack}" = "[tT][rR][aA][eE][fF][iI][kK]" ]]; then ${var_sudo}chmod "${cert_permissions}" "${docker_appdata:?}/${stack}/certs/acme.json"; fi; 94 | done; 95 | # echo -e "\n ${ylw:?}UPDATED ${blu:?}${docker_appdata:?}/${mgn:?}${stack}${def:?} AND ${blu:?}${docker_compose:?}/${mgn:?}${stack}${def:?} FOLDERS AND FILE PERMISSIONS ${def:?}"; 96 | fnc_action_message "FILE AND FOLDER PERMISSIONS UPDATED" "${ylw:?}" 97 | } 98 | fnc_folder_create(){ 99 | exist=0; 100 | # echo; 101 | fnc_check_sudo; 102 | for stack in "${folder_list[@]}"; do 103 | if [ ! -d "${docker_appdata:?}/${stack}/" ]; 104 | then ${var_sudo}install -o "${var_uid:-1000}" -g "${var_gid:-1000}" -m "${folders_permissions}" -d "${docker_appdata:?}/${stack}"; 105 | else fnc_permissions_update "${folder_list[@]}"; fnc_action_message "ALREADY EXISTS" "${blu:?}${docker_appdata:?}/${mgn:?}${stack}${def:?}"; exist=1; # ((++exist)); 106 | fi; 107 | if [ ! -f "${docker_appdata:?}/${stack}/${stack}.log" ]; 108 | then ${var_sudo}install -m "${appdata_permissions}" /dev/null "${docker_appdata:?}/${stack}/${stack}-logs.yml"; 109 | else fnc_action_message "ALREADY EXISTS" "${blu:?}${docker_appdata:?}/${mgn:?}${stack}${cyn:?}/${stack}-logs.yml${def:?}"; 110 | fi; 111 | if [[ "${stack}" = "[tT][rR][aA][eE][fF][iI][kK]" ]] && [ ! -f "${docker_appdata:?}/${stack}/certs/acme.json" ]; 112 | then ${var_sudo}install -m "${cert_permissions}" /dev/null "${docker_appdata:?}/${stack}/certs/acme.json"; 113 | # then touch "${docker_appdata:?}/${stack}/certs/acme.json" && ${var_sudo}chmod "${cert_permissions}" "${docker_appdata:?}/${stack}/certs/acme.json"; 114 | # else echo -e " ${ylw:?}ALREADY EXISTS${def:?} > ${blu:?}${docker_appdata:?}/${mgn:?}${stack}${cyn:?}/certs/acme.json${def:?}"; 115 | fi; 116 | if [ ! -d "${docker_compose:?}/${stack}/" ]; 117 | then ${var_sudo}install -o "${var_uid:-1000}" -g "${var_gid:-1000}" -m "${folders_permissions}" -d "${docker_compose:?}/${stack}"; 118 | if [ ! -f "${docker_compose:?}/${stack}/.env" ]; then ln -s "${var_script_vars:?}" "${docker_compose:?}/${stack}/.env"; fi; 119 | else fnc_permissions_update "${folder_list[@]}"; 120 | echo -e " ${ylw:?}ALREADY EXISTS ${def:?}-> ${blu:?}${docker_compose:?}${mgn:?}/${stack}${def:?}"; exist=1; # ((++exist)); 121 | fi; 122 | if [ ! -f "${docker_compose:?}/${stack}/compose.yml" ]; 123 | then ${var_sudo}install -o "${var_uid:-1000}" -g "${var_gid:-1000}" -m "${compose_permissions}" /dev/null "${docker_compose:?}/${stack}/compose.yml"; 124 | # then touch "${docker_compose:?}/${stack}/compose.yml" && ${var_sudo}chmod "${compose_permissions}" "${docker_compose:?}/${stack}/compose.yml"; 125 | # { printf "# '%s' docker config file created for a homelab environment - https://github.com/qnap-homelab\n\n" "${stack}"; 126 | { fnc_compose_comment; } >> "${docker_compose:?}/${stack}/compose.yml"; 127 | else echo -e " ${ylw:?}ALREADY EXISTS ${def:?}-> ${blu:?}${docker_compose:?}/${mgn:?}${stack}${cyn:?}/compose.yml${def:?}"; 128 | fi; 129 | [ "${exist}" == "0" ] && fnc_action_message "CREATED" "${grn:?}"; 130 | # echo "UID:${var_uid} GID:${var_gid}"; echo; 131 | # ${var_sudo}chown -R "${var_uid:-1000}:${var_gid:-1000}" "${docker_compose:?}/${stack}" 132 | # ${var_sudo}chown -R "${var_uid:-1000}:${var_gid:-1000}" "${docker_appdata:?}/${stack}" 133 | done 134 | } 135 | # fnc_folder_remove_message(){ echo -e " > ${red:?}REMOVED ${blu:?}${docker_compose:?}/${stack}${def:?} AND ${blu:?}${docker_appdata:?}/${mgn:?}${stack}${def:?} FOLDERS AND FILES ${def:?}"; } 136 | fnc_folder_remove(){ 137 | exist=1; fnc_confirm_remove "${*}" ; 138 | while read -r -p " [(Y)es/(N)o] " input; do 139 | case "${input}" in 140 | ([yY]|[yY][eE][sS]) 141 | echo; 142 | for stack in "${folder_list[@]}"; do 143 | if [ -d "${docker_appdata:?}/${stack}" ]; then 144 | ${var_sudo}rm -rf "${docker_appdata:?}/${stack:?}" #&& echo -e " > ${red:?}REMOVED ${mgn:?}${stack} ${def:?}APPDATA FOLDER AND FILES ${def:?}"; 145 | else echo -e " -> ${ylw:?} INFO: ${blu:?}${docker_appdata:?}${mgn:?}/${stack} ${ylw:?}NOT FOUND ${def:?}"; exist=0; 146 | fi 147 | if [ -d "${docker_compose:?}/${stack}" ]; then 148 | ${var_sudo}rm -rf "${docker_compose:?}/${stack:?}" #&& echo -e " > ${red:?}REMOVED ${mgn:?}${stack} ${def:?}COMPOSE FOLDER AND FILES ${def:?}"; 149 | else echo -e " -> ${ylw:?} INFO: ${blu:?}${docker_compose:?}${mgn:?}/${stack} ${ylw:?}NOT FOUND ${def:?}"; exist=0; 150 | fi 151 | [ "${exist}" == "1" ] && fnc_action_message "REMOVED" "${red:?}"; 152 | done 153 | break 154 | ;; 155 | ([nN]|[nN][oO]) break ;; 156 | (*) fnc_invalid_input ;; 157 | esac 158 | done 159 | } 160 | # fnc_folder_clean_message(){ echo -e " > ${ylw:?}CLEANED ${mgn:?}${stack} ${def:?}${content} ${def:?}"; } 161 | # fnc_folder_clean(){ 162 | # unset content IFS; 163 | # fnc_confirm_remove; 164 | # while read -r -p " [(Y)es/(N)o] " input; do 165 | # case "${input}" in 166 | # ([yY]|[yY][eE][sS]) 167 | # echo; 168 | # case "${folder_list[0]}" in 169 | # ("-a") ${var_sudo}rm -rf "${docker_appdata:?}/${stack:?}"/* && content="CONTAINER APPDATA" ;; 170 | # ("-g") ${var_sudo}rm -rf "${docker_compose:?}/${stack:?}"/* && content="CONTAINER CONFIGS" ;; 171 | # ("-w") ${var_sudo}rm -rf "${docker_swarm:?}/${stack:?}"/* && content="SWARM CONFIGS" ;; 172 | # esac 173 | # [ ! "${content}" == "" ] && fnc_folder_clean_message; 174 | # ;; 175 | # ([nN]|[nN][oO]) break ;; 176 | # (*) fnc_invalid_input ;; 177 | # esac 178 | # done 179 | # } 180 | 181 | # script startup checks 182 | fnc_script_intro 183 | fnc_check_sudo 184 | fnc_check_env 185 | 186 | # output determination logic 187 | case "${1}" in 188 | ("") fnc_nothing_to_do ;; 189 | (-*) # validate and perform option 190 | case "${1}" in 191 | ("-c"|"--create") 192 | unset "folder_list[0]"; 193 | fnc_folder_create "${folder_list[*]}"; 194 | ;; 195 | ("-d"|"--delete"|"-r"|"--remove") 196 | unset "folder_list[0]"; 197 | fnc_folder_remove "${folder_list[*]}"; 198 | ;; 199 | # ("-a"|"--appdata") 200 | # unset "folder_list[0]"; 201 | # fnc_folder_clean -a "${folder_list[*]}"; 202 | # ;; 203 | # ("-g"|"--configs") 204 | # unset "folder_list[0]"; 205 | # fnc_folder_clean -g "${folder_list[*]}"; 206 | # ;; 207 | # ("-s"|"-w"|"--swarm") 208 | # unset "folder_list[0]"; 209 | # fnc_folder_clean -w "${folder_list[*]}"; 210 | # ;; 211 | ("-p"|"-u"|"--perms"|"--update") 212 | case "${2}" in 213 | ("") 214 | unset "folder_list[0]"; 215 | folder_list=( "$(IFS=$'\n'; cd "${docker_compose:?}" && find . -type d -not -path '*/\.*' | sed 's/^\.\///g')" ) 216 | fnc_permissions_update "${folder_list[@]}"; 217 | esac 218 | unset "folder_list[0]"; 219 | fnc_permissions_update "${folder_list[@]}"; 220 | ;; 221 | ("-r"|"--replace") 222 | unset "folder_list[0]"; 223 | fnc_folder_remove "${folder_list[*]}"; 224 | fnc_folder_create "${folder_list[*]}"; 225 | ;; 226 | (*) 227 | fnc_invalid_syntax; 228 | ;; 229 | esac 230 | ;; 231 | (*) # default to create folder structure 232 | folder_list=("${@}"); 233 | fnc_folder_create "${folder_list[*]}"; 234 | ;; 235 | esac 236 | 237 | fnc_script_outro -------------------------------------------------------------------------------- /docker_compose_function.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | ################################################################################ 3 | ######### --> **** UPDATE THESE VARIABLES FOR YOUR ENVIRONMENT **** <-- ######## 4 | 5 | export docker_usr="docker" 6 | export docker_grp="docker" 7 | export docker_dir="$HOME/docker" 8 | 9 | ################################################################################ 10 | ##################### NOTHING BELOW HERE SHOULD BE CHANGED ##################### 11 | ################################################################################ 12 | 13 | ################################################################################ 14 | ####################### docker uid/gid/directories setup ####################### 15 | 16 | # alias to easily source this file 17 | alias dkfnc='. $ln_source' 18 | 19 | # docker directory structure 20 | export docker_appdata="$docker_dir/appdata" 21 | export docker_compose="$docker_dir/compose" 22 | export docker_secrets="$docker_dir/secrets" 23 | export docker_swarm="$docker_dir/swarm" 24 | 25 | ## assign docker UID and GID variables 26 | docker_uid=$(id -u "$docker_usr") # docker UID (1000) 27 | export docker_uid #&& echo "DEBUG: docker UID: $docker_uid" 28 | docker_gid=$(id -g "$docker_usr") # docker GID (1000) 29 | export docker_gid #&& echo "DEBUG: docker GID: $docker_gid" 30 | 31 | # folder and file permissions 32 | export perms_cert="a-rwx,u=rwX,g=,o=" # 600 # -rw-rw---- 33 | export perms_conf="a-rwx,u+rwX,g=rwX,o=rX" # 664 # -rw-rw-r-- 34 | export perms_data="a-rwx,u+rwX,g=rwX,o-rX" # 660 # -rw-rw---- 35 | # export dk_dir="" # 775 # -rwxrwxr-x 36 | 37 | # check if sudo is needed for some commands used in these custom docker functions 38 | if [[ $(id -u) -ne 0 ]]; then var_sudo="$(command -v sudo 2>/dev/null) "; else unset var_sudo; fi; 39 | 40 | # create the $HOME/.docker_fnc symlink if it does not exist 41 | ln_source="$HOME/.docker_fnc" 42 | ln_target="$docker_dir/docker_functions" 43 | if [[ ! -f "$ln_source" ]]; then ln -s "$ln_target" "$ln_source"; fi; 44 | 45 | # create docker directory structure and .docker.env if they don't exist 46 | if [[ ! -d "$docker_appdata" ]]; then ${var_sudo}install -o "$docker_uid" -g "$docker_gid" -m "$perms_data" -d "$docker_dir/appdata"; fi 47 | if [[ ! -d "$docker_compose" ]]; then ${var_sudo}install -o "$docker_uid" -g "$docker_gid" -m "$perms_conf" -d "$docker_dir/compose"; fi 48 | if [[ ! -d "$docker_secrets" ]]; then ${var_sudo}install -o "$docker_uid" -g "$docker_gid" -m "$perms_data" -d "$docker_dir/secrets"; fi 49 | # if [[ ! -d "$docker_stacks" ]]; then ${var_sudo}install -o "$docker_uid" -g "$docker_gid" -m "$perms_conf" -d "$docker_dir/stacks"; fi 50 | if [[ ! -d "$docker_swarm" ]]; then ${var_sudo}install -o "$docker_uid" -g "$docker_gid" -m "$perms_conf" -d "$docker_dir/swarm"; fi 51 | 52 | # check if docker.env exists and download if it doesn't otherwise create a blank .docker.env 53 | docker_env_url="https://raw.githubusercontent.com/drauku/bash-scripts/master/docker.env.example" 54 | docker_env_example="$docker_dir/docker.env.example" 55 | docker_env="$docker_dir/.docker.env" 56 | if [[ ! -f "$docker_env" ]]; then 57 | if [[ ! -f "$docker_env_example" ]]; then 58 | if ! wget $docker_env_url -O "$docker_env_example"; then 59 | echo "ERROR: Failed to download $docker_env_url"; 60 | ${var_sudo}install -o "$docker_uid" -g "$docker_gid" -m "$perms_data" /dev/null "$docker_env"; 61 | fi; 62 | else 63 | ${var_sudo}install -o "$docker_uid" -g "$docker_gid" -m "$perms_data" "$docker_env_example" "$docker_env"; 64 | fi 65 | fi; 66 | 67 | ################################################################################ 68 | ########################### general docker functions ########################### 69 | 70 | lda(){ echo "ls $docker_appdata"; ls "$docker_appdata"; echo; } 71 | appdata(){ cd "$docker_appdata/$1" || echo; return; } 72 | alias dka="appdata" 73 | ldc(){ echo "ls $docker_compose"; ls "$docker_compose"; echo; } 74 | compose(){ cd "$docker_compose/$1" || echo; return; } 75 | alias dkc="compose" 76 | lds(){ echo "ls $docker_secrets"; ls "$docker_secrets"; echo; } 77 | secrets(){ cd "$docker_secrets/$1" || echo; return; } 78 | alias dks="secrets" 79 | ldw(){ echo "ls $docker_swarm"; ls "$docker_swarm"; echo; } 80 | swarm(){ cd "$docker_swarm/$1" || echo; return; } 81 | alias dkw="swarm" 82 | 83 | vpncheck(){ echo " > Host IP: $(wget -qO- ifconfig.me)" && echo "Container IP: $(docker container exec -it "${*}" wget -qO- ipinfo.io)"; } 84 | ipcheck(){ echo " > Container IP: $(docker container exec -it "${*}" curl ipinfo.io)"; } 85 | 86 | fnc_check_app(){ if [[ "$1" == "" ]]; then echo; echo " > Application name must be specified. Nothing to do."; echo; return; fi; } 87 | fnc_check_dir(){ if [[ ! -d "$1" ]]; then echo -e " > \`$1\` docker container directory does not exist <"; return 1; fi; } 88 | 89 | fnc_appname_validate(){ 90 | if [[ ${1:0:1} =~ ^[_-]+$ ]] || [[ ! ${1} =~ ^[a-zA-Z0-9_-]+$ ]]; 91 | then echo -e " > \`$1\` is an invalid docker container name <"; return 1; 92 | else return 0; # container name only contains valid characters 93 | fi; 94 | } 95 | 96 | fnc_verify_action(){ 97 | while read -r -p "$2" input; do 98 | case "${input:-N}" in 99 | ([yY]|[yY][eE][sS]) return 0; ;; 100 | ([nN]|[nN][oO]) return 1; ;; 101 | (*) echo -e " > invalid input <"; return 1; ;; 102 | esac 103 | done 104 | } 105 | 106 | docker_file_permissions(){ 107 | case "${1}" in 108 | ("-a"|"--all") # update all docker file permissions 109 | files_dir="${configs_dir}" ;; 110 | (*) # update specific docker file permissions 111 | files_dir="${configs_dir}/${1}" ;; 112 | esac 113 | # update restricted access file permissions to 600 114 | files_restricted=("acme.json" "*.crt" "*.key" "*.pub" "*.ppk" "*.pem"); 115 | for file in "${files_restricted[@]}"; do 116 | ${var_sudo}find "$files_dir" -iname "$file" -type f -exec chmod "$perms_cert" {} + 117 | done 118 | # update limited access file permissions to 660 119 | files_limited=(".conf" "*.env" ".log" "*.secret"); 120 | for file in "${files_limited[@]}"; do 121 | ${var_sudo}find "$files_dir" -iname "$file" -type f -exec chmod "$perms_data" {} + 122 | done 123 | # # update general access file permissions to 664 124 | # files_general=("*.yml" "*.yaml" "*.toml"); 125 | # for file in "${files_general[@]}"; do 126 | # ${var_sudo}find "$docker_dir" -iname "$file" -type f -exec chmod "$perms_conf" {} + 127 | # done 128 | } 129 | docker_folder_permissions(){ 130 | fnc_check_app "$1"; 131 | for stack in ${1}; do 132 | case "${stack}" in 133 | ("-a"|"--all") # update all docker folder permissions 134 | ${var_sudo}chown -R "${docker_uid}:${docker_gid}" "${docker_dir:?}"; 135 | ${var_sudo}chmod -R "${perms_data}" "${docker_appdata:?}"; # -rwXrwX--- 136 | ${var_sudo}chmod -R "${perms_conf}" "${docker_compose:?}"; # -rwXrwXr-X 137 | ${var_sudo}chmod -R "${perms_data}" "${docker_secrets:?}"; # -rwXrwX--- 138 | ${var_sudo}chmod -R "${perms_conf}" "${docker_swarm:?}"; # -rwXrwXr-X 139 | docker_file_permissions --all; 140 | echo -e " > \`ALL\` docker subdirectory and file permissions updated <" 141 | ;; 142 | (*) # update specified docker folder permissions 143 | appdata_dir="${docker_appdata:?}/${stack}"; 144 | appconf_dir="${configs_dir:?}/${stack}"; 145 | if [[ ! -d "${appconf_dir:?}" ]]; then echo -e " > \`${appconf_dir:?}\` docker container directory does not exist <"; return; fi; 146 | ## appdata folder and file permissions 147 | ${var_sudo}chown -R "${docker_uid}:${docker_gid}" "${appdata_dir:?}"; 148 | ${var_sudo}chmod -R "${perms_data}" "${appdata_dir:?}"; 149 | ## compose folder and file permissions 150 | ${var_sudo}chown -R "${docker_uid}:${docker_gid}" "${appconf_dir:?}"; 151 | ${var_sudo}chmod -R "${perms_conf}" "${appconf_dir:?}"; 152 | # echo -e "\n ${ylw:?}UPDATED ${blu:?}${docker_appdata:?}/${mgn:?}${stack}${def:?} AND ${blu:?}${docker_compose:?}/${mgn:?}${stack}${def:?} FOLDERS AND FILE PERMISSIONS ${def:?}"; 153 | docker_file_permissions "${stack}"; 154 | echo -e " > \`${stack}\` docker container subdirectory and file permissions updated <"; 155 | ;; 156 | esac 157 | done; 158 | } 159 | 160 | docker_env_create(){ 161 | case "${1}" in 162 | "-c"|"--copy"|"-f"|"--force") # force copy .docker.env.example to .docker.env 163 | ${var_sudo}install -o "$docker_uid" -g "$docker_gid" -m "$perms_data" "$docker_env" "$configs_dir/$2/.env"; 164 | ;; 165 | *) # symlink .env to .docker.env.example if it does not exist 166 | if [[ ! -f "$configs_dir/$1/.env" ]]; then 167 | ln -s "$docker_env" "$configs_dir/$1/.env"; # symlinks .env to .docker.env 168 | fi 169 | ;; 170 | esac 171 | } 172 | 173 | docker_folders_create(){ 174 | fnc_check_app "$1"; 175 | docheck=0; 176 | if [[ -d "$configs_dir/$1" ]]; then docheck=$((docheck + 1)); 177 | else # create docker container config directories and files 178 | # if [[ $1 =~ ^[compose]+$ ]]; 179 | # then export configs_dir="$docker_compose"; 180 | # elif [[ $1 =~ ^[swarm]+$ ]]; 181 | # then export configs_dir="$docker_swarm"; 182 | # fi; 183 | if fnc_appname_validate "$1"; then 184 | # echo -e " > Creating directories and files for the \` $configs_dir/$1 \` container <"; echo; 185 | ${var_sudo}install -o "$docker_uid" -g "$docker_gid" -m "$perms_conf" -d "$configs_dir/$1"; 186 | ${var_sudo}install -o "$docker_uid" -g "$docker_gid" -m "$perms_conf" /dev/null "$configs_dir/$1/compose.yml"; 187 | docker_env_create "$1"; 188 | echo " > Docker config directories and files created for the \`$1\` application."; 189 | fi; 190 | fi; 191 | if [[ -d "$docker_appdata/$1" ]]; then docheck=$((docheck + 2)); 192 | else # create docker container data directory 193 | if fnc_appname_validate "$1"; then 194 | ${var_sudo}install -o "$docker_uid" -g "$docker_gid" -m "$perms_data" -d "$docker_appdata/$1"; 195 | echo " > Docker appdata directory created for the \`$1\` application."; 196 | fi; 197 | fi; 198 | case "$docheck" in 199 | "1") echo " > Docker config directory for \`$configs_dir/$1\` already exists.";; 200 | "2") echo " > Docker data directory for \`$docker_appdata/$1\` already exists.";; 201 | "3") echo " > Docker config and data directories for the \`$1\` application already exist.";; 202 | esac 203 | echo 204 | } 205 | docker_folders_delete(){ 206 | if ! fnc_verify_action "$1" " > This will forcefully delete all \`$1\` application directories and files. Continue? [y/N] "; then return; fi; echo; 207 | fnc_check_app "$1"; 208 | docheck=0; 209 | if [[ -d "${docker_appdata:?}/$1" ]]; 210 | then 211 | rm -rf "${docker_appdata:?}/$1"; #docheck=$((docheck+1)); 212 | echo " > \`${docker_appdata:?}/$1\` and contents deleted."; 213 | else echo " > \`$docker_appdata/$1\` does not exists. Nothing to remove."; echo; 214 | fi; 215 | if [[ -d "${configs_dir:?}/$1" ]]; 216 | then 217 | rm -rf "${configs_dir:?}/$1"; #docheck=$((docheck+1)); 218 | echo " > \`${configs_dir:?}/$1\` and contents deleted."; 219 | else echo " > \`$configs_dir/$1\` does not exists. Nothing to remove."; echo; 220 | fi; 221 | # if [[ $configs_dir =~ ^[compose]+$ ]]; then 222 | # if [[ -d "$docker_compose/$1" ]]; 223 | # # then rm -rf "${docker_compose:?}/$1"; 224 | # then echo "DEBUG: rm -rf ${docker_compose:?}/$1"; 225 | # else echo " > \`$1\` does not exists. Nothing to remove."; echo; 226 | # fi; 227 | # fi; 228 | # if [[ $configs_dir =~ ^[swarm]+$ ]]; then 229 | # if [[ -d "$docker_swarm/$1" ]]; 230 | # # then rm -rf "${docker_swarm:?}/$1"; 231 | # then echo "DEBUG: rm -rf ${docker_swarm:?}/$1"; 232 | # else echo " > \`$1\` does not exists. Nothing to remove."; echo; 233 | # fi; 234 | # fi; 235 | # if [[ $docheck -eq 0 ]]; then echo " > \`$1\` docker container subdirectories and files deleted."; echo; fi; 236 | echo; 237 | } 238 | docker_folder_actions(){ 239 | case "$1" in 240 | -*) # perform optional action 241 | case "$1" in 242 | "-c"|"--create") docker_folders_create "$2" ;; 243 | "-d"|"--delete") docker_folders_delete "$2" ;; 244 | "-r"|"--remove") docker_folders_delete "$2" ;; 245 | *) echo " > Invalid option \`$1\` used."; echo; 246 | esac 247 | ;; 248 | *) docker_folders_create "$@" ;; 249 | esac; 250 | } 251 | 252 | ################################################################################ 253 | ########################### docker compose functions ########################### 254 | 255 | docker_list_containers(){ 256 | case "$1" in 257 | "-a"|"--all") 258 | docker container list --all --format "table {{.ID}} {{.Names}}\t{{.Status}}\t{{.RunningFor}}\t{{.Image}}";; 259 | "-l"|"--labels") 260 | docker container list --no-trunc --format "table {{.Names}}\t{{.Status}}\t{{.Labels}}\t{{.Command}}";; 261 | "-n"|"--networks") 262 | docker container list --no-trunc --format "table {{.Names}}\t{{.Status}}\t{{.Networks}}\t{{.Ports}}";; 263 | "-v"|"--volumes") 264 | docker container list --no-trunc --format "table {{.Names}}\t{{.Status}}\t{{.LocalVolumes}}\t{{.Mounts}}";; 265 | *) 266 | docker container list --format "table {{.ID}} {{.Names}}\t{{.Status}}\t{{.Image}}\t{{.Command}}";; 267 | esac 268 | } 269 | alias dlc="docker_list_containers" # "docker list containers" 270 | alias dll="docker_list_containers" # "docker list local apps" 271 | 272 | docker_compose_folders(){ 273 | export configs_dir="$docker_compose"; 274 | docker_folder_actions "$@"; 275 | } 276 | alias dcf='docker_compose_folders' 277 | 278 | docker_compose_env(){ 279 | export configs_dir="$docker_compose"; 280 | docker_env_create "$@"; 281 | } 282 | alias dcenv='docker_compose_env' 283 | 284 | docker_compose_permissions(){ 285 | export configs_dir="$docker_compose"; 286 | docker_folder_permissions "$1"; 287 | } 288 | alias dcp="docker_compose_permissions" 289 | 290 | docker_compose_edit(){ nano "$docker_compose/$1/compose.yml"; } 291 | alias dce="docker_compose_edit" 292 | 293 | docker_compose_config(){ docker compose -f "$docker_compose/$1/compose.yml" config; } 294 | alias dcc="docker_compose_config" 295 | alias dct="docker_compose_config" 296 | 297 | docker_compose_logs(){ (cd "$docker_compose/$1" && docker compose logs -f); } 298 | alias dcl="docker_compose_logs" 299 | 300 | docker_compose_networks(){ 301 | docker network create --driver "bridge" --opt "encrypted" --scope "local" --subnet "172.20.0.0/16" --gateway "172.20.0.254" --attachable "docker_socket" 302 | docker network create --driver "bridge" --opt "encrypted" --scope "local" --subnet "172.21.1.0/16" --gateway "172.21.0.254" --attachable "external_edge" 303 | docker network create --driver "bridge" --opt "encrypted" --scope "local" --subnet "172.22.2.0/16" --gateway "172.22.0.254" --attachable "reverse_proxy" 304 | echo "The \`docker_socket\`, \`external_edge\`, and \`reverse_proxy\` docker bridge networks exist or were created."; echo 305 | } 306 | alias dcn="docker_compose_networks" 307 | 308 | docker_list_networks(){ docker network ls; } 309 | alias dln="docker_list_networks" 310 | 311 | fnc_strip_option(){ export applist=( "${applist[@]:1}" ); } # remove first element 312 | 313 | docker_compose_start(){ 314 | applist=( "$*" ) 315 | export configs_dir="$docker_compose"; 316 | fnc_compose_start(){ 317 | for app in "$@"; do 318 | if [[ -f "$docker_compose/$app/compose.yml" ]]; then 319 | docker_env_create "$app"; 320 | docker compose -f "$docker_compose/$app/compose.yml" up -d --remove-orphans; 321 | else echo " > No docker compose configuration file found for the \`$app\` application."; 322 | fi; 323 | done 324 | echo; 325 | } 326 | case "$1" in 327 | -*) # perform optional action 328 | case "$1" in 329 | "-l"|"--logs") 330 | fnc_strip_option "$@" 331 | fnc_compose_start "${applist[@]}" 332 | docker_compose_logs "${2:-${applist[1]}}"; 333 | ;; 334 | *) echo "Invalid option: \`$1\`"; echo; 335 | esac 336 | ;; 337 | *) 338 | fnc_compose_start "${applist[@]}" 339 | ;; 340 | esac 341 | } 342 | alias dcu="docker_compose_start" 343 | 344 | docker_compose_stop(){ 345 | if [[ -f "$docker_compose/$1/compose.yml" && -f "$docker_compose/$1/.env" ]] 346 | then docker compose -f "$docker_compose/$1/compose.yml" down; 347 | else docker stop "$1" && docker container rm "$1" 348 | fi 349 | echo 350 | } 351 | alias dcd="docker_compose_stop" 352 | 353 | docker_compose_bounce(){ docker_compose_stop "$1" && docker_compose_start "$1" ; } 354 | alias dcb="docker_compose_bounce" 355 | 356 | # echo -e "\n>> docker compose aliases and functions created <<"; 357 | 358 | ################################################################################ 359 | ############################ docker swarm functions ############################ 360 | 361 | docker_list_stacks(){ 362 | case "$1" in 363 | "-a"|"--all") 364 | docker stack ls;; 365 | *) 366 | docker stack ls --format "table {{.Name}}\t{{.Description}}";; 367 | esac 368 | } 369 | alias dls="docker_list_stacks" # "docker list stacks" 370 | alias dlw="docker_list_stacks" # "docker list swarm apps" 371 | 372 | docker_swarm_folders(){ 373 | export configs_dir="$docker_swarm"; 374 | docker_folder_actions "$@"; 375 | } 376 | alias dwf="docker_swarm_folders" 377 | 378 | docker_swarm_env(){ 379 | export configs_dir="$docker_swarm"; 380 | docker_env_create "$@"; 381 | } 382 | alias dwenv="docker_swarm_env" 383 | 384 | docker_swarm_permissions(){ 385 | export configs_dir="$docker_swarm"; 386 | docker_folder_permissions "$1"; 387 | } 388 | alias dwp="docker_swarm_permissions" 389 | 390 | docker_swarm_edit(){ nano "$docker_swarm/$1/compose.yml"; } 391 | alias dwe="docker_swarm_edit" 392 | 393 | docker_swarm_config(){ docker compose -f "$docker_swarm/$1/compose.yml" config; } 394 | alias dwc="docker_swarm_config" 395 | alias dwt="docker_swarm_config" 396 | 397 | docker_swarm_logs(){ (cd "$docker_swarm/$1" && docker compose logs -f); } 398 | alias dwl="docker_swarm_logs" 399 | 400 | docker_swarm_networks(){ 401 | docker network create --driver "overlay" --opt "encrypted" --scope "swarm" --subnet "172.20.0.0/16" --gateway "172.20.0.254" --attachable "docker_socket" 402 | docker network create --driver "overlay" --opt "encrypted" --scope "swarm" --subnet "172.21.0.0/16" --gateway "172.21.0.254" --attachable "external_edge" 403 | docker network create --driver "overlay" --opt "encrypted" --scope "swarm" --subnet "172.22.0.0/16" --gateway "172.22.0.254" --attachable "reverse_proxy" 404 | echo "The \`docker_socket\`, \`external_edge\`, and \`reverse_proxy\` docker overlay networks exist or were created."; echo 405 | } 406 | alias dwn="docker_swarm_networks" 407 | 408 | docker_swarm_start(){ 409 | if [[ -f "$docker_swarm/$1/compose.yml" ]]; then 410 | docker_env_create "$1"; 411 | docker stack deploy "${1}" -c "${docker_swarm}/${1}/compose.yml" --prune; 412 | else echo "No docker swarm configuration file found for the \`$1\` application."; 413 | fi; 414 | echo; 415 | } 416 | alias dwu="docker_swarm_start" 417 | 418 | docker_swarm_stop(){ 419 | if [[ -f "$docker_swarm/$1/compose.yml" && -f "$docker_swarm/$1/.env" ]] 420 | then docker compose -f "$docker_swarm/$1/compose.yml" down; 421 | else docker stop "$1" && docker container rm "$1" 422 | fi 423 | echo 424 | } 425 | alias dwd="docker_swarm_stop" 426 | 427 | docker_swarm_bounce(){ docker_swarm_stop "$1" && docker_swarm_start "$1" ; } 428 | alias dwb="docker_swarm_bounce" 429 | 430 | docker_list_swarm_nodes(){ docker node ls -q | xargs docker node inspect -f '{{ .ID }} [hostname={{ .Description.Hostname }}, Addr={{ .Status.Addr }}, State={{ .Status.State }}, Role={{ .Spec.Role }}, Availability={{ .Spec.Availability }}]: Arch={{ .Description.Platform.Architecture }}, OS={{ .Description.Platform.OS }}, NanoCPUs={{ .Description.Resources.NanoCPUs }}, MemoryBytes={{ .Description.Resources.MemoryBytes }}, docker_version={{ .Description.Engine.EngineVersion }}, labels={{ range $k, $v := .Spec.Labels }}{{ $k }}={{ $v }} {{end}}'; } 431 | alias dkwn="docker_list_swarm_nodes" 432 | 433 | # echo -e "\n>> docker swarm aliases and functions created <<"; echo; 434 | 435 | ################################################################################ 436 | 437 | echo -e "\n>> docker aliases and functions created <<"; echo; -------------------------------------------------------------------------------- /docker_compose_logs.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # external variable sources 3 | source /opt/docker/scripts/.color_codes.conf 4 | source /opt/docker/scripts/.vars_docker.env 5 | 6 | # function definitions 7 | fnc_help_compose_logs(){ 8 | echo -e "${blu:?}[-> # This script displays 50 log entries for the indicated docker compose container. <-]${def:?}" 9 | echo -e " -" 10 | echo -e " - SYNTAX: # dcl ${cyn:?}container_name${def:?}" 11 | echo -e " - SYNTAX: # dcl ${cyn:?}-option${def:?}" 12 | echo -e " - VALID OPTIONS:" 13 | echo -e " - ${cyn:?}-h │ --help ${def:?}│ Displays this help message." 14 | echo 15 | exit 1 # Exit script after printing help 16 | } 17 | case "$1" in ("-h"|*"help"*) fnc_help_compose_logs ;; esac 18 | 19 | fnc_script_intro(){ echo -e "${blu:?}[-> LISTING THE 50 MOST RECENT DOCKER COMPOSE LOG ENTRIES <-]${def:?}"; } 20 | fnc_script_outro(){ echo -e "${grn:?}[-- MOST RECENT 50 LOG ENTRIES LISTED --]${def:?}"; echo; } 21 | fnc_nothing_to_do(){ echo -e "${ylw:?} -> no log entries to display${def:?}"; } 22 | fnc_invalid_syntax(){ echo -e "${ylw:?} >> INVALID OPTION SYNTAX, USE THE -${cyn:?}help${ylw:?} OPTION TO DISPLAY PROPER SYNTAX <<${def:?}"; exit 1; } 23 | fnc_compose_logs(){ docker compose logs -tf --tail="50" "${docker_compose}/${1}/compose.yml"; } 24 | 25 | # option logic action determination 26 | case "${1}" in 27 | (-*) # validate entered option exists 28 | case "${1}" in 29 | (*) echo -e "${ylw:?} >> INVALID OPTION SYNTAX -- USE THE -${cyn:?}help${ylw:?} OPTION TO DISPLAY PROPER SYNTAX <<${def:?}"; exit 1 ;; 30 | esac 31 | ;; 32 | (*) fnc_script_intro; 33 | if [ "$(fnc_compose_logs)" ] 34 | then fnc_compose_logs "${1}" 35 | else fnc_nothing_to_do 36 | fi 37 | echo 38 | ;; 39 | esac 40 | -------------------------------------------------------------------------------- /docker_compose_networks.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # external variable sources 3 | source /opt/docker/scripts/.color_codes.conf 4 | source /opt/docker/scripts/.vars_docker.env 5 | 6 | # function definitions 7 | fnc_help(){ 8 | echo -e "${blu:?}[- This script creates Docker ${blu:?}networks${def:?} required for compose and swarm containers by ${cyn:?}Drauku${blu:?} -]${def:?}" 9 | echo -e " - ${blu:?}(modified from ${cyn:?}gkoerk's (RIP)${blu:?} famously awesome networks for stacks)${def:?}" 10 | echo -e " -" 11 | echo -e " - SYNTAX: dnc ${cyn:?}-option${def:?}" 12 | echo -e " - VALID OPTIONS:" 13 | echo -e " - ${cyn:?}-c │ --create ${def:?}│ ${grn:?}Creates${def:?} the ${blu:?}{netproxy,netsocket}${def:?} docker networks" 14 | echo -e " - ${cyn:?}-d │ --delete ${def:?}│ ${red:?}Deletes${def:?} the ${blu:?}{netproxy,netsocket}${def:?} docker networks" 15 | echo -e " - ${cyn:?}-l │ --list ${def:?}│ ${red:?}Lists${def:?} the current docker networks" 16 | echo 17 | } 18 | case "${1}" in ("-h"|*"help"*) fnc_help ;; esac 19 | fnc_script_intro(){ echo -e "${blu:?}[- CREATE DOCKER NETWORKS REQUIRED FOR USE WITH DOCKER SOCKET AND A REVERSE PROXY -]${def:?}"; } 20 | fnc_script_outro(){ echo -e "${grn:?} - DOCKER NETWORKS '${var_net_rproxy} & ${var_net_socket}' CREATED${def:?}"; echo; exit 1; } 21 | fnc_nothing_to_do(){ echo -e "${ylw:?} >> A valid option and container name(s) must be entered for this command to work (use ${cyn:?}--help ${ylw:?}for info)${def:?}"; } 22 | fnc_invalid_syntax(){ echo -e "${ylw:?} >> INVALID OPTION SYNTAX, USE THE ${cyn:?}-help${ylw:?} OPTION TO DISPLAY PROPER SYNTAX <<${def:?}"; echo; exit 1; } 23 | fnc_invalid_input(){ echo -e "${ylw:?}INVALID INPUT${def:?}: Must be any case-insensitive variation of '(Y)es' or '(N)o'."; } 24 | 25 | fnc_create_networks() { 26 | docker network create --driver "bridge" --opt "encrypted" --scope "local" --subnet "172.27.0.0/24" --gateway "172.27.0.254" --attachable "docker_socket" 27 | docker network create --driver "bridge" --opt "encrypted" --scope "local" --subnet "172.27.1.0/24" --gateway "172.27.1.254" --attachable "external_edge" 28 | docker network create --driver "bridge" --opt "encrypted" --scope "local" --subnet "172.27.2.0/24" --gateway "172.27.2.254" --attachable "reverse_proxy" 29 | } 30 | fnc_delete_networks() { 31 | docker network rm "docker_socket" 32 | docker network rm "external_edge" 33 | docker network rm "reverse_proxy" 34 | } 35 | fnc_list_networks() { 36 | docker network ls 37 | } 38 | 39 | case "${1}" in 40 | "-c"|"--create") 41 | fnc_create_networks ;; 42 | "-d"|"--delete") 43 | fnc_delete_networks ;; 44 | "-l"|"--list"|"") 45 | fnc_list_networks ;; 46 | *) 47 | fnc_nothing_to_do ;; 48 | esac -------------------------------------------------------------------------------- /docker_compose_start.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # external variable sources 3 | source /opt/docker/scripts/.color_codes.conf 4 | source /opt/docker/scripts/.vars_docker.env 5 | 6 | # script variable definitions 7 | unset stacks_list IFS 8 | bounce_list="" 9 | 10 | # function definitions 11 | fnc_help_compose_start(){ 12 | echo -e " - ${blu:?}[-> This script STARTS 'up' a single Docker container using a pre-written compose file <-]${def:?}" 13 | echo -e " -" 14 | echo -e " - SYNTAX: # dcu | dcs | dct" 15 | echo -e " - SYNTAX: # dcu ${cyn:?}stack_name${def:?}" 16 | echo -e " - SYNTAX: # dcu ${cyn:?}-option${def:?}" 17 | echo -e " - VALID OPTIONS:" 18 | echo -e " - ${cyn:?}-h │ --help ${def:?}| Displays this help message." 19 | echo -e " - ${cyn:?}-a | --all ${def:?}| Deploys all stacks with a config file inside the '${ylw:?}${docker_compose:?}/${def:?}' path." 20 | echo -e " - NOTE: config files must follow this naming format: '${cyn:?}/stackname${cyn:?}/compose.yml${def:?}'" 21 | echo 22 | exit 1 # Exit script after printing help 23 | } 24 | case "$1" in ("-h"|*"help"*) fnc_help_compose_start ;; esac 25 | 26 | fnc_script_intro(){ echo -e "${blu:?}[- ${grn:?}STARTING${blu:?} LISTED DOCKER CONTAINERS -]${def:?}"; } 27 | fnc_script_outro(){ echo -e "${blu:?}[- List of Docker containers ${grn:?}STARTED${blu:?} <-]${def:?}"; } 28 | fnc_nothing_to_do(){ echo -e "${ylw:?} -> no configuration file exists for the entered stack(s)${def:?}"; } 29 | fnc_invalid_syntax(){ echo -e "${ylw:?} >> INVALID OPTION SYNTAX, USE THE ${cyn:?}--help${ylw:?} OPTION TO DISPLAY PROPER SYNTAX <<${def:?}"; exit 1; } 30 | 31 | # # fnc_remove_cmd_option(){ for i in "${!stacks_list[@]}"; do if [[ "${stacks_list[i]}" = "-*" || "${stacks_list[i]}" = "." ]]; then unset "${stacks_list[i]}"; fi; done; } 32 | # fnc_remove_cmd_option() { # remove elements starting with '-' from array 33 | # local filtered=() 34 | # for element in "$@"; do 35 | # if [[ $element != \-* && $element != . ]]; then 36 | # filtered+=("$element") 37 | # fi 38 | # done 39 | # stacks_list=("${filtered[@]}") 40 | # } 41 | 42 | ## consolidate list_processing in bounce and start functions 43 | ## track down permissions issue with .env, preventing script to run - DONE, was missing 'w' permission for group 44 | ## - figure out why sudo function isn't working 45 | 46 | # fnc_check_sudo_usage(){ 47 | # case "$(awk -F'=' '/^ID=/ { gsub("\"","",$2); print tolower($2) } ' /etc/*-release 2> /dev/null)" in 48 | # ("qts"|"quts"|"debian") 49 | # unset var_sudo IFS; 50 | # case "$(id -un)" in 51 | # ("admin"|"root") 52 | # unset var_sudo IFS; 53 | # ;; 54 | # (*) 55 | # var_sudo="/usr/bin/sudo "; 56 | # ;; 57 | # esac 58 | # ;; 59 | # (*) 60 | # var_sudo="/usr/bin/sudo "; 61 | # ;; 62 | # esac 63 | # } 64 | 65 | fnc_list_all_running(){ IFS=$'\n' bounce_list=("$(docker container list --format '{{.Names}}')"); } 66 | fnc_list_sort(){ deploy_list=( "$(for stack in "${deploy_list[@]}" ; do echo "$stack" ; done | sort -u)" ); } 67 | # fnc_subdirectories_list=( "$(IFS=$'\n'; cd "${docker_compose:?}" && find . -type d -not -path '*/\.*' | sed 's/^\.\///g')" ) 68 | fnc_configs_folder_list(){ IFS=$'\n'; configs_folder_list=( "$(cd "${docker_compose:?}" && find . -maxdepth 1 -type d -not -path '*/\.*' | sed 's/^\.\///g')" ); } 69 | fnc_deploy_list_cleanup(){ # check that each folder has a .yml config file and clean up the array 70 | unset configs_list IFS; 71 | for i in "${!configs_folder_list[@]}"; do 72 | # remove '.' folder name from printed list 73 | if [[ "${configs_folder_list[i]}" = "." ]]; then unset "${configs_folder_list[i]}"; fi 74 | if [[ -f "${docker_compose:?}"/"${configs_folder_list[i]}"/"${var_configs_file:?}" ]] 75 | then configs_list="${configs_list} ${configs_folder_list[i]}" 76 | fi 77 | done 78 | unset deploy_list IFS; 79 | IFS=$'\n'; deploy_list=( "${configs_list[@]}" ) 80 | } 81 | fnc_bounce_list(){ # populate list of stacks to be started 82 | # fnc_check_sudo_usage; 83 | if [[ "${bounce_list[*]}" = "" ]]; then 84 | # populate list of configuration folders 85 | fnc_configs_folder_list 86 | # check that each existing folder has a .yml config file inside 87 | fnc_deploy_list_cleanup 88 | else IFS=$'\n'; deploy_list=( "${bounce_list[@]}" ) 89 | fi 90 | } 91 | fnc_start_containers(){ # perform script main function 92 | # fnc_check_sudo_usage; 93 | # IFS=$'\n'; deploy_list=( $(for stack in "${deploy_list[@]}" ; do echo "${stack}" ; done | sort -u) ) 94 | fnc_list_sort "${deploy_list[@]}" 95 | for stack in "${deploy_list[@]}"; do 96 | # create '.env' file redirect if used 97 | # if [ ! -f "${docker_compose:?}/${deploy_list[stack]}/.env" ]; then ln -s "${var_script_vars:?}" "${docker_compose:?}/${deploy_list[stack]}/.env"; fi 98 | # [ ! -f "${docker_compose:?}/${deploy_list[stack]}/.env" ] && ln -sf "${var_script_vars:?}" "${docker_compose:?}/${deploy_list[stack]}/.env"; 99 | # "${var_sudo}" 100 | if [ ! -f "${docker_compose:?}/${stack}/.env" ]; then ln -sf "${var_script_vars:?}" "${docker_compose:?}/${stack}/.env"; fi; 101 | docker compose -f "${docker_compose:?}/${stack}/${var_configs_file:?}" up -d --remove-orphans 102 | sleep 1 103 | done 104 | } 105 | 106 | # option logic action determination 107 | case "${1}" in 108 | (-*) # validate entered option exists 109 | case "${1}" in 110 | ("-a"|"--all") 111 | unset "deploy_list[0]" 112 | fnc_bounce_list 113 | ;; 114 | (*) 115 | fnc_invalid_syntax 116 | ;; 117 | esac 118 | ;; 119 | (*) 120 | IFS=' ' deploy_list=("$@") 121 | ;; 122 | esac 123 | 124 | # perform script main function 125 | fnc_start_containers 126 | -------------------------------------------------------------------------------- /docker_compose_stop.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # external variable sources 3 | source /opt/docker/scripts/.color_codes.conf 4 | source /opt/docker/scripts/.vars_docker.env 5 | 6 | # script variable definitions 7 | unset stacks_list IFS 8 | IFS=' ' stacks_list=("$@") 9 | 10 | # function definitions 11 | fnc_help_compose_stop(){ 12 | echo -e "${blu:?}[- This script STOPS or brings DOWN a single Docker container using a pre-written compose file -]${def:?}" 13 | echo -e " -" 14 | echo -e " - SYNTAX: # dcd | dcp | dcr ${cyn:?}stack_name${def:?}" 15 | # echo -e " - SYNTAX: # dcd ${cyn:?}-option${def:?}" 16 | echo -e " - VALID OPTIONS:" 17 | echo -e " - ${cyn:?}-h │ --help ${def:?}| Displays this help message." 18 | echo -e " - ${cyn:?}-d | --Down ${def:?}| Brings ${red:?}Down${def:?} docker container(s) and associated network(s)." 19 | echo -e " - ${cyn:?}-p | --stoP ${def:?}| ${ylw:?}stoPs${def:?} currently running docker container(s)." 20 | echo -e " - ${cyn:?}-r | --Remove ${def:?}| ${ylw:?}stoPs${def:?} and ${red:?}Removes${def:?} listed docker container(s)." 21 | echo 22 | exit 1 # Exit script after printing help 23 | } 24 | case "$1" in ("-h"|*"help"*) fnc_help_compose_stop ;; esac 25 | 26 | fnc_intro_compose_stop(){ echo -e "${blu:?}[- ${red:?}STOPPING${blu:?} LISTED DOCKER CONTAINERS -]${def:?}"; } 27 | fnc_outro_compose_stop(){ echo -e "${blu:?}[- LISTED DOCKER CONTAINERS ${red:?}STOPPED${blu:?} -]${def:?}"; } 28 | fnc_invalid_syntax(){ echo -e "${ylw:?} >> INVALID OPTION SYNTAX, USE THE ${cyn:?}-help${ylw:?} OPTION TO DISPLAY PROPER SYNTAX <<${def:?}"; exit 1; } 29 | fnc_nothing_to_do(){ echo -e "${ylw:?} -> No compose or stack specified. Expected synatax: ${def:?}dcd ${cyn:?}stack_name${def:?}"; } 30 | 31 | # fnc_remove_cmd_option(){ for i in "${!stacks_list[@]}"; do if [[ "${stacks_list[i]}" = "-*" || "${stacks_list[i]}" = "." ]]; then unset "${stacks_list[i]}"; fi; done; } 32 | fnc_remove_cmd_option() { # remove args starting with '-' from array 33 | local filtered=() 34 | local args="$@" 35 | for arg in "${args[@]}"; do 36 | # if [[ $arg = . ]]; then unset $args[#]; fi 37 | # if [[ $arg = \-* ]]; then options+=("$arg"); fi 38 | if [[ $arg != \-* && $arg != . ]]; then filtered+=("$arg"); fi 39 | done 40 | option_list=("${options[@]}") 41 | stacks_list=("${filtered[@]}") 42 | } 43 | 44 | # fnc_list_sort(){ IFS=$'\n'; stacks_list=( $(for stack in "${stacks_list[@]}" ; do echo "${stack}" ; done | sort -u) ); } 45 | fnc_list_sort(){ sort_list="${stacks_list[*]}"; IFS=$'\n' read -r stacks_list <<< "$( for stack in "${sort_list[@]}" ; do echo "${stack}" ; done | sort -u )"; } 46 | # fnc_list_sort(){ 47 | # stacks_list=(); 48 | # while IFS=$'' read -r line; do stacks_list+=("$line"); done < <( for stack in "${stacks_list[@]}" ; do echo "${stack}" ; done | sort -u ); 49 | # } 50 | fnc_configs_list_all(){ IFS=$'\n'; stacks_list=($(docker container list --format {{.Names}})); fnc_list_sort; } 51 | # fnc_configs_list_all(){ 52 | # stacks_list=(); 53 | # while IFS=$'' read -r line; do stacks_list+=("$line"); done < <( docker container list --format "{{.Names}}" ); fnc_list_sort; 54 | # } 55 | # fnc_configs_list_all(){ IFS=$'\n' read -r -q stacks_list <<< "$( docker container list --format "{{.Names}}" )"; fnc_list_sort; } 56 | fnc_env_file_remove(){ if [[ -f "${docker_compose:?}/${1}/.env" ]]; then rm -f "${docker_compose:?}/${1}/.env"; fi; } 57 | fnc_docker_stop(){ docker stop "${1}"; } 58 | fnc_docker_container_rm(){ docker container rm -f "${1}"; } #fnc_env_file_remove "${1}"; } 59 | fnc_docker_compose_down(){ docker compose -f "${docker_compose:?}/${1}/${var_configs_file:?}" down; } # fnc_env_file_remove "${1}"; } 60 | fnc_docker_compose_stop(){ docker compose -f "${docker_compose:?}/${1}/${var_configs_file:?}" stop; } 61 | 62 | #### NOTE: below function order must not change 63 | 64 | # TODO: this function might replace individual "rm/down/stop" functions with an "action" variable assigned during case logic 65 | fnc_container_action(){ 66 | for stack in "${stacks_list[@]}"; do 67 | if [[ -f "${docker_compose:?}/${stack}/${var_configs_file:?}" ]]; then 68 | docker compose -f "${docker_compose:?}/${stack}/${var_configs_file:?}" "${action}" 69 | else 70 | if [[ "${action}" == "down" ]]; then 71 | fnc_docker_stop "${stack}" 72 | fnc_docker_container_rm "${stack}" 73 | elif [[ "${action}" == "stop" ]]; then 74 | fnc_docker_stop "${stack}" 75 | fi 76 | fi 77 | sleep 1 78 | done 79 | } 80 | fnc_container_stop(){ 81 | for stack in "${stacks_list[@]}"; do 82 | # TODO: check if compose file exists, if not, try to stop container instead 83 | if [[ -f "${docker_compose:?}/${stack}/${var_configs_file:?}" ]]; then 84 | fnc_docker_compose_stop "${stack}" 85 | else 86 | fnc_docker_stop "${stack}" 87 | fi 88 | sleep 1 89 | done 90 | } 91 | fnc_container_remove(){ 92 | # stacks_list=($(fnc_remove_cmd_option "${stacks_list[@]}")) 93 | fnc_remove_cmd_option "${stacks_list[@]}" 94 | for stack in "${stacks_list[@]}"; do 95 | # TODO: check if compose file exists, if not, try to stop and remove container instead 96 | if [[ -f "${docker_compose:?}/${stack}/${var_configs_file:?}" ]]; then 97 | fnc_docker_compose_down "${stack}" 98 | else 99 | fnc_docker_stop "${stack}" 100 | fnc_docker_container_rm "${stack}" 101 | fi 102 | # fnc_env_file_remove "${stack}" 103 | sleep 1 104 | done 105 | } 106 | 107 | # option logic action determination 108 | case "${1}" in 109 | ("") 110 | fnc_nothing_to_do 111 | ;; 112 | (-*) # validate entered option exists 113 | case "${1}" in 114 | ("-a"|"--all") 115 | unset stacks_list 116 | fnc_configs_list_all 117 | action="down" 118 | fnc_remove_cmd_option "${stacks_list[@]}" 119 | fnc_container_remove "${stacks_list[@]}" 120 | ;; 121 | ("-d"|"--down") 122 | # unset "stacks_list[0]" 123 | action="down" 124 | fnc_remove_cmd_option "${stacks_list[@]}" 125 | fnc_container_remove "${stacks_list[@]}" 126 | ;; 127 | ("-p"|"--stop") 128 | # unset "stacks_list[0]" 129 | action="stop" 130 | fnc_remove_cmd_option "${stacks_list[@]}" 131 | fnc_container_stop "${stacks_list[@]}" 132 | ;; 133 | ("-r"|"--remove") 134 | # unset "stacks_list[0]" 135 | action="rm" 136 | fnc_remove_cmd_option "${stacks_list[@]}" 137 | fnc_container_remove "${stacks_list[@]}" 138 | ;; 139 | ("-l"|"--list") 140 | # unset "stacks_list[0]" 141 | action="ls" 142 | fnc_remove_cmd_option "${stacks_list[@]}" 143 | fnc_configs_list_all 144 | echo "${stacks_list[*]}" 145 | ;; 146 | (*) 147 | fnc_invalid_syntax 148 | ;; 149 | esac 150 | ;; 151 | (*) 152 | # fnc_invalid_syntax 153 | action="down" 154 | fnc_remove_cmd_option "${stacks_list[@]}" 155 | fnc_container_remove "${stacks_list[@]}" 156 | ;; 157 | esac 158 | 159 | # fnc_outro_compose_stop -------------------------------------------------------------------------------- /docker_compose_test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | source /opt/docker/scripts/.color_codes.conf 4 | source /opt/docker/scripts/.vars_docker.env 5 | 6 | #function definitions 7 | fnc_help_docker_compose_test(){ 8 | echo -e "${blu:?}[- This script displays the indicated compose file with variables/secrets filled in. -]${def:?}" 9 | echo -e " -" 10 | echo -e " - SYNTAX: # dcc | dct | dctest ${cyn:?}stack_name${def:?}" 11 | # echo -e " - SYNTAX: # dcd ${cyn:?}-option${def:?}" 12 | echo -e " - VALID OPTIONS:" 13 | echo -e " - ${cyn:?}-h │ --help ${def:?}| Displays this help message." 14 | echo 15 | exit 1 # Exit script after printing help 16 | } 17 | case "$1" in ("-h"|*"help"*) fnc_help_docker_compose_test ;; esac 18 | 19 | fnc_intro_docker_compose_test(){ echo -e "${blu:?}[- ${mgn:?}DISPLAYING${blu:?} COMPLETED COMPOSE FILE FOR ${cyn:?}stack_name${blu:?} -]${def:?}"; } 20 | fnc_outro_docker_compose_test(){ echo -e "${blu:?}[- ${cyn:?}\`docker compose config\`${def:?} display complete. -]${def:?}"; } 21 | fnc_invalid_syntax(){ echo -e "${ylw:?} >> INVALID OPTION SYNTAX, USE THE ${cyn:?}-help${ylw:?} OPTION TO DISPLAY PROPER SYNTAX <<${def:?}"; exit 1; } 22 | fnc_nothing_to_do(){ echo -e "${ylw:?} -> No compose or stack specified. Expected synatax: ${def:?}dcc ${cyn:?}stack_name${def:?}"; } 23 | 24 | fnc_docker_compose_test(){ docker compose -f "${docker_compose:?}/${1}/${var_configs_file:?}" config; } 25 | 26 | case "$1" in 27 | *) fnc_intro_docker_compose_test; fnc_docker_compose_test "${@}"; fnc_outro_docker_compose_test;; 28 | # "dct") fnc_intro_docker_compose_test; fnc_docker_compose_test "${@}"; fnc_outro_docker_compose_test;; 29 | # "dctest") fnc_intro_docker_compose_test; fnc_docker_compose_test "${@}"; fnc_outro_docker_compose_test;; 30 | # "") fnc_nothing_to_do;; 31 | # *) fnc_invalid_syntax;; 32 | esac -------------------------------------------------------------------------------- /docker_folders_create.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # external variable sources 3 | source /opt/docker/scripts/.color_codes.conf 4 | source /opt/docker/scripts/.vars_docker.env 5 | 6 | # script help text 7 | fnc_help_folders_create(){ 8 | echo -e "${blu:?}[-> This script creates Docker configuration folders using the schema developed by ${cyn:?}Drauku${blu:?} <-]${def:?}" 9 | echo -e " - ${blu:?}(modified from ${cyn:?}gkoerk's (RIP)${blu:?} famously awesome folder structure for stacks)${def:?}" 10 | echo -e " -" 11 | echo -e " -NOTE: stack_names must NOT contain spaces, but MUST be separated by a 'space' character: " 12 | echo -e " -" 13 | echo -e " - SYNTAX: ${command_name} ${cyn:?}stack_name1${def:?} ${cyn:?}stack_name2${def:?} etc etc" 14 | echo -e " - SYNTAX: ${command_name} ${cyn:?}-option${def:?}" 15 | echo -e " - VALID OPTIONS:" 16 | echo -e " - ${cyn:?}-h │ --help ${def:?}| Displays this help message." 17 | echo -e " -" 18 | echo -e " - The below folder structure and files are created for each 'stack_name' entered with this command:" 19 | echo -e " - ${ylw:?}${docker_appdata}/${cyn:?}stack_name${mgn:?}/stack_name-logs.yml${def:?}" 20 | echo -e " - ${ylw:?}${docker_compose}/${cyn:?}stack_name${mgn}/${var_configs_file}${def:?}" 21 | echo 22 | exit 1 # Exit script after printing help 23 | } 24 | # case "$1" in ("-h"|*"help"*) fnc_help_folders_create ;; esac # disabled because this script handles both compose and swarm folder creation 25 | 26 | ## function definitions 27 | fnc_intro_folders_create(){ echo -e "${blu:?}[-> CREATE DOCKER FOLDER STRUCTURE FOR LISTED STACKS <-]${def:?}"; } 28 | fnc_outro_folders_create(){ echo -e "${grn:?} -> DOCKER CONFIGS FOLDER STRUCTURE AND FILES CREATED${def:?}"; echo; } 29 | fnc_invalid_syntax(){ echo -e "${ylw:?} >> INVALID OPTION SYNTAX, USE THE -${cyn:?}help${ylw:?} OPTION TO DISPLAY PROPER SYNTAX <<${def:?}"; exit 1; } 30 | fnc_nothing_to_do(){ echo -e "${ylw:?} -> This command requires a valid option followed by container name(s). Use ${cyn:?}-help${ylw:?} do display options. ${def:?}"; } 31 | fnc_create_folders(){ 32 | echo; exist=0; 33 | folder_list=("$@") 34 | for stack in "${folder_list[@]}"; do 35 | if [ ! -d "${appdata_folder}/${stack}" ]; 36 | then install -o "${var_uid}" -g "${var_gid}" -m 664 -d "${appdata_folder}/${stack}"; 37 | else echo -e " > ${cyn:?}${appdata_folder}${cyn:?}/${stack} ${ylw:?}ALREADY EXISTS ${def:?}"; exist=1; 38 | fi; 39 | if [ ! -d "${configs_folder}/${stack}" ]; 40 | then install -o "${var_uid}" -g "${var_gid}" -m 664 -d "${configs_folder}/${stack}"; 41 | else echo -e " > ${cyn:?}${configs_folder}${cyn:?}/${stack} ${ylw:?}ALREADY EXISTS ${def:?}"; exist=1; 42 | fi; 43 | [ "${exist}" == "0" ] && echo -e " > ${cyn:?}${stack} ${ylw:?}COMPOSE FOLDER SET ${grn:?}CREATED ${def:?}"; 44 | done 45 | } 46 | fnc_create_files(){ 47 | echo; exist=0; 48 | folder_list=("$@") 49 | for stack in "${folder_list[@]}"; do 50 | if [ ! -f "${appdata_folder}/${stack}/${stack}-logs.yml" ]; 51 | then install -o "${var_uid}" -g "${var_gid}" -m 660 /dev/null "${appdata_folder}/${stack}/${stack}-logs.yml"; 52 | else echo -e " > ${cyn:?}${appdata_folder}${cyn:?}/${stack} ${ylw:?}ALREADY EXISTS ${def:?}"; exist=1; 53 | fi; 54 | if [ ! -f "${configs_folder}/${stack}/${var_configs_file}" ]; 55 | then install -o "${var_uid}" -g "${var_gid}" -m 664 "${var_template_yaml}" "${configs_folder}/${stack}/${var_configs_file}"; 56 | else echo -e "${ylw:?} > ${cyn:?}${appdata_folder}/${cyn:?}${stack}/${var_configs_file} ${ylw:?}ALREADY EXISTS ${def:?}"; exist=1; 57 | fi; 58 | if [ ! -f "${configs_folder}/${stack}/.env" ]; 59 | then ln -sf "${var_script_vars}" "${configs_folder}/${stack}/.env" 60 | fi; 61 | [ "${exist}" == "0" ] && echo -e " > ${cyn:?}${stack} ${ylw:?}COMPOSE FOLDER SET ${grn:?}CREATED ${def:?}"; 62 | done 63 | } 64 | 65 | # output determination logic 66 | case "${1}" in 67 | ("") 68 | fnc_nothing_to_do 69 | ;; 70 | ("-"*) # validate and perform option 71 | case "${1}" in 72 | ("-c"|"-compose"|"--compose") 73 | echo "1='${1}', 2='${2}', all='${*}'" 74 | case "${2}" in 75 | ("-h"|*"-help"*) 76 | command_name="dcf" 77 | fnc_help_folders_create 78 | ;; 79 | esac 80 | appdata_folder="${docker_appdata}"; 81 | configs_folder="${docker_compose}"; 82 | fnc_create_folders "${*}"; 83 | fnc_create_files "${*}"; 84 | ;; 85 | ("-w"|"-swarm"|"--swarm") 86 | echo "1='${1}', 2='${2}', all='${*}'" 87 | case "${2}" in 88 | ("-h"|*"-help"*) 89 | command_name="dsf || dwf" 90 | fnc_help_folders_create 91 | ;; 92 | esac 93 | appdata_folder="${docker_appdata}"; 94 | configs_folder="${docker_swarm}"; 95 | fnc_create_folders "${*}"; 96 | fnc_create_files "${*}"; 97 | ;; 98 | (*) 99 | fnc_invalid_syntax 100 | ;; 101 | esac 102 | ;; 103 | esac 104 | 105 | # fnc_outro_folders_create -------------------------------------------------------------------------------- /docker_list_configs.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # external variable sources 4 | source /opt/docker/scripts/.color_codes.conf 5 | source /opt/docker/scripts/.vars_docker.env 6 | 7 | # script variable definitions 8 | unset configs_folder_list IFS 9 | unset configs_list IFS 10 | unset configs_path IFS 11 | 12 | # script help text 13 | fnc_help_list_configs(){ 14 | echo -e "${blu:?}[-> This script lists the existing 'stackname.yml' files in the ${ylw:?}../swarm/${blu:?} or ${ylw:?}../compose/${blu:?} folder structure. <-]${def:?}" 15 | echo -e " -" 16 | echo -e " - SYNTAX: # dlg ${cyn:?}-option${def:?}" 17 | echo -e " - SYNTAX: # dccfg | dcg == 'dlg ${cyn:?}--compose${def:?}'" 18 | echo -e " - SYNTAX: # dwcfg | dwg == 'dlg ${cyn:?}--swarm${def:?}'" 19 | echo -e " - VALID OPTIONS:" 20 | echo -e " - ${cyn:?}-h │ --help ${def:?}│ Displays this help message." 21 | echo -e " - ${cyn:?}-c │ --compose ${def:?}│ Displays stacks with config files in the ${ylw:?}..${docker_compose:-/opt/docker/compose}/${def:?} filepath." 22 | echo -e " - ${cyn:?}-w │ --swarm ${def:?}│ Displays stacks with config files in the ${ylw:?}..${docker_swarm:-/opt/docker/swarm}/${def:?} filepath." 23 | echo -e " -" 24 | echo -e " - NOTE: a valid option from above is required for this script to function" 25 | echo 26 | exit 1 # Exit script after printing help 27 | } 28 | case "$1" in ("-h"|*"help"*) fnc_help_list_configs ;; esac 29 | 30 | ## function definitions 31 | # intro message for script 32 | fnc_intro_list_configs(){ echo -e "${blu:?}[-> EXISTING DOCKER ${cyn:?}${conftype:?}${blu:?} CONFIG FILES IN ${ylw:?}${configs_path}/${blu:?} <-]${def:?}"; } 33 | # outro message for script 34 | fnc_outro_list_configs(){ 35 | # echo -e "[-- ${grn:?} DISPLAYED LIST OF CONFIG FILES IN ${ylw:?}${configs_path}/ ${def:?} --]"; 36 | echo; 37 | } 38 | # invalid syntax message 39 | fnc_invalid_syntax(){ echo -e "${ylw:?} >> INVALID OPTION SYNTAX, USE THE -${cyn:?}help${ylw:?} OPTION TO DISPLAY PROPER SYNTAX <<${def:?}"; exit 1; } 40 | # nothing to do message 41 | fnc_nothing_to_do(){ echo -e "${ylw:?} -> no configuration files exist${def:?}"; } 42 | # populate configs list array with docker config files in the '/opt/docker/${conftype}' folder 43 | fnc_list_config_folders(){ 44 | IFS=$'\n' configs_folder_list=( $(cd "${configs_path}" && find . -maxdepth 1 -type d -not -path '*/\.*' | sort | sed 's/^\.\///g') ); 45 | } 46 | # set script variables for Docker Compose configs 47 | fnc_type_compose(){ 48 | conftype="compose"; 49 | configs_path="${docker_compose:-/opt/docker/compose}"; 50 | source "${docker_compose}"/.stackslist-compose.conf; 51 | } 52 | # set script variables for Docker Swarm configs 53 | fnc_type_swarm(){ 54 | conftype="swarm"; 55 | configs_path="${docker_swarm:-/opt/docker/swarm}"; 56 | source "${docker_swarm}"/.stackslist-swarm.conf; 57 | } 58 | # clean up configs list array 59 | fnc_folder_list_cleanup(){ 60 | if [[ "${configs_folder_list[i]}" = "." ]]; then 61 | unset "configs_folder_list[i]"; 62 | fi; 63 | for i in "${!configs_folder_list[@]}"; do 64 | if [ i == "." ]; then unset "configs_folder_list[i]"; fi; 65 | done; 66 | } 67 | # populate the configs_list array 68 | fnc_list_config_files(){ 69 | if [[ -f "${configs_path}/${configs_folder_list[i]}/${var_configs_file:-compose.yml}" ]]; 70 | then configs_list="${configs_list} ${configs_folder_list[i]}"; 71 | fi; 72 | } 73 | fnc_display_config_files(){ 74 | # display config files list if any 75 | if [[ ! ${configs_list} ]]; then 76 | echo -e " -> ${ylw:?}no configuration files exist${def:?}"; 77 | else 78 | echo -e " ->${cyn:?}${configs_list[*]}${def:?}"; 79 | fi; 80 | echo; 81 | } 82 | 83 | # determine configuration type to query 84 | case "$1" in 85 | ("-h"|"-help"|"--help") 86 | fnc_help_list_configs 87 | ;; 88 | ("-c"|"--compose") 89 | fnc_type_compose 90 | fnc_intro_list_configs 91 | ;; 92 | ("-s"|"-w"|"--swarm") 93 | fnc_type_swarm 94 | fnc_intro_list_configs 95 | ;; 96 | (*) 97 | fnc_invalid_syntax 98 | ;; 99 | esac 100 | 101 | # common tasks for all config types 102 | fnc_list_config_folders 103 | # fnd_list_config_files 104 | fnc_display_config_files 105 | # fnc_outro_list_configs -------------------------------------------------------------------------------- /docker_list_container.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # external variable sources 3 | source /opt/docker/scripts/.color_codes.conf 4 | source /opt/docker/scripts/.vars_docker.env 5 | 6 | # function definitions 7 | fnc_help(){ 8 | echo -e "${blu:?}[-> This script lists current '${cyn:?}stacknames${blu:?}' and the number of '${cyn:?}services${blu:?}' in that stack <-]${def:?} " 9 | echo -e "${blu:?}[-> It will also list services inside a '${cyn:?}stacknames${blu:?}' when passing one of the below options <-]${def:?} " 10 | echo -e " -" 11 | echo -e " - SYNTAX: # dlc ${cyn:?}-option${def:?}" 12 | echo -e " - VALID OPTION(S):" 13 | echo -e " - ${cyn:?}-h │ -help ${def:?}| Displays this help message." 14 | echo -e " -" 15 | echo -e " - SYNTAX: # dlc │ Displays '${cyn:?}docker container ls' formatted for easy readability.${def:?}" 16 | echo -e " -" 17 | echo -e " - SYNTAX: # dlc ${cyn:?}stackname${def:?}" 18 | echo -e " - VALID OPTION(S):" 19 | echo -e " - ${cyn:?}-l │ -lbl │ --labels ${def:?}│ Displays '${cyn:?}docker container ls${def:?}' output with only 'Names' and 'Labels' columns." 20 | echo -e " - ${cyn:?}-n │ -net │ --network ${def:?}│ Displays '${cyn:?}docker container ls${def:?}' output with only 'Networks' and 'Ports' columns." 21 | echo -e " - ${cyn:?}-v │ -vol │ --volumes ${def:?}│ Displays '${cyn:?}docker container ls${def:?}' output with only 'Volumes' and 'Mounts' columns." 22 | echo -e " -" 23 | echo -e " - SYNTAX: # dlc ${cyn:?}stackname${def:?} ${cyn:?}-option${def:?}" 24 | echo -e " - VALID OPTION(S):" 25 | echo -e " - ${cyn:?}-l | --list ${def:?}| Displays '${cyn:?}docker container list --no-trunc ${cyn:?}stackname${def:?}' output with non-truncated entries and select columns." 26 | echo -e " - ${cyn:?}-s | --services ${def:?}| Displays '${cyn:?}docker container services ${cyn:?}stackname${def:?}' output with custom selected columns." 27 | echo 28 | exit 1 # Exit after printing help 29 | } 30 | case "$1" in ("-h"|*"help"*) fnc_help ;; esac 31 | fnc_script_intro(){ echo -e "${blu:?}[-> LIST OF CURRENT DOCKER CONTAINERS <-]${def:?} "; } 32 | fnc_script_error(){ echo -e "${blu:?}[-> LIST OF DOCKER CONTAINER ${red:?}ERRORS${blu:?} <-]${def:?} "; } 33 | fnc_nothing_to_do(){ echo -e "${ylw:?} -> no current docker containers exist${def:?}"; } 34 | fnc_invalid_syntax(){ echo -e "${ylw:?} >> INVALID OPTION SYNTAX, USE THE '--${cyn:?}help${ylw:?}' OPTION TO DISPLAY PROPER SYNTAX${def:?} <<"; exit 1; } 35 | fnc_container_list(){ docker container list -a -q; } 36 | fnc_error_check(){ docker container list --no-trunc --format "{{.Error}}" "${1}"; } 37 | fnc_list_container_act(){ docker container list --format "table {{.ID}} {{.Names}}\t{{.Status}}\t{{.Image}}\t{{.Command}}"; } 38 | fnc_list_container_all(){ docker container list --all --format "table {{.ID}} {{.Names}}\t{{.Status}}\t{{.RunningFor}}\t{{.Image}}"; } 39 | fnc_list_container_lbl(){ docker container list --no-trunc --format "table {{.Names}}\t{{.Status}}\t{{.Labels}}\t{{.Command}}"; } 40 | fnc_list_container_net(){ docker container list --no-trunc --format "table {{.Names}}\t{{.Status}}\t{{.Networks}}\t{{.Ports}}"; } 41 | fnc_list_container_vol(){ docker container list --no-trunc --format "table {{.Names}}\t{{.Status}}\t{{.LocalVolumes}}\t{{.Mounts}}"; } 42 | 43 | # output determination logic 44 | case "${1}" in 45 | ("") 46 | fnc_script_intro; 47 | if [ ! "$(fnc_container_list)" ]; then fnc_nothing_to_do; else fnc_list_container_act; fi ;; 48 | (-*) 49 | case "${1}" in 50 | ("-a"|"-all"|"--all") 51 | fnc_script_intro; fnc_list_container_all; 52 | ;; 53 | ("-l"|"-lbl"|"--labels") 54 | fnc_script_intro; fnc_list_container_lbl; 55 | ;; 56 | ("-n"|"-net"|"--network") 57 | fnc_script_intro; fnc_list_container_net; 58 | ;; 59 | ("-v"|"-vol"|"--volumes") 60 | fnc_script_intro; fnc_list_container_vol; 61 | ;; 62 | (*) 63 | fnc_invalid_syntax; 64 | ;; 65 | esac 66 | ;; 67 | (*) 68 | case "${2}" in 69 | ("") 70 | # if [ "$(fnc_error_check)" ]; then fnc_list_service_err "${1}" "${2}"; else fnc_list_service_act "${1}" "${2}"; fi 71 | if [ ! "$(fnc_error_check "${1}" "${2}")" ]; 72 | then fnc_script_intro; fnc_list_service_act "${1}" "${2}"; 73 | else fnc_script_error; fnc_list_service_err "${1}" "${2}"; 74 | fi 75 | ;; 76 | (-*) 77 | case "${2}" in 78 | ("-ls"|"--list") 79 | fnc_script_intro; fnc_list_container_err "${1}" "${2}"; 80 | ;; 81 | ("-sv"|"-svcs"|"--services") 82 | fnc_script_intro; fnc_list_container_act "${1}" "${2}"; 83 | ;; 84 | (*) 85 | fnc_invalid_syntax; 86 | ;; 87 | esac 88 | esac 89 | ;; 90 | esac 91 | echo 92 | 93 | # fnc_script_outro 94 | 95 | # to list possible --format tags, type 'docker command --format='{{json .}}'' 96 | 97 | # docker container --format='{{json .}}' 98 | # {{.Command}} 99 | # {{.CreatedAt}} 100 | # {{.ID}} 101 | # {{.Image}} 102 | # {{.Labels}} 103 | # {{.LocalVolumes}} 104 | # {{.Mounts}} 105 | # {{.Names}} 106 | # {{.Networks}} 107 | # {{.Ports}} 108 | # {{.RunningFor}} 109 | # {{.Size}} 110 | # {{.Status}} 111 | -------------------------------------------------------------------------------- /docker_list_stack.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # external variable sources 4 | source /opt/docker/scripts/.color_codes.conf 5 | source /opt/docker/scripts/.vars_docker.env 6 | 7 | # function definitions 8 | fnc_help(){ 9 | echo -e "${blu:?}[-> This script lists current '${cyn:?}stacknames${blu:?}' and the number of '${cyn:?}services${blu:?}' in that stack <-]${def:?} " 10 | echo -e "${blu:?} -> It will also list services inside a '${cyn:?}stacknames${blu:?}' when passing one of the below options <-]${def:?} " 11 | echo -e " -" 12 | echo -e " - SYNTAX: # dls ${cyn:?}stackname${def:?} │ this is the same as with '-sv' option" 13 | echo -e " - SYNTAX: # dls ${cyn:?}stackname${def:?} ${cyn:?}-option${def:?}" 14 | echo -e " - VALID OPTION(S):" 15 | echo -e " - ${cyn:?}-e | --errors${def:?} │ Displays '${cyn:?}docker stack ps --no-trunc ${cyn:?}stackname${def:?}' output with non-truncated entries and select columns." 16 | echo -e " - ${cyn:?}-s | --services${def:?} │ Displays '${cyn:?}docker stack services ${cyn:?}stackname${def:?}' output with custom selected columns." 17 | echo -e " -" 18 | echo -e " - SYNTAX: # dls ${cyn:?}-option${def:?}" 19 | echo -e " - VALID OPTION(S):" 20 | echo -e " - ${cyn:?}-h | --help${def:?} │ Displays this help message." 21 | echo 22 | exit 1 # Exit script after printing help 23 | } 24 | fnc_script_intro(){ echo -e "${blu:?}[-> LIST OF CURRENT DOCKER SWARM STACKS <-]${def:?} "; } 25 | fnc_script_error(){ echo -e "${blu:?}[-> LIST OF DOCKER SWARM STACK ${red:?}ERRORS${blu:?} <-]${def:?} "; } 26 | fnc_nothing_to_do(){ echo -e "${ylw:?} -> no current docker swarm stacks exist${def:?}"; } 27 | fnc_not_swarm_node(){ echo -e "${ylw:?} -> this docker node is not a swarm manager ${def:?}"; } 28 | fnc_invalid_syntax(){ echo -e "${ylw:?} >> INVALID OPTION SYNTAX, USE THE '${cyn:?}--help${ylw:?}' OPTION TO DISPLAY PROPER SYNTAX <<${def:?}"; } 29 | fnc_stack_lst(){ docker stack ls; } 30 | fnc_stack_svc(){ docker stack services "${1}" --format "table {{.ID}}\t{{.Name}}\t{{.Image}}\t{{.Ports}}"; } 31 | fnc_stack_err(){ docker stack ps --no-trunc --format "table {{.ID}}\t{{.Name}}\t{{.Node}}\t{{.CurrentState}}\t{{.Error}}" "${1}"; } 32 | fnc_stack_chk(){ docker stack ps --no-trunc --format "{{.Error}}" "${1}"; } 33 | 34 | # fnc_node_lst(){ docker node ps "$(docker node ls -q)" --format "table {{.Node}}\t{{.Name}}\t{{.CurrentState}}" --filter desired-state=Running | uniq; } 35 | 36 | # determine script output according to option entered 37 | case "${1}" in 38 | ("") 39 | fnc_script_intro; 40 | case "$(fnc_stack_lst)" in 41 | ("NAME SERVICES") 42 | fnc_nothing_to_do; 43 | ;; 44 | ("Error response from daemon: This node is not a swarm manager. Use \"docker swarm init\" or \"docker swarm join\" to connect this node to swarm and try again.") 45 | fnc_not_swarm_node; 46 | ;; 47 | (*) 48 | fnc_stack_lst; 49 | ;; 50 | esac 51 | ;; 52 | (-*) # confirm entered option is valid 53 | case "${1}" in 54 | ("-"|"-h"|"-help"|"--help") 55 | fnc_help 56 | ;; 57 | (*) 58 | fnc_invalid_syntax 59 | ;; 60 | esac 61 | ;; 62 | (*) 63 | case "${2}" in 64 | (-*) # confirm entered option is valid 65 | case "${2}" in 66 | ("-e"|"--errors") 67 | fnc_script_error; 68 | fnc_stack_err "${1}" "${2}"; 69 | ;; 70 | ("-s"|"--services") 71 | fnc_script_intro; 72 | fnc_stack_svc "${1}" "${2}"; 73 | ;; 74 | (*) 75 | fnc_invalid_syntax; 76 | ;; 77 | esac 78 | ;; 79 | (*) 80 | fnc_script_intro; 81 | case "$(fnc_stack_chk "${1}" "${2}")" in 82 | ("") 83 | fnc_stack_svc "${1}" "${2}"; 84 | ;; 85 | (*) 86 | fnc_stack_err "${1}" "${2}"; 87 | ;; 88 | esac 89 | ;; 90 | esac 91 | ;; 92 | esac 93 | echo 94 | 95 | # to list possible --format tags, type 'docker command --format='{{json .}}'' 96 | 97 | # docker stack services traefik --format='{{json .}}' 98 | # {{.ID}} 99 | # {{.Image}} 100 | # {{.Mode}} 101 | # {{.Name}} 102 | # {{.Ports}} 103 | # {{.Replicas}} 104 | 105 | # docker service ps traefik_app --format='{{json .}}' 106 | # {{.CurrentState}} 107 | # {{.DesiredState}} 108 | # {{.Error}} 109 | # {{.ID}} 110 | # {{.Image}} 111 | # {{.Name}} 112 | # {{.Node}} 113 | # {{.Ports}} 114 | 115 | # fnc_service_lst(){ docker service ps "${1}" --format "table {{.ID}}\t{{.Name}}\t{{.Image}}\t{{.Node}}\t{{.CurrentState}}"; } 116 | # fnc_service_err(){ docker service ps "${1}" --no-trunc --format "table {{.ID}}\t{{.Name}}\t{{.Node}}\t{{.CurrentState}}\t{{.Error}}"; } 117 | # fnc_container_lst(){ docker service ps --no-trunc --format "table {{.Node}}\t{{.ID}}\t{{.Names}}\t{{.Error}}" "${1}"; } 118 | # fnc_container_err(){ docker service ps --no-trunc --format "table {{.Node}}\t{{.ID}}\t{{.Names}}\t{{.Error}}" "${1}"; } 119 | -------------------------------------------------------------------------------- /docker_scripts_setup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # external variables used in this script 4 | red=$'\033[38;2;255;000;000m'; export red 5 | orn=$'\033[38;2;255;075;075m'; export orn 6 | ylw=$'\033[38;2;255;255;000m'; export ylw 7 | grn=$'\033[38;2;000;170;000m'; export grn 8 | cyn=$'\033[38;2;085;255;255m'; export cyn 9 | blu=$'\033[38;2;000;120;255m'; export blu 10 | prp=$'\033[38;2;085;085;255m'; export prp 11 | mgn=$'\033[38;2;255;085;255m'; export mgn 12 | wht=$'\033[38;2;255;255;255m'; export wht 13 | blk=$'\033[38;2;025;025;025m'; export blk 14 | def=$'\033[m'; export def 15 | 16 | # script help message check and display when called 17 | fnc_help_scripts_setup(){ 18 | echo -e "${blu:?}[-> This script installs Docker HomeLab scripts from 'https://www.gitlab.com/qnap-homelab/docker-scripts'. <-]${def:?}" 19 | echo -e " -" 20 | echo -e " - SYNTAX: # dsup" 21 | echo -e " - SYNTAX: # dsup ${cyn:?}-option${def:?}" 22 | echo -e " - VALID OPTIONS:" 23 | echo -e " - ${cyn:?}-h │ --help ${def:?}│ Displays this help message." 24 | # echo -e " - ${cyn:?}-o | --overwrite ${def:?}│ Does not prompt for overwrite of scripts if they already exist." 25 | echo 26 | exit 1 # Exit script after printing help 27 | } 28 | case "$1" in ("-h"|*"help"*) fnc_help_scripts_setup ;; esac 29 | 30 | ## function definitions 31 | fnc_intro_scripts_setup(){ echo; echo -e "${blu:?}[-> DOCKER HOMELAB TERMINAL SCRIPT INSTALLATION ${ylw:?}STARTING${blu:?} <-]${def:?}"; echo; } 32 | fnc_outro_scripts_setup(){ echo; echo -e "${blu:?}[-> DOCKER HOMELAB TERMINAL SCRIPT INSTALLATION ${grn:?}COMPLETE${blu:?} <-]${def:?}"; echo; } 33 | fnc_invalid_input(){ echo -e "${ylw:?}INVALID INPUT${def:?}: Must be any case-insensitive variation of '(Y)es' or '(N)o'."; } 34 | # fnc_invalid_syntax(){ echo -e "${ylw:?} >> INVALID OPTION SYNTAX, USE THE ${cyn:?}-help${ylw:?} OPTION TO DISPLAY PROPER SYNTAX <<${def:?}"; exit 1; } 35 | # fnc_nothing_to_do(){ echo -e " >> ${ylw:?}DOCKER HOMELAB FILES ALREADY EXIST, AND WILL NOT BE OVERWRITTEN${def:?} << "; echo; } 36 | fnc_check_sudo(){ 37 | ## check if user id is 0, if not, set var_sudo 38 | user_id=$(id -u) || { echo "Error getting user id"; exit 1; } 39 | if [[ $user_id -ne 0 ]]; 40 | then var_sudo="$(command -v sudo 2>/dev/null)"; 41 | else unset var_sudo; 42 | fi; 43 | } 44 | fnc_variable_input(){ 45 | unset docker_uid docker_gid exit_code 46 | docker_uid=$(id -u docker 2>/dev/null) || { echo "Error getting docker user id"; return 1; } 47 | docker_gid=$(id -g docker 2>/dev/null) || { echo "Error getting docker group id"; return 1; } 48 | ## ask user to input `docker_uid` and `docker_gid` with defaults of 1000 49 | # echo -e " Currently configured 'docker' user ID: ${orn:?}${docker_uid}${def:?} and docker group ID: ${orn:?}${docker_gid}${def}" 50 | while read -p " ${mgn:?}Confirm${def:?} the 'docker' user ID: ${orn:?}${docker_uid:-UNKNOWN}${def:?} and docker group ID: ${orn:?}${docker_gid:-UNKNOWN}${def}? [Y]es - continue / (N)o - manual entry : " input; do 51 | case "${input}" in 52 | [yY]|[yY][eE][sS]|"") 53 | break ;; 54 | [nN]|[nN][oO]) 55 | echo -e " If you want to set the UID and GID manually, enter below, otherwise enter 'n' to exit the script." 56 | read -p " Enter the UID of the docker user [1000]: " input_uid 57 | case "${input_uid}" in 58 | [nN]|[nN][oO]) 59 | exit_code=1 60 | break ;; 61 | "") 62 | docker_uid=1000 ;; 63 | *) 64 | if [[ ${input_uid} =~ ^[0-9]+$ ]]; 65 | then docker_uid="${input_uid}" 66 | else fnc_invalid_input 67 | fi ;; 68 | esac 69 | read -p " Enter the GID of the docker user [1000]: " input_gid 70 | case "${input_gid}" in 71 | [nN]|[nN][oO]) 72 | exit_code=1 73 | break ;; 74 | "") 75 | docker_gid=1000 ;; 76 | *) 77 | if [[ "${input_gid}" =~ ^[0-9]+$ ]] 78 | then docker_gid="${input_gid}" 79 | else fnc_invalid_input 80 | fi ;; 81 | esac ;; 82 | *) 83 | fnc_invalid_input ;; 84 | esac 85 | done; 86 | if [[ exit_code -eq 1 ]]; then 87 | echo -e "\n Look up the correct UID/GID with the '${cyn:?}id -u docker${def:?}' and '${cyn:?}id -g docker${def:?}' commands.\n" 88 | exit 1 89 | fi 90 | 91 | ## ask user to confirm the docker path, updates according to user input 92 | while read -p " Currently configured 'docker' directory is ${cyn:?}${docker_dir}${def:?} Is this correct? [Y]es / (N)o " input; do 93 | case "${input}" in 94 | [yY]|[yY][eE][sS]|"") 95 | break ;; 96 | [nN]|[nN][oO]) 97 | read -p " Enter the Docker directory [${docker_dir}]: " input_dkdir ;; 98 | *) 99 | fnc_invalid_input ;; 100 | esac 101 | done 102 | 103 | # docker subfolder path variables 104 | docker_dir="${input_dkdir:-$docker_dir}"; export docker_dir 105 | docker_folder="${docker_folder:-$HOME/docker}"; export docker_folder 106 | docker_appdata="${docker_folder}/appdata"; export docker_appdata 107 | docker_compose="${docker_folder}/compose"; export docker_compose 108 | docker_scripts="${docker_folder}/scripts"; export docker_scripts 109 | docker_secrets="${docker_folder}/secrets"; export docker_secrets 110 | docker_swarm="${docker_folder}/swarm"; export docker_swarm 111 | 112 | ## ask user to confirm media data path, updates according to user input 113 | while read -p " Currently configured Media (Data) path is ${cyn:?}${input_data:-$data_dir}${def:?} Is this correct? [Y]es / (N)o " input; do 114 | case "${input}" in 115 | [yY]|[yY][eE][sS]|"") 116 | break ;; 117 | [nN]|[nN][oO]) 118 | read -p " Enter the Media (Data) path [${data_dir}]: " input_data ;; 119 | *) 120 | fnc_invalid_input ;; 121 | esac 122 | done 123 | data_dir="${input_data:-$data_dir}"; export data_dir 124 | } 125 | fnc_create_directory(){ 126 | dir_path="${1}"; 127 | permissions="${2:-755}"; 128 | if [[ -z "${dir_path}" ]]; then 129 | echo -e " ${red:?}ERROR${def:?}: Missing required argument for 'fnc_create_directory' function."; return 1; 130 | fi 131 | if [[ ! -d "${dir_path}" ]]; then ${var_sudo:-} install -o "${docker_uid}" -g "${docker_gid}" -m "${permissions}" -d "${dir_path}"; fi 132 | } 133 | fnc_docker_dir_setup(){ 134 | # fnc_check_sudo 135 | 136 | ## folder and file permissions 137 | perms_cert='a-rwx,u=rwX,g=,o='; export perms_cert # 600 # -rw-rw---- 138 | perms_conf='a-rwx,u+rwX,g=rwX,o=rX'; export perms_conf # 664 # -rw-rw-r-- 139 | perms_data='a-rwx,u+rwX,g=rwX,o='; export perms_data # 660 # -rw-rw---- 140 | perms_main='a=rwX,o-w'; export perms_main # 775 # -rwxrwxr-x 141 | 142 | # if [[ ! -d "${docker_folder}" ]]; then 143 | # ${var_sudo:-} install -o "${docker_uid}" -g "${docker_gid}" -m 755 -d "${docker_folder}" 144 | # ${var_sudo:-} chmod g+s "${docker_folder}" 145 | # fi 146 | # if [[ ! -d "${docker_appdata}" ]]; then ${var_sudo:-} install -o "${docker_uid}" -g "${docker_gid}" -m 755 -d "${docker_appdata}"; fi 147 | # if [[ ! -d "${docker_compose}" ]]; then ${var_sudo:-} install -o "${docker_uid}" -g "${docker_gid}" -m 755 -d "${docker_compose}"; fi 148 | # if [[ ! -d "${docker_scripts}" ]]; then ${var_sudo:-} install -o "${docker_uid}" -g "${docker_gid}" -m 776 -d "${docker_scripts}"; fi 149 | # if [[ ! -d "${docker_secrets}" ]]; then ${var_sudo:-} install -o "${docker_uid}" -g "${docker_gid}" -m 660 -d "${docker_secrets}"; fi 150 | # if [[ ! -d "${docker_swarm}" ]]; then ${var_sudo:-} install -o "${docker_uid}" -g "${docker_gid}" -m 755 -d "${docker_swarm}"; fi 151 | fnc_create_directory "${docker_folder}" "${perms_main}" # 755 152 | ${var_sudo:-} chmod g+s "${docker_folder}" 153 | fnc_create_directory "${docker_appdata}" "${perms_data}" # 660 154 | fnc_create_directory "${docker_compose}" "${perms_conf}" # 664 155 | fnc_create_directory "${docker_swarm}" "${perms_conf}" # 664 156 | fnc_create_directory "${docker_scripts}" "${perms_main}" # 775 157 | fnc_create_directory "${docker_secrets}" "${perms_data}" # 660 158 | ## create symlink from $HOME/docker to $docker_folder 159 | if [[ ! -d "$HOME/docker" ]]; then ln -s "${docker_folder}" "$HOME/docker"; fi 160 | ## update the docker_dir variable in this script 161 | ${var_sudo:-} sed -i "s|docker_dir=/opt/docker|docker_dir=${docker_folder}|g" "${docker_scripts}/docker_scripts_setup.sh"; 162 | } 163 | fnc_download_scripts(){ 164 | # fnc_check_sudo 165 | # download all script files from the qnap-homelab repo to the $docker_scripts directory 166 | ${var_sudo:-} wget -qO - https://api.github.com/repos/qnap-homelab/docker-scripts/tarball/master | ${var_sudo:-} tar -xzf - -C "${docker_scripts}" --strip=1 167 | echo -e " ${grn:?}Successfully${def:?} downloaded docker helper scripts." 168 | 169 | # copy .vars_docker.example to .vars_docker.env 170 | ${var_sudo:-} install -o "${docker_uid}" -g "${docker_gid}" -m "${perms_conf}" "${docker_scripts}/.vars_docker.example" "${docker_scripts}/.vars_docker.env"; 171 | 172 | ## update .vars_docker.env with variables input or changed via user input in this script 173 | ${var_sudo:-} sed -i "s|var_uid=1000|var_uid=${docker_uid}|g" "${docker_scripts}/.vars_docker.env"; 174 | ${var_sudo:-} sed -i "s|var_gid=1000|var_gid=${docker_gid}|g" "${docker_scripts}/.vars_docker.env"; 175 | ${var_sudo:-} sed -i "s|data_dir=/mnt/data|data_dir=${data_dir}|g" "${docker_scripts}/.vars_docker.env"; 176 | ${var_sudo:-} sed -i "s|docker_dir=/opt/docker|docker_dir=${docker_dir}|g" "${docker_scripts}/.vars_docker.env"; 177 | 178 | # fix ownership of all files and folders inside $docker_scripts 179 | ${var_sudo:-} chown -R "${docker_uid}":"${docker_gid}" -R "${docker_scripts}"; 180 | } 181 | fnc_script_prep(){ 182 | ## get distribution common name 183 | var_distro="$(awk -F'=' '/^ID=/ { gsub("\"","",$2); print tolower($2) } ' /etc/*-release 2> /dev/null)" 184 | ## check for `docker` folder and link or create if not present 185 | case ${var_distro} in 186 | "qts"|"quts") 187 | unset exit_code 188 | if [[ ! -d "/share/docker" ]] ; then 189 | echo -e " ${red:?}ERROR${def:?}: You must first create the '${cyn:?}docker${def:?}' (${ylw:?}all lowercase${def:?}) Shared Folder in QTS before running this script." 190 | exit_code=1; 191 | fi 192 | if [[ ! -f "/opt/etc/profile" ]] ; then 193 | echo -e " ${red:?}ERROR${def:?}: You must install the '${cyn:?}entware-std${def:?}' from myqnap.org before running this script." 194 | exit_code=1; 195 | fi 196 | if [[ exit_code -eq 1 ]]; then exit 1; fi 197 | data_dir=/share/Multimedia 198 | docker_dir=/share/docker 199 | fnc_variable_input 200 | fnc_docker_dir_setup 201 | ## create symlink from docker_folder to /share/docker for qnap nas only 202 | if [[ -d "/share/docker" ]] && [[ ! -d "${docker_folder}" ]]; then ln -s "/share/docker" "${docker_folder}"; fi 203 | # [[ -d "${docker_folder}" ]] && ln -s "/share/docker" "${docker_folder}" 204 | ## check if /opt/etc/profile automatically loads docker scripts 205 | source="/opt/docker/scripts/docker_commands_list.sh"; 206 | line="[ -f ${source} ] && . ${source}"; 207 | file="/opt/etc/profile"; 208 | grep -qxF "${line}" "${file}" || echo "${line}" >> "${file}"; 209 | # ln -s "${file}" "${docker_scripts}"/.profile ## create a symlink to /opt/etc/profile 210 | ;; 211 | *) 212 | data_dir=/mnt/data 213 | docker_dir=/opt/docker 214 | fnc_variable_input 215 | fnc_docker_dir_setup 216 | ;; 217 | esac 218 | ## check if ~/.bashrc automatically loads docker scripts 219 | source="${docker_scripts}/docker_commands_list.sh"; 220 | line="[ -f ${source} ] && . ${source}"; 221 | file="$HOME/.bashrc"; 222 | grep -sqxF "${line}" "${file}" || echo "${line}" >> "${file}"; 223 | # create /opt/docker if not present 224 | if [ ! -d "${docker_folder}" ] ; then 225 | # fnc_check_sudo 226 | ${var_sudo:-} install -o "${docker_uid}" -g "${docker_gid}" -m 755 "${docker_folder}"; 227 | fi 228 | # ## create symlink from $HOME/docker to docker_folder 229 | # if [[ -d "${docker_folder}" ]] && [[ ! -d "$HOME/docker" ]]; then ln -s "${docker_folder}" "$HOME/docker"; fi 230 | } 231 | 232 | ## script intro message 233 | fnc_intro_scripts_setup 234 | 235 | ## script execution logic 236 | fnc_check_sudo 237 | fnc_script_prep 238 | fnc_download_scripts 239 | 240 | ## script completion message 241 | fnc_outro_scripts_setup 242 | -------------------------------------------------------------------------------- /docker_service_error.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # external variable sources 3 | source /opt/docker/scripts/.color_codes.conf 4 | source /opt/docker/scripts/.vars_docker.env 5 | 6 | # function definitions 7 | fnc_help(){ 8 | echo -e "${blu:?}[-> This script lists 'current state' for the indicated '${cyn:?}stackname_${cyn:?}servicename${blu:?}' <-]${def:?} " 9 | echo -e " -" 10 | echo -e " - SYNTAX: # dve ${cyn:?}-option${def:?}" 11 | echo -e " - VALID OPTION(S):" 12 | echo -e " - ${cyn:?}-h │ --help ${def:?}| Displays this help message." 13 | echo -e " -" 14 | echo -e " - SYNTAX: # dve ${cyn:?}appname${def:?}" 15 | echo -e " - SYNTAX: # dve ${cyn:?}appname${def:?} ${cyn:?}-option${def:?}" 16 | echo -e " - VALID OPTION(S):" 17 | echo -e " - ${cyn:?}-l │ --long ${def:?}| Displays '${cyn:?}docker service ps --no-trunk ${cyn:?}appname${def:?}' output with non-truncated entries." 18 | echo -e " -" 19 | echo -e " - NOTE: ${cyn:?}appname${def:?} MUST consist of '${cyn:?}stackname_${cyn:?}servicename${def:?}' as defined in the .yml file. ex: 'traefik_app' or 'traefik_whoami'" 20 | echo 21 | exit 1 # Exit script after printing help 22 | } 23 | fnc_invalid_syntax(){ echo -e "${ylw:?} >> INVALID OPTION SYNTAX, USE THE -${cyn:?}help${ylw:?} OPTION TO DISPLAY PROPER SYNTAX <<${def:?}"; exit 1; } 24 | fnc_service_basic(){ docker service ps "${1}"; } 25 | fnc_service_check(){ docker service ps "${1}" --format "{{.Error}}"; } 26 | fnc_service_short(){ docker service ps "${1}" --format "table {{.ID}}\t{{.Name}}\t{{.Node}}\t{{.CurrentState}}\t{{.Ports}}"; } 27 | fnc_service_error(){ docker service ps "${1}" --no-trunc --format "table {{.ID}}\t{{.Name}}\t{{.Node}}\t{{.CurrentState}}\t{{.Error}}"; } 28 | 29 | # determine script output according to option entered 30 | case "${1}" in 31 | (-*) 32 | case "${1}" in 33 | ("-h"|"-help"|"--help") fnc_help ;; 34 | (*) fnc_invalid_syntax ;; 35 | esac 36 | ;; 37 | (*) 38 | case "${2}" in 39 | ("-l"|"--long") fnc_service_basic "${1}" ;; 40 | (*) 41 | if [[ ! "$(fnc_service_check "${1}")" ]] 42 | then fnc_service_short "${1}" 43 | else fnc_service_error "${1}" 44 | fi 45 | ;; 46 | esac 47 | ;; 48 | esac 49 | -------------------------------------------------------------------------------- /docker_service_logs.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # external variable sources 3 | source /opt/docker/scripts/.color_codes.conf 4 | source /opt/docker/scripts/.vars_docker.env 5 | 6 | # function definitions 7 | fnc_help(){ 8 | echo -e "${blu:?}[-> This script lists logs for the indicated '${cyn:?}stackname_${cyn:?}servicename${blu:?}' <-]${def:?} " 9 | echo -e " -" 10 | echo -e " - SYNTAX: # dvl ${cyn:?}-option${def:?}" 11 | echo -e " - VALID OPTION(S):" 12 | echo -e " - ${cyn:?}-h │ --help ${def:?}| Displays this help message." 13 | echo -e " -" 14 | echo -e " - SYNTAX: # dvl ${cyn:?}appname${def:?}" 15 | echo -e " - SYNTAX: # dvl ${cyn:?}appname${def:?} ${cyn:?}-option${def:?}" 16 | echo -e " - VALID OPTION(S):" 17 | echo -e " - ${cyn:?}-l │ --long ${def:?}| Displays '${cyn:?}docker service ps --no-trunk ${cyn:?}appname${def:?}' output with non-truncated entries." 18 | echo 19 | echo -e " - NOTE: ${cyn:?}appname${def:?} MUST consist of '${cyn:?}stackname_${cyn:?}servicename${def:?}' as defined in the .yml file. ex: 'traefik_app' or 'traefik_whoami'" 20 | echo 21 | exit 1 # Exit script after printing help 22 | } 23 | fnc_invalid_syntax(){ echo -e "${ylw:?} >> INVALID OPTION SYNTAX, USE THE -${cyn:?}help${ylw:?} OPTION TO DISPLAY PROPER SYNTAX <<${def:?}"; exit 1; } 24 | fnc_service_logs(){ docker service logs "${1}"; } 25 | fnc_service_logs_long(){ docker service logs --no-trunc "${1}"; } 26 | 27 | # determine script output according to option entered 28 | case "${1}" in 29 | ("") fnc_invalid_syntax ;; 30 | (-*) 31 | case "${1}" in 32 | ("-h"|"-help"|"--help") fnc_help ;; 33 | (*) fnc_invalid_syntax ;; 34 | esac 35 | ;; 36 | (*) 37 | case "${2}" in 38 | ("-l"|"--long") fnc_service_logs_long "{$1}" ;; 39 | (*) fnc_service_logs "${1}" ;; 40 | esac 41 | ;; 42 | esac 43 | -------------------------------------------------------------------------------- /docker_stack_bounce.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # external variable sources 3 | source /opt/docker/scripts/.color_codes.conf 4 | source /opt/docker/scripts/.vars_docker.env 5 | # source /opt/docker/swarm/stackslist-swarm.conf 6 | 7 | # script variable definitions 8 | unset bounce_list IFS 9 | 10 | # function definitions 11 | fnc_help(){ 12 | echo -e "${blu:?}[-> This script bounces (removes then re-deploys) a single or pre-defined list of Docker Swarm stack <-]${def:?}" 13 | echo -e " -" 14 | echo -e " - SYNTAX: # dsb ${cyn:?}stack_name${def:?}" 15 | echo -e " - SYNTAX: # dsb ${cyn:?}-option${def:?}" 16 | echo -e " - VALID OPTIONS:" 17 | echo -e " - ${cyn:?}-a | --all ${def:?}│ Bounces all stacks with a corresponding folder inside the '${ylw:?}${docker_swarm}/${def:?}' path." 18 | echo -e " - ${cyn:?}-d | --default ${def:?}│ Bounces the 'default' array of stacks defined in '${ylw:?}${docker_secrets}/${cyn:?}stackslist-swarm.conf${def:?}'" 19 | echo -e " - ${cyn:?}-p | --preset ${def:?}│ Bounces the 'preset' array of stacks defined in '${ylw:?}${docker_secrets}/${cyn:?}stackslist-swarm.conf${def:?}'" 20 | echo -e " - ${cyn:?}-h │ --help ${def:?}│ Displays this help message." 21 | echo 22 | exit 1 # Exit script after printing help 23 | } 24 | fnc_script_intro(){ echo -e "${blu:?}[-> STOP THEN RESTART LISTED CONTAINERS <-]${def:?}"; echo -e "${cyn:?} -> ${bounce_list[*]} ${def:?}"; echo; } 25 | fnc_nothing_to_do(){ echo -e "${ylw:?} -> no containers exist to bounce${def:?}"; } 26 | fnc_invalid_syntax(){ echo -e "${ylw:?} >> INVALID OPTION SYNTAX, USE THE -${cyn:?}help${ylw:?} OPTION TO DISPLAY PROPER SYNTAX <<${def:?}"; exit 1; } 27 | fnc_list_all(){ IFS=$'\n'; bounce_list=( $(docker stack ls --format {{.Name}}) ); } 28 | fnc_list_preset(){ IFS=$'\n'; bounce_list=( "${stacks_preset[@]}" ); } 29 | fnc_list_default(){ IFS=$'\n'; bounce_list=( "${stacks_default[@]}" ); } 30 | fnc_docker_stack_stop(){ sh ${docker_scripts}/docker_stack_stop.sh "${bounce_list[@]}"; } 31 | fnc_docker_stack_start(){ sh ${docker_scripts}/docker_stack_start.sh "${bounce_list[@]}"; } 32 | fnc_script_outro(){ echo -e "[-- ${grn:?}BOUNCE (REMOVE & REDEPLOY) STACK SCRIPT COMPLETE${def:?} --]"; echo; } 33 | 34 | # determine script output according to option entered 35 | case "${1}" in 36 | (-*) 37 | case "${1}" in 38 | ("-h"|"-help"|"--help") fnc_help ;; 39 | ("-a"|"--all") fnc_list_all ;; 40 | ("-d"|"--default") fnc_list_default ;; 41 | ("-p"|"--preset") fnc_list_preset ;; 42 | (*) fnc_invalid_syntax ;; 43 | esac 44 | ;; 45 | (*) bounce_list=("$@") ;; 46 | esac 47 | 48 | # # display script intro 49 | # fnc_script_intro 50 | # remove all stacks in list defined above 51 | fnc_docker_stack_stop 52 | # wait 4 sec for ports to fall off assignment 53 | sleep 4 54 | # (re)deploy all stacks in list defined above 55 | fnc_docker_stack_start 56 | # # display script outro 57 | # fnc_script_outro -------------------------------------------------------------------------------- /docker_stack_folders.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # external variable sources 3 | source /opt/docker/scripts/.color_codes.conf 4 | source /opt/docker/scripts/.vars_docker.env 5 | 6 | # function definitions 7 | fnc_help(){ 8 | echo -e "${blu:?}[-> This script creates ${cyn:?}Drauku's${blu:?} folder structure for the listed stack(s). <-]${def:?}" 9 | echo -e " - ${blu:?}(modified from ${cyn:?}gkoerk's${blu:?} famously awesome folder structure for stacks.)${def:?}" 10 | echo -e " -" 11 | echo -e " - Enter up to nine(9) swarm_stacks in a single command, separated by a 'space' character: " 12 | echo -e " - SYNTAX: dsf ${cyn:?}swarm_stack1${def:?} ${cyn:?}swarm_stack2${def:?} ... ${cyn:?}swarm_stack9${def:?}" 13 | echo -e " - SYNTAX: dsf ${cyn:?}-option${def:?}" 14 | echo -e " - VALID OPTIONS:" 15 | # echo -e " - ${cyn:?}-d │ --delete ${def:?}│ ${red:?}Deletes${def:?} all sub-folders and files in ${ylw:?}${docker_appdata}/${cyn:?}swarm_stack${def:?} & ${ylw:?}${docker_swarm}/${cyn:?}swarm_stack${def:?}" 16 | # echo -e " - ${cyn:?}-r │ --reset ${def:?}│ ${red:?}Deletes${def:?} all files contained in ${ylw:?}${docker_appdata}/${cyn:?}swarm_stack${def:?}" 17 | echo -e " - ${cyn:?}-h │ --help ${def:?}│ Displays this help message." 18 | echo -e " -" 19 | echo -e " - NOTE: The below folder structure is created for each 'swarm_stack' entered with this command:" 20 | echo -e " - ${ylw:?}${docker_appdata}/${cyn:?}swarm_stack${def:?}" 21 | echo -e " - ${ylw:?}${docker_swarm}/${cyn:?}swarm_stack${def:?}" 22 | # echo -e " - ${ylw:?}${swarm_runtime}/${cyn:?}swarm_stack${def:?}" 23 | # echo -e " - ${ylw:?}/share/swarm/secrets/${cyn:?}swarm_stack${def:?}" 24 | echo 25 | exit 1 # Exit script after printing help 26 | } 27 | fnc_script_intro(){ echo -e "${blu:?}[-> CREATE DOCKER SWARM FOLDER STRUCTURE FOR LISTED STACKS <-]${def:?}"; } 28 | fnc_script_outro(){ echo -e "${grn:?} -> FOLDER STRUCTURE CREATED${def:?} FOR LISTED CONTAINERS: "; echo -e " -> ${cyn:?}$1, $2, $3, $4, $5, $6, $7, $8, $9 ${def:?}"; echo; } 29 | fnc_nothing_to_do(){ echo -e "${ylw:?} -> between 1 and 9 names must be entered for this command to work${def:?}"; exit 1; } 30 | fnc_invalid_syntax(){ echo -e "${ylw:?} >> INVALID OPTION SYNTAX, USE THE -${cyn:?}help${ylw:?} OPTION TO DISPLAY PROPER SYNTAX <<${def:?}"; exit 1; } 31 | fnc_folder_ownership_msg(){ echo -e " -> ${grn:?}FOLDER OWNERSHIP UPDATED ${def:?}"; echo; } 32 | fnc_folder_ownership_update(){ chown -R ${var_uid}:${var_gid} ${swarm_folder}; chmod 600 -c {$docker_appdata,$docker_swarm}/{$1,$2,$3,$4,$5,$6,$7,$8,$9}; } 33 | fnc_docker_appdata_folders(){ mkdir -p ${docker_appdata}/{$1,$2,$3,$4,$5,$6,$7,$8,$9}; } 34 | fnc_docker_swarm_folders(){ mkdir -p ${docker_swarm}/{$1,$2,$3,$4,$5,$6,$7,$8,$9}; } 35 | fnc_swarm_runtime_folders(){ mkdir -p ${swarm_runtime}/{$1,$2,$3,$4,$5,$6,$7,$8,$9}; } 36 | fnc_swarm_secrets_folders(){ mkdir -p ${swarm_secrets}/{$1,$2,$3,$4,$5,$6,$7,$8,$9}; } 37 | fnc_swarm_folders_create(){ mkdir -p {$docker_appdata,$docker_swarm}/{$1,$2,$3,$4,$5,$6,$7,$8,$9}; } 38 | fnc_swarm_delete_folders(){ rmdir {$docker_appdataa,$docker_swarm}/{$2,$3,$4,$5,$6,$7,$8,$9}; } 39 | fnc_swarm_delete_appdata(){ 40 | rm -i ${docker_appdata}/{$2,$3,$4,$5,$6,$7,$8,$9}; 41 | while read -r -p " - Also delete the ${ylw:?}${docker_appdata}/${cyn:?}swarm_stack${def:?} folder? [(Y)es/(N)o] " input; do 42 | case "${input}" in 43 | ([yY]|[yY][eE][sS]) fnc_swarm_delete_folders $2 $3 $4 $5 $6 $7 $8 $9 ;; 44 | ([nN]|[nN][oO]) break ;; 45 | (*) fnc_invalid_input ;; 46 | esac 47 | done; 48 | } 49 | fnc_swarm_delete_configs(){ 50 | rm -i {$docker_appdata,$docker_swarm}/{$2,$3,$4,$5,$6,$7,$8,$9}; 51 | while read -r -p " - Also delete the ${ylw:?}${docker_swarm}/${cyn:?}swarm_stack${def:?} folder? [(Y)es/(N)o] " input; do 52 | case "${input}" in 53 | ([yY]|[yY][eE][sS]) fnc_swarm_delete_folders $2 $3 $4 $5 $6 $7 $8 $9 ;; 54 | ([nN]|[nN][oO]) break ;; 55 | (*) fnc_invalid_input ;; 56 | esac 57 | done; 58 | } 59 | 60 | # output determination logic 61 | case "${1}" in 62 | ("") fnc_nothing_to_do ;; 63 | (-*) # validate and perform option 64 | case "${1}" in 65 | ("-h"|"-help"|"--help") 66 | fnc_help ;; 67 | ("-d"|"-del"|"--delete") 68 | fnc_swarm_delete_configs $2 $3 $4 $5 $6 $7 $8 $9 ;; 69 | ("-r"|"-res"|"--reset") 70 | fnc_swarm_delete_appdata $2 $3 $4 $5 $6 $7 $8 $9 ;; 71 | (*) 72 | fnc_invalid_syntax ;; 73 | esac 74 | ;; 75 | (*) 76 | case "${2}" in 77 | (-*) 78 | # tmpvar="${2}"; 2="${1}"; 1="${tmpvar}"; unset tmpvar IFS; 79 | tmp2="${2}"; set -- "${1}"; set -- "${tmp2}"; unset tmp2 IFS; 80 | case "${1}" in 81 | ("-h"|"-help"|"--help") 82 | fnc_help ;; 83 | ("-d"|"-del"|"--delete") 84 | fnc_swarm_delete_configs $2 $3 $4 $5 $6 $7 $8 $9 ;; 85 | ("-r"|"-res"|"--reset") 86 | fnc_swarm_delete_appdata $2 $3 $4 $5 $6 $7 $8 $9 ;; 87 | (*) 88 | fnc_invalid_syntax ;; 89 | esac 90 | fnc_swarm_folders_create $1 $2 $3 $4 $5 $6 $7 $8 $9 91 | # Create folder structure 92 | # fnc_swarm_appdata_folders $1 $2 $3 $4 $5 $6 $7 $8 $9 93 | # fnc_swarm_configs_folders $1 $2 $3 $4 $5 $6 $7 $8 $9 94 | # fnc_swarm_runtime_folders $1 $2 $3 $4 $5 $6 $7 $8 $9 # disabled due to not being used 95 | # fnc_swarm_secrets_folders $1 $2 $3 $4 $5 $6 $7 $8 $9 # disabled due to not being used 96 | # fnc_folder_ownership_update $1 $2 $3 $4 $5 $6 $7 $8 $9 97 | # fnc_folder_ownership_msg 98 | # fnc_script_outro 99 | esac 100 | ;; 101 | esac 102 | -------------------------------------------------------------------------------- /docker_stack_start.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # external variable sources 3 | source /opt/docker/scripts/.color_codes.conf 4 | source /opt/docker/scripts/.vars_docker.env 5 | # source /opt/docker/swarm/stackslist-swarm.conf 6 | 7 | # script variable definitions 8 | unset config_list IFS 9 | unset deploy_list IFS 10 | 11 | # function definitions 12 | fnc_help(){ 13 | echo -e "${blu:?}[-> This script deploys a single stack or a pre-defined list of Docker Swarm stack <-]${def:?}" 14 | echo -e " -" 15 | echo -e " - SYNTAX: # dsd ${cyn:?}stack_name${def:?}" 16 | echo -e " - SYNTAX: # dsd ${cyn:?}-option${def:?}" 17 | echo -e " - VALID OPTIONS:" 18 | echo -e " - ${cyn:?}-a │ --all ${def:?}│ Deploys all stacks with a corresponding .yml config file inside the '${ylw:?}${docker_swarm}/${def:?}' path." 19 | echo -e " - ${cyn:?}-d │ --default ${def:?}│ Deploys the '${cyn:?}default${def:?}' array of stacks defined in '${ylw:?}${docker_vars}/${cyn:?}swarm_stacks.conf${def:?}'" 20 | echo -e " - ${cyn:?}-p │ --preset ${def:?}│ Deploys the '${cyn:?}preset${def:?}' array of stacks defined in '${ylw:?}${docker_vars}/${cyn:?}swarm_stacks.conf${def:?}'" 21 | echo -e " - ${cyn:?}-h │ --help ${def:?}│ Displays this help message." 22 | echo 23 | exit 1 # Exit script after printing help 24 | } 25 | fnc_deploy_all(){ IFS=$'\n'; deploy_list=( $(cd "${docker_swarm}" && find -maxdepth 1 -type d -not -path '*/\.*' | sed 's/^\.\///g') ); } 26 | fnc_deploy_bounce(){ IFS=$'\n'; deploy_list=("${bounce_list[@]}"); } 27 | fnc_deploy_preset(){ IFS=$'\n'; deploy_list=("${stacks_preset[@]}"); } 28 | fnc_deploy_default(){ IFS=$'\n'; deploy_list=("${stacks_default[@]}"); } 29 | fnc_deploy_list_cleanup(){ 30 | if [[ ! "${bounce_list[*]}" ]]; then fnc_deploy_all 31 | for stack in "${!deploy_list[@]}"; do 32 | if [[ "${deploy_list[stack]}" = "." ]]; then unset deploy_list[stack]; fi 33 | if [[ -f "${docker_swarm}/${deploy_list[stack]}/${deploy_list[stack]}${conftype}.yml" ]]; then config_list="${config_list} ${deploy_list[stack]}"; fi 34 | done 35 | unset deploy_list IFS; IFS=$'\n'; deploy_list=("${config_list[@]}"); unset config_list IFS 36 | else fnc_deploy_bounce 37 | fi; 38 | } 39 | 40 | # determine script output according to option entered 41 | case "${1}" in 42 | (-*) 43 | case "${1}" in 44 | ("-h"|"-help"|"--help") 45 | fnc_help 46 | ;; 47 | ("-a"|"--all") 48 | if [[ "${bounce_list[*]}" = "" ]]; then 49 | IFS=$'\n'; deploy_list=( $(cd "${docker_swarm}" && find -maxdepth 1 -type d -not -path '*/\.*' | sed 's/^\.\///g') ); 50 | for stack in "${!deploy_list[@]}"; do 51 | if [[ "${deploy_list[stack]}" = "." ]]; then unset deploy_list[stack]; fi 52 | if [[ -f "${docker_swarm}/${deploy_list[stack]}/${deploy_list[stack]}${conftype}.yml" ]]; 53 | then config_list="${config_list} ${deploy_list[stack]}" 54 | fi 55 | done 56 | unset deploy_list IFS 57 | IFS=$'\n'; deploy_list=("${config_list[@]}"); 58 | unset config_list IFS 59 | else fnc_deploy_bounce 60 | fi 61 | ;; 62 | ("-p"|"--preset") 63 | fnc_deploy_preset 64 | ;; 65 | ("-d"|"--default") 66 | fnc_deploy_default 67 | ;; 68 | (*) 69 | echo -e "${ylw:?} >> INVALID OPTION SYNTAX -- USE THE -${cyn:?}help${ylw:?} OPTION TO DISPLAY PROPER SYNTAX <<${def:?}"; exit 1 ;; 70 | esac 71 | ;; 72 | (*) 73 | deploy_list=("$@") 74 | ;; 75 | esac 76 | 77 | # remove duplicate entries in deploy_list 78 | # echo -e "${blu:?}[-> DEPLOYING LISTED STACK(S) <-]${def:?}" 79 | deploy_list=(`for stack in "${deploy_list[@]}" ; do echo "${stack}" ; done | sort -u`) 80 | if [[ ! "$(docker network ls --filter name="${var_net_rproxy}" -q)" ]]; then 81 | docker network create --driver=overlay --subnet=${var_subnet_rproxy} --attachable ${var_net_rproxy} 82 | # Pause until 'network create' operation is finished 83 | while [[ ! "$(docker network ls --filter name=${var_net_rproxy} -q)" ]]; do sleep 1; done 84 | echo -e " -> '${cyn:?}${var_net_rproxy}${def:?}' OVERLAY NETWORK ${grn:?}CREATED${def:?}" 85 | echo 86 | fi 87 | 88 | # perform stack setup and deployment tasks 89 | for stack in "${deploy_list[@]}"; do 90 | # check if indicated stack configuration file exists, otherwise exit 91 | if [[ -f "${docker_swarm}/${stack}/${conftype}.yml" ]]; then 92 | # echo -e "${cyn:?} -> DEPLOY '${cyn:?}${stack}${cyn:?}' STACK <-${def:?}" 93 | # check if required folders exist, create if missing 94 | if [[ ! -d "${docker_appdata}/${stack}" || ! -d "${docker_swarm}/${stack}" ]]; then 95 | echo -e "Creating ${ylw:?}Required folders${def:?}" 96 | . "${docker_scripts}/docker_stack_folders.sh" "${stack}" 97 | fi 98 | # check for required traefik files, create if missing 99 | if [[ "${stack}" = [tT][rR][aA][eE][fF][iI][kK] ]]; then 100 | # create required letsencrypt certificate file if not already made 101 | if [[ ! -f "${docker_appdata}/traefik/acme.json" ]]; then 102 | echo -e "Creating ${ylw:?}Required cert file${def:?}" 103 | mkdir -p "${docker_appdata}/traefik" 104 | touch "${docker_appdata}/traefik/acme.json" 105 | chmod 600 "${docker_appdata}/traefik/acme.json" 106 | fi 107 | # check if required log files exist, create if missing 108 | if [[ ! -f "${docker_appdata}/${stack}/access.log" || ! -f "${docker_appdata}/${stack}/${stack}.log" ]]; then 109 | echo -e "Creating ${ylw:?}Required log file(s)${def:?}" 110 | touch "${docker_appdata}/${stack}/{access.log,${stack}.log"} 111 | chmod 600 "${docker_appdata}/${stack}/{access.log,${stack}.log"} 112 | fi 113 | fi 114 | # deploy the requested stack 115 | # docker stack deploy "${stack}" -c "${docker_swarm}/${stack}/${conftype}.yml" --prune 116 | docker stack deploy "${stack}" -c "${docker_swarm}/${stack}/${conftype}.yml" --prune 117 | sleep 1 118 | if [[ ! "$(docker service ls --filter name="${stack}" -q)" ]]; then 119 | echo -e " ${red:?}ERROR${def:?}: '${cyn:?}${stack}${def:?}' ${ylw:?}*NOT* DEPLOYED${def:?}"; echo 120 | else 121 | # Pause until stack is deployed 122 | while [ ! "$(docker service ls --filter label=com.docker.stack.namespace=$stack -q)" ]; 123 | do sleep 1; done 124 | echo -e "${grn:?} ++ '${cyn:?}$stack${grn:?}' STACK ${grn:?}DEPLOYED${grn:?} ++ ${def:?}"; echo 125 | fi 126 | else echo -e " ${red:?}ERROR${def:?}: '${cyn:?}${stack}${def:?}' ${ylw:?}CONFIG FILE DOES NOT EXIST${def:?}"; echo 127 | fi 128 | done 129 | 130 | # print script complete message 131 | # echo 132 | # echo -e "${grn:?}[>> STACK DEPLOY SCRIPT COMPLETE <<]${def:?}" 133 | # echo -------------------------------------------------------------------------------- /docker_stack_stop.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # external variable sources 3 | source /opt/docker/scripts/.color_codes.conf 4 | source /opt/docker/scripts/.vars_docker.env 5 | # source /opt/docker/swarm/.swarm_stacks.conf 6 | 7 | # script variable definitions 8 | unset remove_list IFS 9 | 10 | # function definitions 11 | fnc_help(){ 12 | echo -e "${blu:?}[-> This script removes a single or pre-defined list of Docker Swarm stack(s) <-]${def:?}" 13 | echo -e " -" 14 | echo -e " - SYNTAX: # dsr ${cyn:?}stack_name${def:?}" 15 | echo -e " - SYNTAX: # dsr ${cyn:?}-option${def:?}" 16 | echo -e " - VALID OPTIONS:" 17 | echo -e " - ${cyn:?}-a | --all ${def:?}│ ${ylw:?}CAUTION${def:?}: Removes ${BLD}all${def:?} stacks currently listed with 'docker stack ls' command." 18 | echo -e " - ${cyn:?}-d | --default ${def:?}│ Removes the '${cyn:?}default${def:?}' array of stacks defined in '${ylw:?}${docker_vars}/${cyn:?}swarm_stacks.conf${def:?}'" 19 | echo -e " - ${cyn:?}-p | --preset ${def:?}│ Removes the '${cyn:?}preset${def:?}' array of stacks defined in '${ylw:?}${docker_vars}/${cyn:?}swarm_stacks.conf${def:?}'" 20 | echo -e " - ${cyn:?}-h │ --help ${def:?}│ Displays this help message." 21 | echo 22 | exit 1 # Exit script after printing help 23 | } 24 | fnc_script_intro(){ echo -e "${blu:?}[-> REMOVE THE INDICATED DOCKER STACK(S) <-]${def:?}"; } 25 | fnc_script_outro(){ echo -e "${grn:?}[>> STACK REMOVE SCRIPT COMPLETE <<]${def:?}"; echo; } 26 | fnc_nothing_to_do(){ echo -e "${ylw:?} -> between 1 and 9 names must be entered for this command to work${def:?}"; exit 1; } 27 | fnc_invalid_syntax(){ echo -e "${ylw:?} >> INVALID OPTION SYNTAX, USE THE -${cyn:?}help${ylw:?} OPTION TO DISPLAY PROPER SYNTAX <<${def:?}"; exit 1; } 28 | 29 | # fnc_stack_remove_list(){ ; } 30 | 31 | fnc_docker_service_list(){ docker service ls --filter label=com.docker.stack.namespace=$stack -q; } 32 | fnc_docker_network_list(){ docker network ls --filter label=com.docker.stack.namespace=$stack -q; } 33 | 34 | fnc_msg_no_stacks(){ echo -e "${ylw:?} -> no docker stacks to remove${def:?}"; echo; } 35 | fnc_stack_remove_error(){ echo -e " ${red:?}ERROR: ${ylw:?}STACK NAME${def:?} '${cyn:?}$stack${def:?}' ${ylw:?}NOT FOUND${def:?} "; echo; } 36 | fnc_stack_remove_success(){ echo -e "${red:?} -- '${cyn:?}$stack${red:?}' STACK ${red:?}REMOVED${red:?} -- ${def:?}"; echo; } 37 | 38 | # determine script output according to option entered 39 | case "${1}" in 40 | (-*) 41 | case "${1}" in 42 | ("-h"|"-help"|"--help") fnc_help ;; 43 | ("-a"|"--all") IFS=$'\n'; remove_list=("$(docker stack ls --format {{.Name}})") ;; 44 | ("-d"|"--default") IFS=$'\n'; remove_list=("${stacks_default[@]}") ;; 45 | ("-p"|"--preset") IFS=$'\n'; remove_list=("${stacks_preset[@]}") ;; 46 | (*) fnc_invalid_syntax ;; 47 | esac 48 | ;; 49 | (*) remove_list=("$@") ;; 50 | esac 51 | 52 | # Remove indicated stacks 53 | # echo -e "${blu:?}[-> REMOVING LISTED STACK(S) <-]${def:?}" 54 | # de-duplicate and remove carriage returns in remove_list entries 55 | remove_list=(`for stack in "${remove_list[@]}"; do echo "${stack}"; done | sort -u`) 56 | # echo " -> ${remove_list[@]}"; echo 57 | 58 | # Remove indicated stack(s) 59 | if [[ ! "${remove_list}" ]] 60 | then fnc_msg_no_stacks 61 | else 62 | for stack in "${remove_list[@]}"; do 63 | if [ ! "$(fnc_docker_service_list)" ]; 64 | then fnc_stack_remove_error 65 | else # echo -e "${cyn:?} -> REMOVE '${cyn:?}$stack${cyn:?}' STACK <-${def:?}" 66 | docker stack rm "$stack" 67 | #[ -f "${docker_swarm}/${stack}/.env" ] && rm -f "${docker_swarm}/${stack}/.env" 68 | # Pause until stack is removed 69 | while [ "$(fnc_docker_service_list)" ] || [ "$(fnc_docker_network_list)" ] 70 | do sleep 1; 71 | done 72 | fnc_stack_remove_success 73 | fi 74 | done 75 | fi 76 | 77 | # fnc_script_outro -------------------------------------------------------------------------------- /docker_swarm_init.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # external variable sources 3 | source /opt/docker/scripts/.color_codes.conf 4 | source /opt/docker/scripts/.vars_docker.env 5 | 6 | # script variable definitions 7 | unset deploy_list IFS 8 | 9 | # function definitions 10 | fnc_help(){ 11 | echo -e "${blu:?}[-> This script performs Docker Swarm initialization tasks on QNAP Container Station architecture. <-]${def:?}" 12 | echo -e " -" 13 | echo -e " - SYNTAX: # dwinit" 14 | echo -e " - SYNTAX: # dwinit ${cyn:?}-option${def:?}" 15 | echo -e " - VALID OPTIONS:" 16 | echo -e " - ${cyn:?}stackname ${def:?}│ Creates the Docker Swarm, then deploys the '${cyn:?}stackname${def:?}' swarm stack if a config file exists." 17 | echo -e " - ${cyn:?}-a | --all ${def:?}│ Creates the Docker Swarm, then deploys all stacks with a corresponding folder inside the '${ylw:?}${docker_swarm}/${def:?}' path." 18 | echo -e " - ${cyn:?}-d | --default ${def:?}│ Creates the Docker Swarm, then deploys the 'default' array of stacks defined in '${ylw:?}${docker_vars}/${cyn:?}swarm_stacks.conf${def:?}'" 19 | echo -e " - ${cyn:?}-p | --preset ${def:?}│ Creates the Docker Swarm, then deploys the 'preset' array of stacks defined in '${ylw:?}${docker_vars}/${cyn:?}swarm_stacks.conf${def:?}'" 20 | echo -e " - ${cyn:?}-h │ --help ${def:?}│ Displays this help message." 21 | echo 22 | exit 1 # Exit script after printing help 23 | } 24 | fnc_script_intro(){ echo -e "${blu:?}[-> INITIALIZE DOCKER SWARM AND INSTALL INDICATED STACKS <-]${def:?}"; } 25 | fnc_script_outro(){ echo -e "${grn:?}[-> DOCKER SWARM INITIALIZATION SCRIPT COMPLETE <-]${def:?}"; echo; } 26 | fnc_invalid_input(){ echo -e "${ylw:?}INVALID INPUT${def:?}: Must be any case-insensitive variation of '(Y)es' or '(N)o'."; } 27 | fnc_invalid_syntax(){ echo -e "${ylw:?} >> INVALID OPTION SYNTAX, USE THE -${cyn:?}help${ylw:?} OPTION TO DISPLAY PROPER SYNTAX <<${def:?}"; exit 1; } 28 | fnc_nothing_to_do(){ echo -e " >> ${ylw:?}SWARM STACKS WILL NOT BE DEPLOYED${def:?} << "; echo; } 29 | fnc_deploy_query(){ echo -e "Do you want to deploy the '-${cyn:?}default${def:?}' list of Docker Swarm stacks?"; } 30 | fnc_deploy_stack(){ if [ ! "${deploy_list}" ] || [ "${deploy_list}" = "-n" ]; then fnc_nothing_to_do; else sh "${docker_scripts}"/docker_stack_start.sh "${deploy_list}"; fi; } 31 | fnc_traefik_query(){ echo -e " - Should ${cyn:?}traefik${def:?} still be installed (${ylw:?}recommended${def:?})?"; } 32 | fnc_folder_creation(){ if [[ ! -d "${docker_folder}/{scripts,secrets,swarm,compose}" ]]; then mkdir -pm 600 "${docker_folder}"/{scripts,secrets,swarm/{appdata,configs},compose/{appdata,configs}}; fi; } 33 | fnc_folder_owner(){ chown -R ${var_user}:${var_group} ${swarm_folder}; echo "FOLDER OWNERSHIP UPDATED"; echo; } 34 | fnc_folder_auth(){ chmod -R 600 ${swarm_folder}; echo "FOLDER PERMISSIONS UPDATED"; echo; } 35 | fnc_swarm_init(){ docker swarm init --advertise-addr "${var_host_ip}"; } 36 | fnc_swarm_verify(){ while [[ "$(docker stack ls)" != "NAME SERVICES ORCHESTRATOR" ]]; do sleep 1; done; } 37 | # fnc_swarm_check(){ while [[ ! "$(docker stack ls --format "{{.Name}}")" ]]; do sleep 1; done; } 38 | fnc_swarm_success(){ echo; echo -e " >> ${grn:?}DOCKER SWARM INITIALIZED SUCCESSFULLY${def:?} << "; echo; } 39 | fnc_swarm_error(){ 40 | docker network ls 41 | echo 42 | echo -e " >> THE ABOVE LIST MUST INCLUDE THE '${cyn:?}docker_gwbridge${def:?}' AND '${cyn:?}${var_net_rproxy}${def:?}' NETWORKS" 43 | echo -e " >> IF EITHER OF THOSE NETWORKS ARE NOT LISTED, YOU MUST LEAVE, THEN RE-INITIALIZE THE SWARM" 44 | echo -e " >> IF YOU HAVE ALREADY ATTEMPTED TO RE-INITIALIZE, ASK FOR HELP HERE: ${mgn:?} https://discord.gg/KekSYUE ${def:?}" 45 | echo 46 | echo -e " >> ${ylw:?}DOCKER SWARM STACKS WILL NOT BE DEPLOYED${def:?} << " 47 | echo 48 | echo -e " -- ${red:?}ERROR${def:?}: DOCKER SWARM SETUP WAS ${ylw:?}NOT SUCCESSFUL${def:?} -- " 49 | exit 1 # Exit script here 50 | } 51 | fnc_network_gwbridge(){ 52 | docker network rm docker_gwbridge 53 | docker network create --driver bridge --scope local --opt encrypted --subnet 172.20.0.0/16 --gateway 172.20.0.254 \ 54 | --opt com.docker.network.bridge.enable_icc=false \ 55 | --opt com.docker.network.bridge.enable_ip_masquerade=true \ 56 | --opt com.docker.network.bridge.name=docker_gwbridge \ 57 | docker_gwbridge 58 | } 59 | # docker network rm ingress 60 | # docker network create --driver overlay --opt encrypted --ingress --subnet 10.27.0.0/16 --gateway 10.27.0.254 ingress 61 | # docker network create --driver overlay --opt encrypted --scope swarm --subnet=172.27.0.0/16 --gateway=172.27.0.254 --attachable docker_socket 62 | # docker network create --driver overlay --opt encrypted --scope swarm --subnet=172.27.1.0/16 --gateway=172.27.1.254 --attachable external_edge 63 | # docker network create --driver overlay --opt encrypted --scope swarm --subnet=172.27.2.0/16 --gateway=172.27.2.254 --attachable reverse_proxy 64 | fnc_network_init(){ # copy fnc_network_check from docker/scripts/docker_system_network.sh 65 | docker network rm ingress && docker network create --driver overlay --opt encrypted --ingress --subnet "${var_subnet_ingress}" --gateway "${var_gateway_ingress}" ${var_net_ingress}; 66 | docker network create --driver overlay --opt encrypted --scope swarm --subnet "${var_subnet_socket}" --gateway "${var_gateway_socket}" --attachable "${var_net_socket}"; 67 | docker network create --driver overlay --opt encrypted --scope swarm --subnet "${var_subnet_rproxy}" --gateway "${var_gateway_rproxy}" --attachable "${var_net_rproxy}"; 68 | docker network create --driver overlay --opt encrypted --scope swarm --subnet "${var_subnet_exedge}" --gateway "${var_gateway_exedge}" --attachable "${var_net_exedge}"; 69 | } 70 | fnc_network_check_dockersocket(){ docker network ls --filter name="${var_net_socket}" -q; } 71 | fnc_network_check_proxynet(){ docker network ls --filter name="${var_net_rproxy}" -q; } 72 | fnc_network_check_gwbridge(){ docker network ls --filter name=docker_gwbridge -q; } 73 | fnc_network_verify(){ 74 | unset increment IFS; 75 | while [[ ! "$(fnc_network_check_proxynet)" ]] || [[ ! "$(fnc_network_check_gwbridge)" ]]; 76 | do sleep 1; 77 | increment=$((increment+1)); # should it be '$increment++'? 78 | if [[ $increment -gt 10 ]]; 79 | then fnc_swarm_error; 80 | fi; 81 | done; 82 | } 83 | fnc_network_success(){ echo; echo -e " ++ ${grn:?}CREATED '${cyn:?}docker_gwbridge${grn:?}' AND '${cyn:?}${var_net_rproxy}${grn:?}' NETWORKS${def:?} ++ "; } 84 | 85 | # fnc_script_intro 86 | 87 | # determine script output according to option entered 88 | case "${1}" in 89 | ("") fnc_deploy_query 90 | while read -r -p " [(Y)es/(N)o] " input; do 91 | case "${input}" in 92 | ([yY]|[yY][eE][sS]) deploy_list="--default"; break ;; 93 | ([nN]|[nN][oO]) fnc_traefik_query 94 | while read -r -p " [(Y)es/(N)o] " confirm; do 95 | case "${confirm}" in 96 | ([yY]|[yY][eE][sS]) deploy_list="traefik"; break ;; 97 | ([nN]|[nN][oO]) break ;; 98 | (*) fnc_invalid_input ;; 99 | esac 100 | done 101 | break ;; 102 | (*) fnc_invalid_input ;; 103 | esac 104 | done 105 | echo 106 | ;; 107 | (-*) # confirm entered option switch is valid 108 | case "${1}" in 109 | ("-h"|"-help"|"--help") fnc_help ;; 110 | ("-a"|"--all") deploy_list="${1}" ;; 111 | ("-d"|"--default") deploy_list="${1}" ;; 112 | ("-p"|"--preset") deploy_list="${1}" ;; 113 | ("-n"|"--none") deploy_list="-n" ;; 114 | (*) fnc_invalid_syntax ;; 115 | esac 116 | ;; 117 | (*) deploy_list=("$@") ;; 118 | esac 119 | 120 | fnc_folder_creation 121 | # fnc_folder_owner 122 | # fnc_folder_auth 123 | 124 | # must remove and recreate docker_gwbridge before swarm init to make it encrypted 125 | # fnc_network_gwbridge 126 | fnc_swarm_init 127 | fnc_swarm_verify 128 | 129 | fnc_network_init 130 | fnc_network_verify 131 | fnc_network_success 132 | 133 | fnc_swarm_success 134 | 135 | fnc_deploy_stack 136 | 137 | fnc_script_outro 138 | 139 | 140 | 141 | ## from docker_scripts_setup: 142 | 143 | 144 | # # Swarm initialization 145 | # #echo -e " -> INITIALIZING SWARM <- " 146 | # docker swarm init --advertise-addr "${var_host_ip}" 147 | 148 | # # Required networks creation verification 149 | # docker network create --driver=overlay --subnet=${var_subnet_rproxy} --attachable ${var_net_rproxy} 150 | # increment=0; # reset the increment variable 151 | # while [[ "$(docker network ls --filter name=traefik -q)" = "" ]] || [[ "$(docker network ls --filter name=gwbridge -q)" = "" ]]; do 152 | # sleep 1; 153 | # increment=$(($increment+1)); 154 | # if [[ $increment -gt 10 ]]; then # max 10 seconds wait for network to be created 155 | # docker network ls 156 | # echo 157 | # echo -e " ->> THE ABOVE LIST MUST INCLUDE THE '${cyn:?}docker_gwbridge${def:?}' AND '${cyn:?}traefik_public${def:?}' NETWORKS" 158 | # echo -e " ->> IF EITHER OF THOSE NETWORKS ARE NOT LISTED, YOU MUST LEAVE, THEN RE-INITIALIZE THE SWARM" 159 | # echo -e " ->> IF YOU HAVE ALREADY ATTEMPTED TO RE-INITIALIZE, ASK FOR HELP HERE: ${mgn:?} https://discord.gg/KekSYUE ${def:?}" 160 | # echo 161 | # echo -e " ->> ${ylw:?}DOCKER SWARM STACKS WILL NOT BE DEPLOYED${def:?} << " 162 | # echo 163 | # echo -e " --- ${red:?}ERROR${def:?}: DOCKER SWARM SETUP WAS ${ylw:?}NOT SUCCESSFUL${def:?} -- " 164 | # exit 1 # Exit script here 165 | # fi 166 | # done 167 | # # while [[ "$(docker network ls --filter name=traefik_public -q)" = "" ]]; do sleep 1; done 168 | # # while [[ "$(docker network ls --filter name=docker_gwbridge -q)" = "" ]]; do sleep 1; done 169 | # echo 170 | # echo -e " ++ '${cyn:?}docker_gwbridge${def:?}' AND '${cyn:?}traefik_public${def:?}' NETWORKS ${grn:?}CREATED${def:?} ++ " 171 | 172 | # # Pause until swarm is initialized 173 | # while [[ "$(docker stack ls)" != "NAME SERVICES" ]]; do sleep 1; done 174 | # echo 175 | # echo -e " >> ${grn:?}SWARM INITIALIZED${def:?} << " 176 | # echo 177 | 178 | # # Stack deployment 179 | # if [[ "$1" = "" ]]; then 180 | # case "${input}" in 181 | # ([yY]|[yY][eE][sS]) 182 | # . "${docker_scripts}"/docker_stack_start.sh -default 183 | # ;; 184 | # ([nN]|[nN][oO]) 185 | # case "${confirm}" in 186 | # ([yY]|[yY][eE][sS]) 187 | # . "${docker_scripts}"/docker_stack_start.sh traefik 188 | # ;; 189 | # (*) echo -e " >> ${ylw:?}DOCKER SWARM STACKS WILL NOT BE DEPLOYED${def:?} << " ;; 190 | # esac 191 | # ;; 192 | # esac 193 | # else 194 | # . "${docker_scripts}"/docker_stack_start.sh "$1" 195 | # fi 196 | 197 | 198 | # if [[ "$1" = "" ]] ; then 199 | # printf "Do you want to deploy the '-${cyn:?}default${def:?}' list of Docker Swarm stacks?"; read -r -p " [(Y)es/(N)o] " input 200 | # case $input in 201 | # ([yY]|[yY][eE][sS]) ;; 202 | # ([nN]|[nN][oO]) 203 | # # Query if Traefik should still be deployed 204 | # printf " - Should ${cyn:?}traefik${def:?} still be installed (${ylw:?}recommended${def:?})?"; read -r -p " [(Y)es/(N)o] " confirm 205 | # case $input in 206 | # ([yY]|[yY][eE][sS]) ;; 207 | # ([nN]|[nN][oO]) ;; 208 | # (*) echo -e "${ylw:?}INVALID INPUT${def:?}: Must be any case-insensitive variation of 'yes' or 'no'." ;; 209 | # esac 210 | # ;; 211 | # (*) echo -e "${ylw:?}INVALID INPUT${def:?}: Must be any case-insensitive variation of 'yes' or 'no'." ;; 212 | # esac 213 | # echo 214 | # fi 215 | 216 | -------------------------------------------------------------------------------- /docker_swarm_leave.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # external variable sources 3 | source /opt/docker/scripts/.color_codes.conf 4 | source /opt/docker/scripts/.vars_docker.env 5 | 6 | # function definitions 7 | fnc_help(){ 8 | echo -e "${blu:?}[-> This script leaves a Docker Swarm environment and removes a list of stacks on QNAP Container Station architecture. <-]${def:?}" 9 | echo -e " -" 10 | echo -e " - SYNTAX: # dwlv" 11 | echo -e " - SYNTAX: # dwlv ${cyn:?}-option${def:?}" 12 | echo -e " - VALID OPTIONS:" 13 | echo -e " - ${cyn:?}-a | --all ${def:?}│ ${ylw:?}CAUTION${def:?}: Removes ${BLD}all${def:?} stacks currently listed with ${cyn:?}'docker stack ls'${def:?} command, then laves the Swarm." 14 | echo -e " - ${cyn:?}-n | --none ${def:?}│ Leaves the Docker Swarm, but Does ${BLD}*NOT*${def:?} remove any currently deployed stacks." 15 | echo -e " - ${cyn:?}-h | --help ${def:?}│ Displays this help message." 16 | echo 17 | exit 1 # Exit script after printing help 18 | } 19 | fnc_script_intro(){ echo -e "${blu:?}[-> LEAVING THE DOCKER SWARM AND REMOVING INDICATED STACKS <-]${def:?}"; } 20 | fnc_script_outro(){ echo -e "${grn:?}[-> DOCKER SWARM LEAVE SCRIPT COMPLETE <-]${def:?}"; echo; } 21 | fnc_nothing_to_do(){ echo -e "${ylw:?}[-> THIS NODE IS NOT PART OF A SWARM, CANNOT LEAVE NON-EXISTENT SWARM <-]${def:?}"; echo; } 22 | fnc_invalid_input(){ echo -e "${ylw:?}INVALID INPUT${def:?}: Must be any case-insensitive variation of '(Y)es' or '(N)o'."; } 23 | fnc_invalid_syntax(){ echo -e "${ylw:?} >> INVALID OPTION SYNTAX, USE THE -${cyn:?}help${ylw:?} OPTION TO DISPLAY PROPER SYNTAX <<${def:?}"; exit 1; } 24 | fnc_remove_all_query(){ echo -e " Do you want to remove all Docker Swarm stacks (${ylw:?}highly recommended${def:?})? "; } 25 | fnc_msg_suggest_cleaning(){ echo -e "${ylw:?} >> CLEANING THE DOCKER ENVIRONMENT (${cyn:?}dprn${ylw:?}/${cyn:?}dcln${ylw:?}) AFTER LEAVING A SWARM IS RECOMMENDED <<${def:?}"; echo; } 26 | fnc_msg_stack_not_removed(){ echo -e " >> ${ylw:?}DOCKER SWARM STACKS WILL NOT BE REMOVED${def:?} << "; } 27 | fnc_swarm_check(){ if [[ "$(docker swarm leave -f)" == "Error response from daemon: This node is not part of a swarm" ]]; then fnc_nothing_to_do; exit 1; fi; } 28 | fnc_swarm_leave_force(){ docker swarm leave -f; echo; } 29 | fnc_docker_stack_stop(){ sh ${docker_scripts}/docker_stack_stop.sh -all; } 30 | fnc_docker_system_prune(){ sh ${docker_scripts}/docker_system_prune.sh --all; } 31 | fnc_docker_system_cleanup(){ if [[ "$input" = "yes" ]]; then fnc_docker_system_prune; else fnc_msg_suggest_cleaning; fi; } 32 | 33 | # determine script output according to option entered 34 | case "${1}" in 35 | ("") # fnc_script_intro 36 | # fnc_swarm_check 37 | fnc_remove_all_query 38 | while read -r -p " [(Y)es/(N)o] " input; do 39 | case "${input}" in 40 | ([yY]|[yY][eE][sS]) break ;; 41 | ([nN]|[nN][oO]) break ;; 42 | (*) fnc_invalid_input ;; 43 | esac 44 | done 45 | echo 46 | ;; 47 | (-*) # confirm entered option is valid 48 | case "${1}" in 49 | ("-h"|"-help"|"--help") fnc_help ;; 50 | ("-a"|"--all") input="yes" ;; 51 | ("-n"|"--none") input="no" ;; 52 | (*) fnc_invalid_syntax ;; 53 | esac 54 | ;; 55 | esac 56 | 57 | # Remove stacks if input is Yes 58 | case $input in 59 | ([yY][eE][sS]|[yY]) fnc_docker_stack_stop ;; 60 | ([nN][oO]|[nN]) fnc_msg_stack_not_removed ;; 61 | esac 62 | 63 | # Leave the swarm 64 | fnc_swarm_leave_force 65 | fnc_docker_system_cleanup 66 | fnc_script_outro 67 | -------------------------------------------------------------------------------- /docker_system_backup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # home\drauku\docker_backup.sh 3 | # USAGE: docker_backup.sh 4 | # DESCRIPTION: This script will create an archive of the local docker folders and copy it to a remote server. 5 | # AUTHOR: Drauku 6 | 7 | # SET THESE VARIABLES IN ADVANCE IF YOU DO NOT WANT TO ANSWER THE PROMPTS 8 | archive_target="" #"local" 9 | backup_path="" #"$docker_path/backup" 10 | server_ip="" #"192.168.1.150" 11 | username="" #"admin" 12 | 13 | query_docker_paths(){ # Query for the docker config file paths 14 | echo -e "\nThis script creates a docker folder archive and optionally copies the archive to a remote server." 15 | echo -e "NOTE: This host must be set up to use SSH keys with the remote host.\n" 16 | read -r -p "Enter the path to the docker config directory [~/.docker]: " docker_path 17 | docker_path=${docker_path:-~/.docker} 18 | } 19 | 20 | set_list_of_containers(){ # Set the list of containers to be stopped and backed up 21 | # Unset variable container_list 22 | unset container_list 23 | 24 | # Store the output of `docker container list` into `container_list` 25 | # TODO: determine which of these methods works best to populate `container_list` 26 | # IFS=$'\n' container_list=( $(docker container list --format "{{.Names}}") ) 27 | IFS=$'\n' read -r -a container_list <<< "$(docker container list --format "{{.Names}}")" 28 | # mapfile -t container_list < <(docker container list --format "{{.Names}}") 29 | # container_list=(); while IFS= read -r line; do container_list+=("$line"); done < <(docker container list --format "{{.Names}}") 30 | # container_list=(); docker container list --format "{{.Names}}" | while IFS= read -r line; do container_list+=("$line"); done 31 | 32 | # Verify the listed containers should be stopped, exit script if not 33 | # echo -e "The below list of containers are currently running:" 34 | echo -e "\n ${container_list[*]}\n" 35 | while read -r -p "Would you like to stop the above list of currently running containers? [y]es / (n)o " stop_answer; do 36 | case "$stop_answer" in 37 | [nN][oO]|[nN]) 38 | echo ">>> No changes made to the docker environment. Exiting script. <<>> Failed to create archive. Please verify adequate disk space. Starting containers back up. <<<" 86 | fi 87 | 88 | # start all containers 89 | if manage_containers start; then 90 | echo ">>> Successfully restarted containers. <<<" 91 | else 92 | echo -e "\n>>> Failed to restart containers. Please restart containers manually. <<<\n" 93 | return 1 94 | fi 95 | else 96 | echo -e "\n>>> Failed to stop containers. Please stop containers manually. <<<\n" 97 | return 1 98 | fi 99 | } 100 | 101 | 102 | # copy the archive to a remote server 103 | archive_copy_to_server(){ # USAGE: archive_copy_to_server 104 | if scp "$backup_path/docker-backup-$backup_date.tar.gz" "$username"@"$server_ip":"$backup_path"; then 105 | # remove the local copy of the archive if the scp task completed successfully 106 | rm "$backup_path/docker-backup-$backup_date.tar.gz" 107 | echo ">>> Successfully copied archive to remote server. <<<" 108 | else 109 | echo -e ">>> Failed to copy archive to remote server. <<<\n" 110 | fi 111 | } 112 | 113 | # script output logic 114 | 115 | # query for the docker config file paths 116 | [ -z "$docker_path" ] && query_docker_paths 117 | 118 | # Set the list of containers to be stopped and backed up 119 | set_list_of_containers 120 | 121 | # query for the destination IP 122 | [ -z "$archive_target" ] && query_backup_destination 123 | 124 | # create a tar archive from all docker config file directories 125 | archive_create 126 | 127 | # copy the archive to a remote server if desired 128 | [ -z "$archive_target" ] && archive_copy_to_server 129 | -------------------------------------------------------------------------------- /docker_system_clean.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # external variable sources 3 | source /opt/docker/scripts/.color_codes.conf 4 | source /opt/docker/scripts/.vars_docker.env 5 | 6 | # function definitions 7 | fnc_help_system_clean(){ 8 | echo -e "${blu:?}[-> This script cleans (removes) '${cyn:?}container${blu:?}' ${cyn:?}images${def:?}, ${cyn:?}volumes${def:?} and ${CUR}unused${def:?} ${cyn:?}networks${def:?} <-]${def:?} " 9 | echo -e " -" 10 | echo -e " - SYNTAX: # dclean" 11 | echo -e " - SYNTAX: # dclean ${cyn:?}-option${def:?}" 12 | echo -e " - VALID OPTION(S):" 13 | echo -e " - ${cyn:?}-a │ --all ${def:?}│ Stops all containers then removes all ${cyn:?}container${blu:?} ${cyn:?}images${def:?}, ${cyn:?}volumes${def:?} and ${cyn:?}networks${def:?}" 14 | echo -e " - ${cyn:?}-c │ --containers ${def:?}│ Stops all containers then removes all ${CUR}exited ${cyn:?}container${def:?}" 15 | echo -e " - ${cyn:?}-i │ --images ${def:?}│ Stops all containers then removes all ${CUR}dangling ${cyn:?}images${def:?}" 16 | echo -e " - ${cyn:?}-n │ --networks ${def:?}│ Stops all containers then removes all ${CUR}unused ${cyn:?}networks${def:?}" 17 | echo -e " - ${cyn:?}-v │ --volumes ${def:?}│ Stops all containers then removes all ${cyn:?}volumes${def:?}" 18 | echo -e " -" 19 | echo -e " - ${cyn:?}-h │ --help ${def:?}│ Displays this help message" 20 | echo 21 | exit 1 # Exit script after printing help 22 | } 23 | case "$1" in ("-h"|*"help"*) fnc_help_system_clean ;; esac 24 | 25 | fnc_script_intro(){ echo -e "${blu:?}[- ${ylw:?}STARTING${blu:?} CLEANUP OF THE DOCKER SYSTEM (CONTAINERS, IMAGES, VOLUMES, NETWORKS) -]${def:?}"; } 26 | fnc_script_outro(){ echo -e "${blu:?}[- DOCKER SYSTEM CLEANUP ${grn:?}COMPLETED${blu:?} -]${def:?}"; echo; } 27 | fnc_nothing_to_do(){ echo -e "${ylw:?} -> No cleanup to be done.${def:?}"; } 28 | fnc_invalid_syntax(){ echo -e "${ylw:?} >> INVALID OPTION SYNTAX, USE THE ${cyn:?}-help${ylw:?} OPTION TO DISPLAY PROPER SYNTAX <<${def:?}"; exit 1; } 29 | fnc_operation_message(){ echo -e "${blu:?}[-> REMOVE UNUSED DOCKER ${mgn:?}${operation_type}${def:?}"; } 30 | fnc_clean_volumes(){ 31 | fnc_operation_message; 32 | #docker volume ls -qf dangling=true | xargs -r docker volume rm; 33 | VOLUMES_DANGLING=$(docker volume ls -qf dangling=true); 34 | if [[ ! ${VOLUMES_DANGLING} = "" ]]; 35 | then docker volume rm ${VOLUMES_DANGLING}; 36 | else echo -e " - ${ylw:?}No dangling volumes to remove.${def:?}"; 37 | fi 38 | echo 39 | } 40 | fnc_clean_networks(){ 41 | fnc_operation_message; 42 | #docker network ls | grep "bridge"; 43 | NETWORKS_BRIDGED="$(docker network ls | grep "bridge" | awk '/ / { print $1 }')"; 44 | if [[ ! ${NETWORKS_BRIDGED} = "" ]]; 45 | then docker network rm ${NETWORKS_BRIDGED}; 46 | else echo -e " - No disconnected, bridged networks to remove."; 47 | fi 48 | echo 49 | } 50 | fnc_clean_images(){ 51 | fnc_operation_message; 52 | #docker images 53 | IMAGES_DANGLING=$(docker images --filter "dangling=true" -q --no-trunc); 54 | # IMAGES_DANGLING="$(docker images --filter "dangling=false" -q)"; 55 | if [[ ! ${IMAGES_DANGLING} = "" ]] 56 | then docker rmi ${IMAGES_DANGLING}; 57 | else echo -e " - ${ylw:?}No dangling images to remove.${def:?}"; 58 | fi 59 | #docker images | grep "none" 60 | IMAGES_NONE=$(docker images | grep "none" | awk '/ / { print $3 }'); 61 | if [[ ! ${IMAGES_NONE} = "" ]]; 62 | then docker rmi ${IMAGES_NONE}; 63 | else echo -e " - ${ylw:?}No unassigned images to remove.${def:?}"; 64 | fi 65 | echo 66 | } 67 | fnc_clean_containers(){ 68 | fnc_operation_message; 69 | #docker ps 70 | #docker ps -a 71 | CONTAINERS_EXITED=$(docker ps -qa --no-trunc --filter "status=exited"); 72 | if [[ ! ${CONTAINERS_EXITED} = "" ]]; 73 | then docker rm ${CONTAINERS_EXITED}; 74 | else echo -e " - ${ylw:?}No exited containers to remove.${def:?}"; 75 | fi 76 | echo 77 | } 78 | 79 | # option logic action determination 80 | case "${1}" in 81 | ("") 82 | fnc_invalid_syntax 83 | ;; 84 | (-*) # validate entered option exists 85 | # fnc_script_intro 86 | case "${1}" in 87 | ("-a"|"--all") 88 | operation_type="containers"; fnc_clean_containers 89 | operation_type="images"; fnc_clean_images 90 | # operation_type="networks"; fnc_clean_networks 91 | # operation_type="volumes"; fnc_clean_volumes 92 | ;; 93 | ("-c"|"--containers") 94 | operation_type="containers"; fnc_clean_containers 95 | ;; 96 | ("-i"|"--images") 97 | operation_type="images"; fnc_clean_images 98 | ;; 99 | ("-n"|"--networks") 100 | operation_type="networks"; fnc_clean_networks 101 | ;; 102 | ("-v"|"--volumes") 103 | operation_type="volumes"; fnc_clean_volumes 104 | ;; 105 | (*) 106 | fnc_invalid_syntax 107 | ;; 108 | esac 109 | ;; 110 | (*) 111 | fnc_invalid_syntax 112 | ;; 113 | esac 114 | 115 | fnc_script_outro -------------------------------------------------------------------------------- /docker_system_image.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # external variable sources 3 | source /opt/docker/scripts/.color_codes.conf 4 | source /opt/docker/scripts/.vars_docker.env 5 | 6 | # function definitions 7 | fnc_help(){ 8 | echo -e "${blu:?}[-> This script displays '${cyn:?}docker image${blu:?}' information. <-]${def:?} " 9 | echo -e " -" 10 | echo -e " - SYNTAX: # dimage" 11 | echo -e " - SYNTAX: # dimage ${cyn:?}-option${def:?}" 12 | echo -e " - VALID OPTION(S):" 13 | echo -e " - ${cyn:?}-a │ --all ${def:?}│ " 14 | echo -e " - ${cyn:?}-h │ --help ${def:?}│ Displays this help message" 15 | echo 16 | exit 1 # Exit script after printing help 17 | } 18 | -------------------------------------------------------------------------------- /docker_system_network.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # external variable sources 4 | source /opt/docker/scripts/.color_codes.conf 5 | source /opt/docker/scripts/.vars_docker.env 6 | 7 | # function definitions 8 | fnc_script_intro(){ echo -e "${blu:?}[-> LISTING CURRENT DOCKER NETWORKS <-]${def:?}";} 9 | fnc_script_outro(){ echo; exit 1; } 10 | fnc_help_system_clean(){ 11 | echo -e "${blu:?}[-> This script allows the user to manage docker ${cyn:?}networks${def:?} <-]${def:?} " 12 | echo -e " -" 13 | echo -e " - SYNTAX: # dyn" 14 | echo -e " - SYNTAX: # dyn ${cyn:?}-option${def:?}" 15 | echo -e " - VALID OPTION(S):" 16 | echo -e " - ${cyn:?}-h │ --help ${def:?}│ Displays this help message" 17 | fnc_script_outro 18 | } 19 | fnc_invalid_syntax(){ echo -e "${ylw:?} >> INVALID OPTION SYNTAX, USE THE '${cyn:?}--help${ylw:?}' OPTION TO DISPLAY PROPER SYNTAX${def:?} <<" && fnc_script_outro; } 20 | fnc_network_list(){ docker network ls; } 21 | fnc_network_check(){ docker network ls -q --filter name="$1"; } 22 | fnc_network_swarm_verify(){ 23 | unset increment IFS; 24 | while [[ ! "$(fnc_network_check "${var_net_socket}")" ]] || [[ ! "$(fnc_network_check "${var_net_rproxy}")" ]] || [[ ! "$(fnc_network_check "docker_gwbridge")" ]]; 25 | do sleep 1; 26 | increment=$((increment+1)); 27 | if [[ $increment -gt 10 ]]; 28 | then fnc_swarm_error; 29 | fi; 30 | done; 31 | } 32 | fnc_network_create(){ 33 | # if [ "${scope}" = "swarm" ] && [[ ! "$(fnc_network_check "ingress")" = "" ]]; then docker network rm ingress; fi; 34 | # if [ "${scope}" = "swarm" ]; then docker network create --ingress --driver "${driver}" --opt encrypted --subnet "10.0.0.0/16" --gateway "10.0.0.254" ingress; fi; 35 | # if [ "${scope}" = "local" ] && [[ ! "$(fnc_network_check "docker_gwbridge")" = "" ]]; then docker network rm "docker_gwbridge"; fi; 36 | case "${scope}" in 37 | "local") 38 | if [[ ! "$(fnc_network_check "docker_gwbridge")" = "" ]]; then docker network rm "docker_gwbridge"; fi; 39 | ;; 40 | "swarm") 41 | if [[ ! "$(fnc_network_check "ingress")" = "" ]]; then docker network rm ingress; fi; 42 | # docker network create --ingress --driver overlay --opt encrypted --subnet "10.27.0.0/16" --gateway "10.27.0.254" "ingress"; 43 | docker network create --ingress --driver overlay --opt encrypted --subnet "${var_subnet_ingress}" --gateway "${var_gateway_ingress}" "${var_net_ingress}"; 44 | ;; 45 | *) 46 | echo -e "${ylw:?} >> ERROR: ${red:?}INVALID NETWORK SCOPE${ylw:?} Please notify the script author <<${def:?}" && fnc_script_outro; 47 | ;; 48 | esac 49 | docker network create --scope "${scope}" --driver "${driver}" --opt encrypted --subnet "${var_subnet_exedge}" --gateway "${var_gateway_exedge}" --attachable "${var_net_exedge}"; 50 | docker network create --scope "${scope}" --driver "${driver}" --opt encrypted --subnet "${var_subnet_rproxy}" --gateway "${var_gateway_rproxy}" --attachable "${var_net_rproxy}"; 51 | docker network create --scope "${scope}" --driver "${driver}" --opt encrypted --subnet "${var_subnet_socket}" --gateway "${var_gateway_socket}" --attachable "${var_net_socket}"; 52 | unset "${scope}"; 53 | unset "${driver}"; 54 | echo -e "\n>> DOCKER NETWORK(s) ${grn:?}CREATED${def:?} <<" && fnc_script_outro; 55 | } 56 | fnc_network_remove(){ 57 | docker network rm "${*}"; 58 | } 59 | 60 | # output determination logic 61 | case "${1}" in 62 | (""|"-l"|"--list") 63 | fnc_script_intro; 64 | fnc_network_list; 65 | fnc_script_outro; 66 | ;; 67 | (-*) 68 | case "${1}" in 69 | ("-h"|"-help"|"--help") 70 | fnc_help_system_clean; 71 | ;; 72 | ("-c"|"--compose") 73 | driver="bridge" 74 | scope="local" 75 | fnc_network_create; 76 | ;; 77 | ("-d"|"-r"|"--delete"|"--remove") 78 | fnc_network_remove "${1}"; 79 | ;; 80 | ("-w"|"-s"|"--swarm") 81 | driver="overlay" 82 | scope="swarm" 83 | fnc_network_create; 84 | ;; 85 | (*) 86 | fnc_invalid_syntax; 87 | ;; 88 | esac 89 | ;; 90 | (*) 91 | fnc_invalid_syntax; 92 | ;; 93 | esac -------------------------------------------------------------------------------- /docker_system_prune.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # external variable sources 3 | source /opt/docker/scripts/.color_codes.conf 4 | source /opt/docker/scripts/.vars_docker.env 5 | 6 | # function definitions 7 | fnc_help(){ 8 | echo -e "${blu:?}[-> This script prunes (removes) '${cyn:?}container${blu:?}' ${cyn:?}images${def:?}, ${cyn:?}volumes${blu:?} and ${CUR}unused${def:?} ${cyn:?}networks${blu:?} <-]${def:?} " 9 | echo -e " -" 10 | echo -e " - SYNTAX: # dprn" 11 | echo -e " - SYNTAX: # dprn ${cyn:?}-option${def:?}" 12 | echo -e " - VALID OPTION(S):" 13 | echo -e " - ${cyn:?}-a │ --all ${def:?}│ Stops all containers then removes all '${cyn:?}container${blu:?}' ${cyn:?}images${def:?}, ${cyn:?}volumes${def:?} and ${CUR}unused${def:?} ${cyn:?}networks${def:?}" 14 | echo -e " - ${cyn:?}-h │ --help ${def:?}│ Displays this help message" 15 | echo 16 | exit 1 # Exit script after printing help 17 | } 18 | fnc_intro(){ echo -e "${blu:?}[-> PRUNING THE DOCKER SYSTEM <-]${def:?}"; } 19 | fnc_outro(){ echo -e "${grn:?}[-- DOCKER SYSTEM PRUNE COMPLETE --]${def:?}"; echo; } 20 | fnc_prune(){ docker system prune --all --force --volumes; } 21 | fnc_container_list(){ docker container ls --all --quiet; } 22 | fnc_container_stop(){ docker stop $(fnc_container_list); } 23 | fnc_invalid_syntax(){ echo -e "${ylw:?} >> INVALID OPTION SYNTAX, USE THE -${cyn:?}help${ylw:?} OPTION TO DISPLAY PROPER SYNTAX <<${def:?}"; exit 1; } 24 | fnc_invalid_input(){ echo -e "${ylw:?}INVALID INPUT${def:?}: Must be any case-insensitive variation of '(Y)es' or '(N)o'."; } 25 | fnc_nothing_to_do(){ echo -e " - ${ylw:?}nothing to prune from the docker environment${def:?}"; } 26 | fnc_query_remove_all(){ echo -e "Are you sure you want to ${red:?}STOP${def:?} and ${ylw:?}REMOVE${def:?} all containers?"; } 27 | 28 | # Script start notification 29 | fnc_intro 30 | 31 | # Script logic and execution 32 | case "${1}" in 33 | (-*) 34 | case "${1}" in 35 | ("-h"|"-help"|"--help") fnc_help ;; 36 | ("-a"|"--all") 37 | if [[ "$(fnc_container_list)" ]]; then 38 | fnc_query_remove_all 39 | while read -r -p " [(Y)es/(N)o] " input; do 40 | case "${input}" in 41 | ([yY]|[yY][eE][sS]) fnc_container_stop && echo && fnc_prune && break;; 42 | ([nN]|[nN][oO]) break ;; 43 | (*) fnc_invalid_input ;; 44 | esac 45 | done 46 | else fnc_nothing_to_do 47 | fi 48 | ;; 49 | (*) fnc_invalid_syntax ;; 50 | esac 51 | ;; 52 | (*) fnc_prune ;; 53 | esac 54 | 55 | # Script completion notice 56 | echo 57 | # fnc_outro -------------------------------------------------------------------------------- /docker_system_stats.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # external variable sources 3 | source /opt/docker/scripts/.color_codes.conf 4 | source /opt/docker/scripts/.vars_docker.env 5 | 6 | # function definitions 7 | fnc_help(){ 8 | echo -e "${blu:?}[-> This script displays system resources used by current docker stacks/containers. <-]${def:?} " 9 | echo -e " -" 10 | echo -e " - SYNTAX: # dls" 11 | echo -e " - SYNTAX: # dls ${cyn:?}-option${def:?}" 12 | echo -e " - VALID OPTION(S):" 13 | echo -e " - ${cyn:?}-l | --live ${def:?}│ Displays a live-updating resource usage table for current docker services." 14 | echo -e " - ${cyn:?}-p | --part ${def:?}│ Displays a resource usage table for current docker services." 15 | echo -e " - ${cyn:?}-h | --help ${def:?}│ Displays this help message." 16 | echo 17 | exit 1 # Exit script after printing help 18 | } 19 | fnc_invalid_syntax(){ echo -e "${ylw:?} >> INVALID OPTION SYNTAX, USE THE -${cyn:?}help${ylw:?} OPTION TO DISPLAY PROPER SYNTAX <<${def:?}"; exit 1; } 20 | fnc_stats_full(){ docker stats --format "table {{.Container}}\t{{.Name}}\t{{.CPUPerc}} {{.MemPerc}} {{.MemUsage}}\t{{.NetIO}}\t{{.BlockIO}}"; } 21 | fnc_stats_part(){ docker stats --format "table {{.Name}}\t{{.CPUPerc}} {{.MemPerc}}\t{{.MemUsage}}\t{{.NetIO}}"; } 22 | 23 | # determine script output according to option entered 24 | case "${1}" in 25 | ("") fnc_stats_part ;; 26 | (-*) 27 | case "${1}" in 28 | ("-h"|"-help"|"--help") fnc_help ;; 29 | ("-l"|"--live") fnc_stats_full ;; 30 | ("-p"|"--part") fnc_stats_part ;; 31 | (*) fnc_invalid_syntax ;; 32 | esac 33 | ;; 34 | (*) fnc_stats_full ;; 35 | esac 36 | -------------------------------------------------------------------------------- /docker_system_volume.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # external variable sources 3 | source /opt/docker/scripts/.color_codes.conf 4 | source /opt/docker/scripts/.vars_docker.env 5 | 6 | # function definitions 7 | fnc_help(){ 8 | echo -e "${blu:?}[-> This script lists all docker ${cyn:?}volumes${def:?} <-]${def:?} " 9 | echo -e " -" 10 | echo -e " - SYNTAX: # dlv" 11 | echo -e " - SYNTAX: # dlv ${cyn:?}-option${def:?}" 12 | echo -e " - VALID OPTION(S):" 13 | echo -e " - ${cyn:?}-h │ --help ${def:?}│ Displays this help message" 14 | echo 15 | exit 1 # Exit script after printing help 16 | } 17 | fnc_script_intro(){ echo -e "${blu:?}[-> LISTING UNUSED DOCKER VOLUMES <-]${def:?}";} 18 | fnc_script_outro(){ echo; } 19 | fnc_nothing_to_do(){ echo -e "${ylw:?} -> no volumes exist${def:?}"; } 20 | fnc_invalid_syntax(){ echo -e "${ylw:?} >> INVALID OPTION SYNTAX, USE THE '--${cyn:?}help${ylw:?}' OPTION TO DISPLAY PROPER SYNTAX${def:?} <<"; exit 1; } 21 | fnc_docker_volumes_check(){ docker volume ls -qf dangling=true; } 22 | fnc_docker_volumes_list(){ docker volume ls; } 23 | 24 | # output determination logic 25 | case "${1}" in 26 | ("") 27 | fnc_script_intro 28 | if [ "$(fnc_docker_volumes_check)" ] 29 | then fnc_docker_volumes_list 30 | else fnc_nothing_to_do 31 | fi 32 | fnc_script_outro 33 | ;; 34 | (-*) 35 | case "${1}" in 36 | ("-h"|"-help"|"--help") fnc_help ;; 37 | (*) fnc_invalid_syntax ;; 38 | esac 39 | esac 40 | --------------------------------------------------------------------------------