Как скопировать артефакты сборки из Docker-контейнера на хост-машину в CI/CD конвейере
Копирование артефактов сборки из Docker-контейнера на хост-машину в CI/CD конвейере
Для копирования артефактов сборки из Docker-контейнера на хост-машину в CI/CD конвейере можно использовать несколько методов, включая команды docker cp, монтирование томов, многоэтапные сборки или использование встроенных возможностей платформ CI/CD. Наиболее эффективный подход зависит от архитектуры вашего конвейера, но монтирование томов и многоэтапные сборки обычно рекомендуются для производственных сред, поскольку они обеспечивают лучшую производительность и более чистое управление артефактами по сравнению с ручными операциями копирования.
Содержание
- Понимание проблемы в CI/CD конвейерах
- Метод 1: Использование команды
docker cp - Метод 2: Монтирование томов для постоянных артефактов
- Метод 3: Многоэтапные сборки для эффективного управления артефактами
- Метод 4: Встроенные возможности платформ CI/CD
- Лучшие практики и рекомендации
- Примеры реализации
Понимание проблемы в CI/CD конвейерах
В современных CI/CD конвейерах Docker-контейнеры широко используются для обеспечения согласованных сред сборки. Однако возникает фундаментальная проблема: артефакты сборки, созданные внутри контейнеров, необходимо извлечь на хост-машину для развертывания, тестирования или дальнейшей обработки. Эта операция становится критически важной в автоматизированных конвейерах, где контейнеры эфемерны и временные.
Сложность возрастает при работе с:
- Крупными артефактами, влияющими на время запуска контейнера
- Различными типами артефактов (бинарные файлы, отчеты, пакеты)
- Масштабируемостью конвейера и параллельным выполнением
- Вопросами безопасности, связанными с доступом к артефактам
- Требованиями к кроссплатформенной совместимости
Понимание этих ограничений помогает выбрать наиболее подходящий метод извлечения артефактов для вашего конкретного случая использования. Каждый подход имеет свои компромиссы в terms of производительности, сложности и поддерживаемости.
Метод 1: Использование команды docker cp
Команда docker cp предоставляет простой способ копирования файлов из работающего контейнера в файловую систему хоста. Этот метод особенно полезен для периодического извлечения артефактов или при работе с существующими контейнеризованными процессами.
Базовая реализация
# Синтаксис: docker cp <контейнер>:<исходный_путь> <путь_назначения>
docker cp my-builder-container:/app/build/output.tar.gz ./artifacts/
Пример интеграции в CI/CD
В типичном CI/CD конвейере, таком как Jenkins или GitHub Actions, вы бы сделали следующее:
# Пример для GitHub Actions
- name: Сборка приложения
run: docker build -t my-builder .
- name: Запуск контейнера и сборка
run: docker run --name my-builder-container my-builder make build
- name: Копирование артефактов
run: docker cp my-builder-container:/app/dist ./dist
- name: Очистка
run: docker rm my-builder-container
Преимущества и ограничения
Преимущества:
- Простота реализации и понимания
- Не требует дополнительной конфигурации
- Работает с любым контейнером, независимо от его внутренней настройки
- Мгновенный доступ к артефактам после выполнения команды
Ограничения:
- Требует, чтобы контейнер был запущен во время операции копирования
- Добавляет накладные расходы на управление жизненным циклом контейнера
- Не подходит для очень крупных артефактов из-за ограничений производительности
- Требуется ручная очистка для предотвращения утечек ресурсов
Метод 2: Монтирование томов для постоянных артефактов
Монтирование томов предоставляет более эффективное решение, создавая общую файловую систему между хостом и контейнером. Артефакты, записанные в смонтированный том, становятся доступны на хосте без необходимости явных операций копирования.
Реализация с Docker Run
# Создание директории артефактов на хосте
mkdir -p ./build-artifacts
# Запуск контейнера с монтированием тома
docker run --rm -v $(pwd)/build-artifacts:/app/output my-builder \
sh -c "make build && cp -r /app/build/* /app/output/"
Интеграция в Dockerfile
Для лучшей интеграции измените ваш Dockerfile для работы с монтируемыми томами:
FROM alpine:latest
# Создание директории вывода с правильными правами доступа
RUN mkdir -p /app/output && chown -R 1000:1000 /app/output
# Установка рабочей директории
WORKDIR /app
# Копирование инструментов сборки и исходного кода
COPY . .
# Команда сборки записывает данные непосредственно в смонтированный том
CMD ["sh", "-c", "make build && cp -r /app/build/* /app/output/"]
Интеграция в CI/CD конвейер
# Пример конвейера Jenkins
pipeline {
agent any
stages {
stage('Сборка') {
steps {
script {
// Создание директории артефактов
sh 'mkdir -p ./artifacts'
// Запуск контейнера с монтированием тома
sh 'docker run --rm -v ${pwd}/artifacts:/app/output my-builder'
}
}
}
}
}
Продвинутые техники монтирования томов
Для более сложных сценариев рассмотрите:
# Монтирование исходного кода только для чтения, вывода для чтения/записи
docker run --rm \
-v $(pwd)/src:/app/src:ro \
-v $(pwd)/artifacts:/app/output:rw \
-v $(pwd)/cache:/app/cache \
my-builder
Ключевые преимущества:
- Производительность: Практически мгновенная доступность артефактов
- Простота: Не требуется отдельный шаг копирования
- Масштабируемость: Эффективная работа с крупными артефактами
- Гибкость: Работает с различными платформами CI/CD
Метод 3: Многоэтапные сборки для эффективного управления артефактами
Многоэтапные сборки представляют наиболее совершенный подход, разделяя зависимости сборки от конечных артефактов. Этот метод создает чистый, минимальный финальный образ, содержащий только необходимые артефакты.
Пример многоэтапного Dockerfile
# Этап сборки со всеми зависимостями
FROM node:18-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
RUN npm run build
# Финальный этап с минимальными зависимостями
FROM nginx:alpine
COPY --from=builder /app/dist /usr/share/nginx/html
COPY --from=builder /app/nginx.conf /etc/nginx/nginx.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
Стратегия извлечения артефактов
Для CI/CD конвейеров можно извлекать артефакты из промежуточного этапа:
# Сборка и извлечение артефактов
docker build --target builder -t my-builder .
docker run --rm -v $(pwd)/artifacts:/output my-builder \
sh -c "cp -r /app/dist /output/"
# Или использование buildkit для лучшей производительности
DOCKER_BUILDKIT=1 docker build --target builder -o ./artifacts .
Реализация в GitHub Actions
name: Сборка и извлечение артефактов
on: [push]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Настройка Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Сборка и извлечение артефактов
run: |
export DOCKER_BUILDKIT=1
docker build --target builder -o ./dist .
- name: Загрузка артефактов
uses: actions/upload-artifact@v3
with:
name: build-artifacts
path: ./dist/
Преимущества многоэтапного подхода:
- Меньшие финальные образы: Сокращенный размер развертывания и поверхность атаки
- Чистое разделение: Инструменты сборки изолированы от зависимостей выполнения
- Улучшенная безопасность: Отсутствие инструментов сборки в производственной среде
- Оптимизированная производительность: Эффективное создание артефактов сборки
Метод 4: Встроенные возможности платформ CI/CD
Современные платформы CI/CD предлагают встроенные возможности управления артефактами, которые бесшовно интегрируются с Docker-рабочими процессами. Эти решения часто обеспечивают встроенную обработку, версионирование и распространение артефактов.
Артефакты GitHub Actions
- name: Сборка Docker-образа
run: docker build -t my-app .
- name: Запуск контейнера сборки
run: |
docker run --rm -v ${{ github.workspace }}/artifacts:/output \
my-app sh -c "make build && cp build/* /output/"
- name: Загрузка артефактов
uses: actions/upload-artifact@v3
with:
name: build-output
path: artifacts/
retention-days: 30
Конвейер Jenkins с артефактами
pipeline {
agent any
stages {
stage('Сборка') {
steps {
script {
// Запуск контейнера с извлечением артефактов
sh '''
docker run --rm \
-v ${WORKSPACE}/artifacts:/output \
my-builder
'''
}
}
}
stage('Архивация артефактов') {
steps {
archiveArtifacts artifacts: 'artifacts/**', fingerprint: true
}
}
}
}
GitLab CI/CD артефакты
stages:
- build
- deploy
build_job:
stage: build
script:
- docker build -t my-builder .
- docker run --rm -v ${CI_PROJECT_DIR}/artifacts:/output my-builder
artifacts:
paths:
- artifacts/
expire_in: 1 week
deploy_job:
stage: deploy
script:
- echo "Развертывание из артефактов"
dependencies:
- build_job
Управление артефактами AWS CodeBuild
version: 0.2
phases:
build:
commands:
- docker build -t my-builder .
- docker run --rm -v $CODEBUILD_SRC_DIR/artifacts:/output my-builder
post_build:
commands:
- aws s3 sync ./artifacts s3://my-artifacts-bucket/$CODEBUILD_BUILD_ID
Преимущества, специфичные для платформ:
- Интегрированное хранилище: Собственные репозитории и реестры артефактов
- Версионирование: Автоматическое версионирование артефактов и отслеживание истории
- Безопасность: Встроенные системы контроля доступа и сканирования безопасности
- Распространение: Автоматическое распространение артефактов по средам
Лучшие практики и рекомендации
Оптимизация производительности
Используйте buildkit для более быстрой сборки:
export DOCKER_BUILDKIT=1
docker build --target builder -o ./dist .
Кешируйте тома для повторяющихся сборок:
docker run --rm \
-v $(pwd)/artifacts:/output \
-v $(pwd)/cache:/app/cache \
my-builder
Вопросы безопасности
Минимизируйте привилегии контейнера:
# Запуск от имени непривилегированного пользователя
docker run --rm -u 1000:1000 -v $(pwd)/artifacts:/output my-builder
Используйте файловые системы только для чтения, когда это возможно:
docker run --rm \
-v $(pwd)/src:/app/src:ro \
-v $(pwd)/artifacts:/app/output:rw \
my-builder
Шаблоны масштабируемости
Параллельная обработка артефактов:
# Параллельная обработка нескольких артефактов
docker run --rm -v $(pwd)/artifacts:/output my-builder \
sh -c "make build && cp -r /app/build/* /app/output/" &
Автоматизация очистки артефактов:
# Очистка старых артефактов
find ./artifacts -name "*.tar.gz" -mtime +7 -delete
Примеры реализации
Пример полного CI/CD конвейера
Вот комплексный рабочий процесс GitHub Actions, демонстрирующий управление артефактами:
name: Сборка и развертывание
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
build:
runs-on: ubuntu-latest
outputs:
version: ${{ steps.version.outputs.version }}
steps:
- uses: actions/checkout@v3
- name: Настройка Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Сборка приложения
run: |
export DOCKER_BUILDKIT=1
docker build --target builder -o ./dist .
- name: Извлечение версии
id: version
run: echo "version=$(cat ./dist/version.txt)" >> $GITHUB_OUTPUT
- name: Загрузка артефактов
uses: actions/upload-artifact@v3
with:
name: build-artifacts-${{ steps.version.outputs.version }}
path: ./dist/
retention-days: 90
test:
needs: build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Скачивание артефактов
uses: actions/download-artifact@v3
with:
name: build-artifacts-${{ needs.build.outputs.version }}
path: ./test-artifacts/
- name: Запуск тестов
run: |
# Тестирование со скачанными артефактами
./test-artifacts/test-runner
deploy:
needs: [build, test]
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
steps:
- uses: actions/checkout@v3
- name: Скачивание артефактов
uses: actions/download-artifact@v3
with:
name: build-artifacts-${{ needs.build.outputs.version }}
path: ./deploy/
- name: Развертывание в production
run: |
# Скрипт развертывания с использованием артефактов
./deploy/deploy.sh
Docker Compose для локальной разработки
version: '3.8'
services:
builder:
build:
context: .
target: builder
volumes:
- ./src:/app/src:ro
- ./artifacts:/app/output
- ./cache:/app/cache
environment:
- NODE_ENV=development
command: sh -c "npm run build && cp -r /app/build/* /app/output/"
Скрипт управления артефактами продвинутого уровня
#!/bin/bash
# artifact-manager.sh
set -e
ARTIFACT_DIR="./artifacts"
CONTAINER_NAME="builder-container"
IMAGE_NAME="my-builder"
# Убедимся, что директория артефактов существует
mkdir -p "$ARTIFACT_DIR"
# Сборка Docker-образа
echo "Сборка Docker-образа..."
docker build -t "$IMAGE_NAME" .
# Запуск контейнера с правильным монтированием
echo "Запуск контейнера сборки..."
docker run --rm \
--name "$CONTAINER_NAME" \
-u "$(id -u):$(id -g)" \
-v "$(pwd)/src:/app/src:ro" \
-v "$ARTIFACT_DIR:/app/output" \
-v "$(pwd)/cache:/app/cache" \
"$IMAGE_NAME" \
sh -c "make build && cp -r /app/build/* /app/output/ && chmod -R 755 /app/output/*"
echo "Артефакты успешно извлечены в $ARTIFACT_DIR"
ls -la "$ARTIFACT_DIR"
Заключение
Копирование артефактов сборки из Docker-контейнеров на хост-машины в CI/CD конвейерах требует тщательного учета производительности, безопасности и поддерживаемости. Четыре основных подхода — docker cp, монтирование томов, многоэтапные сборки и возможности платформ CI/CD — каждый предлагает свои преимущества в зависимости от конкретных требований.
Ключевые выводы:
- Монтирование томов обеспечивает наилучший баланс между производительностью и простотой для большинства сценариев CI/CD
- Многоэтапные сборки предлагают превосходную эффективность и безопасность для производственных сред
- Возможности платформ CI/CD предоставляют интегрированное управление артефактами с версионированием и распространением
- Вопросы безопасности должны определять выбор прав доступа пользователей и доступа к файловой системе
Для большинства современных CI/CD конвейеров комбинация монтирования томов с многоэтапными сборками представляет оптимальный подход, обеспечивая как преимущества производительности, так и чистое управление артефактами. Всегда учитывайте ваши конкретные требования по размеру артефактов, ограничениям безопасности и масштабируемости конвейера при реализации этих шаблонов.