/
/
/
1#!/bin/bash
2# ==============================================================================
3# Docker Start All Script
4# ==============================================================================
5#
6# Description: Starts all connectivity Docker services in proper order
7# Usage: ./docker-start-all.sh [force|validate|quiet]
8#
9# This script is automatically generated by Ansible - DO NOT EDIT MANUALLY
10# Template: docker-start-all.sh.j2
11#
12# ==============================================================================
13
14set -euo pipefail
15
16# Configuration
17DOCKER_COMPOSE_DIR="{{ docker_base_path }}"
18LOG_FILE="/var/log/docker-start-all.log"
19STARTUP_DELAY={{ service_startup_delay | default(10) }}
20
21# Service startup order (dependency order)
22SERVICES=(
23 "{{ unbound_service_name }}"
24 "{{ pihole_service_name }}"
25 "{{ nginx_proxy_db_service_name }}"
26 "{{ nginx_proxy_service_name }}"
27 "{{ wireguard_service_name }}"
28)
29
30# Logging function
31log() {
32 if [[ "${1:-}" != "quiet" ]]; then
33 echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a "${LOG_FILE}"
34 else
35 echo "$(date '+%Y-%m-%d %H:%M:%S') - $2" >> "${LOG_FILE}"
36 fi
37}
38
39# Error handling function
40error_exit() {
41 log "ERROR: $1"
42 exit 1
43}
44
45# Check if container exists
46container_exists() {
47 docker inspect "$1" >/dev/null 2>&1
48}
49
50# Check if container is running
51container_running() {
52 docker inspect -f '{{.State.Running}}' "$1" 2>/dev/null | grep -q "true"
53}
54
55# Wait for container to become healthy
56wait_for_healthy() {
57 local container="$1"
58 local timeout="${2:-60}"
59 local start_time=$(date +%s)
60
61 log "Waiting for ${container} to become healthy (timeout: ${timeout}s)"
62
63 while [[ $(($(date +%s) - start_time)) -lt timeout ]]; do
64 if docker inspect -f '{{.State.Health.Status}}' "${container}" 2>/dev/null | grep -q "healthy"; then
65 log "${container} is healthy"
66 return 0
67 fi
68 sleep 5
69 done
70
71 log "WARNING: ${container} did not become healthy within ${timeout} seconds"
72 return 1
73}
74
75# Validate Docker environment
76validate_environment() {
77 log "Validating Docker environment"
78
79 # Check if Docker is running
80 if ! docker info >/dev/null 2>&1; then
81 error_exit "Docker daemon is not running"
82 fi
83
84 # Check if compose files exist
85 for service in "${SERVICES[@]}"; do
86 local compose_file="${DOCKER_COMPOSE_DIR}/${service}/docker-compose.yml"
87 if [[ ! -f "${compose_file}" ]]; then
88 log "WARNING: Compose file not found for ${service}: ${compose_file}"
89 fi
90 done
91
92 log "Environment validation completed"
93}
94
95# Start a specific service
96start_service() {
97 local service="$1"
98 local force="${2:-false}"
99
100 local compose_file="${DOCKER_COMPOSE_DIR}/${service}/docker-compose.yml"
101
102 if [[ ! -f "${compose_file}" ]]; then
103 log "WARNING: Compose file not found for ${service}, skipping"
104 return 1
105 fi
106
107 if container_running "${service}"; then
108 if [[ "${force}" == "true" ]]; then
109 log "Restarting ${service} (forced)"
110 docker-compose -f "${compose_file}" down --timeout 30 2>/dev/null || true
111 sleep 2
112 docker-compose -f "${compose_file}" up -d 2>/dev/null || true
113 else
114 log "${service} is already running, skipping"
115 return 0
116 fi
117 else
118 log "Starting ${service}"
119 docker-compose -f "${compose_file}" up -d 2>/dev/null || true
120 fi
121
122 # Wait for service to become healthy
123 wait_for_healthy "${service}" 60 || true
124
125 return 0
126}
127
128# Start all services in order
129start_all_services() {
130 local force="${1:-false}"
131 local quiet="${2:-false}"
132
133 log "Starting all connectivity services"
134
135 local started_count=0
136 local skipped_count=0
137 local failed_count=0
138
139 for service in "${SERVICES[@]}"; do
140 if start_service "${service}" "${force}" "${quiet}"; then
141 started_count=$((started_count + 1))
142 else
143 failed_count=$((failed_count + 1))
144 fi
145
146 # Add delay between service starts
147 if [[ ${STARTUP_DELAY} -gt 0 ]]; then
148 sleep ${STARTUP_DELAY}
149 fi
150 done
151
152 # Summary
153 log "Startup completed: ${started_count} services started, ${skipped_count} skipped, ${failed_count} failed"
154
155 if [[ ${failed_count} -gt 0 ]]; then
156 return 1
157 fi
158
159 return 0
160}
161
162# Show service status
163show_status() {
164 log "Current service status:"
165
166 for service in "${SERVICES[@]}"; do
167 if container_exists "${service}"; then
168 local status=$(docker inspect -f '{{.State.Status}}' "${service}" 2>/dev/null || echo "unknown")
169 local health=$(docker inspect -f '{{.State.Health.Status}}' "${service}" 2>/dev/null || echo "no healthcheck")
170 local restarts=$(docker inspect -f '{{.RestartCount}}' "${service}" 2>/dev/null || echo "0")
171
172 echo "${service}: status=${status}, health=${health}, restarts=${restarts}"
173 else
174 echo "${service}: does not exist"
175 fi
176 done
177}
178
179# Validate service dependencies
180validate_dependencies() {
181 log "Validating service dependencies"
182
183 # Check Unbound (DNS dependency)
184 if ! container_running "{{ unbound_service_name }}"; then
185 log "WARNING: Unbound is not running - DNS services may be affected"
186 fi
187
188 # Check database dependency
189 if ! container_running "{{ nginx_proxy_db_service_name }}"; then
190 log "WARNING: Database is not running - Nginx Proxy Manager may not function"
191 fi
192
193 log "Dependency validation completed"
194}
195
196# Show usage
197usage() {
198 cat << EOF
199Docker Start All Script
200
201Usage: $0 [option]
202
203Options:
204 force Force restart of all services (even if already running)
205 validate Validate environment and dependencies only
206 quiet Quiet mode (minimal output)
207 status Show current service status
208 help Show this help message
209
210Service Startup Order:
211 1. {{ unbound_service_name }} (DNS resolver)
212 2. {{ pihole_service_name }} (DNS/ad-blocker)
213 3. {{ nginx_proxy_db_service_name }} (Database)
214 4. {{ nginx_proxy_service_name }} (Reverse proxy)
215 5. {{ wireguard_service_name }} (VPN)
216
217Startup delay: ${STARTUP_DELAY} seconds between services
218EOF
219}
220
221# Main execution
222main() {
223 local option="${1:-}"
224
225 case "${option}" in
226 force)
227 validate_environment
228 start_all_services "true"
229 validate_dependencies
230 ;;
231 validate)
232 validate_environment
233 validate_dependencies
234 show_status
235 ;;
236 quiet)
237 validate_environment "quiet"
238 start_all_services "false" "quiet"
239 ;;
240 status)
241 show_status
242 ;;
243 help|*)
244 usage
245 ;;
246 esac
247}
248
249# Run main function with all arguments
250main "$@"