Поиск по сайту:

Как настроить среду тестирования непрерывной интеграции с помощью Docker и Docker Compose в Ubuntu 14.04


Статья от Докера

Введение

Непрерывная интеграция (CI) относится к практике, при которой разработчики интегрируют код как можно чаще, а каждая фиксация проверяется до и после объединения в общий репозиторий с помощью автоматизированная сборка.

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

Docker Compose, независимо от приложения и базовой ОС.

В этом руководстве используется Docker Compose для демонстрации автоматизации рабочих процессов непрерывной интеграции.

Мы создадим Dockerized приложение Python типа «Hello world» и тестовый сценарий Bash. Для запуска приложения Python потребуются два контейнера: один для самого приложения и контейнер Redis для хранилища, который требуется в качестве зависимости для приложения.

Затем тестовый скрипт будет Dockerized в своем собственном контейнере, а вся среда тестирования будет перемещена в файл docker-compose.test.yml, чтобы мы могли убедиться, что выполняем каждое выполнение теста на новой и единая прикладная среда.

Этот подход показывает, как вы можете создавать идентичную, новую среду тестирования для вашего приложения, включая его зависимости, каждый раз, когда вы тестируете его.

Таким образом, мы автоматизируем рабочие процессы CI независимо от тестируемого приложения и базовой инфраструктуры.

Требования

Прежде чем начать, вам понадобится:

  • Сервер Ubuntu 14.04
  • Пользователь без полномочий root с привилегиями sudo. Вы можете следовать этому руководству, чтобы настроить это
  • Некоторое знакомство с Docker Compose; ссылки приведены для справки, так как мы установим программное обеспечение во время этого урока.
  • Тестирование, тестирование и еще раз (автоматическое) тестирование! Вы уже должны быть уверены в преимуществах тестирования и применения CI в рабочих процессах разработки.

Шаг 1 — Установите Докер

Если Docker еще не доступен на вашем сервере, проще всего загрузить и выполнить официальный скрипт установки Docker, который запрашивает пароль sudo (дополнительную информацию об установке Docker см. здесь):

  1. wget -qO- https://get.docker.com/ | sh

Чтобы упростить работу с Docker, добавьте своего пользователя в группу docker с помощью следующей команды:

  1. sudo usermod -aG docker $(whoami)

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

Шаг 2 — Установите Docker Compose

Docker Compose — это инструмент с открытым исходным кодом для определения и запуска многоконтейнерных приложений с использованием декларативного подхода. Чтобы установить Docker Compose, выполните следующие команды:

  1. sudo apt-get update
  2. sudo apt-get -y install python-pip
  3. sudo pip install docker-compose

Убедитесь, что docker-compose правильно установлен, выполнив:

  1. docker-compose --version

Вы должны увидеть что-то вроде:

docker-compose version 1.6.2, build 4d72027

Это должно сообщить вам версию docker-compose, которую вы установили.

Шаг 3 — Создайте приложение Python «Hello World»

На этом шаге мы создадим простое приложение Python в качестве примера приложения, которое вы можете протестировать с помощью этой настройки.

Создайте новую папку для нашего приложения, выполнив:

  1. cd ~
  2. mkdir hello_world
  3. cd hello_world

Отредактируйте новый файл app.py с помощью nano:

  1. nano app.py

Добавьте следующее содержимое:

from flask import Flask
from redis import Redis

app = Flask(__name__)
redis = Redis(host="redis")

@app.route("/")
def hello():
    visits = redis.incr('counter')
    html = "<h3>Hello World!</h3>" \
           "<b>Visits:</b> {visits}" \
           "<br/>"
    return html.format(visits=visits)

if __name__ == "__main__":
    app.run(host="0.0.0.0", port=80)

app.py — это веб-приложение на основе Flask, которое подключается к службе данных Redis. Строка visits=redis.incr(counter) увеличивает количество посещений и сохраняет это значение в Redis. Наконец, в формате HTML возвращается сообщение Hello World с количеством посещений.

Наше приложение имеет две зависимости, Flask и Redis, которые вы видите в первых двух строках. Эти зависимости должны быть определены до того, как мы сможем выполнить приложение. Отредактируйте новый файл:

  1. nano requirements.txt

Добавьте содержимое:

Flask
Redis

Шаг 4. Докеризация приложения «Hello World»

Docker использует файл с именем Dockerfile, чтобы указать необходимые шаги для создания образа Docker для данного приложения. Отредактируйте новый файл:

  1. nano Dockerfile

Добавьте следующее содержимое:

FROM python:2.7

WORKDIR /app

ADD requirements.txt /app/requirements.txt
RUN pip install -r requirements.txt

ADD app.py /app/app.py

EXPOSE 80

CMD ["python", "app.py"]

Давайте проанализируем значение каждой строки:

  • FROM python:2.7: указывает, что наш образ приложения «Hello World» создан из официального образа python:2.7 Docker
  • WORKDIR /app: устанавливает рабочий каталог внутри образа Docker в /app
  • ДОБАВИТЬ requirements.txt /app/requirements.txt: добавляет файл requirements.txt в наш образ Docker
  • ЗАПУСТИТЬ pip install -r requirements.txt: устанавливает зависимости приложения pip
  • ДОБАВИТЬ app.py /app/app.py: добавляет исходный код нашего приложения в образ Docker
  • EXPOSE 80: указывает, что наше приложение доступно через порт 80 (стандартный общедоступный веб-порт)
  • CMD [python, app.py]: команда, которая запускает наше приложение

Этот файл Dockerfile содержит всю информацию, необходимую для создания основного компонента нашего приложения \Hello World.

Зависимость

Теперь мы переходим к более сложной части примера. Наше приложение требует Redis в качестве внешней службы. Это тип зависимости, который может быть сложно настроить одинаковым образом каждый раз в традиционной среде Linux, но с Docker Compose мы можем каждый раз настраивать его повторяемым образом.

Давайте создадим файл docker-compose.yml, чтобы начать использовать Docker Compose.

Отредактируйте новый файл:

  1. nano docker-compose.yml

Добавьте следующее содержимое:

web:
  build: .
  dockerfile: Dockerfile
  links:
    - redis
  ports:
    - "80:80"
redis:
  image: redis

Этот файл Docker Compose показывает, как запустить приложение «Hello World» локально в двух контейнерах Docker.

Он определяет два контейнера: web и redis.

  • web использует текущую папку для контекста build и создает наше приложение Python из только что созданного файла Dockerfile. Это локальный образ Docker, который мы создали специально для нашего приложения Python. Он определяет ссылку на контейнер redis, чтобы иметь доступ к IP-адресу контейнера redis. Это также делает порт 80 общедоступным из Интернета, используя общедоступный IP-адрес вашего сервера Ubuntu.
  • redis выполняется из стандартного общедоступного образа Docker с именем redis.

Шаг 5 — Разверните приложение «Hello World»

На этом этапе мы развернем приложение, и к концу оно будет доступно через Интернет. Для целей вашего рабочего процесса развертывания вы можете рассматривать это как среду разработки, промежуточную или производственную среду, поскольку вы можете развертывать приложение одним и тем же образом множество раз.

Файлы docker-compose.yml и Dockerfile позволяют автоматизировать развертывание локальных сред, выполняя:

  1. docker-compose -f ~/hello_world/docker-compose.yml build
  2. docker-compose -f ~/hello_world/docker-compose.yml up -d

Первая строка создает образ нашего локального приложения из файла Dockerfile. Вторая строка запускает контейнеры web и redis в режиме демона (-d), как указано в файле docker-compose.yml. файл.

Убедитесь, что контейнеры приложений созданы, выполнив:

  1. docker ps

Это должно показать два запущенных контейнера с именами helloworld_web_1 и helloworld_redis_1.

Давайте проверим, что приложение запущено. Мы можем получить IP-адрес контейнера helloworld_web_1, выполнив:

  1. WEB_APP_IP=$(docker inspect --format '{{ .NetworkSettings.IPAddress }}' helloworld_web_1)
  2. echo $WEB_APP_IP

Убедитесь, что веб-приложение возвращает правильное сообщение:

  1. curl http://${WEB_APP_IP}:80

Это должно вернуть что-то вроде:

<h3>Hello World!</h3><b>Visits:</b> 1<br/>

Количество посещений увеличивается каждый раз, когда вы достигаете этой конечной точки. Вы также можете получить доступ к приложению «Hello World» из своего браузера, посетив общедоступный IP-адрес вашего сервера Ubuntu.

Как настроить для вашего собственного приложения

Ключом к настройке собственного приложения является размещение вашего приложения в собственном контейнере Docker и запуск каждой зависимости из своего собственного контейнера. Затем вы можете определить отношения между контейнерами с помощью Docker Compose, как показано в примере. Docker Compose более подробно рассматривается в этой статье Docker Compose.

В качестве другого примера того, как запустить приложение в нескольких контейнерах, прочитайте эту статью о запуске WordPress и phpMyAdmin с Docker Compose.

Шаг 6 — Создайте тестовый сценарий

Теперь мы создадим тестовый скрипт для нашего приложения Python. Это будет простой скрипт, который проверяет вывод HTTP приложения. Сценарий является примером типа теста, который вы можете запустить как часть процесса развертывания непрерывной интеграции.

Отредактируйте новый файл:

  1. nano test.sh

Добавьте следующее содержимое:

sleep 5
if curl web | grep -q '<b>Visits:</b> '; then
  echo "Tests passed!"
  exit 0
else
  echo "Tests failed!"
  exit 1
fi

test.sh проверяет базовое веб-подключение нашего приложения «Hello World». Он использует cURL для получения количества посещений и отчетов о том, был ли пройден тест или нет.

Шаг 7 — Создайте среду тестирования

Чтобы протестировать наше приложение, нам нужно развернуть тестовую среду. И мы хотим убедиться, что она идентична рабочей среде приложения, которую мы создали на шаге 5.

Во-первых, нам нужно Dockerize наш сценарий тестирования, создав новый файл Dockerfile. Отредактируйте новый файл:

  1. nano Dockerfile.test

Добавьте следующее содержимое:

FROM ubuntu:trusty

RUN apt-get update && apt-get install -yq curl && apt-get clean

WORKDIR /app

ADD test.sh /app/test.sh

CMD ["bash", "test.sh"]

Dockerfile.test расширяет официальный образ ubuntu:trusty для установки зависимости curl, добавляет tests.sh в image и указывает на команду CMD, которая выполняет тестовый сценарий с помощью Bash.

Как только наши тесты докеризованы, их можно выполнять воспроизводимым и независимым способом.

Следующий шаг — связать наш тестовый контейнер с нашим приложением «Hello World». Здесь снова приходит на помощь Docker Compose. Отредактируйте новый файл:

  1. nano docker-compose.test.yml

Добавьте следующее содержимое:

sut:
  build: .
  dockerfile: Dockerfile.test
  links:
    - web
web:
  build: .
  dockerfile: Dockerfile
  links:
    - redis
redis:
  image: redis

Вторая половина файла Docker Compose развертывает основное приложение web и его зависимость redis так же, как и предыдущий файл docker-compose.yml. файл. Это часть файла, определяющая контейнеры web и redis. Единственное отличие состоит в том, что контейнер web больше не предоставляет порт 80, поэтому приложение не будет доступно через общедоступный Интернет во время тестов. Итак, вы можете видеть, что мы создаем приложение и его зависимости точно так же, как и в реальном развертывании.

Файл docker-compose.test.yml также определяет контейнер sut (названный в честь тестируемой системы), который отвечает за выполнение наших интеграционных тестов. . Контейнер sut указывает текущий каталог как наш каталог build и указывает наш файл Dockerfile.test. Он ссылается на контейнер web, поэтому IP-адрес контейнера приложения доступен для нашего скрипта test.sh.

Как настроить для вашего собственного приложения

Обратите внимание, что docker-compose.test.yml может включать десятки внешних служб и несколько тестовых контейнеров. Docker сможет запускать все эти зависимости на одном хосте, потому что каждый контейнер использует общую ОС.

Если у вас есть дополнительные тесты для запуска вашего приложения, вы можете создать для них дополнительные файлы Dockerfile, аналогичные файлу Dockerfile.test, показанному выше.

Затем вы можете добавить дополнительные контейнеры под контейнером sut в файле docker-compose.test.yml, ссылаясь на дополнительные файлы Dockerfile.

Шаг 8 — Протестируйте приложение «Hello World»

Наконец, расширяя идеи Docker от локальных сред до сред тестирования, мы получили автоматизированный способ тестирования нашего приложения с помощью Docker, выполнив:

  1. docker-compose -f ~/hello_world/docker-compose.test.yml -p ci build

Эта команда создает локальные образы, необходимые docker-compose.test.yml. Обратите внимание, что мы используем -f для указания на docker-compose.test.yml и -p для указания имени конкретного проекта.

Теперь разверните вашу свежую тестовую среду, выполнив:

  1. docker-compose -f ~/hello_world/docker-compose.test.yml -p ci up -d

Проверьте вывод контейнера sut, выполнив:

  1. docker logs -f ci_sut_1
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100    42  100    42    0     0   3902      0 --:--:-- --:--:-- --:--:--  4200
Tests passed!

И, наконец, проверьте код выхода контейнера sut, чтобы убедиться, что ваши тесты прошли успешно:

  1. docker wait ci_sut_1
0

После выполнения этой команды значение $? будет равно 0, если тесты пройдены. В противном случае наши тесты приложений провалились.

Обратите внимание, что другие инструменты CI могут клонировать наш репозиторий кода и выполнять эти несколько команд, чтобы проверить, проходят ли тесты с последними битами вашего приложения, не беспокоясь о зависимостях времени выполнения или конфигурациях внешних служб.

Вот и все! Мы успешно провели наш тест в свежесозданной среде, идентичной нашей производственной среде.

Заключение

Благодаря Docker и Docker Compose мы смогли автоматизировать создание приложения (Dockerfile), развертывание локальной среды (docker-compose.yml), как создать тестовый образ (Dockerfile.test) и как выполнить (интеграционные) тесты (docker-compose.test.yml) для любого приложения.

В частности, преимущества использования файла docker-compose.test.yml для тестирования заключаются в том, что процесс тестирования:

  • Автоматизированный: способ выполнения инструментом docker-compose.test.yml не зависит от тестируемого приложения
  • Легкий: сотни внешних сервисов могут быть развернуты на единый хост, имитирующий сложные (интеграционные) тестовые среды
  • Независимо: избегайте привязки к поставщику CI, и ваши тесты могут выполняться в любом инфраструктуры и на любой ОС, поддерживающей Docker
  • Неизменный: тесты, проходящие на вашем локальном компьютере, будут проходить и в вашем инструменте непрерывной интеграции.

В этом руководстве показан пример тестирования простого приложения «Hello World».

Теперь пришло время использовать ваши собственные файлы приложений, Dockerize собственные сценарии тестирования приложений и создать собственный docker-compose.test.yml для тестирования вашего приложения в свежей и неизменной среде.