Типичный сценарий: ваша команда поддерживает десятки файлов Jenkinsfile / .gitlab-ci.yml / любого другого, каждый из которых соответствует потребностям своих проектов. Вы пытались повторно использовать эти сценарии непрерывной интеграции из одного репо в другое. Но это сложно, потому что каждый проект имеет свой собственный стек технологий, версии, зависимости от других инструментов и т. Д.
Более того, вы мечтаете иметь возможность тестировать свой конвейер CI локально, а не отлаживать на сервере CI.
Я прав? Тогда для вас созданы многоступенчатые сборки докеров.
Этот метод существует уже много лет, но пользователи обычно не осознают его весь потенциал.
Идея проста: объединить несколько Dockerfile в один Dockerfile. Каждый из них может выполнять разные задачи в процессе строительства.
Давайте рассмотрим пример. Я добавил некоторые дополнительные сложности, чтобы продемонстрировать продвинутые концепции, но пока сосредоточусь на сути. Пожалуйста, обратитесь к официальной документации для кикстарта. Этот пост является демонстрацией возможностей CI.
На первом этапе проводятся гидроакустические испытания:
FROM newtmitch/sonar-scanner AS sonar
COPY src src
RUN sonar-scanner
На следующем этапе устанавливаются зависимости и строится приложение:
FROM node:11 AS build
WORKDIR /usr/src/app
COPY . .
RUN yarn install \
yarn run lint \
yarn run build \
yarn run generate-docs
LABEL stage=build
Следующий, юнит-тесты:
FROM build AS unit-tests
RUN yarn run unit-tests
LABEL stage=unit-tests
В-третьих, отправьте документы на S3:
FROM containerlabs/aws-sdk AS push-docs
ARG push-docs=false
COPY --from=build docs docs
RUN [[ "$push-docs" == true ]] && aws s3 cp -r docs s3://my-docs-bucket/
Наконец, последний этап - единственный, который будет отражен в полученном изображении. Он использует меньшее базовое изображение и содержит только необходимые артефакты:
FROM node:11-slim
EXPOSE 8080
WORKDIR /usr/src/app
COPY --from=build /usr/src/app/node_modules node_modules
COPY --from=build /usr/src/app/dist dist
USER node
CMD ["node", "./dist/server/index.js"]
Jenkinsfile становится намного проще (пример для Jenkins в Kubernetes):
#!/usr/bin/env groovypodTemplate(label: "example", name: "example",
containers: [
containerTemplate(name: 'dind',
privileged: true, image: 'docker:18.06-dind', command: 'dockerd-entrypoint.sh'),
containerTemplate(name: 'docker', image: 'docker:18.06', command: 'cat', ttyEnabled: true)
],
envVars: [
envVar(key: 'DOCKER_HOST', value: 'tcp://localhost:2375')
]
){node('example'){container('docker'){stage('checkout'){
checkout scm
}stage('Docker build + push'){
sh """#!/bin/bash
docker build -t test --build-arg push-docs=true .
docker push test
"""
}stage('deploy'){
.......
}
}
}
}
Его можно использовать практически для любого проекта!
Основные преимущества:
Его можно многократно использовать из одной системы CI в другую (т. Е. При переходе с Jenkins на действия GitHub). Это особенно удобно для проектов с открытым исходным кодом.
Вы можете проверить это, просто запустив сборку докеров в локальном.
Все, что связано со сборкой и тестированием исходного кода, находится в Dockerfile. Таким образом, сценарии CI остаются абстрактными от исходного кода.
Меньше места для человеческих ошибок: каждый шаг неизбежно выполняется внутри непривилегированного контейнера докеров. Вы даже можете избежать демона докеров, используя такие инструменты, как Kaniko.
Подводя итог, можно сказать, что все, что относится к проекту, является самодостаточным, и сценарии CI можно повторно использовать из одного репозитория в другой, что делает инфраструктуру проще, дешевле и удобнее в обслуживании. Дайте ему шанс и переключитесь на Dockerfile как можно больше рабочих нагрузок!
Дополнительные советы
Есть некоторые предостережения, но их легко преодолеть. Расскажу о двух из них:
Пропуск определенных шагов по запросу
Например, я добавил этап для отправки сгенерированных документов в корзину на S3. Это полезно, только если сборка выполняется в моей системе CI, где я предоставляю учетные данные для записи в эту корзину.
Для этого я установил аргумент сборки с помощью команды ARG. По умолчанию это false, но на моем CI-сервере я запускаю docker build --build-arg push-docs = true, а затем запускается commandaws s3 cp.
Экспорт отчетов об испытаниях или любых других артефактов
Самая важная оговорка при выполнении всего в сборке докеров заключается в том, что артефакты остаются в промежуточных образах докеров. Например, для меня полезно иметь результаты тестов в рабочем пространстве Jenkins для генерации статистики.
Любой артефакт с любого промежуточного этапа легко взять с этикетками.
Я обозначил вторую стадию как stage = test. Итак, после сборки докера я могу запустить небольшой скрипт, чтобы получить файл test-results.xml.
docker cp $(docker create — name temp $(docker image ls — filter label=stage=test -q | head -n 1)):/usr/src/app/tests-results.xml .; docker rm temp
Он использует docker image ls для получения идентификатора изображения этого этапа и docker cp для копирования файла.
Лучшее решение - использовать больше МЕТКИ, чтобы отфильтровать вашу конкретную сборку от других аналогичных сборок.
Перевод статьи с сайта: https://itnext.io/
Более того, вы мечтаете иметь возможность тестировать свой конвейер CI локально, а не отлаживать на сервере CI.
Я прав? Тогда для вас созданы многоступенчатые сборки докеров.
Этот метод существует уже много лет, но пользователи обычно не осознают его весь потенциал.
Идея проста: объединить несколько Dockerfile в один Dockerfile. Каждый из них может выполнять разные задачи в процессе строительства.
Давайте рассмотрим пример. Я добавил некоторые дополнительные сложности, чтобы продемонстрировать продвинутые концепции, но пока сосредоточусь на сути. Пожалуйста, обратитесь к официальной документации для кикстарта. Этот пост является демонстрацией возможностей CI.
На первом этапе проводятся гидроакустические испытания:
FROM newtmitch/sonar-scanner AS sonar
COPY src src
RUN sonar-scanner
На следующем этапе устанавливаются зависимости и строится приложение:
FROM node:11 AS build
WORKDIR /usr/src/app
COPY . .
RUN yarn install \
yarn run lint \
yarn run build \
yarn run generate-docs
LABEL stage=build
Следующий, юнит-тесты:
FROM build AS unit-tests
RUN yarn run unit-tests
LABEL stage=unit-tests
В-третьих, отправьте документы на S3:
FROM containerlabs/aws-sdk AS push-docs
ARG push-docs=false
COPY --from=build docs docs
RUN [[ "$push-docs" == true ]] && aws s3 cp -r docs s3://my-docs-bucket/
Наконец, последний этап - единственный, который будет отражен в полученном изображении. Он использует меньшее базовое изображение и содержит только необходимые артефакты:
FROM node:11-slim
EXPOSE 8080
WORKDIR /usr/src/app
COPY --from=build /usr/src/app/node_modules node_modules
COPY --from=build /usr/src/app/dist dist
USER node
CMD ["node", "./dist/server/index.js"]
Jenkinsfile становится намного проще (пример для Jenkins в Kubernetes):
#!/usr/bin/env groovypodTemplate(label: "example", name: "example",
containers: [
containerTemplate(name: 'dind',
privileged: true, image: 'docker:18.06-dind', command: 'dockerd-entrypoint.sh'),
containerTemplate(name: 'docker', image: 'docker:18.06', command: 'cat', ttyEnabled: true)
],
envVars: [
envVar(key: 'DOCKER_HOST', value: 'tcp://localhost:2375')
]
){node('example'){container('docker'){stage('checkout'){
checkout scm
}stage('Docker build + push'){
sh """#!/bin/bash
docker build -t test --build-arg push-docs=true .
docker push test
"""
}stage('deploy'){
.......
}
}
}
}
Его можно использовать практически для любого проекта!
Основные преимущества:
Его можно многократно использовать из одной системы CI в другую (т. Е. При переходе с Jenkins на действия GitHub). Это особенно удобно для проектов с открытым исходным кодом.
Вы можете проверить это, просто запустив сборку докеров в локальном.
Все, что связано со сборкой и тестированием исходного кода, находится в Dockerfile. Таким образом, сценарии CI остаются абстрактными от исходного кода.
Меньше места для человеческих ошибок: каждый шаг неизбежно выполняется внутри непривилегированного контейнера докеров. Вы даже можете избежать демона докеров, используя такие инструменты, как Kaniko.
Подводя итог, можно сказать, что все, что относится к проекту, является самодостаточным, и сценарии CI можно повторно использовать из одного репозитория в другой, что делает инфраструктуру проще, дешевле и удобнее в обслуживании. Дайте ему шанс и переключитесь на Dockerfile как можно больше рабочих нагрузок!
Дополнительные советы
Есть некоторые предостережения, но их легко преодолеть. Расскажу о двух из них:
Пропуск определенных шагов по запросу
Например, я добавил этап для отправки сгенерированных документов в корзину на S3. Это полезно, только если сборка выполняется в моей системе CI, где я предоставляю учетные данные для записи в эту корзину.
Для этого я установил аргумент сборки с помощью команды ARG. По умолчанию это false, но на моем CI-сервере я запускаю docker build --build-arg push-docs = true, а затем запускается commandaws s3 cp.
Экспорт отчетов об испытаниях или любых других артефактов
Самая важная оговорка при выполнении всего в сборке докеров заключается в том, что артефакты остаются в промежуточных образах докеров. Например, для меня полезно иметь результаты тестов в рабочем пространстве Jenkins для генерации статистики.
Любой артефакт с любого промежуточного этапа легко взять с этикетками.
Я обозначил вторую стадию как stage = test. Итак, после сборки докера я могу запустить небольшой скрипт, чтобы получить файл test-results.xml.
docker cp $(docker create — name temp $(docker image ls — filter label=stage=test -q | head -n 1)):/usr/src/app/tests-results.xml .; docker rm temp
Он использует docker image ls для получения идентификатора изображения этого этапа и docker cp для копирования файла.
Лучшее решение - использовать больше МЕТКИ, чтобы отфильтровать вашу конкретную сборку от других аналогичных сборок.
Перевод статьи с сайта: https://itnext.io/