Після кількох годин роботи над інтеграцією Circle CI / Elastic Beanstalk / Docker, я вирішив, що буде корисно записати свої нотатки, щоб заощадити час наступного разу, коли мені знову потрібно буде налаштувати подібну систему, і уникнути довгих ночей, проклинаючи богів (хмар) інтернету.
Ми припускаємо наступне:
- розгортання на Elastic Beanstalk для одного контейнера (EB),
- використання Circle як CI-двигуна, я впевнений, що інші сервіси (наприклад, Travis, Codeship тощо) надають еквівалентні функціональності,
- використання приватного реєстру для зберігання скомпільованих Docker-образів: я використовую Quay.io, оскільки він дешевший за Docker Hub і цілком підходить для моїх потреб,
- розгортання Python Django додатка, хоча це не є строго необхідним, оскільки більшість кроків підходять для будь-якого веб-додатка.
Є багато документації, пов'язаної з EB, а також кілька прикладів, які можуть бути хорошою відправною точкою для розуміння того, що потрібно для розгортання Docker-образу в середовищі одного контейнера на EB (наприклад, тут та тут), але вони не охоплюють усі аспекти реальних реалізацій.
Метою цього матеріалу є надання швидкого покрокового посібника для створення та розгортання додатка на EB, а також опис деяких деталей, які розкидані по різних документах Circle, EB та Docker.
Крок 1. Elastic Beanstalk на AWS
За допомогою веб-консолі AWS, перейдіть до IAM і створіть нового користувача, надайте йому повний доступ до EB, збережіть ключ і секретний ключ і відредагуйте файл ~/.aws/config на вашому комп'ютері для створення нового профілю, він має виглядати наступним чином:
[profile eb-admin]
aws_access_key_id = ACCESSKEY
aws_secret_access_key = SECRETKEY
Знову в AWS Web Console, перейдіть до Elastic Beanstalk і створіть новий веб додаток, вибравши наступні налаштування:
- Docker середовище,
- налаштуйте авто-масштабування,
- не використовуйте RDS, що йде разом з EB, краще налаштувати власну RDS і підключити її до EB пізніше,
- активуйте VPC,
- встановіть інші налаштування, враховуючи, що ви маєте базові знання про AWS для налаштування груп безпеки, ключів тощо.
Тепер на вашому комп'ютері створіть Python віртуальне середовище (використовуючи virtualenvwrapper тут) та встановіть інструменти командного рядка AWS:
mkvirtualenv aws
# ймовірно не обов'язково, але стане в нагоді пізніше…
pip install awscli
pip install awsebcli
Час налаштувати EB на локальному комп'ютері та підключити його до додатка, створеного в AWS Web Console! Перейдіть в директорію, де знаходиться ваш веб-додаток (у моєму випадку це місце, де знаходиться manage.py для Django), потім підніміться на один рівень вище і виконайте (припускаючи, що ми запускаємо EB в європейському центрі обробки даних Amazon, EU-West):
eb init --region eu-west-1 --profile eb-admin
Ініціалізація запитає кілька питань:
- вона має показати EB-додатки, які ви створили у своєму AWS акаунті, виберіть той, який хочете використовувати з цього списку, він має відповідати тому, що був щойно створений у AWS Web Console,
- усі інші параметри мають автоматично налаштуватися відповідно до налаштувань в Інтернеті.
Я думаю, що ті самі параметри можна налаштувати вручну, викликавши опції для команди eb init, але на цьому етапі я б не рекомендував це робити.
Якщо майстер налаштування не працює (наприклад,
через наявність незвичних файлів, які спонукають до автоматичного визначення), пройдіть через запитання ініціалізації, вибравши наступне:
- пропустіть автоматичне визначення платформи та виберіть Docker (якщо знайдений Dockerfile, ймовірно, не буде запитуватись про деталі платформи)
- виберіть існуючу конфігурацію ключа ssh
Після цього у вас повинна з’явитись нова директорія .elasticbeanstalk, що містить файл config.yml, який відображає налаштування додатка, які ви щойно створили. Додайте рядок до вашого файлу .gitignore, оскільки команда eb init може надто активно ігнорувати файли, які вам можливо доведеться поділитися з вашою командою:
!.elasticbeanstalk/config.yml
Тепер вам потрібно трохи налаштувати AWS, щоб EB міг розгорнути додаток, зчитуючи конфігураційний файл з S3. Поверніться до IAM в AWS Web Console, ви повинні побачити 2 нові створені ролі (детальніше в цьому статті):
- роль екземпляра (або роль EC2), яку використовує EB для розгортання та доступу до інших ресурсів
- роль сервісу, яку використовує EB для моніторингу працюючих екземплярів і надсилання сповіщень
додайте дозволи READ для S3 до ролі екземпляра, щоб EB міг зчитувати необхідні файли при розгортанні. Врешті-решт, перейдіть до S3, там має бути новий бакет з кількома файлами, пов'язаними з EB, запам'ятайте його ім'я, ви будете використовувати його пізніше.
Крок 2. Docker
Створіть приватний репозиторій на Quay.io: я припускаю, що ми будемо запускати суперсекретний код, який ми не хочемо зберігати на публічному реєстрі Docker, тому я додаю додаткову інформацію для дозволу Elastic Beanstalk аутентифікуватися на приватному реєстрі.
- на Quay.io створіть робот-акаунт і призначте йому права на запис до приватного репозиторію
- завантажте файл .dockercfg, пов’язаний з робот-акаунтом, і покладіть його І ТУТ в домашню директорію на вашому комп'ютері (щоб ви могли аутентифікуватися на Quay.io з командного рядка), І в корінь вашого репозиторію (використовуватиметься пізніше Circle)
Тепер створіть ваш Dockerfile — є багато хороших прикладів, мені подобається один від +rehabstudio, який запускає простий Flask тестовий додаток з Gunicorn і NGINX, ви можете знайти його тут — і переконайтесь, що він містить дві наступні інструкції:
EXPOSE 80
CMD [“your-startup-file.sh”]
your-startup-file.sh — це в основному щось, що запускає веб-сервер, або веб-додаток, або будь-яку іншу службу, яка слухає на порту 80 і генерує певний вихід. У моєму випадку це Supervisor, який запускає NGINX та Gunicorn.
Коли ви будете задоволені вашим Docker-образом, запустіть його на Quay.io за допомогою команди
docker push quay.io/my_account/my_image:latest
Тепер настав час інтегрувати автоматичне тестування та побудову в Circle.
Крок 3.
Circle CI
Створіть акаунт на Circle, авторизуючись через Github, і дозволяйте йому підключити репозиторій Github, який ви хочете використовувати для безперервної інтеграції (CI).
Створіть кастомний файл circle.yml у корені вашого репозиторію: цей файл вказуватиме Circle, щоб запускати тести та розгортати ваш додаток на EB при коміті в гілки релізу, він повинен виглядати приблизно так:
machine:
python:
version: 2.7.3
services:
— dockerdependencies:
cache_directories:
— “~/docker”pre:
# використовується для запуску скрипту розгортання
— pip install awscli
# використовується для аутентифікації на quay.io
— cp .dockercfg ~override:
# кешуємо тестовий Docker образ на Circle CI
— if [[-e ~/docker/image.tar]]; then docker load -i ~/docker/image.tar; fi
— docker build -f Dockerfile.test -t test ./project_root/
— mkdir -p ~/docker; docker save test > ~/docker/image.tartest:
post:
# запускаємо тести
— docker run test python runtests.pydeployment:
staging:
branch: release/stg
commands:
# цей скрипт може бути складнішим
# з кількома додатковими параметрами
— ./deploy.sh $CIRCLE_SHA1 eb-stg-env
Цей yml файл інструктує Circle запускати тести на Docker образі і розгортати, якщо буде зроблено push в гілку release/stg і тести пройдуть успішно. Цікава особливість цього підходу в тому, що deploy.sh можна запускати (і, що важливо, тестувати!) локально.
Увага! Можливо, вам знадобиться використовувати приватні SSH ключі для доступу до вашого репозиторію і побудови Docker образу для розгортання, це абсолютно можливо, додавши ключі в середовище проекту Circle (перевірте це тут).
Крок 4. Розгортання
Гаразд, майже готово! Тепер нам потрібно створити файл deploy.sh, згаданий на попередньому кроці: цей файл автоматизує процес побудови нашого Docker образу для розгортання і поміщає його в таке місце, щоб EB міг його завантажити: ми використовуємо командний інтерфейс AWS для цього. Кроки тут досить прості:
- побудувати Docker образ і відправити на Quay.io
- створити файл Dockerrun для EB (деталі нижче) і відправити його в S3
- сказати EB створити нову версію додатка і розгорнути її
# deploy.sh
#!/bin/bash# назва образу для розгортання на quay.io
BUILD=”quay.io/my_account/my_image:$SHA1"# зберігаємо автентифікацію quay.io в S3
aws s3 cp .dockercfg s3://$EB_BUCKET/dockercfg# тег для розгортання
SHA1=$1# середовище Elastic Beanstalk для розгортання
EB_ENV=$2APP_NAME=”MyEBApp”# пам’ятаєте ім’я бакету, яке я просив запам’ятати
# вище в цьому пості? ось де ви його використовуєте!
EB_BUCKET=”bucket-where-EB-deploys-its-stuff”# куди поміщати речі в S3 бакет
PREFIX=”deploy/$SHA1"# будуємо головний образ
docker build -f Dockerfile.build -t $BUILD:$SHA1 .
docker push $BUILD:$SHA1# замінюємо змінні в DOCKERRUN_FILE
# щоб EB знав, звідки брати файли
DOCKERRUN_FILE=”Dockerrun.aws.json”
| sed ‘s||’$BUILD’|g’ \
| sed ‘s||’$SHA1'|g’ \
> $DOCKERRUN_FILEaws s3 cp $DOCKERRUN_FILE_WEB s3://$EB_BUCKET/$PREFIX/$DOCKERRUN_FILE
rm $DOCKERRUN_FILE# Створюємо версію додатка з файлу Dockerrun
echo “створення нової версії Elastic Beanstalk”aws elasticbeanstalk create-application-version \
--application-name $APP_NAME \
--version-label $SHA1 \
--source-bundle S3Bucket=$EB_BUCKET,S3Key=$PREFIX/$DOCKERRUN_FILE#
--environment-name $EB_ENV \
--version-label $SHA1
Що ж це за загадковий файл Dockerrun.aws.json? Це простий дескриптор, який говорить AWS, звідки забирати Docker образ, яку версію і за якими обліковими даними.
Нижче наведений шаблон файлу, де , і замінюються на змінні під час виконання скрипту deploy.sh, а dockercfg вказує EB, де знайти облікові дані для приватних Docker образів.
{
“AWSEBDockerrunVersion”: “1”,
“Authentication”: {
“Bucket”: “”,
“Key”: “dockercfg”
},
“Image”: {
“Name”: “:”,
“Update”: “true”
},
“Ports”: [{
“ContainerPort”: “80”
}],
“Logging”: “/var/eb_log”
}
Крок 5. Налаштування, змінні середовища та інше
Docker на EB потребує змінних середовища для коректної роботи! Ви можете або налаштувати їх безпосередньо в EB, або запустити скрипт, який автоматизує цей процес, використовуючи стандартний формат, прийнятий командним інтерфейсом AWS, за допомогою параметра update-environment. Ось приклад формату параметрів AWS (припустимо, що він збережений під назвою EB-options.txt.template
):
[
{
“Namespace”: “aws:elasticbeanstalk:application:environment”,
“OptionName”: “DJANGO_SETTINGS_MODULE”,
“Value”: “$DJANGO_SETTINGS_MODULE”
},
{
“Namespace”: “aws:elasticbeanstalk:application:environment”,
“OptionName”: “SECRET_KEY”,
“Value”: “$SECRET_KEY”
}
]
Цей файл можна обробити, замінивши локальні змінні середовища та надіславши їх до EB:
# update-env.sh
#!/bin/bashOPTIONS_FILE=”EB-options-$(date +%Y-%m-%d:%H:%M:%S).txt”
cat EB-options.txt.template | envsubst > $OPTIONS_FILEaws elasticbeanstalk update-environment \
--environment-name $EB_ENV \
--option-settings file://$OPTIONS_FILErm $OPTIONS_FILE
Кінець!
Це було досить складно, але Ура! Коли ви побачите це в роботі на EB, це справжнє задоволення!
Перекладено з: Continuous Integration with Docker on Amazon Elastic Beanstalk