#!/usr/bin/env bash set -euo pipefail if (( $# < 4 )); then printf 'Использование: %s <каталог-исходников> <образ> [--copy <каталог> <путь>] [--env <ИМЯ=значение>] -- <команда> [аргументы...]\n' \ "${0##*/}" >&2 exit 2 fi SOURCE_DIR=$1 IMAGE=$2 shift 2 EXTRA_SOURCE_DIRS=() EXTRA_DESTINATIONS=() CREATE_ARGS=() while (( $# > 0 )); do case "$1" in --copy) if (( $# < 3 )); then printf '[CI-КОНТЕЙНЕР] Ошибка: для --copy нужны каталог и путь в контейнере\n' >&2 exit 2 fi EXTRA_SOURCE_DIRS+=("$2") EXTRA_DESTINATIONS+=("$3") shift 3 ;; --env) if (( $# < 2 )) || [[ ! "$2" =~ ^[A-Za-z_][A-Za-z0-9_]*=.*$ ]]; then printf '[CI-КОНТЕЙНЕР] Ошибка: для --env ожидается ИМЯ=значение\n' >&2 exit 2 fi CREATE_ARGS+=(--env "$2") shift 2 ;; --) shift break ;; *) printf '[CI-КОНТЕЙНЕР] Ошибка: неизвестный аргумент до команды: %s\n' "$1" >&2 exit 2 ;; esac done if (( $# == 0 )); then printf '[CI-КОНТЕЙНЕР] Ошибка: не указана команда контейнера\n' >&2 exit 2 fi if [[ ! -d "$SOURCE_DIR" ]]; then printf '[CI-КОНТЕЙНЕР] Ошибка: каталог исходников не найден: %s\n' "$SOURCE_DIR" >&2 exit 2 fi for index in "${!EXTRA_SOURCE_DIRS[@]}"; do extra_source=${EXTRA_SOURCE_DIRS[$index]} extra_destination=${EXTRA_DESTINATIONS[$index]} if [[ ! -d "$extra_source" ]]; then printf '[CI-КОНТЕЙНЕР] Ошибка: дополнительный каталог не найден: %s\n' \ "$extra_source" >&2 exit 2 fi if [[ "$extra_destination" != /* || "$extra_destination" == *..* ]]; then printf '[CI-КОНТЕЙНЕР] Ошибка: путь назначения должен быть абсолютным без ..: %s\n' \ "$extra_destination" >&2 exit 2 fi done CONTAINER_ID= cleanup() { if [[ -n "$CONTAINER_ID" ]]; then docker rm --force "$CONTAINER_ID" >/dev/null 2>&1 || true fi } trap cleanup EXIT CONTAINER_ID=$(docker create --workdir /workspace "${CREATE_ARGS[@]}" "$IMAGE" "$@") docker cp "$SOURCE_DIR/." "$CONTAINER_ID:/workspace" for index in "${!EXTRA_SOURCE_DIRS[@]}"; do docker cp "${EXTRA_SOURCE_DIRS[$index]}/." \ "$CONTAINER_ID:${EXTRA_DESTINATIONS[$index]}" done docker start --attach "$CONTAINER_ID"