В этой статье рассматривается простой способ создания и тестирования образов docker. По ходу повествования, используя Goss, мы напишем тесты, с помощью которых можно проверить официальный образ Nginx всего за ~0,5 с.


В итоге у нас получится небольшой YAML-файл, описывающий желаемое состояние образа, с помощью которого мы сможем протестировать контейнер nginx:


docker run -p 8080:80 nginx

выполнив простую команду:


dgoss run -p 8080:80 nginx

Процедура займет около 500 миллисекунд и выдаст следующий результат:


INFO: Starting docker container
INFO: Container ID: 25d23a24
INFO: Running Tests
File: /var/log/nginx/error.log: exists: matches expectation: [true]
File: /var/log/nginx/error.log: linkedto: matches expectation: ["/dev/stderr"]
File: /var/log/nginx/error.log: filetype: matches expectation: ["symlink"]
File: /var/log/nginx/access.log: exists: matches expectation: [true]
File: /var/log/nginx/access.log: linkedto: matches expectation: ["/dev/stdout"]
File: /var/log/nginx/access.log: filetype: matches expectation: ["symlink"]
Process: nginx: running: matches expectation: [true]
Port: tcp:80: listening: matches expectation: [true]
Port: tcp:80: ip: matches expectation: [["0.0.0.0"]]
HTTP: http://localhost: status: matches expectation: [200]
HTTP: http://localhost: Body: matches expectation: [Welcome to nginx!]
Package: nginx: installed: matches expectation: [true]
Package: nginx: version: matches expectation: [["1.11.10-1~jessie"]]
Total Duration: 0.012s
Count: 13, Failed: 0, Skipped: 0
INFO: Deleting container

Замечание: если вам удобнее смотреть, нежели читать, в конце статьи вы можете найти ссылку на видеоверсию (на английском).


Необходимые инструменты


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


Установка инструментария для тестирования


В качестве инструмента для тестирования мы возьмем Goss. Установка его проста и занимает несколько секунд.


curl -fsSL https://goss.rocks/install | sh

Замечание: если вам не нравится curl | sh, можно установить Goss вручную, воспользовавшись этими инструкциями.


Что же такое Goss?


Goss — это использующий YAML инструмент для проверки конфигурации серверов, являющийся альтернативой serverspec. Он упрощает написание тестов, которые могут быть сгенерированы на основе текущего состояния системы. Написанные тесты можно запустить на выполнение либо использовать в качестве желаемого конечного состояния системы.

Более подробную информацию см. на странице проекта.


Написание тестов


dgoss — это идущий в комплекте с Goss вспомогательный инструмент, который радикально упрощает написание тестов для docker. Предположим, что мы запустили контейнер следующим образом:


docker run -p 8080:80 nginx:1.11.10

Чтобы начать создание тестов, замените docker run на dgoss edit:


dgoss edit -p 8080:80 nginx:1.11.10

Эта команда запустит контейнер, установит Goss и откроет консоль контейнера:


INFO: Starting docker container
INFO: Container ID: 9468c0c3
INFO: Run goss add/autoadd to add resources

Теперь мы можем начать написание тестов. Вставьте в консоль следующие команды, которые сгенерируют тесты на основе текущего состояния системы:


goss a file /var/log/nginx/access.log /var/log/nginx/error.log
goss a process nginx
goss a port 80
goss a package nginx
goss a http http://localhost
exit

Замечание: “a” — это сокращенная форма от “add”.


После выполнения команды exit контейнер будет удален, а в текущей директории появится файл goss.yaml:


file:
  /var/log/nginx/access.log:
    exists: true
    mode: "0777"
    size: 11
    owner: root
    group: root
    linked-to: /dev/stdout
    filetype: symlink
    contains: []
  /var/log/nginx/error.log:
    exists: true
    mode: "0777"
    size: 11
    owner: root
    group: root
    linked-to: /dev/stderr
    filetype: symlink
    contains: []
package:
  nginx:
    installed: true
    versions:
    - 1.11.10-1~jessie
port:
  tcp:80:
    listening: true
    ip:
    - 0.0.0.0
process:
  nginx:
    running: true
http:
  http://localhost:
    status: 200
    allow-insecure: false
    no-follow-redirects: false
    timeout: 5000
    body: []

Эти тесты могут быть выполнены с помощью команды:


dgoss run nginx

Изменение тестов вручную


Сгенерированный ранее YAML-файл также может быть написан вручную. Команда dgoss edit создана для облегчения процесса написания тестов. Но в большинстве случаев сгенерированный YAML-файл все же приходится подправлять. Далее мы этим и займемся.


В секции файлов нам важно только то, чтобы журналы были связаны с stdout/stderr символьными ссылками. Поэтому давайте удалим проверки mode, size, owner, group и contains. Секция файлов должна выглядеть следующим образом:


file:
  /var/log/nginx/access.log:
    exists: true
    linked-to: /dev/stdout
    filetype: symlink
  /var/log/nginx/error.log:
    exists: true           
    linked-to: /dev/stderr
    filetype: symlink

Далее удалим флаги, связанные с https, и добавим проверку того, что в теле ответа есть строка «Welcome to nginx!»:


http:
  http://localhost:
    status: 200
    timeout: 5000
    body:
    - Welcome to nginx!

В нашем YAML-файле теперь должно быть 28 строк:


file:
  /var/log/nginx/access.log:
    exists: true
    linked-to: /dev/stdout
    filetype: symlink
  /var/log/nginx/error.log:
    exists: true
    linked-to: /dev/stderr
    filetype: symlink
package:
  nginx:
    installed: true
    versions:
    - 1.11.10-1~jessie
port:
  tcp:80:
    listening: true
    ip:
    - 0.0.0.0
process:
  nginx:
    running: true
http:
  http://localhost:
    status: 200
    timeout: 5000
    body:
    - Welcome to nginx!

Запустить эти тесты по-прежнему очень просто:


dgoss run nginx

Что дальше?


Эта статья предназначена для быстрого старта и демонстрирует простой тестовый сценарий. Более подробную информацию и продвинутые варианты использования можно найти на следующих страницах:


  • Goss?—?используемый в этой статье инструмент.
  • dgoss?— утилита, которая находится в составе goss (также была рассмотрена в этой статье).
  • dgoss-examples?—?репозиторий, в котором можно найти более сложные примеры использования dgoss для проверки образов докер.
  • Goss manual?— документация по ?Goss.




Ссылки:


  1. Оригинал: Tutorial: How to test your docker image in half a second.
Поделиться с друзьями
-->

Комментарии (15)


  1. Caravus
    11.04.2017 10:54
    -1

    Что-то я не понял зачем это всё нужно. Вы что сомневаетесь в возможностях Dockerfile описать нужное состояние системы?


    1. Ciiol
      11.04.2017 14:11
      +1

      А что, Dockerfile уже позволяет описать нужное состояние системы? Мне почему-то казалось, что там описан порядок действий, а в какое состояние придет система после этих действий, докеру совершенно безразлично.


    1. vlfesko
      11.04.2017 14:11
      +1

      Dockerfile это не более чем сценарий, по которому образ будет собран. Все хорошо, когда образ состоит только из условно локальных файлов, но когда какой-то пакет ставится извне, то в какой-то момент после пересборки образ уже не будет работать как должен. Или же, например, nginx конфиг будет примонтирован в образ, чтобы сделать его хоть сколько-то полезным — с этого момента поведение nginx может измениться и он либо не на том порту запустится, либо не тот ответ, что нужно будет отдавать.

      Таким образом, можно не только тестировать образ после каждой пересборки (например, push в gitlab, запуск CI для билда образа, базовые тесты и push в docker registry), но и тестировать образ в рамках како-то проекта. Мне видится такой сценарий и особенно полезным применением как раз было бы тестирование в рамках Gitlab CI после билда образа.


    1. VolCh
      11.04.2017 14:21
      +1

      Это проверка того, что Dockerfile содержит последовательность команд, приводящую систему в нужное состояние. Как в юнит-тестировании кода проверяется, что модуль делает то, что от него ожидается, содержит последовательность инструкций, выдающую нужный результат.


      1. Caravus
        11.04.2017 14:26
        -1

        Смысл докерфайла как раз в том чтобы собирать из раза в раз одинаковый образ, вне зависимости от внешних факторов. Если у вас докерфайл может собрать нерабочий образ (или работающий не так как задумано) — это не правильный докерфайл.


        1. VolCh
          11.04.2017 14:28
          +2

          Смысл тестирования образа — это автоматическое определение правильный докерфайл или неправильный.


          1. Caravus
            11.04.2017 14:29

            Ага, вот так понимаю :) Спасибо.


        1. sshikov
          12.04.2017 22:02

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


  1. D1abloRUS
    11.04.2017 11:29
    +3

    Такими темпами, скоро нужно будет писать тесты для тестов…


    1. ggo
      12.04.2017 10:07

      они уже пишутся.
      понятно, не массово


  1. SicYar
    11.04.2017 17:50

    Отлично, постоянно от вашей команды статьи, которые как нельзя кстати попадаются)))
    Пишите истчо, не останавливайтесь)


  1. ALexhha
    15.04.2017 14:28

    Есть несколько вопросов

    1. Правильно ли я понял, что для запуска тестов у нас должен быть запущен и сам контейнер? Если да, то как запускать подобные тесты на CI. У нас например CI уже поднимает слейв ноды в докере, так что нет возможности запускать докер

    2. С учетом философии докера: 1 контейнер — 1 процесс, в чем смысл таких проверок? Или мы просто проверяем, что наш единственный сервис был правильно установлен и были выставлены корректные права?

    3. Как быть со случаем когда у нас микросервисная архитектура и по отдельности делать проверки особого смысла нет. Ну например, у нас есть два контейнера nginx и php-fpm. По отдельности мы их проверили, и там все было нормально. Но когда мы запустим их одновременно, то обнаружатся проблемы, например в nginx был указан не тот порт или путь к сокету php-fpm


    1. ggo
      17.04.2017 09:40
      +1

      2. Если у вас в баше стена текста для билда образа, декларативная проверка готового образа на формальное соответствие требованиям немного упростит жизнь.

      3. Тестирование в связке и тестирование в изоляции — это разные уровни абстракции, со своими подходами, целями и пр. Тестирование в изоляции докер-инфраструктуры и логики приложения — тоже разные абстракции.
      Если тестировать по отдельности смысла нет, не тестируйте. У всего есть бенефиты и косты. Рациональное и бережное отношение к ним, один из признаков профессионализма.


    1. Manowar
      19.04.2017 11:06

      1. пробросьте сокет докера с хоста внутрь контейнеризированого дженкис слейва, будет «докер-в-докере».

      -v /var/run/docker.sock:/var/run/docker.sock

      Подробнее в последней секции.


      1. ALexhha
        19.04.2017 13:06

        Ну это не вариант, ибо в таком случае я получаю доступ ко всем контейнерам. Или я что то упускаю?