Всем привет! Перед вами последняя часть туториала, в котором мы учимся самостоятельно разворачивать Rails-приложение с помощью Docker и инструментов AWS.
В предыдущих частях туториала мы уже успели проделать много работы.
В первой частимы рассмотрели теорию Docker: принцип работы, его компоненты, а также преимущества и недостатки работы Docker в сравнении с виртуальными машинами. Кроме того, мы прошли пошаговую сборку Rails-приложения в Dockerfile и запустили наше Spree-приложение и все зависимые сервисы на локальной машине.
Во второй части мы:
- Реализовали возможность хранения sensitive data приложения.
- Создали Docker образ для веб-сервера Nginx.
- Подготовили конфигурацию для развертывания staging инфраструктуры на AWS.
- Запустили staging приложение на AWS.
В этой части мы переходим к этапу развертыванию production-окружения. Поехали!
Какую проблему решаем
Итак, как уже было сказано ранее, в предыдущей части мы развернули наше staging-приложение, протестировали его и убедились, что все работает. Теперь необходимо развернуть готовое к масштабированию production-приложение.
На инфографике мы видим, что мы находимся на последнем этапе: Production. Также мы видим этапы нашей работы и стэк технологий, который будем использовать.
В этой части мы рассматриваем последний этап — Production. Также мы видим ПО, которое будем использовать на данном этапе
Решение
Стек сервисов production-приложения остается таким же, как и на предыдущем этапе Staging. Инфраструктура имеет следующие отличия:
- Cloud database.В качестве базы данных для нашего приложения мы будем использовать Amazon RDS, который упрощает развертывание и настройку реляционных баз данных в облаке.
- Cloud in-memory storage.В качестве in-memory store мы будем использовать Amazon ElastiCache, который облегчает развертывание и управление средами Redis и Memcached.
- Масштабирование и балансировщик нагрузки.В случае увеличения количества запросов, мощностей одного сервера может быть недостаточно. Нужен сервис, который будет распределять запросы между несколькими серверами в зависимости от их нагрузки. Мы будем использовать Amazon Elasticloadbalancing.
- Декомпозиция.Если на предыдущих этапах все зависимые сервисы приложения размещались на одном инстансе, то в условиях горизонтальной масштабируемости приложения нужно увеличивать только те количества сервисов, на которые приходится наибольшая нагрузка. В контексте нашей инфраструктуры, необходимо вынести в отдельные инстансы Server App и Worker App, так как не всегда, когда нужно масштабировать Server App, нужно масштабировать и Worker App, и наоборот.
Таким образом, архитектура production-приложения преображается в следующую структуру:
Постановка задачи
Для корректной и безопасной работы production-окружения нам понадобится:
- Сохранить все переменные production окружения в зашифрованном виде.
- Создать Postgresql инстанс с помощью RDS.
- Создать Redis инстанс с помощью ElasticCache.
- Создать кластер для production приложения на AWS ECS.
- Создать compose файл для запуска приложения и его зависимых сервисов на AWS ECS.
- Запустить сервис с production версией приложения на AWS.
Поскольку количество окружений возросло, необходимо автоматизировать процесс деплоя, а именно, интегрировать CircleCIдля автоматизации деплоя для staging-окружения.
Хранение данных приложения
Начнем с добавления AWS credentials в файл с глобальными переменными приложения, используя команду EDITOR=nano rails credentials:edit.
production: # ... AWS_ACCESS_KEY_ID: 'YOUR_AWS_ACCESS_KEY_ID' AWS_SECRET_ACCESS_KEY: 'YOUR_AWS_SECRET_ACCESS_KEY' DEVISE_SECRET_KEY: 'YOUR_DEVISE_SECRET_KEY' SECRET_KEY_BASE: 'YOUR_SECRET_KEY_BASE'
Конфигурация сервисов AWS
Конфигурация доступа
Коммуникация клиента с инфраструктурой нашего приложения будет происходить через elasticloadbalancing. В целях безопасности, доступ ко всем остальным сервисам будет предоставлен только в рамках внутренней сети AWS и определенных security groups.
Исходя из диаграммы production-окружения, указанной в начале, создадим группы доступа:
# GroupId группы load balancer обозначим, как `$BALANCER_SG` aws ec2 create-security-group \ --group-name spreeproject-production-balancer \ --description "Spree project Production Balancer" # GroupId группы серверного приложения обозначим, как `$SERVER_APP_SG` aws ec2 create-security-group \ --group-name spreeproject-production-server-app \ --description "Spree project Production Server App" # GroupId группы баз данных приложения обозначим, как `$DB_SG` aws ec2 create-security-group \ --group-name spreeproject-production-db \ --description "Spree project Production DB" # GroupId группы для memory stores сервиса обозначим, как `$STORE_SG` aws ec2 create-security-group \ --group-name spreeproject-production-store \ --description "Spree project Production Memory Store"
И укажем правила коммуникации сервисов:
# Откроем доступ любому клиенту на 80-й порт балансера. aws ec2 authorize-security-group-ingress \ --group-id $BALANCER_SG \ --protocol tcp \ --port 80 \ --cidr 0.0.0.0/0 # Откроем доступ балансеру на 8080-й порт будущим инстансам, где будет запущен Nginx. aws ec2 authorize-security-group-ingress \ --group-id $SERVER_APP_SG \ --protocol tcp \ --port 8080 \ --source-group $BALANCER_SG # Откроем доступ будущим инстансам с приложением к RDS, где по 5432 порту будет доступен Postgres. aws ec2 authorize-security-group-ingress \ --group-id $DB_SG \ --protocol tcp \ --port 5432 \ --source-group $SERVER_APP_SG # Откроем доступ будущим инстансам с приложением к ElastiCache, где по 6379 порту будет доступен Redis. aws ec2 authorize-security-group-ingress \ --group-id $STORE_SG \ --protocol tcp \ --port 6379 \ --source-group $SERVER_APP_SG
Хранение изображений и быстрый доступ к ним
Для хранения изображений наше приложение будет использовать S3-bucket. Создадим его с помощью следующей команды:
aws s3api create-bucket --bucket spreeproject-production
После создания bucket на S3 обновим переменные credentials:
production: # ... S3_BUCKET_NAME: 'spreeproject-production' S3_REGION: 'us-east-1' S3_HOST_NAME: 's3.amazonaws.com'
RDS
Amazon предоставляет управляемый сервис RDS, который упрощает настройку, использование и масштабирование реляционной базы данных.
Чтобы начать работать, вам достаточно просто создать RDS-инстанс с выбранной вами базой данных и получить хост-сервиса для подключения вашего приложения к нему.
В качестве базы данных мы будем использовать инстанс RDS с готовой сборкой для Postgres. В $YOUR_DB_USERNAME и $YOUR_DB_PASSWORD укажите собственные значения.
aws rds create-db-instance \ --engine postgres \ --no-multi-az \ --vpc-security-group-ids $DB_SG \ --db-instance-class db.t2.micro \ --allocated-storage 20 \ --db-instance-identifier spreeproject-production \ --db-name spreeproject_production \ --master-username $YOUR_DB_USERNAME \ --master-user-password $YOUR_DB_PASSWORD
Выполним команду для проверки статуса RDS инстанса:
aws rds describe-db-instances
В отличие от EC2-инстансов, RDS будет доступен через некоторое время, и после успешной инициализации будет доступен его endpoint.
Обновим наш файл с encrypted credentials:
production: # ... DB_NAME: 'spreeproject_production' DB_USERNAME: 'YOUR_DB_USERNAME' DB_PASSWORD: 'YOUR_DB_PASSWORD' DB_HOST: 'YOUR_RDS_ENDPOINT' DB_PORT: '5432'
ElastiCache
Amazon предоставляет управляемый сервис ElastiCache, который облегчает развертывание и запуск в облаке серверных узлов, совместимых с протоколами Memcached или Redis. Сервис упрощает и берет на себя управление средами в памяти, их мониторинг и решение связанных операционных вопросов, позволяя клиентам сосредоточить усилия технических специалистов на разработке приложений.
В качестве in-memory store будем использовать сервис ElastiCache с готовой сборкой Redis:
aws elasticache create-cache-cluster \ --engine redis \ --security-group-ids $STORE_SG \ --cache-node-type cache.t2.micro \ --num-cache-nodes 1 \ --cache-cluster-id spree-production
Команда для проверки статуса инстанса:
aws elasticache describe-cache-clusters --show-cache-node-info
На инициализацию ElastiCache также потребуется некоторое время. После успешной инициализации ElastiCache сохраним полученный Address сервиса в encrypted credentials:
production: # ... REDIS_DB: "redis://YOUR_EC_ENDPOINT:6379"
ELB
В случае увеличения количества запросов, мощностей одного сервера может быть недостаточно. Это приводит к увеличению времени обслуживания запросов. Чтобы устранить эту проблему, подключим к нашей инфраструктуре балансировщик нагрузки (load balancer), который будет распределять запросы между несколькими нодами в зависимости от их нагрузки. У AWS есть готовое решение Elasticloadbalancing.
Использование ELB для распределения нагрузки
Для создания инстанса необходимо получить Subnets, VPС и Keypair для будущего инстанса:
aws ec2 describe-subnets
В результате команды выбираем SubnetId, у которых одинаковый VpcId и DefaultForAz параметр имеет значение true. И записываем их в переменную.
# Пример AWS_SUBNETS=subnet-e49c19b8,subnet-20ae1647,subnet-319d1a1f
Создаем непосредственно сам loadbalancer:
aws elb create-load-balancer \ --load-balancer-name spreeproject-balancer-production \ --listeners "Protocol=HTTP,LoadBalancerPort=80,InstanceProtocol=HTTP,InstancePort=8080" \ --subnets $YOUR_SUBNETS \ --security-groups $BALANCER_SG
Добавим к нему connection settings:
aws elb modify-load-balancer-attributes \ --load-balancer-name spreeproject-balancer-production \ --load-balancer-attributes "{\"ConnectionSettings\":{\"IdleTimeout\":5}}"
Состояние созданного балансировщика можно проверить с помощью команды:
aws elb describe-load-balancers
В дальнейшем, наше Spree-приложение будет доступно через его DNSName.
Настраиваем production окружение
ECS Cluster
Работа с ECS Cluster и создание в нем сервисов идентична главе ECS Clusterиз предыдущей части, где мы разворачивали staging-приложение.
Создадим конфигурацию для будущего кластера spreeproject-production, введя следующую команду в консоли:
CLUSTER_NAME=spreeproject-production ecs-cli configure --region us-east-1 --cluster $CLUSTER_NAME --config-name $CLUSTER_NAME
Необходимо получить список доступных VPC:
aws ec2 describe-vpcs
Дальше VpcId этих subnets записываем в переменную $AWS_VPC. Например:
AWS_VPC=vpc-0e934a76
После, создадим кластер spreeproject-production, к которому будет подвязан один EC2 инстанс типа t2.micro. Для этого вводим в терминале следующую команду:
ecs-cli up \ --keypair spreeproject_keypair \ --capability-iam \ --size 3 \ --instance-type t2.micro \ --vpc $AWS_VPC \ --subnets $AWS_SUBNETS \ --image-id ami-0a6be20ed8ce1f055 \ --security-group $SERVER_APP_SG \ --cluster-config $CLUSTER_NAME \ --verbose
ECR
Создадим репозитории для хранения образов production-версии приложения.
Предварительно нужно аутентифицироваться с помощью следующей команды:
$(aws ecr get-login --region us-east-1 --no-include-email)
Актуализируем образы наших сервисов, вызвав команду:
docker-compose -p spreeproject -f docker-compose.development.yml build
После, загрузим локальный образ в репозиторий YOUR_ECR_ID.dkr.ecr.us-east-1.amazonaws.com. YOUR_ECR_ID — registryId созданного репозитория:
docker tag spreeproject_server_app:latest $YOUR_ECR_ID.dkr.ecr.us-east-1.amazonaws.com/spreeproject/server_app:production
docker push $YOUR_ECR_ID.dkr.ecr.us-east-1.amazonaws.com/spreeproject/server_app:production
Сделаем то же самое для web_server, в котором будет образ Nginx:
aws ecr create-repository --repository-name spreeproject/web_server
docker tag spreeproject_web_server:latest $YOUR_ECR_ID.dkr.ecr.us-east-1.amazonaws.com/spreeproject/web_server:production
docker push $YOUR_ECR_ID.dkr.ecr.us-east-1.amazonaws.com/spreeproject/web_server:production
ECS Tasks
После, создадим docker-compose.production.yml как compose production версии приложения. Замените YOUR_ECR_ID и YOUR_RAILS_MASTER_KEY на собственные значения:
cd ../docker && touch docker-compose.production.yml
version: '3' services: web_server: image: YOUR_ECR_ID.dkr.ecr.us-east-1.amazonaws.com/spreeproject/web_server:production ports: - 8080:8080 links: - server_app server_app: image: YOUR_ECR_ID.dkr.ecr.us-east-1.amazonaws.com/spreeproject/server_app:production command: bundle exec puma -C config/puma.rb entrypoint: "./docker-entrypoint.sh" expose: - 3000 environment: RAILS_ENV: production RAILS_MASTER_KEY: YOUR_RAILS_MASTER_KEY
Создадим файл схему ecs-params
touch ecs-params.production.yml
version: 1 task_definition: ecs_network_mode: bridge task_size: cpu_limit: 768 mem_limit: 0.5GB services: web_server: essential: true server_app: essential: true
Запускаем production-окружение
ECS Services
Создаем задачу для будущего сервиса ECS:
# создайте task definition для контейнера docker ecs-cli compose \ --file docker-compose.production.yml \ --project-name $CLUSTER_NAME \ --ecs-params ecs-params.production.yml \ --cluster-config $CLUSTER_NAME \ create
После создания задачи ей будет присвоенный определенный номер. Запишем этот номер в переменную TASK_NUMBER и создадим сервис ECS:
aws ecs create-service \ --service-name 'spreeproject' \ --cluster $CLUSTER_NAME \ --task-definition "$CLUSTER_NAME:$TASK_NUMBER" \ --load-balancers "loadBalancerName=$BALANCER_NAME,containerName=web_server,containerPort=8080" \ --desired-count 2 \ --deployment-configuration "maximumPercent=200,minimumHealthyPercent=50"
Теперь на оставшемся незанятом инстансе нашего кластера, запустим приложение для background processing.
Создадим docker-compose-worker.production.yml как compose production версии Sidekiq приложения. Замените YOUR_ECR_ID и YOUR_RAILS_MASTER_KEY на собственные значения:
touch docker-compose-worker.production.yml
version: '3' services: worker_app: image: YOUR_ECR_ID.dkr.ecr.us-east-1.amazonaws.com/spreeproject/server_app:production command: bundle exec sidekiq -C config/sidekiq.yml environment: RAILS_ENV: production RAILS_MASTER_KEY: YOUR_RAILS_MASTER_KEY
Создадим файл схему ecs-params touch ecs-params-worker.production.yml:
version: 1 task_definition: ecs_network_mode: bridge task_size: cpu_limit: 768 mem_limit: 0.5GB services: worker_app: essential: true
Создаем задачу для будущего сервиса ECS:
# create task definition for a docker container ecs-cli compose \ --file docker-compose-worker.production.yml \ --project-name "$CLUSTER_NAME-worker" \ --ecs-params ecs-params-worker.production.yml \ --cluster-config $CLUSTER_NAME \ create
И создадим сервис для этой задачи:
aws ecs create-service \ --service-name "spreeproject-worker" \ --cluster $CLUSTER_NAME \ --task-definition "$CLUSTER_NAME-worker:$TASK_NUMBER" \ --desired-count 1 \ --deployment-configuration "maximumPercent=200,minimumHealthyPercent=50"
Continuous Deployment
Какую проблему решаем
Поскольку поддерживаемых окружений стало больше, нужно упростить процесс обновления приложения.
Решение
В основе термина Continuous deployment лежит слово Continuous, которое, несмотря на широкое употребление, разработчики трактуют по-разному. Понимание этого слова заключается в определении трех аспектов:
- Continuous Delivery‒ отвечает за поставку бизнесу каждой части функционала постепенно. Такой подход позволяет получить отклик от клиента своевременно и, при необходимости, сделать изменения.
- Continuous Deployment‒ отвечает за то, чтобы весь новый функционал после тестирования сразу же интегрировался в работающее приложение без ручного вмешательства инженеров DevOps.
- Continuous Integration‒ ключевой компонент практики Agile Development. Основывается на постоянном попадании кода в центральный репозиторий после успешного прохождения тестов. Основные цели Continuous Integration — поиск и устранение потенциальных проблем как можно быстрее, улучшение качества ПО и сокращение времени на выпуск обновлений.
В качестве сервиса, который позволяет реализовать Continuous методологию, мы будем использовать CircleCI. Для Continuous Deployment будем использовать ecs-deploy. Все связанные скрипты для развертывания приложения будем хранить в директории config/deploy. Там же определим список зависимых инструментов для развертывания.
Конфигурация процесса деплоя
Создадим файл dependencies.txt
cd ../spree-docker-demo mkdir config/deploy touch config/deploy/dependencies.txt
И укажем в нем пакеты, которые понадобятся для деплоя:
ecs-deploy==1.4.3 awscli==1.16.38
Далее в deploy.shсоздадим собственный скрипт с удобным интерфейсом для обновления наших сервисов на ECS:
mkdir config/deploy/lib touch config/deploy/lib/deploy.sh
#!/bin/bash # Required variables: # - region # ECR Region # - aws-access-key # AWS Access Id # - aws-secret-key # AWS Secret Key # - service # Service's name # - repo # Service's repository # - cluster # Service's cluster # - name # Application's container name # - task # AWS ECS task name set -e deploy() { while [[ $# -gt 0 ]] do key="$1" case $key in --region) REGION="$2" shift shift ;; --aws-access-key) AWS_ACCESS_KEY_ID="$2" shift shift ;; --aws-secret-key) AWS_SECRET_ACCESS_KEY="$2" shift shift ;; --repo) REPO="$2" shift shift ;; --cluster) CLUSTER="$2" shift shift ;; --task) TASK="$2" shift shift ;; --service) SERVICE="$2" shift shift ;; --name) APP_NAME="$2" shift shift ;; --skip-build) SKIP_BUILD="$2" shift shift ;; *) echo "Unknown option $1\n" shift shift esac done VERSION=${CIRCLE_BRANCH:="$(git rev-parse --abbrev-ref HEAD)"} BUILD_APP=$APP_NAME:$VERSION BUILD_REPO=$REPO:$VERSION echo "📦 Install dependencies" dependencies_setup echo "🐳 Build docker image $BUILD_APP" push_to_docker echo "🚀 Deploy $BUILD_APP to $CLUSTER:$SERVICE" ecs_deploy echo '✅ Deploy successfully finished' } # Устанавливаем пакеты, необходимые для деплоя dependencies_setup () { python3 -m venv venv . venv/bin/activate pip install -r config/deploy/dependencies.txt } # Пушим текущую версию в репозиторий push_to_docker() { if [ -n "$SKIP_BUILD" ]; then echo 'Skip build' else $(aws ecr get-login --region $REGION --no-include-email) docker build --cache-from=$BUILD_APP -t $BUILD_APP . docker tag $BUILD_APP $BUILD_REPO docker push $BUILD_REPO fi } # Деплоим сервис ecs_deploy() { aws ecs update-service \ --service $SERVICE \ --cluster $CLUSTER \ --task-definition $TASK \ --force-new-deployment } exec "$@"
После того как мы создали скрипт деплоя приложения на ECS, создадим скрипты для деплоя staging- и production-окружений.
Конфигурация деплоя Staging окружения
После, опишим скрипт для деплоя основного сервиса на staging:
touch config/deploy/staging.sh chmod +x config/deploy/staging.sh
AWS_ACCESS_KEY_ID и AWS_SECRET_ACCESS_KEY будут взяты из окружения, где запускается этот скрипт:
source 'config/deploy/lib/deploy.sh' RAILS_ENV='staging' deploy \ --name 'spreeproject_server_app' \ --aws-access-key "$AWS_ACCESS_KEY_ID" \ --aws-secret-key "$AWS_SECRET_ACCESS_KEY" \ --region 'us-east-1' \ --repo "$YOUR_ECR_ID.dkr.ecr.us-east-1.amazonaws.com/spreeproject/server_app" \ --cluster 'spreeproject-staging' \ --service 'spreeproject' --task 'spreeproject-staging'
Конфигурация деплоя Production-окружения
Внимание! Процесс обновления production-сервера необходимо контролировать. Поскольку возможна ситуация ошибочного мержа изменений в production-ветку, то настоятельно рекомендуется избежать использования данного скрипта вместе с CircleCI или другими инструментами, реализующими continuous delivery.
Опишем скрипт для деплоя основного сервиса на production:
touch config/deploy/production.sh chmod +x config/deploy/production.sh
source 'config/deploy/lib/deploy.sh' RAILS_ENV='production' # Deploy server app deploy \ --name 'spreeproject_server_app' \ --aws-access-key "$AWS_ACCESS_KEY_ID" \ --aws-secret-key "$AWS_SECRET_ACCESS_KEY" \ --region 'us-east-1' \ --repo "$YOUR_ECR_ID.dkr.ecr.us-east-1.amazonaws.com/spreeproject/server_app" \ --cluster 'spreeproject-production' \ --service 'spreeproject' --task 'spreeproject-production' # Deploy worker app deploy \ --name 'spreeproject_worker_app' \ --aws-access-key "$AWS_ACCESS_KEY_ID" \ --aws-secret-key "$AWS_SECRET_ACCESS_KEY" \ --region 'us-east-1' \ --repo "$YOUR_ECR_ID.dkr.ecr.us-east-1.amazonaws.com/spreeproject/server_app" \ --cluster 'spreeproject-production' \ --service 'spreeproject-worker' --task 'spreeproject-production-worker' --skip-build true
Создадим production ветку приложения:
git checkout -b production
Примечание: перед деплоем вручную создайте следующие теги, чтобы переиспользовать ранее созданные слои:
docker tag spreeproject_server_app:latest spreeproject_server_app:production docker tag spreeproject_web_server:latest spreeproject_web_server:production
Создадим файл с конфигурацией CircleCI:
touch circle.yml
app_image: &app_image docker: - image: circleci/ruby:2.5-node environment: RAILS_ENV: test DB_HOST: localhost DB_PORT: 5432 DB_NAME: spreedemo_test DB_USERNAME: postgres DB_PASSWORD: postgres SECRET_KEY_BASE: SECRET_KEY_BASE DEVISE_SECRET_KEY: DEVISE_SECRET_KEY - image: circleci/postgres:10 environment: POSTGRES_USER: postgres POSTGRES_PASSWORD: postgres POSTGRES_DB: spreedemo_test deploy_image: &deploy_image docker: - image: circleci/python:3.7 caches: - &bundle_cache spreedemo-bundle-v1-{{ checksum "Gemfile.lock" }} - &docker_images_cache spreedemo-docker-v1-{{ checksum "Gemfile.lock" }}-{{ checksum "Dockerfile" }} - &deploy_dependencies_cache spreedemo-pip-v1-{{ checksum "config/deploy/dependencies.txt" }} steps: - &restore_bundle_cache restore_cache: name: Restore bundle cache keys: - *bundle_cache - &store_bundle_cache save_cache: name: Store bundle cache key: *bundle_cache paths: - vendor/bundle - &restore_docker_images_cache restore_cache: name: Restore docker images cache keys: - *docker_images_cache - &store_docker_images_cache save_cache: name: Store docker images cache key: *docker_images_cache paths: - images - &load_docker_image run: name: Load Docker image layer cache command: set +o pipefail && docker load -i images/spreeproject_server_app-$CIRCLE_BRANCH.tar | true - &save_docker_image run: name: Save Docker image layer cache command: mkdir -p images && docker save -o images/spreeproject_server_app-$CIRCLE_BRANCH.tar spreeproject_server_app:$CIRCLE_BRANCH - &restore_deploy_dependencies_cache restore_cache: name: Restore deploy dependecies keys: - *deploy_dependencies_cache - &store_deploy_dependencies_cache save_cache: name: Store deploy dependecies key: *deploy_dependencies_cache paths: - venv - &bundle_install run: bundle install --path vendor/bundle - &migrate_db run: bundle exec rails db:migrate - &run_test run: name: Run tests command: bundle exec rspec --color -f d spec - &deploy run: name: Deploy command: config/deploy/$CIRCLE_BRANCH.sh version: 2 jobs: build_and_test: <<: *app_image steps: - checkout - *restore_bundle_cache - *bundle_install - *store_bundle_cache - *migrate_db - *run_test deploy: <<: *deploy_image steps: - checkout - setup_remote_docker - *restore_deploy_dependencies_cache - *restore_docker_images_cache - *load_docker_image - *deploy - *save_docker_image - *store_docker_images_cache - *store_deploy_dependencies_cache workflows: version: 2 build: jobs: - build_and_test - deploy: requires: - build_and_test filters: branches: only: - dev - staging
Важно! Для того, чтобы инстансы CircleCI могли развертывать приложение на AWS ECS, ему необходимо предоставить AWS credentials. Для этого добавьте их в setting проекта.
Результат:после мержа определенных изменений в staging или dev branches будет происходить автоматический запуск тестов, по успешному прохождению которых будет происходить деплой.
Делаем выводы
Целью этого туториала было заинтересовать Ruby/Ruby on Rails разработчиков Docker-ом, показать способы развертывания на AWS с рабочими примерами. Я хотел собрать полезный туториал в едином формате, чтобы человек, который до этого не работал с Docker и ECS, сэкономил время на поиск информации, которая могла бы помочь решить ему задачу деплоя. Надеюсь, что у меня это получилось :) Буду рад вашим комментариям, замечаниям и советам и отвечу на каждый из них.
Спасибо команде RubyGarage за помощь в подготовке этого туториала, без вас этот туториал не получился бы таким, как он есть. Спасибо Владимиру Воробьевуза вдохновение, менторинг и технически правки, Анастасии Щербаньза классные иллюстрации, Марине Завийбородеза фасилитацию процесса и команде DOU за публикацию!