Сборка контейнеров docker с помощью контейнеров docker
Организация процесса сборки приложений, а также их упаковка в контейнера.
Каждый работающий с Docker всегда сталкивается с некими сложностями. Наиболее частая их них — организация процесса сборки приложений, а также их упаковка в контейнера.
Это предварительно сделанный docker image необходимый для каких либо операций над исходным кодом программы. Это может быть компиляция исходников, установка зависимостей, анализ кода и многое др.
Чтобы проще было понять, рассмотрим вот такой пример: у нас есть абстрактный проект. Для его сборки и запуска необходимо выполнить некоторые действия:
Для вышеописанной задачи лучше всего подойдет npm-builder. Это сборочный конвейер, включающий в себя npm, make, nodejs, g++. чтобы выполнить все три шага выше, наберите:
$ docker run --rm -v `pwd`:/data -w /data leanlabs/npm-builder npm install
$ docker run --rm -v `pwd`:/data -w /data leanlabs/npm-builder bower install --allow-root
$ docker run --rm -v `pwd`:/data -w /data leanlabs/npm-builder grunt build
Вот и все, получится собрать проект буквально с помощью 3 строк кода.
Давайте разбираться, что же мы сделали. Контейнер docker с npm-builder мы запускаем в корневой папке проекта. Потом текущая директория монтируется в /data, указывающаяся как рабочая. Это необходимо для того, чтобы в ней выполнялись все команды.
Первая команда выполняет установку всех модулей nodejs в папку node_modules. Поставятся модули, прописанные в файле package.json. Вторая строчка кода необходима для инсталляции в созданную папку bower_components всех зависимостей, которые прописаны в файле bower.json. Сборка с помощью grunt осуществляется последней строкой. Опция --rm указывается при запуске контейнера и помогает удалять его после инсталляции.
Используя проект на php, у нас получится применить сборочный контейнер komposer при установке зависимостей. Наберите:
$ docker run --rm -v `pwd`:/data imega/composer:1.1.0 install --no-dev
1. Время сборки проекта. Если все сборочные инструкции задавать в Dockerfile, то пропорционально количеству шагов будет возрастать время сборки.
2. Проектный порог вхождения. Сборочные конвейеры дают возможность не заморачиваться над установкой разного ПО на компьютере разработчика. Для начала работы просто скопируйте репозиторий проекта, поставьте docker, docker-compose и сделать docker-compose up -d. А потом с docker hub сами подтянутся все контейнеры, которые нужны для сборки и установки проекта.
3. Повторное применение сборочных этапов. Если прописать в Dockerfile саму сборку, то все этапы придется прописать заново. Частично проблему получится решить за счет инструкции ONBUILD, но тогда уровень гибкости ухудшится. Это проявится когда потребуются дополнительные шаги сборки, которые придется все равно заново прописывать. Прозрачность сборки также может пострадать. Чтобы понять ход сборки, вам нужно будет смотреть на исходный файл родительского контейнера.
4. Единообразие среды, в которой происходит исполнение. Запуск приложения не зависит от этапа его сборки. А упаковка в контейнер является лишь копированием собранной программы. Что это значит? Если одни и те же приложения исполняются в контейнерах в разных средах, то в случае поломки летит всё везде одинаково.
5. Предсказуемость сборки. Не стоит проводить запуск grunt на хостовой машине, даже в самом начале применения docker.
6. Одинаковый процесс сборки. Docker не должен выступать средством управления конфигурациями. Его нужно использовать для упаковки, доставки и пуска программ. Если убрать из Dockerfile процесс сборки, они станут значительно проще и будут выглядеть так:
FROM leanlabs/nginx:1.0.1вк
COPY . /var/www/client/
COPY ./build/sites-enabled/client.conf /etc/nginx/sites-enabled/client.conf
CMD ["nginx", "-g", "daemon off;"]
7. Применение уже имеющихся инструментов. Экосистема Docker уже включает в себя кучу инструментов вроде docker-compouse. Здесь сборочные контейнеры тоже подойдут.
При использовании идеи сборочных контейнеров можно выделить несколько соглашений по применению и разработке.
Контейнера выгодно использовать в среде разработчика в связке с docker-compose. Это может вам пригодится если нужно внести изменения в исходники. С docker-compose если некоторые нюансы. Применить одноразовый контейнер вы сможете только с опцией -d при выполнении docker-compose. Иначе после завершения его работы закроются и все остальные контейнера.
Вот так будет выглядеть инсталляция зависимостей с применением composer для php-приложений:
phpbuilder:
image: imega/composer:1.1.0
volumes:
- "./:/data"
- "$HOME/.composer:/cache"
command: ["update"]
Однако, долгоиграющие контейнеры работают без проблем. Например, вот так будет выглядеть инсталляция nodejs, зависимостей bower, а также запуск grunt:
clientbuilder:
image: leanlabs/npm-builder
volumes:
- "./:/data"
- "$HOME/.node_cache:/cache"
command: ["/bin/sh", "-c", "npm install && bower install --allow-root && grunt"]
В связке с docker make, а также сборочные контейнеры применяем для сборки релизов. Команда может также применяться в качестве замены для docker-compose. Вот так будет выглядеть makefile, использующий подход со сборочными контейнерами:
IMAGE = leanlabs/client
TAG = 1.1.9
build:
@docker run --rm -v $(CURDIR):/data -v $$HOME/node_cache:/cache leanlabs/npm-builder npm install
@docker run --rm -v $(CURDIR):/data -v $$HOME/node_cache:/cache leanlabs/npm-builder bower install —allow-root
@docker run --rm -v $(CURDIR):/data -v $$HOME/node_cache:/cache leanlabs/npm-builder grunt build
release:
@docker build -t $(IMAGE).
@docker tag $(IMAGE):latest $(IMAGE):$(TAG)
@docker push $(IMAGE):latest
@docker push $(IMAGE):$(TAG)
.PHONY: build release
Прочитав данный материал и воплотив в жизнь советы из него, вы получите универсальный, легкий процесс сборки и упаковки программ в контейнеры. Кроме того, его можно применять вместе с уже установленными утилитами. Сделав один раз хороший сборочный контейнер, вы сможете постоянно пользоваться им при необходимости.
Опубликовано: Апрель 11, 2017