برنامه نویسی

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

مقدمه

استقرار آبی-سبز یک استراتژی استقرار است که برای به حداقل رساندن خرابی و خطرات در حین به روزرسانی برنامه طراحی شده است. این رویکرد شامل اجرای دو محیط جداگانه ، آبی و سبز است ، جایی که یکی در خدمت ترافیک (محیط فعال) است در حالی که دیگری بیکار یا به روزرسانی ها است. پس از تأیید به روزرسانی ها در محیط بیکار ، ترافیک یکپارچه تغییر می کند ، از ثبات و به حداقل رساندن اختلال استفاده می شود.

در این راهنما ، ما نحوه اجرای استقرار آبی-سبز را با استفاده از Docker در یک محیط محلی با Laravel به عنوان نمونه نمونه نشان می دهیم. این رویکرد برای اهداف آموزشی متناسب است و راهی برای درک اصول استقرار آبی سبز ارائه می دهد.

چرا داکر برای استقرار آبی-سبز؟

Docker روشی کارآمد برای جداسازی و شبیه سازی محیط برای استقرار آبی-سبز در یک مجموعه محلی فراهم می کند. با استفاده از ظروف داکر ، می توانید محیط های مستقل “آبی” و “سبز” را ایجاد کنید ، با خیال راحت تغییرات را آزمایش کنید و ترافیک بین آنها را تغییر دهید.

این راهنما از داکر استفاده می کند:

  • رفتار استقرار در دنیای واقعی را شبیه سازی کنید.
  • روند استقرار آبی-سبز را به روشی در دسترس تجسم کنید.
  • بررسی های بهداشتی و مسیریابی ترافیک ، مشابه تنظیمات موجود در سیستم عامل هایی مانند AWS ECS یا Kubernetes.

در حالی که روش های دیگری برای آزمایش استقرارها به صورت محلی وجود دارد ، این روش به سادگی و وضوح متمرکز است و به توسعه دهندگان این امکان را می دهد تا استراتژی را بدون پیچیدگی مدیریت زیرساخت های ابری درک کنند.

چرا به صورت محلی تست کنید؟

آزمایش استقرار آبی-سبز به صورت محلی مزایای مختلفی را ارائه می دهد:

  • اشکال زدایی ایمن: بدون تأثیر بر تولید ، موضوعات موجود در اسکریپت های استقرار را شناسایی کنید.
  • بازپرداخت گردش کار: اعتبار سنجی انتقال محیط ، ادغام API و کارهای برنامه ریزی شده.
  • آزمایش بدون خرابی: ترافیک یکپارچه بین ظروف ، و اطمینان از تجربیات صاف کاربر.
  • یادگیری دستی: با مشاهده اثرات آنها در زمان واقعی ، درک عمیقی از استراتژی های استقرار کسب کنید.

این تنظیم محلی شما را قادر می سازد قبل از مقیاس بندی آنها به محیط های تولید ، با اطمینان از استراتژی های استقرار استفاده کنید.

تنظیم تظاهرات

برای این تظاهرات از اجزای زیر استفاده می شود:

  1. NGINX: به عنوان پروکسی معکوس برای هدایت ترافیک به محیط فعال عمل می کند.
  2. بررسی های بهداشتی: آمادگی کانتینر را کنترل کنید و تصمیم بگیرید که چه موقع ترافیک را تغییر دهید.
  3. 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)   |
+-------------------+                   +--------------------+
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

چرا بررسی های بهداشتی بسیار مهم است

بررسی های بهداشتی ستون فقرات این استراتژی استقرار آبی-سبز است زیرا آنها:

  • جلوگیری از خرابی: فقط ظروف که از بررسی های بهداشتی عبور می کنند ، ترافیک دریافت می کنند ، اطمینان حاصل می کنند که کاربران همیشه به یک محیط کاربردی هدایت می شوند.
  • فعال کردن برگه های خودکار: اگر یک کانتینر از سلامت خود استفاده نکند ، اسکریپت به محیط قبلاً فعال باز می گردد.
  • ترویج اعتماد به نفس: با اعتبارسنجی آمادگی محیط جدید ، بررسی های بهداشتی خطر استقرار به روزرسانی های معیوب را کاهش می دهد.

مؤلفه ها و پرونده ها

در اینجا یک مرور کلی از پرونده های مورد استفاده در این تنظیم وجود دارد:

  1. اسکریپت استقرار: ایجاد ، سوئیچینگ و بازگرداندن محیط های آبی-سبز را خودکار می کند.

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!"
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

  1. پیکربندی 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;
    }
}
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

  1. پیکربندی 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
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

  1. 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"]
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

  1. 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
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

بررسی های بهداشتی در عمل

چگونه کار می کند

  1. هنگام استقرار به روزرسانی ها:
    • یک محیط جدید (آبی یا سبز) شروع می شود.
    • بررسی های بهداشتی آمادگی ظرف را تأیید می کند.
  2. اگر بررسی های بهداشتی انجام شود:
    • ترافیک به محیط جدید هدایت می شود.
    • محیط قدیمی بیکار می شود ، آماده به روزرسانی های آینده است.
  3. در صورت عدم موفقیت بررسی های بهداشتی:
    • یک بازگشت برگشت ایجاد می شود و محیط فعال بدون تغییر باقی می ماند.

نمونه برگشت خودکار

اسکریپت استقرار تضمین می کند که هنگام عدم موفقیت بررسی های بهداشتی ، بازپرداخت رخ می دهد. به عنوان مثال:

  • آبی فعال است و سبز بررسی های بهداشتی را شکست می دهد.
  • ترافیک همچنان به رنگ آبی هدایت می شود.
  • ظرف سبز معیوب برداشته می شود و ثبات برنامه را حفظ می کند.

مثالها:

پایان

این راهنما نحوه شبیه سازی و درک استقرار آبی-سبز را با استفاده از Docker در یک محیط محلی نشان می دهد. با استفاده از بررسی های بهداشتی ، تعویض ترافیک و بازگشت خودکار ، می توانید خرابی را به حداقل برسانید و از ثبات در طول استقرار اطمینان حاصل کنید. در حالی که این رویکرد ساده شده است ، مفاهیم به راحتی می توانند در سیستم های درجه تولید گسترش یابد.

قبل از مقیاس گذاری به تولید ، از این تنظیم برای آزمایش و اصلاح استراتژی های استقرار با اطمینان استفاده کنید.

کد کامل در این مخزن

اعتبار تصویر: آرنولد فرانسیسکا ، از طریق Unsplash (https://unsplash.com/)

نوشته های مشابه

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

دکمه بازگشت به بالا