استقرار آبی-سبز در یک محیط محلی با Docker

مقدمه
استقرار آبی-سبز یک استراتژی استقرار است که برای به حداقل رساندن خرابی و خطرات در حین به روزرسانی برنامه طراحی شده است. این رویکرد شامل اجرای دو محیط جداگانه ، آبی و سبز است ، جایی که یکی در خدمت ترافیک (محیط فعال) است در حالی که دیگری بیکار یا به روزرسانی ها است. پس از تأیید به روزرسانی ها در محیط بیکار ، ترافیک یکپارچه تغییر می کند ، از ثبات و به حداقل رساندن اختلال استفاده می شود.
در این راهنما ، ما نحوه اجرای استقرار آبی-سبز را با استفاده از Docker در یک محیط محلی با Laravel به عنوان نمونه نمونه نشان می دهیم. این رویکرد برای اهداف آموزشی متناسب است و راهی برای درک اصول استقرار آبی سبز ارائه می دهد.
چرا داکر برای استقرار آبی-سبز؟
Docker روشی کارآمد برای جداسازی و شبیه سازی محیط برای استقرار آبی-سبز در یک مجموعه محلی فراهم می کند. با استفاده از ظروف داکر ، می توانید محیط های مستقل “آبی” و “سبز” را ایجاد کنید ، با خیال راحت تغییرات را آزمایش کنید و ترافیک بین آنها را تغییر دهید.
این راهنما از داکر استفاده می کند:
- رفتار استقرار در دنیای واقعی را شبیه سازی کنید.
- روند استقرار آبی-سبز را به روشی در دسترس تجسم کنید.
- بررسی های بهداشتی و مسیریابی ترافیک ، مشابه تنظیمات موجود در سیستم عامل هایی مانند AWS ECS یا Kubernetes.
در حالی که روش های دیگری برای آزمایش استقرارها به صورت محلی وجود دارد ، این روش به سادگی و وضوح متمرکز است و به توسعه دهندگان این امکان را می دهد تا استراتژی را بدون پیچیدگی مدیریت زیرساخت های ابری درک کنند.
چرا به صورت محلی تست کنید؟
آزمایش استقرار آبی-سبز به صورت محلی مزایای مختلفی را ارائه می دهد:
- اشکال زدایی ایمن: بدون تأثیر بر تولید ، موضوعات موجود در اسکریپت های استقرار را شناسایی کنید.
- بازپرداخت گردش کار: اعتبار سنجی انتقال محیط ، ادغام API و کارهای برنامه ریزی شده.
- آزمایش بدون خرابی: ترافیک یکپارچه بین ظروف ، و اطمینان از تجربیات صاف کاربر.
- یادگیری دستی: با مشاهده اثرات آنها در زمان واقعی ، درک عمیقی از استراتژی های استقرار کسب کنید.
این تنظیم محلی شما را قادر می سازد قبل از مقیاس بندی آنها به محیط های تولید ، با اطمینان از استراتژی های استقرار استفاده کنید.
تنظیم تظاهرات
برای این تظاهرات از اجزای زیر استفاده می شود:
- NGINX: به عنوان پروکسی معکوس برای هدایت ترافیک به محیط فعال عمل می کند.
- بررسی های بهداشتی: آمادگی کانتینر را کنترل کنید و تصمیم بگیرید که چه موقع ترافیک را تغییر دهید.
- Laravel: مثال کاربردی برای تجسم انتقال محیط.
نقش حیاتی بررسی های بهداشتی در استقرار آبی-سبز
یکی از مؤلفه های اصلی این تنظیم ، استفاده از بررسی های بهداشتی است. این چک ها به طور مداوم وضعیت یک ظرف را کنترل می کنند تا مشخص شود که آیا آماده رسیدگی به ترافیک است یا خیر. بررسی های بهداشتی در استقرار آبی سبز ضروری است ، زیرا آنها ثبات را تضمین می کنند و خطرات را در هنگام انتقال بین محیط ها به حداقل می رسانند.
در این تنظیم محلی ، بررسی های بهداشتی نقش های زیر را بازی می کنند:
1. شبیه سازی رفتار تولید: سیستم عامل هایی مانند AWS ECS و Kubernetes به شدت به بررسی های بهداشتی متکی هستند تا مشخص شود که آیا یک سرویس عملیاتی است یا خیر. با تعریف بررسی های بهداشتی در پرونده docker-compose.yml ما ، ما این رفتار را در یک محیط محلی تکرار می کنیم و یک تجربه نزدیک به واقعیت را ارائه می دهیم.
2. تصمیمات استقرار خودکار: اسکریپت استقرار از چک های بهداشتی برای تصمیم گیری در مورد اینکه آیا ترافیک می تواند به محیط جدید هدایت شود ، استفاده می کند. اگر یک کانتینر بررسی های بهداشتی خود را از دست ندهد ، اسکریپت از تعویض ترافیک جلوگیری می کند و باعث می شود تا در دسترس بودن برنامه ، بازپرداخت را انجام دهد.
3. اطمینان از آمادگی برنامه: قبل از جابجایی ترافیک به یک محیط جدید ، بررسی های بهداشتی تأیید می کند که ظرف جدید کاملاً عملیاتی است. این مانع از خرابی ناشی از استقرار ناقص یا خطاهای برنامه می شود.
پیکربندی بررسی سلامتی
healthcheck:
test: ["CMD-SHELL", "curl -f http://localhost || exit 1"]
interval: 30s
timeout: 10s
retries: 3
start_period: 5s
- آزمون: یک دستور را اجرا می کند تا بررسی کند که آیا ظرف پاسخ می دهد یا خیر. در این حالت ، درخواست HTTP را به برنامه ارسال می کند و انتظار پاسخ موفقیت آمیز را دارد.
- فاصله: فرکانس اجرای بررسی سلامت را تعیین می کند.
- Timeout: مشخص می کند که بررسی سلامت چه مدت می تواند قبل از عدم موفقیت در نظر گرفته شود.
- احیای مجدد: تعداد خرابی های متوالی را قبل از اینکه ظرف به عنوان ناسالم مشخص شود ، مشخص می کند.
- start_period: اجازه می دهد تا یک دوره فضل برای ظرف قبل از شروع بررسی های بهداشتی به طور کامل اولیه شود.
نمای بصری استقرار آبی-سبز
در اینجا یک نمودار ساده از فرآیند استقرار آبی-سبز آورده شده است:
+-------------------+ +--------------------+
| | | |
| Active (Blue) | <--- Traffic --->| Idle (Green) |
| | | |
+-------------------+ +--------------------+
↑ ↑
| |
Updates & Tests Updates & Tests
| |
↓ ↓
+-------------------+ +--------------------+
| New Green | | New Blue |
| Deployment | | Deployment |
+-------------------+ +--------------------+
| |
Health Checks Passed Health Checks Passed
↓ ↓
+-------------------+ +--------------------+
| Idle (Blue) | <--- Traffic ---| Active (Green) |
+-------------------+ +--------------------+
چرا بررسی های بهداشتی بسیار مهم است
بررسی های بهداشتی ستون فقرات این استراتژی استقرار آبی-سبز است زیرا آنها:
- جلوگیری از خرابی: فقط ظروف که از بررسی های بهداشتی عبور می کنند ، ترافیک دریافت می کنند ، اطمینان حاصل می کنند که کاربران همیشه به یک محیط کاربردی هدایت می شوند.
- فعال کردن برگه های خودکار: اگر یک کانتینر از سلامت خود استفاده نکند ، اسکریپت به محیط قبلاً فعال باز می گردد.
- ترویج اعتماد به نفس: با اعتبارسنجی آمادگی محیط جدید ، بررسی های بهداشتی خطر استقرار به روزرسانی های معیوب را کاهش می دهد.
مؤلفه ها و پرونده ها
در اینجا یک مرور کلی از پرونده های مورد استفاده در این تنظیم وجود دارد:
- اسکریپت استقرار: ایجاد ، سوئیچینگ و بازگرداندن محیط های آبی-سبز را خودکار می کند.
abin/install.sh
#!/bin/bash
set -e # Stop script execution on error
NGINX_CONF_PATH="./docker/nginx/active_backend.conf"
NGINX_CONTAINER="app"
ENV_FILE=".env"
build_containers() {
echo "📦 Building Docker containers..."
docker compose build
echo "✅ Docker containers built successfully."
}
prepare_nginx_config() {
if [ ! -d "./docker/nginx" ]; then
echo "📂 Nginx directory not found. Creating it..."
mkdir -p ./docker/nginx
echo "✅ Nginx directory created."
fi
}
update_nginx_config() {
local active_color=$1
echo "🔄 Updating Nginx configuration to route traffic to '$active_color' containers..."
cat > "$NGINX_CONF_PATH" <<EOL
upstream app_backend {
server $active_color:9000 max_fails=3 fail_timeout=30s;
}
EOL
echo "📋 Copying Nginx configuration to the container..."
docker cp "$NGINX_CONF_PATH" "$NGINX_CONTAINER:/etc/nginx/conf.d/active_backend.conf"
echo "🔁 Reloading Nginx to apply the new configuration..."
docker exec "$NGINX_CONTAINER" nginx -s reload >/dev/null 2>&1
echo "✅ Nginx configuration updated and reloaded successfully."
}
wait_for_health() {
local container_prefix=$1
local retries=5
local unhealthy_found
echo "⏳ Waiting for containers with prefix '$container_prefix' to become healthy..."
while (( retries > 0 )); do
unhealthy_found=false
for container_name in $(docker ps --filter "name=$container_prefix" --format "{{.Names}}"); do
health_status=$(docker inspect --format '{{if .State.Health}}{{.State.Health.Status}}{{else}}unknown{{end}}' "$container_name" || echo "unknown")
if [[ "$health_status" != "healthy" ]]; then
unhealthy_found=true
echo "🚧 Container '$container_name' is not ready. Current status: $health_status."
fi
done
if ! $unhealthy_found; then
echo "✅ All containers with prefix '$container_prefix' are healthy."
return 0
fi
echo "⏳ Retrying... ($retries retries left)"
((retries--))
sleep 5
done
echo "❌ Error: Some containers with prefix '$container_prefix' are not healthy. Aborting deployment."
rollback
exit 0
}
rollback() {
echo "🛑 Rolling back deployment. Ensuring the active environment remains intact."
if [ -n "$PREVIOUS_COLOR" ]; then
echo "🔄 Restoring CONTAINER_COLOR=$PREVIOUS_COLOR in .env."
sed -i.bak "s/^CONTAINER_COLOR=.*/CONTAINER_COLOR=$PREVIOUS_COLOR/" "$ENV_FILE"
rm -f "$ENV_FILE.bak"
echo "✅ Restored CONTAINER_COLOR=$PREVIOUS_COLOR in .env."
else
echo "🚧 No previous CONTAINER_COLOR found to restore."
fi
if docker ps --filter "name=green" --format "{{.Names}}" | grep -q "green"; then
echo "✅ Active environment 'green' remains intact."
echo "🛑 Stopping and removing 'blue' containers..."
docker compose stop "blue" >/dev/null 2>&1 || true
docker compose rm -f "blue" >/dev/null 2>&1 || true
elif docker ps --filter "name=blue" --format "{{.Names}}" | grep -q "blue"; then
echo "✅ Active environment 'blue' remains intact."
echo "🛑 Stopping and removing 'green' containers..."
docker compose stop "green" >/dev/null 2>&1 || true
docker compose rm -f "green" >/dev/null 2>&1 || true
else
echo "❌ No active environment detected after rollback. Manual intervention might be needed."
fi
echo "🔄 Rollback completed."
}
update_env_file() {
local active_color=$1
# check if .env file exists
if [ ! -f "$ENV_FILE" ]; then
echo "❌ .env file not found. Creating a new one..."
echo "CONTAINER_COLOR=$active_color" > "$ENV_FILE"
echo "✅ Created .env file with CONTAINER_COLOR=$active_color."
return
fi
# backup previous CONTAINER_COLOR value
if grep -q "^CONTAINER_COLOR=" "$ENV_FILE"; then
PREVIOUS_COLOR=$(grep "^CONTAINER_COLOR=" "$ENV_FILE" | cut -d '=' -f 2)
echo "♻️ Backing up previous CONTAINER_COLOR=$PREVIOUS_COLOR."
else
PREVIOUS_COLOR=""
fi
# update CONTAINER_COLOR value in .env
if grep -q "^CONTAINER_COLOR=" "$ENV_FILE"; then
sed -i.bak "s/^CONTAINER_COLOR=.*/CONTAINER_COLOR=$active_color/" "$ENV_FILE"
echo "🔄 Updated CONTAINER_COLOR=$active_color in .env"
else
echo "CONTAINER_COLOR=$active_color" >> "$ENV_FILE"
echo "🖋️ Added CONTAINER_COLOR=$active_color to .env"
fi
# remove backup file
if [ -f "$ENV_FILE.bak" ]; then
rm "$ENV_FILE.bak"
fi
}
install_dependencies() {
local container=$1
echo "📥 Installing dependencies in container '$container'..."
# Install Laravel dependencies
docker exec -u root -it "$container" bash -c "composer install --no-dev --optimize-autoloader"
docker exec -u root -it "$container" bash -c "mkdir -p database && touch database/database.sqlite"
# Permissions setup
docker exec -u root -it "$container" bash -c "chown www-data:www-data -R ./storage ./bootstrap ./database"
docker exec -u root -it "$container" bash -c "chmod -R 775 ./storage ./bootstrap/cache"
# Clear caches and run migrations
docker exec -u root -it "$container" bash -c "php artisan cache:clear"
docker exec -u root -it "$container" bash -c "php artisan config:clear"
docker exec -u root -it "$container" bash -c "php artisan route:clear"
docker exec -u root -it "$container" bash -c "php artisan view:clear"
docker exec -u root -it "$container" bash -c "php artisan migrate --force"
echo "✅ Dependencies installed and database initialized successfully in container '$container'."
}
deploy() {
local active=$1
local new=$2
# Update .env before deploying
update_env_file "$new"
echo "🚀 Starting deployment. Current active environment: '$active'. Deploying to '$new'..."
docker compose --profile "$new" up -d
wait_for_health "$new"
install_dependencies "$new"
update_nginx_config "$new"
echo "🗑️ Removing old environment: '$active'..."
echo "🛑 Stopping '$active' containers..."
docker compose stop $active >/dev/null 2>&1 || true
echo "🗑️ Removing '$active' containers..."
docker compose rm -f $active >/dev/null 2>&1 || true
update_env_file "$new"
echo "✅ Deployment to '$new' completed successfully."
}
get_active_container() {
if [ -f "$ENV_FILE" ] && grep -q "CONTAINER_COLOR" "$ENV_FILE"; then
grep "CONTAINER_COLOR" "$ENV_FILE" | cut -d '=' -f 2
else
echo ""
fi
}
# Main script logic
prepare_nginx_config
build_containers
ACTIVE_COLOR=$(get_active_container)
if [ -z "$ACTIVE_COLOR" ]; then
# if no active container found, deploy 'blue'
echo "🟦 Initial setup. Bringing up 'blue' containers..."
docker compose --profile blue up -d
wait_for_health "blue"
install_dependencies "blue"
update_nginx_config "blue"
update_env_file "blue"
elif [ "$ACTIVE_COLOR" == "green" ]; then
# if the active is 'green', deploy 'blue'
PREVIOUS_COLOR="green"
deploy "green" "blue"
elif [ "$ACTIVE_COLOR" == "blue" ]; then
# if the active is 'blue', deploy 'green'
PREVIOUS_COLOR="blue"
deploy "blue" "green"
else
# if the active is neither 'green' nor 'blue', reset to 'blue'
echo "🚧 Unexpected CONTAINER_COLOR value. Resetting to 'blue'..."
PREVIOUS_COLOR=""
docker compose --profile blue up -d
wait_for_health "blue"
install_dependencies "blue"
update_nginx_config "blue"
update_env_file "blue"
fi
echo "🎉 Deployment successful!"
- پیکربندی NGINX: مسیریابی ترافیک را به محیط فعال کنترل می کند.
nginx/default.conf
server {
listen 80;
index index.php index.html;
client_max_body_size 20M;
root /var/www/html/public;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
fastcgi_pass app_backend;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
location ~ /\.ht {
deny all;
}
}
- پیکربندی PHP-FPM: فرآیندهای PHP را برای لاراول مدیریت می کند.
php/www.conf
listen = 9000
user = www-data
group = www-data
[www]
pm = dynamic
pm.max_children = 20
pm.start_servers = 10
pm.min_spare_servers = 5
pm.max_spare_servers = 15
- Dockerfile: محیط Laravel را با وابستگی های مورد نیاز تنظیم می کند.
Dockerfile
FROM php:8.2.0-fpm
WORKDIR /var/www/html
RUN apt-get update && apt-get install -y \
curl \
dos2unix \
git \
libonig-dev \
libpng-dev \
libxml2-dev \
libzip-dev \
unzip \
zip \
libfcgi0ldbl \
&& apt-get clean && rm -rf /var/lib/apt/lists/* \
&& docker-php-ext-install pdo_mysql mbstring exif pcntl bcmath gd zip \
&& curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer \
&& mkdir -p /var/www/html/storage /var/www/html/bootstrap/cache && \
chown -R :www-data ./bootstrap/cache && \
mkdir -p storage && \
cd storage/ && \
mkdir -p logs && \
mkdir -p app && \
mkdir -p framework/sessions && \
mkdir -p framework/views && \
mkdir -p framework/cache && \
chmod -R 775 framework logs app && \
chown -R :www-data ./framework ./logs ./app && \
git config --global --add safe.directory '*'
COPY ./scripts/start.sh /usr/local/bin/start.sh
RUN chmod +x /usr/local/bin/start.sh
CMD ["/usr/local/bin/start.sh"]
- Docker Compose: ظروف آبی-سبز ، NGINX و تنظیمات بررسی سلامت را تعریف می کند.
docker-compose.yml
services:
blue:
container_name: blue
env_file:
- .env
profiles:
- blue
build:
context: ./docker
dockerfile: Dockerfile
volumes:
- ./:/var/www/html
- ./docker/supervisor/supervisord.conf:/etc/supervisor/supervisord.conf
- ./docker/php/www.conf:/usr/local/etc/php-fpm.d/www.conf
healthcheck:
test: ["CMD-SHELL", "SCRIPT_FILENAME=/var/www/html/public/index.php REQUEST_METHOD=GET cgi-fcgi -bind -connect 127.0.0.1:9000 || exit 1"]
interval: 30s
timeout: 10s
retries: 3
start_period: 5s
green:
container_name: green
profiles:
- green
env_file:
- .env
build:
context: ./docker
dockerfile: Dockerfile
volumes:
- ./:/var/www/html
- ./docker/supervisor/supervisord.conf:/etc/supervisor/supervisord.conf
- ./docker/php/www.conf:/usr/local/etc/php-fpm.d/www.conf
healthcheck:
test: ["CMD-SHELL", "SCRIPT_FILENAME=/var/www/html/public/index.php REQUEST_METHOD=GET cgi-fcgi -bind -connect 127.0.0.1:9000 || exit 1"]
interval: 30s
timeout: 10s
retries: 3
start_period: 5s
app:
image: nginx:alpine
container_name: app
profiles:
- blue
- green
ports:
- "${PORT-80}:80"
volumes:
- ./:/var/www/html
- ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost"]
interval: 30s
timeout: 10s
retries: 3
start_period: 5s
بررسی های بهداشتی در عمل
چگونه کار می کند
- هنگام استقرار به روزرسانی ها:
- یک محیط جدید (آبی یا سبز) شروع می شود.
- بررسی های بهداشتی آمادگی ظرف را تأیید می کند.
- اگر بررسی های بهداشتی انجام شود:
- ترافیک به محیط جدید هدایت می شود.
- محیط قدیمی بیکار می شود ، آماده به روزرسانی های آینده است.
- در صورت عدم موفقیت بررسی های بهداشتی:
- یک بازگشت برگشت ایجاد می شود و محیط فعال بدون تغییر باقی می ماند.
نمونه برگشت خودکار
اسکریپت استقرار تضمین می کند که هنگام عدم موفقیت بررسی های بهداشتی ، بازپرداخت رخ می دهد. به عنوان مثال:
- آبی فعال است و سبز بررسی های بهداشتی را شکست می دهد.
- ترافیک همچنان به رنگ آبی هدایت می شود.
- ظرف سبز معیوب برداشته می شود و ثبات برنامه را حفظ می کند.
مثالها:
پایان
این راهنما نحوه شبیه سازی و درک استقرار آبی-سبز را با استفاده از Docker در یک محیط محلی نشان می دهد. با استفاده از بررسی های بهداشتی ، تعویض ترافیک و بازگشت خودکار ، می توانید خرابی را به حداقل برسانید و از ثبات در طول استقرار اطمینان حاصل کنید. در حالی که این رویکرد ساده شده است ، مفاهیم به راحتی می توانند در سیستم های درجه تولید گسترش یابد.
قبل از مقیاس گذاری به تولید ، از این تنظیم برای آزمایش و اصلاح استراتژی های استقرار با اطمینان استفاده کنید.
کد کامل در این مخزن
اعتبار تصویر: آرنولد فرانسیسکا ، از طریق Unsplash (https://unsplash.com/)