НейроАгент

Как копировать артефакты сборки Docker на хост в CI/CD

Узнайте лучшие методы копирования артефактов сборки из Docker-контейнеров на хост-машины в CI/CD-конвейерах. Изучите docker cp, монтирование томов, многоэтапные сборки и возможности платформ для эффективного управления артефактами.

Как скопировать артефакты сборки из Docker-контейнера на хост-машину в CI/CD конвейере

НейроАгент

Копирование артефактов сборки из Docker-контейнера на хост-машину в CI/CD конвейере

Для копирования артефактов сборки из Docker-контейнера на хост-машину в CI/CD конвейере можно использовать несколько методов, включая команды docker cp, монтирование томов, многоэтапные сборки или использование встроенных возможностей платформ CI/CD. Наиболее эффективный подход зависит от архитектуры вашего конвейера, но монтирование томов и многоэтапные сборки обычно рекомендуются для производственных сред, поскольку они обеспечивают лучшую производительность и более чистое управление артефактами по сравнению с ручными операциями копирования.

Содержание

Понимание проблемы в CI/CD конвейерах

В современных CI/CD конвейерах Docker-контейнеры широко используются для обеспечения согласованных сред сборки. Однако возникает фундаментальная проблема: артефакты сборки, созданные внутри контейнеров, необходимо извлечь на хост-машину для развертывания, тестирования или дальнейшей обработки. Эта операция становится критически важной в автоматизированных конвейерах, где контейнеры эфемерны и временные.

Сложность возрастает при работе с:

  • Крупными артефактами, влияющими на время запуска контейнера
  • Различными типами артефактов (бинарные файлы, отчеты, пакеты)
  • Масштабируемостью конвейера и параллельным выполнением
  • Вопросами безопасности, связанными с доступом к артефактам
  • Требованиями к кроссплатформенной совместимости

Понимание этих ограничений помогает выбрать наиболее подходящий метод извлечения артефактов для вашего конкретного случая использования. Каждый подход имеет свои компромиссы в terms of производительности, сложности и поддерживаемости.


Метод 1: Использование команды docker cp

Команда docker cp предоставляет простой способ копирования файлов из работающего контейнера в файловую систему хоста. Этот метод особенно полезен для периодического извлечения артефактов или при работе с существующими контейнеризованными процессами.

Базовая реализация

bash
# Синтаксис: docker cp <контейнер>:<исходный_путь> <путь_назначения>
docker cp my-builder-container:/app/build/output.tar.gz ./artifacts/

Пример интеграции в CI/CD

В типичном CI/CD конвейере, таком как Jenkins или GitHub Actions, вы бы сделали следующее:

yaml
# Пример для 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

bash
# Создание директории артефактов на хосте
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 для работы с монтируемыми томами:

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 конвейер

yaml
# Пример конвейера Jenkins
pipeline {
    agent any
    stages {
        stage('Сборка') {
            steps {
                script {
                    // Создание директории артефактов
                    sh 'mkdir -p ./artifacts'
                    
                    // Запуск контейнера с монтированием тома
                    sh 'docker run --rm -v ${pwd}/artifacts:/app/output my-builder'
                }
            }
        }
    }
}

Продвинутые техники монтирования томов

Для более сложных сценариев рассмотрите:

bash
# Монтирование исходного кода только для чтения, вывода для чтения/записи
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

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 конвейеров можно извлекать артефакты из промежуточного этапа:

bash
# Сборка и извлечение артефактов
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

yaml
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

yaml
- 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 с артефактами

groovy
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 артефакты

yaml
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

yaml
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 для более быстрой сборки:

bash
export DOCKER_BUILDKIT=1
docker build --target builder -o ./dist .

Кешируйте тома для повторяющихся сборок:

bash
docker run --rm \
  -v $(pwd)/artifacts:/output \
  -v $(pwd)/cache:/app/cache \
  my-builder

Вопросы безопасности

Минимизируйте привилегии контейнера:

bash
# Запуск от имени непривилегированного пользователя
docker run --rm -u 1000:1000 -v $(pwd)/artifacts:/output my-builder

Используйте файловые системы только для чтения, когда это возможно:

bash
docker run --rm \
  -v $(pwd)/src:/app/src:ro \
  -v $(pwd)/artifacts:/app/output:rw \
  my-builder

Шаблоны масштабируемости

Параллельная обработка артефактов:

bash
# Параллельная обработка нескольких артефактов
docker run --rm -v $(pwd)/artifacts:/output my-builder \
  sh -c "make build && cp -r /app/build/* /app/output/" &

Автоматизация очистки артефактов:

bash
# Очистка старых артефактов
find ./artifacts -name "*.tar.gz" -mtime +7 -delete

Примеры реализации

Пример полного CI/CD конвейера

Вот комплексный рабочий процесс GitHub Actions, демонстрирующий управление артефактами:

yaml
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 для локальной разработки

yaml
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/"

Скрипт управления артефактами продвинутого уровня

bash
#!/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 конвейеров комбинация монтирования томов с многоэтапными сборками представляет оптимальный подход, обеспечивая как преимущества производительности, так и чистое управление артефактами. Всегда учитывайте ваши конкретные требования по размеру артефактов, ограничениям безопасности и масштабируемости конвейера при реализации этих шаблонов.

Источники

  1. Документация Docker - Монтирование томов
  2. Документация Docker - Многоэтапные сборки
  3. Документация GitHub Actions - Артефакты
  4. Документация Jenkins - Примеры конвейеров
  5. Лучшие практики CI/CD - Интеграция с Docker