🚀 Release and Deploy Recipes
Reliable release and deployment processes are crucial for delivering software consistently and safely. This recipe provides patterns for automated deployments, version management, and rollback strategies.
🎯 Core Principles
Automated Deployment Pipeline
Build repeatable, automated deployment workflows with proper validation.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106 | #!/bin/bash
# deployment-pipeline.sh - Structured deployment framework
# Deployment configuration
DEPLOYMENT_CONFIG_DIR="/etc/deployments"
DEPLOYMENT_LOG_DIR="/var/log/deployments"
DEPLOYMENT_STATE_DIR="/var/lib/deployments"
DEPLOYMENT_LOCK_FILE="/var/run/deployment.lock"
# Deployment states
STATE_PENDING="pending"
STATE_DEPLOYING="deploying"
STATE_VERifying="verifying"
STATE_COMPLETED="completed"
STATE_FAILED="failed"
STATE_ROLLED_BACK="rolled_back"
# Initialize deployment environment
init_deployment() {
local deployment_name="$1"
# Create directories
mkdir -p "$DEPLOYMENT_LOG_DIR"
mkdir -p "$DEPLOYMENT_STATE_DIR"
# Set up logging
exec 3>&1 4>&2
exec 1>>"$DEPLOYMENT_LOG_DIR/${deployment_name}.log"
exec 2>&1
echo "[$(date)] Initializing deployment: $deployment_name"
}
# Deployment state management
get_deployment_state() {
local deployment_name="$1"
local state_file="$DEPLOYMENT_STATE_DIR/${deployment_name}.state"
if [ -f "$state_file" ]; then
cat "$state_file"
else
echo "$STATE_PENDING"
fi
}
set_deployment_state() {
local deployment_name="$1"
local state="$2"
local state_file="$DEPLOYMENT_STATE_DIR/${deployment_name}.state"
echo "$state" > "$state_file"
echo "[$(date)] Deployment $deployment_name state set to: $state"
}
# Lock management for concurrent execution prevention
acquire_deployment_lock() {
local deployment_name="$1"
if [ -f "$DEPLOYMENT_LOCK_FILE" ]; then
local existing_lock
existing_lock=$(cat "$DEPLOYMENT_LOCK_FILE")
echo "[$(date)] Deployment lock held by: $existing_lock" >&2
return 1
fi
echo "$deployment_name" > "$DEPLOYMENT_LOCK_FILE"
echo "[$(date)] Acquired deployment lock for: $deployment_name"
return 0
}
release_deployment_lock() {
local deployment_name="$1"
if [ -f "$DEPLOYMENT_LOCK_FILE" ]; then
local lock_holder
lock_holder=$(cat "$DEPLOYMENT_LOCK_FILE")
if [ "$lock_holder" = "$deployment_name" ]; then
rm -f "$DEPLOYMENT_LOCK_FILE"
echo "[$(date)] Released deployment lock for: $deployment_name"
else
echo "[$(date)] Warning: Attempted to release lock held by $lock_holder" >&2
fi
fi
}
# Version management
get_current_version() {
local service_name="$1"
local version_file="${2:-/etc/${service_name}/VERSION}"
if [ -f "$version_file" ]; then
cat "$version_file"
else
echo "0.0.0"
fi
}
set_current_version() {
local service_name="$1"
local version="$2"
local version_file="${3:-/etc/${service_name}/VERSION}"
echo "$version" > "$version_file"
echo "[$(date)] Set version for $service_name to: $version"
}
|
🔧 Application Deployment Patterns
Container-Based Deployment
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164 | # container-deployment.sh - Container deployment utilities
# Deploy Docker container with health checks
deploy_docker_container() {
local service_name="$1"
local image_name="$2"
local tag="$3"
local port_mapping="$4"
local env_file="$5"
local full_image="${image_name}:${tag}"
local container_name="${service_name}-${tag}-$(date +%s)"
echo "[$(date)] Deploying container: $container_name"
echo "[$(date)] Image: $full_image"
# Pull latest image
if ! docker pull "$full_image"; then
echo "[$(date)] Failed to pull image: $full_image" >&2
return 1
fi
# Stop existing container if running
if docker ps -q -f name="$service_name" | grep -q .; then
echo "[$(date)] Stopping existing container for $service_name"
docker stop "$service_name" 2>/dev/null || true
docker rm "$service_name" 2>/dev/null || true
fi
# Run new container
local docker_run_cmd="docker run -d --name $service_name"
# Add port mappings
if [ -n "$port_mapping" ]; then
IFS=',' read -ra ports <<< "$port_mapping"
for port in "${ports[@]}"; do
docker_run_cmd="$docker_run_cmd -p $port"
done
fi
# Add environment file
if [ -n "$env_file" ] && [ -f "$env_file" ]; then
docker_run_cmd="$docker_run_cmd --env-file $env_file"
fi
# Add health check
docker_run_cmd="$docker_run_cmd --health-cmd='curl -f http://localhost:8080/health || exit 1' --health-interval=30s --health-timeout=10s --health-retries=3"
# Add restart policy
docker_run_cmd="$docker_run_cmd --restart=unless-stopped"
# Add image
docker_run_cmd="$docker_run_cmd $full_image"
# Execute docker run
if eval "$docker_run_cmd"; then
echo "[$(date)] Container deployed successfully: $container_name"
# Wait for container to be healthy
if wait_for_container_healthy "$service_name" 300; then
echo "[$(date)] Container is healthy: $service_name"
return 0
else
echo "[$(date)] Container failed health check: $service_name" >&2
docker logs "$service_name" >&2
return 1
fi
else
echo "[$(date)] Failed to deploy container: $container_name" >&2
return 1
fi
}
# Wait for container to become healthy
wait_for_container_healthy() {
local container_name="$1"
local timeout="${2:-300}"
local count=0
while [ $count -lt $timeout ]; do
local status
status=$(docker inspect --format='{{.State.Health.Status}}' "$container_name" 2>/dev/null || echo "unknown")
case "$status" in
healthy)
return 0
;;
unhealthy)
return 1
;;
*)
# Still starting or unknown
sleep 1
count=$((count + 1))
;;
esac
done
echo "[$(date)] Timeout waiting for container to become healthy: $container_name" >&2
return 1
}
# Rolling update for container services
rolling_update_containers() {
local service_name="$1"
local image_name="$2"
local new_tag="$3"
local replicas="${4:-3}"
local delay="${5:-30}"
echo "[$(date)] Starting rolling update for $service_name"
echo "[$(date)] New image: ${image_name}:${new_tag}"
echo "[$(date)] Replicas: $replicas"
# Pull new image
if ! docker pull "${image_name}:${new_tag}"; then
echo "[$(date)] Failed to pull new image" >&2
return 1
fi
# Update containers one by one
for i in $(seq 1 $replicas); do
echo "[$(date)] Updating replica $i/$replicas"
# Stop and remove current container
if docker ps -q -f name="${service_name}-$i" | grep -q .; then
docker stop "${service_name}-$i" 2>/dev/null || true
docker rm "${service_name}-$i" 2>/dev/null || true
fi
# Start new container
if ! docker run -d \
--name "${service_name}-$i" \
--health-cmd='curl -f http://localhost:8080/health || exit 1' \
--health-interval=30s \
--health-timeout=10s \
--health-retries=3 \
--restart=unless-stopped \
-p "808$i:8080" \
"${image_name}:${new_tag}"; then
echo "[$(date)] Failed to start new container for replica $i" >&2
return 1
fi
# Wait for container to be healthy
if ! wait_for_container_healthy "${service_name}-$i" 120; then
echo "[$(date)] New container failed health check for replica $i" >&2
docker logs "${service_name}-$i" >&2
return 1
fi
echo "[$(date)] Replica $i updated successfully"
# Delay before updating next replica (unless it's the last one)
if [ $i -lt $replicas ]; then
echo "[$(date)] Waiting $delay seconds before updating next replica"
sleep $delay
fi
done
echo "[$(date)] Rolling update completed successfully"
return 0
}
|
📦 Package-Based Deployment
System Package Deployment
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210 | # package-deployment.sh - System package deployment utilities
# Deploy RPM/DEB packages with dependency management
deploy_system_packages() {
local packages=("$@")
echo "[$(date)] Deploying system packages: ${packages[*]}"
# Detect package manager
if command -v apt-get >/dev/null 2>&1; then
deploy_debian_packages "${packages[@]}"
elif command -v yum >/dev/null 2>&1; then
deploy_redhat_packages "${packages[@]}"
elif command -v pacman >/dev/null 2>&1; then
deploy_arch_packages "${packages[@]}"
else
echo "[$(date)] Unsupported package manager" >&2
return 1
fi
}
deploy_debian_packages() {
local packages=("$@")
# Update package cache
if ! apt-get update; then
echo "[$(date)] Failed to update package cache" >&2
return 1
fi
# Install packages with automatic dependency resolution
if ! apt-get install -y "${packages[@]}"; then
echo "[$(date)] Failed to install packages: ${packages[*]}" >&2
return 1
fi
echo "[$(date)] Debian packages deployed successfully"
return 0
}
deploy_redhat_packages() {
local packages=("$@")
# Update package cache
if ! yum makecache; then
echo "[$(date)] Failed to update package cache" >&2
return 1
fi
# Install packages with automatic dependency resolution
if ! yum install -y "${packages[@]}"; then
echo "[$(date)] Failed to install packages: ${packages[*]}" >&2
return 1
fi
echo "[$(date)] RedHat packages deployed successfully"
return 0
}
deploy_arch_packages() {
local packages=("$@")
# Update package cache
if ! pacman -Sy; then
echo "[$(date)] Failed to update package cache" >&2
return 1
fi
# Install packages with automatic dependency resolution
if ! pacman -S --noconfirm "${packages[@]}"; then
echo "[$(date)] Failed to install packages: ${packages[*]}" >&2
return 1
fi
echo "[$(date)] Arch packages deployed successfully"
return 0
}
# Deploy application packages with configuration management
deploy_application_package() {
local package_file="$1"
local config_dir="$2"
local service_name="$3"
echo "[$(date)] Deploying application package: $package_file"
# Backup current configuration
local backup_dir="/tmp/config_backup_$(date +%s)"
if [ -d "$config_dir" ]; then
echo "[$(date)] Backing up current configuration"
cp -r "$config_dir" "$backup_dir"
fi
# Install package
if [[ "$package_file" == *.deb ]]; then
if ! dpkg -i "$package_file"; then
echo "[$(date)] Failed to install DEB package" >&2
# Restore configuration backup
if [ -d "$backup_dir" ]; then
cp -r "$backup_dir"/* "$config_dir"/
fi
return 1
fi
elif [[ "$package_file" == *.rpm ]]; then
if ! rpm -Uvh "$package_file"; then
echo "[$(date)] Failed to install RPM package" >&2
# Restore configuration backup
if [ -d "$backup_dir" ]; then
cp -r "$backup_dir"/* "$config_dir"/
fi
return 1
fi
else
echo "[$(date)] Unsupported package format: $package_file" >&2
return 1
fi
# Post-installation configuration
if [ -n "$config_dir" ] && [ -d "$config_dir" ]; then
echo "[$(date)] Applying post-installation configuration"
apply_post_install_config "$config_dir" "$service_name"
fi
# Start service
if [ -n "$service_name" ]; then
echo "[$(date)] Starting service: $service_name"
if ! systemctl restart "$service_name"; then
echo "[$(date)] Failed to start service: $service_name" >&2
return 1
fi
# Wait for service to be ready
if ! wait_for_service_ready "$service_name" 120; then
echo "[$(date)] Service failed to become ready: $service_name" >&2
return 1
fi
fi
echo "[$(date)] Application package deployed successfully"
return 0
}
# Apply post-installation configuration
apply_post_install_config() {
local config_dir="$1"
local service_name="$2"
# Apply configuration templates
find "$config_dir" -name "*.template" | while read -r template; do
local config_file
config_file="${template%.template}"
echo "[$(date)] Applying configuration template: $template"
# Process template with environment variables
envsubst < "$template" > "$config_file"
# Set appropriate permissions
chmod 644 "$config_file"
done
# Reload service configuration
if [ -n "$service_name" ]; then
systemctl reload "$service_name" 2>/dev/null || true
fi
}
# Wait for service to be ready
wait_for_service_ready() {
local service_name="$1"
local timeout="${2:-120}"
local count=0
while [ $count -lt $timeout ]; do
if systemctl is-active --quiet "$service_name"; then
# Service is active, check if it's responding
if check_service_health "$service_name"; then
return 0
fi
fi
sleep 1
count=$((count + 1))
done
echo "[$(date)] Timeout waiting for service to be ready: $service_name" >&2
return 1
}
# Check service health
check_service_health() {
local service_name="$1"
# Check service-specific health endpoint or status
case "$service_name" in
nginx)
curl -sf http://localhost/nginx_status >/dev/null 2>&1
;;
postgresql)
pg_isready >/dev/null 2>&1
;;
redis)
redis-cli ping >/dev/null 2>&1
;;
*)
# Generic health check
systemctl is-active --quiet "$service_name"
;;
esac
}
|
🔄 Deployment Verification
Post-Deployment Validation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187 | # deployment-validation.sh - Deployment verification utilities
# Comprehensive deployment verification
verify_deployment() {
local service_name="$1"
local expected_version="$2"
echo "[$(date)] Starting deployment verification for: $service_name"
local errors=()
# Verify service is running
if ! verify_service_running "$service_name"; then
errors+=("Service not running")
fi
# Verify correct version deployed
if [ -n "$expected_version" ]; then
if ! verify_service_version "$service_name" "$expected_version"; then
errors+=("Incorrect version deployed")
fi
fi
# Verify service health
if ! verify_service_health "$service_name"; then
errors+=("Service health check failed")
fi
# Verify dependencies
if ! verify_service_dependencies "$service_name"; then
errors+=("Service dependencies not met")
fi
# Verify performance metrics
if ! verify_service_performance "$service_name"; then
errors+=("Service performance below threshold")
fi
# Report results
if [ ${#errors[@]} -eq 0 ]; then
echo "[$(date)] Deployment verification PASSED"
return 0
else
echo "[$(date)] Deployment verification FAILED:" >&2
for error in "${errors[@]}"; do
echo " - $error" >&2
done
return 1
fi
}
# Verify service is running
verify_service_running() {
local service_name="$1"
if systemctl is-active --quiet "$service_name"; then
echo "[$(date)] Service $service_name is running"
return 0
else
echo "[$(date)] Service $service_name is not running" >&2
return 1
fi
}
# Verify service version
verify_service_version() {
local service_name="$1"
local expected_version="$2"
local current_version
current_version=$(get_current_version "$service_name")
if [ "$current_version" = "$expected_version" ]; then
echo "[$(date)] Service $service_name version verified: $current_version"
return 0
else
echo "[$(date)] Service $service_name version mismatch. Expected: $expected_version, Actual: $current_version" >&2
return 1
fi
}
# Verify service health
verify_service_health() {
local service_name="$1"
# Service-specific health checks
case "$service_name" in
web-app)
if curl -sf http://localhost:8080/health >/dev/null 2>&1; then
echo "[$(date)] Web application health check passed"
return 0
else
echo "[$(date)] Web application health check failed" >&2
return 1
fi
;;
database)
if pg_isready >/dev/null 2>&1; then
echo "[$(date)] Database health check passed"
return 0
else
echo "[$(date)] Database health check failed" >&2
return 1
fi
;;
cache)
if redis-cli ping | grep -q "PONG"; then
echo "[$(date)] Cache health check passed"
return 0
else
echo "[$(date)] Cache health check failed" >&2
return 1
fi
;;
*)
# Generic health check
if systemctl is-active --quiet "$service_name"; then
echo "[$(date)] Generic service health check passed"
return 0
else
echo "[$(date)] Generic service health check failed" >&2
return 1
fi
;;
esac
}
# Verify service dependencies
verify_service_dependencies() {
local service_name="$1"
# Load dependency configuration
local deps_file="/etc/${service_name}/dependencies.conf"
if [ ! -f "$deps_file" ]; then
echo "[$(date)] No dependencies file found for $service_name"
return 0
fi
local failed_deps=()
while IFS='=' read -r dep_name dep_check || [ -n "$dep_name" ]; do
if [ -n "$dep_name" ]; then
echo "[$(date)] Checking dependency: $dep_name"
if ! eval "$dep_check"; then
echo "[$(date)] Dependency check failed: $dep_name" >&2
failed_deps+=("$dep_name")
fi
fi
done < "$deps_file"
if [ ${#failed_deps[@]} -eq 0 ]; then
echo "[$(date)] All dependencies verified for $service_name"
return 0
else
echo "[$(date)] Failed dependencies for $service_name: ${failed_deps[*]}" >&2
return 1
fi
}
# Verify service performance
verify_service_performance() {
local service_name="$1"
local response_time_threshold="${2:-2000}" # milliseconds
# Service-specific performance checks
case "$service_name" in
web-app)
local response_time
response_time=$(curl -w "%{time_total}" -o /dev/null -s http://localhost:8080/)
response_time=$(echo "$response_time * 1000" | bc | cut -d'.' -f1)
if [ "$response_time" -lt "$response_time_threshold" ]; then
echo "[$(date)] Web app response time acceptable: ${response_time}ms"
return 0
else
echo "[$(date)] Web app response time too slow: ${response_time}ms (threshold: ${response_time_threshold}ms)" >&2
return 1
fi
;;
*)
echo "[$(date)] Performance verification not implemented for $service_name"
return 0
;;
esac
}
|
🎨 Advanced Deployment Features
Blue-Green Deployment
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156 | # blue-green-deployment.sh - Blue-green deployment utilities
# Perform blue-green deployment
perform_blue_green_deployment() {
local service_name="$1"
local new_version="$2"
local blue_env="$3"
local green_env="$4"
local current_active_env="$5"
local new_active_env
if [ "$current_active_env" = "blue" ]; then
new_active_env="green"
local new_env_config="$green_env"
local old_env_config="$blue_env"
else
new_active_env="blue"
local new_env_config="$blue_env"
local old_env_config="$green_env"
fi
echo "[$(date)] Starting blue-green deployment for $service_name"
echo "[$(date)] Current active environment: $current_active_env"
echo "[$(date)] Deploying to: $new_active_env"
# Step 1: Deploy to inactive environment
echo "[$(date)] Deploying new version to $new_active_env environment"
if ! deploy_to_environment "$service_name" "$new_version" "$new_env_config"; then
echo "[$(date)] Deployment to $new_active_env failed" >&2
return 1
fi
# Step 2: Validate new environment
echo "[$(date)] Validating $new_active_env environment"
if ! validate_environment "$new_active_env" "$service_name" "$new_version"; then
echo "[$(date)] Validation of $new_active_env failed" >&2
rollback_environment "$old_env_config" "$service_name"
return 1
fi
# Step 3: Switch traffic
echo "[$(date)] Switching traffic to $new_active_env environment"
if ! switch_traffic "$service_name" "$new_active_env"; then
echo "[$(date)] Traffic switch failed, rolling back" >&2
switch_traffic "$service_name" "$current_active_env"
rollback_environment "$old_env_config" "$service_name"
return 1
fi
# Step 4: Decommission old environment
echo "[$(date)] Decommissioning $current_active_env environment"
decommission_environment "$old_env_config" "$service_name"
echo "[$(date)] Blue-green deployment completed successfully"
echo "[$(date)] New active environment: $new_active_env"
return 0
}
# Deploy to specific environment
deploy_to_environment() {
local service_name="$1"
local version="$2"
local env_config="$3"
# Source environment configuration
if [ -f "$env_config" ]; then
source "$env_config"
fi
# Deploy application
if ! deploy_application_package "/tmp/${service_name}-${version}.deb" "/etc/$service_name" "$service_name"; then
echo "[$(date)] Failed to deploy to environment" >&2
return 1
fi
return 0
}
# Validate environment
validate_environment() {
local environment="$1"
local service_name="$2"
local expected_version="$3"
# Set environment-specific variables
export DEPLOYMENT_ENVIRONMENT="$environment"
# Perform validation
if ! verify_deployment "$service_name" "$expected_version"; then
echo "[$(date)] Environment validation failed: $environment" >&2
return 1
fi
return 0
}
# Switch traffic to environment
switch_traffic() {
local service_name="$1"
local target_environment="$2"
# Update load balancer configuration
local lb_config="/etc/haproxy/haproxy.cfg"
if [ -f "$lb_config" ]; then
# Update backend servers
sed -i "s/backend $service_name.*/backend $service_name-$target_environment/" "$lb_config"
# Reload haproxy
if ! systemctl reload haproxy; then
echo "[$(date)] Failed to reload haproxy" >&2
return 1
fi
fi
echo "[$(date)] Traffic switched to $target_environment environment"
return 0
}
# Rollback environment
rollback_environment() {
local env_config="$1"
local service_name="$2"
echo "[$(date)] Rolling back environment using config: $env_config"
# Deploy previous version
if [ -f "$env_config" ]; then
local prev_version
prev_version=$(grep "SERVICE_VERSION=" "$env_config" | cut -d'=' -f2)
if [ -n "$prev_version" ]; then
deploy_to_environment "$service_name" "$prev_version" "$env_config"
fi
fi
return 0
}
# Decommission environment
decommission_environment() {
local env_config="$1"
local service_name="$2"
echo "[$(date)] Decommissioning environment: $env_config"
# Stop services
systemctl stop "$service_name-blue" 2>/dev/null || true
systemctl stop "$service_name-green" 2>/dev/null || true
# Clean up resources
# Implementation depends on infrastructure (containers, VMs, etc.)
return 0
}
|
🧾 Summary Best Practices
Deployment Guidelines
- Automated Pipelines: Use automated deployment pipelines to reduce human error
- Version Control: Maintain strict version control for all deployment artifacts
- Rollback Planning: Always have a rollback plan before deploying
- Gradual Rollout: Use blue-green or canary deployments for critical services
- Health Checks: Implement comprehensive health checks for all services
- Monitoring: Monitor deployments closely and have alerting in place
- Validation: Validate deployments with automated tests
- Documentation: Document deployment procedures and rollback steps
- Security: Follow security best practices for deployment processes
- Testing: Test deployments in staging environments first
Sample Deployment Configuration
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26 | # deployment-config-example.sh - Deployment configuration template
# General deployment settings
export DEPLOYMENT_TIMEOUT=3600
export HEALTH_CHECK_TIMEOUT=300
export ROLLBACK_ON_FAILURE=true
# Container deployment settings
export DOCKER_REGISTRY="registry.example.com"
export DOCKER_USERNAME="deploy-user"
export DOCKER_PASSWORD_FILE="/etc/docker/password"
# Package deployment settings
export PACKAGE_REPOSITORY="https://packages.example.com"
export PACKAGE_GPG_KEY="/etc/apt/trusted.gpg.d/example.gpg"
# Blue-green deployment settings
export BLUE_ENV_CONFIG="/etc/deploy/blue.env"
export GREEN_ENV_CONFIG="/etc/deploy/green.env"
export TRAFFIC_SWITCH_DELAY=30
# Service health check settings
export DEFAULT_HEALTH_ENDPOINT="/health"
export DEFAULT_HEALTH_PORT=8080
export HEALTH_CHECK_RETRIES=3
export HEALTH_CHECK_INTERVAL=10
|
🧠 Complete Deployment Script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76 | #!/bin/bash
# complete-deployment-system.sh - Production-ready deployment framework
set -euo pipefail
# Source deployment modules
source deployment-pipeline.sh
source container-deployment.sh
source package-deployment.sh
source deployment-validation.sh
source blue-green-deployment.sh
# Main deployment controller
main() {
local deployment_type="$1"
shift
case "$deployment_type" in
container)
execute_container_deployment "$@"
;;
package)
execute_package_deployment "$@"
;;
blue-green)
execute_blue_green_deployment "$@"
;;
rolling-update)
execute_rolling_update "$@"
;;
verify)
execute_deployment_verification "$@"
;;
*)
echo "Usage: $0 {container|package|blue-green|rolling-update|verify} [options]" >&2
return 1
;;
esac
}
# Execute container deployment
execute_container_deployment() {
local service_name="$1"
local image_name="$2"
local tag="$3"
local port_mapping="$4"
local env_file="$5"
init_deployment "${service_name}_${tag}"
if acquire_deployment_lock "$service_name"; then
if deploy_docker_container "$service_name" "$image_name" "$tag" "$port_mapping" "$env_file"; then
if verify_deployment "$service_name" "$tag"; then
set_deployment_state "${service_name}_${tag}" "$STATE_COMPLETED"
echo "[$(date)] Container deployment completed successfully"
else
set_deployment_state "${service_name}_${tag}" "$STATE_FAILED"
echo "[$(date)] Container deployment verification failed" >&2
release_deployment_lock "$service_name"
return 1
fi
else
set_deployment_state "${service_name}_${tag}" "$STATE_FAILED"
echo "[$(date)] Container deployment failed" >&2
release_deployment_lock "$service_name"
return 1
fi
release_deployment_lock "$service_name"
else
echo "[$(date)] Deployment already in progress" >&2
return 1
fi
}
# Run main function
main "$@"
|
🧾 See Also