Хабрахабр

[Из песочницы] Deploy Symfony + React приложения на AWS посредством CI

Добрый день, в данной статье я покажу как развернуть Symfony 4 приложение на AWS. В официальной документации есть пример подобного процесса, однако мой вариант не столь тривиален, как загрузка zip архива с приложением. На дворе 2019, в моде docker, микросервисная архитектура и CI/CD практики наконец-то начинают входит в инструментарий не только DevOps-инженеров, но и простых смертных разработчиков. Чтобы статья была более интересна, я добавил фронт на React.JS, для охвата потребностей большей массы людей, если ваше приложение не использует Encore — не беда, я укажу как изменить Docker-файл для вас, поддержка React.JS тут влияет только на него. Кому будет интересен данный туториал? В первую очередь он направлен на PHP-разработчиков, желающих изменить свою практику деплоя — отойти от привычных канонов и воспользоваться docker для паковки своего приложения и выкладки образа. Но можно пойти чуть глубже, и дальнейшее повествование будет направлено на автоматический деплой приложения из Git'а посредством CI/CD платформы (будет использован CircleCI, но если интересует конфиг Gitlab'а, пишите в комментариях, я приложу). По сути, тут абсолютно не важно React/PHP ли у вас приложение или, скажем, на .NET Core, данная часть будет интересна разработчикам для получения навыков автоматизации деплоя в целом. Исходный код доступен в github-репозитории, ссылка в конце статьи. Ну что же, поехали!
Я предполагаю, что у вас имеется собственное Symfony приложение, я же в демонстрационных целях набросал «hello, world!», содержащее следующие пакеты:

На данный момент структура папок у вас должна быть такая: `symfony/webpack-encore-bundle symfony/form symfony/orm-pack symfony/profiler-pack symfony/security-bundle symfony/twig-bundle symfony/validator symfony/phpunit-bridge` — минимальный джентельменский набор.

image

Не буду заострять внимание на регистрации и активации пробного периода AWS, на данном этапе нам нужно создать 2 инстанса БД — я буду использовать 2 типа окружения: STG (staging) для тестирования внедрения новых «фич» и PROD (production) как непосредственно «боевой» сервер. Теперь необходимо настроить облачную инфраструктуру. В качестве СУБД для данного примера я использовал PostgreSQL, вы вольны выбирать любую подходящую вам, перейдите в сервис RDS и создайте 2 инстанса необходимой вам мощности и объема. О преимуществах, managed service БД написано немало статей, к тому же мы преследуем в данном руководстве главным образом удобство для разработчика, потому пользуемся именно RDS, а не поднимаем свой отдельный сервер БД. Так как «из коробки» в Symfony для нас доступен файл .env, будем использовать его, например, для PROD, а для STG создадим его копию .env.stg и изменим APP_ENV=dev на APP_ENV=stg в .env.stg и APP_ENV=dev на APP_ENV=prod в .env, а также впишем параметры подключения к Базе Данных для каждого из созданных экземпляров.

Как известно, Symfony-зависимости устанавливаются через composer, для его установки воспользуемся файлом composer.sh, который положим в корень проекта: Прекрасно, начало положено!

composer.sh

#!/bin/sh EXPECTED_SIGNATURE="$(wget -q -O - https://composer.github.io/installer.sig)"
php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
ACTUAL_SIGNATURE="$(php -r "echo hash_file('sha384', 'composer-setup.php');")" if [ "$EXPECTED_SIGNATURE" != "$ACTUAL_SIGNATURE" ]
then >&2 echo 'ERROR: Invalid installer signature' rm composer-setup.php exit 1
fi php composer-setup.php --quiet
RESULT=$?
rm composer-setup.php
exit $RESULT

Это инструкция по программной установке с сайта composer.

Теперь, для каждого из окружений создадим свой Dockerfile в корне проекта:

Dockerfile.stg (staging)

FROM php:7.2.19-apache EXPOSE 80 RUN mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini" && a2enmod rewrite
RUN sed -ri -e 's!memory_limit = 128M!memory_limit = 256M!g' "$PHP_INI_DIR/php.ini" RUN apt-get update && apt-get install -y \ wget \ curl \ libfreetype6-dev \ libjpeg62-turbo-dev \ libpng-dev \ libzip-dev \ zip \ libpq-dev \ && docker-php-ext-configure gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ \ && docker-php-ext-configure zip --with-libzip \ && docker-php-ext-configure pgsql -with-pgsql=/usr/local/pgsql \ && docker-php-ext-install -j$(nproc) gd \ && docker-php-ext-install zip \ && docker-php-ext-install pdo pdo_pgsql pgsql WORKDIR /var/www ENV APACHE_DOCUMENT_ROOT /var/www/public
RUN sed -ri -e 's!/var/www/html!$!g' /etc/apache2/sites-available/*.conf
RUN sed -ri -e 's!/var/www/!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/apache2.conf /etc/apache2/conf-available/*.conf
RUN echo "ServerName localhost" >> /etc/apache2/apache2.conf COPY ./composer.sh ./
RUN chmod +x ./composer.sh && ./composer.sh && mv composer.phar /usr/local/bin/composer RUN curl -sL https://deb.nodesource.com/setup_10.x | bash - \ && apt-get install -y nodejs RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - \ && echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list \ && apt-get update -qq \ && apt-get install -y yarn COPY ./ ./
COPY ./.env.stg ./.env RUN composer install && yarn && yarn run build

и

Dockerfile (production)

FROM php:7.2.19-apache EXPOSE 80 RUN mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini" && a2enmod rewrite
RUN sed -ri -e 's!memory_limit = 128M!memory_limit = 256M!g' "$PHP_INI_DIR/php.ini" RUN apt-get update && apt-get install -y \ wget \ curl \ libfreetype6-dev \ libjpeg62-turbo-dev \ libpng-dev \ libzip-dev \ zip \ libpq-dev \ && docker-php-ext-configure gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ \ && docker-php-ext-configure zip --with-libzip \ && docker-php-ext-configure pgsql -with-pgsql=/usr/local/pgsql \ && docker-php-ext-install -j$(nproc) gd \ && docker-php-ext-install zip \ && docker-php-ext-install pdo pdo_pgsql pgsql WORKDIR /var/www ENV APACHE_DOCUMENT_ROOT /var/www/public
RUN sed -ri -e 's!/var/www/html!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/sites-available/*.conf
RUN sed -ri -e 's!/var/www/!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/apache2.conf /etc/apache2/conf-available/*.conf
RUN echo "ServerName localhost" >> /etc/apache2/apache2.conf COPY ./composer.sh ./
RUN chmod +x ./composer.sh && ./composer.sh && mv composer.phar /usr/local/bin/composer RUN curl -sL https://deb.nodesource.com/setup_10.x | bash - \ && apt-get install -y nodejs RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - \ && echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list \ && apt-get update -qq \ && apt-get install -y yarn COPY ./ ./ RUN composer install && yarn && yarn run build

Файлы вполне можно использовать «как есть», никаких макросов для изменения не используется. Давайте пройдемся по содержимому Dockerfile'а, чтобы развеять налет «магии». В качестве «основы» мы используем официальный образ PHP 7.2.19 с интегрированным веб-сервером Apache (вы вольны использовать любой по своему усмотрению, настроить связку с Nginx и так далее, в данном примере я использую означенную выше как самую, на мой взгляд, удобную). Строка expose в данный момент нам не важна, сама по себе она ничего не делает, однако в дальнейшем ее будет использовать ElasticBeanstalk, которому она необходима для корректного развертывания. Следующие конструкции используют оптимизированные для production настройки PHP, рекомендованные производителем, активируют mod_rewrite для Apache и увеличивают максимальный объем памяти для PHP скрипта со 128 до 256 мб, что необходимо для корректной работы composer. Далее мы устанавливаем необходимые приложения, PHP-зависимости и расширения, и сразу их настраиваем. Рабочей директорией нашего приложения назначаем папку /var/www – туда будет скопирован исходный код нашего приложения. Так как apache по-умолчанию использует /var/www как энтрипоинт для своего хоста, а индексный файл symfony находится в /var/www/public, следующей конструкцией меняем apache document root. Затем мы последовательно устанавливаем composer, nodejs и yarn (если в своем приложении вы не используете encore/react.js, то последние из указанных два пункта вам не нужны). Наконец мы копируем наш исходный код и запускаем установку зависимостей через composer для symfony и yarn для react.js. Смысл отдельного Dockerfile’а для STG кроется в предпоследней инструкции для docker’а – копировании .env.stg в .env, таким образом в образе для STG .env-файл будет содержать актуальные для данного окружения параметры. Можете локально (разумеется при установленном docker) собрать образ, запустить и убедиться, что приложение работает и ничего больше для этой работы ему не требуется:

docker build -t tmp:stg -f Dockerfile.stg .
docker run -p 80:80 tmp:stg

для STG и

docker build -t tmp:prod .
docker run -p 80:80 tmp:prod

для PROD.
Мы можем использовать EC2, настраивать ELB/ASG и тд или же воспользоваться ElasticBeanstalk, что для нас в плане удобства просто подарок. Зайдите в раздел ElasticBeanstalk и создайте новое приложение, указав его название и описание. Затем создадите 2 окружения, о которых говорилось ранее: STG и PROD, оба окружения создайте как окружение веб-сервера (Web server environment), в качестве платформы укажите “Docker”, а в качестве кода приложения оставьте Sample application. Деплой на ElasticBeanstalk осуществляется посредством «заливки» файлов проекта или инструкций, обычно в zip-архиве. В нашем случае флоу будет таким: собираем docker-образ нашего приложения, загружаем его в хранилище и загружаем вместо архива с исходниками или docker-образа инструкцию, которая укажет ElasticBeanstalk взять образ с удаленного сервера и развернуть. И все это – автоматически.

Тут есть 2 варианта: Начнем с создания репозитория для хранения docker-образов.

В данном случае вы или держите где-то свой собственный регистр образов или пользуетесь приватным облаком. 1 – у вас проект приватный, код его закрыт и репозиторий, соответственно, тоже должен быть закрыт. Для данных целей в AWS есть ECR, вы можете создать репозиторий там, но никто вас к этому не принуждает.

2 – у вас проект с открытым кодом и вы можете использовать dockerhub.

Первое, что нам понадобится это создание самого репозитория, после этого вы получите его уникальный URI. В нашем примере код хоть и открыт, но я покажу как использовать именно закрытые репозитории, после понимания данного процесса подключение образа из dockerhub не составит труда. Дальнейшее повествование пойдет для сторонних (не AWS ECR репозиториях и их интеграции), для ECR напишу после этого.

И так, авторизуемся в выбранном сервисе хранения регистров ваших образов: После создания репозитория, нам необходимо авторизоваться на в данном сервисе и тут есть небольшая хитрость… Зайдите в настройки своего локально установленного docker’а и проверьте, чтобы у вас была убрана возможность сохранения паролей во внешнем хранилище (для пользователей macOS: “Securely store docker logins in macOS Keychain”), иначе необходимый нам конфигурационный файл будет пуст.

docker login -u LOGIN -p PASSWORD REGISTRY

после удачной аутентификации в конфигурационном файле ~/.docker/config.json появится конструкция следующего вида:

"REGISTRY" : { "auth" : "BASE64_ENCODED_TOKEN"
}

Если не появилась, еще раз проверьте настройку docker, описанную выше.

Теперь все готово, чтобы приготовить файл-инструкцию для ElasticBeanstalk – Dockerrun.aws.json, его код будет таким:

Dockerrun.aws.json

{ "AWSEBDockerrunVersion": "1", "Authentication": { "Bucket": "BUCKET_ID", "Key": "KEY_PATH" }, "Image": { "Name": "IMAGE_URL", "Update": "true" }, "Ports": [ { "ContainerPort": "80" } ]
}

В общем виде инструкция выглядит так: авторизовавшись с помощью ключа, расположенного по KEY_PATH в S3-хранилище BUCKET_ID, загрузить образ по IMAGE_URL перезаписав сохраненный, запустить его пробросив 80 порт на такой же порт контейнера. Теперь про использованные константы:

BUCKET_ID – это автоматически созданный для вас «рюкзак» в сервисе S3, имеющий вид elasticbeanstalk-REGION-HASH, именно там система располагает служебные файлы для вашего ElasticBeanstalk, в том числе и файлы приложения, которые вы загружаете по кнопке «Upload and deploy».

KEY_PATH – путь до авторизационного файла к хранилищу образов, я использую формат APP_NAME/cr.json, то есть в папку внутри BUCKET_ID под именем моего приложения (создаю, если пока нет) кладу файл cr.json, содержащий код, полученный после авторизации в регистре образов локально:

BUCKET_ID/APP_NAME/cr.json

{ "REGISTRY" : { "auth" : "BASE64_ENCODED_TOKEN" }
}

IMAGE_URL – это уникальный URI вашего регистра образов + тег самого образа, тут все должно быть понятно.

Все, теперь можем загрузить данный файл как версию нашего приложения в ElasticBeanstalk, и он сам подтянет указанный образ и развернет его.

А чтобы было совсем интересно, я реализую последовательность шагов для следующего флоу: для всех коммитов НЕ в мастер-ветку образ будет собираться и разворачиваться в STG окружении, а если мы пушим в мастер, или что лучше, его вообще закрыть и наливать только merge request’ами, то код будет деплоиться на PROD. Осталось автоматизировать данный процесс. Для данной реализации нам понадобится инструкция для заливки не latest-образов, скопируйте Dockerrun.aws.json в Dockerrun.aws.stg.json, а сам Dockerrun.aws.json переименуйте в Dockerrun.aws.prod.json (просто для удобства). Таким образом мы получим в PROD актуальный мастер, в котором все должно быть хорошо, а ветки для разработки и тестирования нового кода в STG.

Единственное, что отличает Dockerrun.aws.stg.json от Dockerrun.aws.prod.json – это IMAGE_URL:

Dockerrun.aws.stg.json

{ "AWSEBDockerrunVersion": "1", "Authentication": { "Bucket": "BUCKET_ID", "Key": "KEY_PATH" }, "Image": { "Name": "IMAGE_URL:dev", "Update": "true" }, "Ports": [ { "ContainerPort": "80" } ]
}

Как я уже говорил в начале статьи, в качестве CI/CD я буду использовать CircleCI, который по личным ощущениям быстрее GitlabCI, если использовать бесплатную SaaS версию. Бесплатный Travis бы подошел, но так как с приватными git-репозиториями он работать не умеет, я не стал специально проводить демонстрацию на нем, дабы не было разочарования, когда такая возможность понадобится. Настройку проекта в CircleCI я оставлю читателям для самостоятельного изучения, сам же приведу необходимые для деплоя инструкции — в корне нашего проекта создадим папку .circleci, в ней config.yml следующего содержания:

.circleci/config.yml

version: 2
jobs: build: machine: true steps: - checkout - run: echo "$CI_REGISTRY_PASSWORD" | docker login -u $CI_REGISTRY_USER --password-stdin $CI_REGISTRY - run: docker build -t $CI_REGISTRY/$CI_REGISTRY_ID:dev -f Dockerfile.stg . - run: docker push $CI_REGISTRY/$CI_REGISTRY_ID:dev build-master: machine: true steps: - checkout - run: echo "$CI_REGISTRY_PASSWORD" | docker login -u $CI_REGISTRY_USER --password-stdin $CI_REGISTRY - run: docker build -t $CI_REGISTRY/$CI_REGISTRY_ID:latest . - run: docker push $CI_REGISTRY/$CI_REGISTRY_ID:latest deploy-stg: docker: - image: circleci/python:latest steps: - checkout - run: sudo pip install awsebcli --upgrade - run: | mkdir ~/.aws touch ~/.aws/config chmod 600 ~/.aws/config echo "[profile eb-cli]" > ~/.aws/config echo "aws_access_key_id=$AWS_ACCESS_KEY_ID" >> ~/.aws/config echo "aws_secret_access_key=$AWS_SECRET_ACCESS_KEY" >> ~/.aws/config - run: eb init --region EB_REGION --platform Docker EB_APP - run: cp Dockerrun.aws.stg.json Dockerrun.aws.json - run: eb use EB_ENV_STG --region EB_REGION - run: eb deploy -v --staged --profile eb-cli deploy-prod: docker: - image: circleci/python:latest steps: - checkout - run: sudo pip install awsebcli --upgrade - run: | mkdir ~/.aws touch ~/.aws/config chmod 600 ~/.aws/config echo "[profile eb-cli]" > ~/.aws/config echo "aws_access_key_id=$AWS_ACCESS_KEY_ID" >> ~/.aws/config echo "aws_secret_access_key=$AWS_SECRET_ACCESS_KEY" >> ~/.aws/config - run: eb init --region EB_REGION --platform Docker EB_APP - run: cp Dockerrun.aws.prod.json Dockerrun.aws.json - run: eb use EB_ENV_STG --region EB_REGION - run: eb deploy -v --staged --profile eb-cli workflows: version: 2 build: jobs: - build: filters: branches: ignore: - master - deploy-stg: requires: - build filters: branches: ignore: - master build-deploy: jobs: - build-master: filters: branches: only: - master - deploy-prod: requires: - build-master filters: branches: only: - master

Сам флоу я расписал чуть раньше, тут он переведен в yaml-инструкции для CircleCI, пройдемся по реализации конкретных шагов. Важно отметить наличие определенных для CI переменных окружения, которые будут использованы им в процессе работы:

CI_REGISTRY, CI_REGISTRY_USER, CI_REGISTRY_PASSWORD необходимы для доступа в хранилище docker-образов — тоже самое, что мы клали в cr.json, только без base64

CI_REGISTRY / CI_REGISTRY_ID составляют уникальный URL образа, без тега

Зайдите в AWS IAM и создайте пользователя, добавьте его в группу администраторов и предоставьте только программный доступ. AWS_ACCESS_KEY_ID и AWS_SECRET_ACCESS_KEY — названия говорят за себя сами, это креды AWS пользователя, от имени которого CircleCI будет производить деплой. Помните, что AWS_SECRET_ACCESS_KEY доступен для просмотра/копирования лишь однажды, после того как нажмете ссылку «show», больше вы ее не увидите.

В чем «магия»? Вернемся к шагам конфигурации CircleCI. В процессе build мы последовательно авторизуемся в хранилище, собираем код на основе Dockerfile.stg под тегом XXX:dev и отправляем его в хранилище. Checkout загружает исходный код из git-ветки в текущую рабочую директорию, этот процесс повторяется в каждом джобике. build-master делает тоже самое, только для сборки использует «обычный» Dockerfile под тегом XXX:latest.

Следом мы копируем содержимое Dockerrun.aws.stg.json в новый файл Dockerrun.aws.json и, используя конкретный environment и регион, даем команду на деплой нашего приложения, применив созданный авторизационный профиль. deploy-stg устанавливает AWS EB CLI и создает авторизационный профиль в файле ~/.aws/config, который необходим для корректной работы CLI, далее инициализирует переменные для CLI – потребуется указать выбранный вами регион, платформу – всегда Docker и имя вашего приложения. Создадим для этого в корне проекта файл .ebignore: По умолчанию в результате работы данной команды весь код отслеживаемой ветки попадет в zip-архив, который будет загружен в ElasticBeanstalk и там распакован, но эта операция сравнительно затратная, потому мы и создали новый файл Dockerrun.aws.json, которого достаточно для развертывания созданного нами удаленного образа, и загрузить нам, по сути, нужно только его.

.ebignore

*
!Dockerrun.aws.json

Данный файл использует синтаксис .gitignore да и является он .gitignore, но не для Git CLI, а для AWS EB CLI. В данном файле я говорю CLI пропустить все файлы, кроме Dockerrun.aws.json. Все, теперь при выполнении джобика deploy-stg в ElasticBeanstalk отправится только созданный нами файл. deploy-prod делает все тоже самое, только копирует в Dockerrun.aws.json содержимое файла Dockerrun.aws.prod.json, и последнее, это указание в «формате» CircleCI последовательности джобов (deploy-stg после build и deploy-prod после build-master), и на какие ветки смотрят данные джобики (ignore: — master и only: — master).

Вам не нужно логиниться удаленно на ECR и создавать файл cr.json, так как ElasticBeanstalk “знает собрата в лицо”. Немного иначе дело состоит с AWS ECR, как я и обещал, вернемся к нему. Соответственно и Dockerrun.aws.json будет выглядеть иначе – там попросту будет отсутствовать блок аутентификации:

Dockerrun.aws.json (AWS ECR)

{ "AWSEBDockerrunVersion": "1", "Image": { "Name": "IMAGE_URL", "Update": "true" }, "Ports": [ { "ContainerPort": "80" } ]
}

Но как же тогда произойдет аутентификация? Дело в том, что сервис, который обращается к ECR имеет некий набор прав, которые в свою очередь базируются на определенных политиках безопасности. В нашем случае, когда деплой запускается посредством AWS CLI со стороннего сервера (из CI), применяется роль “aws-elasticbeanstalk-ec2-role”, найдите ее в AWS IAM в разделе ролей и прикрепите к ней дополнительную политику “AmazonEC2ContainerRegistryReadOnly”. Теперь загрузка из приватного репозитория его «соседу» удастся без ошибок.

Но это именно загрузка из той же VPC, посредством CLI же команда docker login то же не «без примудростей»: креденшалы для docker login вы должны получить (именно получить) посредством AWS CLI, для этого существует команда

aws ecr get-login --region REGION --no-include-email

Данная команда вернет вам строку вида docker login …, проще говоря, в консоли необходимо выполнить

eval $(aws ecr get-login --region EB_REGION --no-include-email)

В виду данных правил для AWS ECR файл-инструкций для CircleCI будет выглядеть следующим образом: Команда сначала получит строку для аутентификации, а затем запустит соответствующий процесс.

.circleci/config.yml (для AWS ECR)

version: 2
jobs: build: docker: - image: circleci/python:latest steps: - checkout - run: sudo pip install awscli --upgrade - run: | mkdir ~/.aws touch ~/.aws/config chmod 600 ~/.aws/config echo "[profile eb-cli]" > ~/.aws/config echo "aws_access_key_id=$AWS_ACCESS_KEY_ID" >> ~/.aws/config echo "aws_secret_access_key=$AWS_SECRET_ACCESS_KEY" >> ~/.aws/config - setup_remote_docker - run: eval $(aws ecr get-login --region EB_REGION --no-include-email) - run: docker build -t $CI_REGISTRY/$CI_REGISTRY_ID:dev -f Dockerfile.stg . - run: docker push $CI_REGISTRY/$CI_REGISTRY_ID:dev build-master: docker: - image: circleci/python:latest steps: - checkout - run: sudo pip install awscli --upgrade - run: | mkdir ~/.aws touch ~/.aws/config chmod 600 ~/.aws/config echo "[profile eb-cli]" > ~/.aws/config echo "aws_access_key_id=$AWS_ACCESS_KEY_ID" >> ~/.aws/config echo "aws_secret_access_key=$AWS_SECRET_ACCESS_KEY" >> ~/.aws/config - setup_remote_docker - run: eval $(aws ecr get-login --region EB_REGION --no-include-email) - run: docker build -t $CI_REGISTRY/$CI_REGISTRY_ID:latest . - run: docker push $CI_REGISTRY/$CI_REGISTRY_ID:latest deploy-stg: docker: - image: circleci/python:latest steps: - checkout - run: sudo pip install awsebcli --upgrade - run: | mkdir ~/.aws touch ~/.aws/config chmod 600 ~/.aws/config echo "[profile eb-cli]" > ~/.aws/config echo "aws_access_key_id=$AWS_ACCESS_KEY_ID" >> ~/.aws/config echo "aws_secret_access_key=$AWS_SECRET_ACCESS_KEY" >> ~/.aws/config - run: eb init --region EB_REGION --platform Docker EB_APP - run: cp Dockerrun.aws.stg.json Dockerrun.aws.json - run: eb use EB_ENV_STG --region EB_REGION - run: eb deploy -v --staged --profile eb-cli deploy-prod: docker: - image: circleci/python:latest steps: - checkout - run: sudo pip install awsebcli --upgrade - run: | mkdir ~/.aws touch ~/.aws/config chmod 600 ~/.aws/config echo "[profile eb-cli]" > ~/.aws/config echo "aws_access_key_id=$AWS_ACCESS_KEY_ID" >> ~/.aws/config echo "aws_secret_access_key=$AWS_SECRET_ACCESS_KEY" >> ~/.aws/config - run: eb init --region EB_REGION --platform Docker EB_APP - run: cp Dockerrun.aws.prod.json Dockerrun.aws.json - run: eb use EB_ENV_STG --region EB_REGION - run: eb deploy -v --staged --profile eb-cli workflows: version: 2 build: jobs: - build: filters: branches: ignore: - master - deploy-stg: requires: - build filters: branches: ignore: - master build-deploy: jobs: - build-master: filters: branches: only: - master - deploy-prod: requires: - build-master filters: branches: only: - master

Для поддержки docker-in-docker мы добавили setup_remote_docker на этапах сборок, остальное вам уже должно быть известно из содержания данной статьи. Вот и все, теперь структура нашего проекта выглядит следующем образом:

image

Никаких больше «движений» для выкладки обновлений. Попробуйте изменить код, запушить его в задачную ветку, а потом сделать мердж (пулл) реквест на мастер и принять его. Можно (и кому-то нужно) пойти далее, написать свои джобики для раскатки миграций, сделать промежуточный обязательный шаг прохождения автотестов и так далее, надеюсь данная статья положит начало для подобных экспериментов и последующих внедрений качественной и правильной доставки контента.

Исходный код на GitHub: tutorial-aws-symfony-ci

Теги
Показать больше

Похожие статьи

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Кнопка «Наверх»
Закрыть