В последнее время мне задают много вопросов о контейнеризации сред для автоматизированного тестирования при использовании систем непрерывной интеграции. Если вы не поняли большую часть этого предложения, не волнуйтесь, потому что мы собираемся полностью погрузиться в контейнеры, Docker и как использовать их в вашей встроенной среде и тестировании с оборудованием в цикле.
Существует множество отличных статей о контейнерах, включая эту от Docker (один из самых популярных движков для выполнения контейнеров). Контейнеры в средах сборки (например, встроенные системы) и тестовых средах (например, тестирование с оборудованием в цикле) дают нам возможность абстрагироваться от всей сложной настройки каждый раз, когда мы хотим запустить новую машину. Это касается не только новых тестовых машин, но и масштабирования нашей операции в облаке также для сборки встроенного программного обеспечения.
Независимо от размера операции, которую вы ведете в настоящее время, многие компании используют облако, чтобы не заниматься поддержкой физических серверов. В принципах DevOps мы всегда хотим гарантировать, что любое программное обеспечение, которое мы пишем, может быть собрано и запущено в любое время, в любом месте. Постоянное создание новых машин в облаке и установка программного обеспечения для компиляции, библиотек и других программных пакетов не масштабируется хорошо. Именно поэтому контейнеризация стала такой популярной. Мы можем взять нашу среду сборки (или среду выполнения), упаковать ее в очень легковесную виртуальную машину и доставить ее на любую машину для выполнения, будь то облако или наш личный компьютер.
Давайте рассмотрим, как на самом деле создавать и использовать эти контейнеры в ваших проектах. Когда мы впервые начинаем создавать образ контейнера, нам нужно начать с существующего «базового образа». В большинстве случаев подойдет какой-либо вариант операционной системы Linux, такой как Debian, Ubuntu или Alpine. Как только вы создадите свой Dockerfile, вы укажете образ так:
FROM ubuntu:latest
Это указывает, что в качестве базовой операционной системы будет использоваться последний образ Ubuntu Docker. После этого нам нужно будет установить все необходимые библиотеки для нашей среды сборки или тестирования. В одном примере репозитория я установил среду разработки Arduino с помощью менеджера пакетов Debian (Apt), а затем добавил дополнительные слои, установив драйверы платы Arduino Sam. Запуская этот контейнер в привилегированном режиме (или передавая точку монтирования устройства в качестве тома), я могу компилировать и загружать скетч Arduino через командную строку на совершенно новой машине, на которой установлен только Docker (т.е. без IDE или драйверов).
Мы можем делать то же самое с машинами, которые подключены к нашим устройствам, подлежащим тестированию. В этом Docker контейнере, который я собрал, я установил все зависимости и программное обеспечение, необходимое для работы с устройством Analog Discovery 2. Теоретически, я могу запустить Docker контейнер на совершенно новой машине (на которой установлен только Docker) и начать общение с Analog Discovery 2 без всяких проблем. С помощью Analog Discovery 2 я могу писать тесты для проверки моих АЦП, ЦАП или отправлять команды I2C/SPI на разные чипы на моей плате (наряду с множеством других возможностей).
Теперь давайте обсудим, как контейнеры могут улучшить системы непрерывной интеграции, чтобы повысить эффективность и масштабируемость. Настоящая магия начинается, когда мы начинаем использовать контейнеры в сочетании с системами непрерывной интеграции (CI). У нас может быть десятки, если не сотни физических тестовых машин или доступ к тысячам облачных машин для наших серверов тестирования и сборки. Чтобы масштабироваться на практике, как упоминалось выше, мы не можем настраивать каждую отдельную машину по мере их подключения. Поставка контейнера с каждым запуском CI дает нам не только систематический, повторяемый способ выполнения сборок и тестов, но и освобождает нас от необходимости перенастраивать машину каждый раз, когда мы ее запускаем (что в облаке происходит почти при каждом запуске CI). Используя контейнеры для встроенных сборок и тестирования физического оборудования, мы обеспечиваем себе и нашим компаниям определенный уровень масштабируемости, о котором предыдущие поколения могли только мечтать.
В этой статье мы подчеркнули критически важную роль контейнеров в разработке встроенных систем, особенно для обеспечения согласованных сред сборки и тестирования на различных типах инфраструктуры. Их интеграция с системами непрерывной интеграции не только упрощает разработку, но и повышает масштабируемость и надежность продукта. По мере развития технологии контейнеров их принятие станет все более важным для разработчиков. Погрузитесь глубже и экспериментируйте с различными настройками, посетив некоторые примеры репозиториев на https://gitlab.com/docker-embedded.