Промежуточный стабильный вариант

This commit is contained in:
Alexander Zhirov 2025-04-28 11:14:51 +03:00
parent ab7a65969e
commit 92ff34dbf3
5 changed files with 111 additions and 46 deletions

67
build.sh Normal file → Executable file
View file

@ -1,17 +1,19 @@
#!/bin/sh
usage() {
echo "✏️ Использование: $0 -n <имя> -v <версия> [-a <адрес>] [-p <порт>] [-r]"
echo "✏️ Использование: $0 -n <имя> -v <версия> -d <версия_docker> -b <версия_базового_образа> [-r <адрес_registry>] [-p <порт>]"
echo "🔧 Опции:"
echo " -n, --name Имя образа (обязательно)"
echo " -v, --version Версия образа в формате X.Y.Z (обязательно)"
echo " -a, --address Адрес registry (требуется с -r)"
echo " -p, --port Порт registry (опционально)"
echo " -r, --push-to-registry Создать теги и отправить образы в registry"
echo " -d, --docker-version Версия Docker для сборки (обязательно)"
echo " -b, --base-image-version Версия базового образа (обязательно)"
echo " -r, --push-to-registry Адрес registry для отправки образов (например, registry.example.com)"
echo " -p, --port Порт registry (по умолчанию 5000)"
echo ""
echo "📌 Примеры:"
echo " Только сборка: $0 -n myapp -v 2.5.7"
echo " Сборка и отправка: $0 -n myapp -v 2.5.7 -a registry.example.com -p 5000 -r"
echo " Только сборка: $0 -n myapp -v 2.5.7 -d 20.10 -b 3.8"
echo " Сборка и отправка: $0 -n myapp -v 2.5.7 -d 20.10 -b 3.8 -r registry.example.com"
echo " Сборка и отправка с другим портом: $0 -n myapp -v 2.5.7 -d 20.10 -b 3.8 -r registry.example.com -p 8080"
exit 1
}
@ -24,9 +26,9 @@ validate_version() {
validate_address() {
if [ -z "$1" ]; then
echo "❌ Ошибка: Адрес не может быть пустым"
echo "❌ Ошибка: Адрес registry не может быть пустым"
exit 1
fi
}
}
validate_port() {
@ -38,53 +40,68 @@ validate_port() {
fi
}
check_dockerfile() {
if [ ! -f "Dockerfile.$1" ]; then
echo "❌ Ошибка: Файл Dockerfile.$1 не найден в директории docker"
exit 1
fi
}
push_to_registry=false
name=""
version=""
address=""
port=""
docker_version=""
base_image_version=""
registry_address=""
port="5000"
while getopts ":n:v:a:p:r" opt; do
while getopts ":n:v:d:b:p:r:" opt; do
case $opt in
n) name="$OPTARG" ;;
v) version="$OPTARG" ;;
a) address="$OPTARG" ;;
d) docker_version="$OPTARG" ;;
b) base_image_version="$OPTARG" ;;
p) port="$OPTARG" ;;
r) push_to_registry=true ;;
r) push_to_registry=true; registry_address="$OPTARG" ;;
\?) echo "❌ Неверный аргумент -$OPTARG" >&2; usage ;;
:) echo "❌ Опция -$OPTARG требует аргумент" >&2; usage ;;
esac
done
if [ -z "$name" ] || [ -z "$version" ]; then
echo "❌ Ошибка: Не указаны обязательные аргументы (-n и -v)"
if [ -z "$name" ] || [ -z "$version" ] || [ -z "$docker_version" ] || [ -z "$base_image_version" ]; then
echo "❌ Ошибка: Не указаны обязательные аргументы (-n, -v, -d и -b)"
usage
fi
validate_version "$version"
if [ "$push_to_registry" = true ]; then
if [ -z "$address" ]; then
echo "❌ Ошибка: Для отправки в registry необходимо указать адрес (-a)"
if [ -z "$registry_address" ]; then
echo "❌ Ошибка: Для отправки в registry необходимо указать адрес с -r"
usage
fi
validate_address "$address"
validate_address "$registry_address"
validate_port "$port"
fi
echo "🐳 Сборка образа $name:$version..."
docker build . -t "${name}:${version}" || {
echo "📂 Переход в директорию docker..."
cd docker || {
echo "❌ Ошибка: Не удалось перейти в директорию docker"
exit 1
}
echo "🔍 Проверка наличия Dockerfile..."
check_dockerfile "$docker_version"
echo "🐳 Сборка образа $name:$version с использованием Dockerfile.$docker_version и базового образа версии $base_image_version..."
docker build . -f "Dockerfile.$docker_version" -t "${name}:${version}" --build-arg BASE_IMAGE_VERSION="$base_image_version" || {
echo "❌ Ошибка при сборке образа"
exit 1
}
if [ "$push_to_registry" = true ]; then
if [ -z "$port" ]; then
registry="$address"
else
registry="$address:$port"
fi
registry="$registry_address:$port"
echo "🏷 Создание тегов для registry..."

View file

@ -1,4 +1,5 @@
FROM alpine:3.16.9
ARG BASE_IMAGE_VERSION=latest
FROM alpine:${BASE_IMAGE_VERSION}
# Метаданные для CI/CD
LABEL maintainer="Alexander Zhirov <alexander@zhirov.kz>"
@ -16,7 +17,7 @@ ENV USER=builder \
NAME_KEY=builder
# Копируем скрипт запуска в контейнер
COPY apk-build /usr/bin/apk-build
COPY build-apk /usr/bin/build-apk
# Устанавливаем необходимые пакеты для сборки APK и NFS
RUN echo "http://mirror.yandex.ru/mirrors/alpine/v3.16/main" > /etc/apk/repositories && \
@ -27,7 +28,7 @@ RUN echo "http://mirror.yandex.ru/mirrors/alpine/v3.16/main" > /etc/apk/reposito
adduser -D builder && \
addgroup builder abuild && \
echo "builder ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/builder && \
chmod 0755 /usr/bin/apk-build && \
chmod 0755 /usr/bin/build-apk && \
mkdir /home/builder/package && \
chown builder:builder /home/builder/package
@ -38,7 +39,7 @@ USER builder
WORKDIR /home/builder/package
# Указываем точку входа для CI/CD
ENTRYPOINT ["/usr/bin/apk-build"]
ENTRYPOINT ["/usr/bin/build-apk"]
# Указываем команду по умолчанию с переменными окружения
CMD ["-p", "/package"]

View file

@ -1,4 +1,5 @@
FROM alpine:3.16.9
ARG BASE_IMAGE_VERSION=latest
FROM alpine:${BASE_IMAGE_VERSION}
# Метаданные для CI/CD
LABEL maintainer="Alexander Zhirov <alexander@zhirov.kz>"
@ -16,7 +17,7 @@ ENV USER=builder \
NAME_KEY=builder
# Копируем скрипт запуска в контейнер
COPY --chmod=0755 apk-build /usr/bin/apk-build
COPY --chmod=0755 build-apk /usr/bin/build-apk
# Устанавливаем необходимые пакеты для сборки APK и NFS
RUN <<EOF
@ -37,7 +38,7 @@ USER builder
WORKDIR /home/builder/package
# Указываем точку входа для CI/CD
ENTRYPOINT ["/usr/bin/apk-build"]
ENTRYPOINT ["/usr/bin/build-apk"]
# Указываем команду по умолчанию с переменными окружения
CMD ["-p", "/package"]

View file

@ -2,16 +2,16 @@
# Функция для вывода справки
usage() {
echo "Использование: $0 -p <путь_к_APKBUILD> [-s <NFS_сервер> -n <NFS_путь>] [-r <приватный_ключ> -u <публичный_ключ>] [-d <путь_к_репозиторию>]"
echo "Использование: $0 -p <путь_к_APKBUILD> -k <наименование_ключа> [-s <NFS_сервер> -n <NFS_путь>] [-r <приватный_ключ> -u <публичный_ключ>] [-d <путь_к_репозиторию>]"
echo "Параметры:"
echo " -p <путь_к_APKBUILD> Путь к директории с APKBUILD (обязательный)"
echo " -k <наименование_ключа> Наименование файла ключа (обязательный)"
echo " -s <NFS_сервер> IP или имя NFS-сервера (опционально)"
echo " -n <NFS_путь> Путь к NFS-ресурсу (опционально, требуется с -s)"
echo " -r <приватный_ключ> Содержимое файла приватного ключа (опционально)"
echo " -u <публичный_ключ> Содержимое файла публичного ключа (опционально)"
echo " -d <путь_к_репозиторию> Путь к директории репозитория в ~/packages (опционально)"
echo " -k <наименование_ключа> Наименование файла ключа (опционально)"
echo "Пример: $0 -p /package -s 192.168.1.100 -n /nfs/share -r \"<содержимое_ключа.rsa>\" -u \"<содержимое_ключа.rsa.pub>\" -d /repo -k \"mykey\""
echo "Пример: $0 -p /package -k mykey -s 192.168.1.100 -n /nfs/share -r \"<содержимое_ключа.rsa>\" -u \"<содержимое_ключа.rsa.pub>\" -d /repo"
echo "Флаги -s и -n включают монтирование NFS, должны использоваться вместе."
echo "Флаги -r и -u содержат текст приватного и публичного ключей для abuild."
echo "Флаг -d задаёт директорию для сохранения пакетов."
@ -25,7 +25,7 @@ usage() {
: "${PRIVATE_KEY:=}"
: "${PUBLIC_KEY:=}"
: "${REPODEST_DIR:=}"
: "${NAME_KEY:=builder}"
: "${NAME_KEY:=}"
PACKAGES_DIR="/home/builder/packages"
NFS_ENABLED=0
@ -49,6 +49,18 @@ if [ -z "$PACKAGE_DIR" ]; then
usage
fi
# Проверка наличия обязательного аргумента -k
if [ -z "$NAME_KEY" ]; then
echo "🚫 Ошибка: Не указан обязательный параметр -k"
usage
fi
# Проверка валидности имени ключа
if ! echo "$NAME_KEY" | grep -qE '^[a-zA-Z0-9_-]+$'; then
echo "🚫 Ошибка: Имя ключа должно содержать только буквы, цифры, символы '_' или '-'"
exit 1
fi
# Проверка, что если указан один из -s или -n, то указан и другой
if [ -n "$NFS_SERVER" ] && [ -z "$NFS_PATH" ] || [ -z "$NFS_SERVER" ] && [ -n "$NFS_PATH" ]; then
echo "🚫 Ошибка: Флаги -s и -n должны быть указаны вместе"
@ -72,21 +84,35 @@ if [ ! -f "$PACKAGE_DIR/APKBUILD" ]; then
exit 1
fi
if [ -z "$NAME_KEY" ]; then
echo "🚫 Ошибка: Необходимо указать наименование ключа подписи"
# Проверка прав доступа к директории
if [ ! -r "$PACKAGE_DIR" ] || [ ! -x "$PACKAGE_DIR" ]; then
echo "🚫 Ошибка: Недостаточно прав для доступа к директории $PACKAGE_DIR"
exit 1
fi
# Проверка и настройка ключей abuild
if [ -n "$PRIVATE_KEY" ] || [ -n "$PUBLIC_KEY" ]; then
echo "🔑 Настраиваю переданные ключи abuild..."
# Проверяем, что переданы все три компонента
# Проверяем, что переданы все компоненты
if [ -z "$PRIVATE_KEY" ] || [ -z "$PUBLIC_KEY" ]; then
echo "🚫 Ошибка: Для использования ключей нужны все флаги: -r, -u"
echo "🚫 Ошибка: Для использования ключей нужны оба флага: -r, -u"
exit 1
fi
# Проверка формата ключей
if ! echo "$PRIVATE_KEY" | grep -q "BEGIN RSA PRIVATE KEY"; then
echo "🚫 Ошибка: Приватный ключ имеет неверный формат"
exit 1
fi
if ! echo "$PUBLIC_KEY" | grep -q "ssh-rsa"; then
echo "🚫 Ошибка: Публичный ключ имеет неверный формат"
exit 1
fi
# Создаем директорию .abuild
mkdir -p /home/builder/.abuild
if [ $? -ne 0 ]; then
echo "🚫 Ошибка: Не удалось создать директорию /home/builder/.abuild"
exit 1
fi
# Записываем abuild.conf
echo "PACKAGER_PRIVKEY=\"/home/builder/.abuild/$NAME_KEY.rsa\"" > /home/builder/.abuild/abuild.conf
if [ $? -ne 0 ]; then
@ -110,6 +136,10 @@ if [ -n "$PRIVATE_KEY" ] || [ -n "$PUBLIC_KEY" ]; then
chmod 644 /home/builder/.abuild/$NAME_KEY.rsa.pub /home/builder/.abuild/abuild.conf
# Копирование ключа для apk менеджера
sudo cp -v /home/builder/.abuild/$NAME_KEY.rsa.pub /etc/apk/keys/
if [ $? -ne 0 ]; then
echo "🚫 Ошибка при копировании публичного ключа в /etc/apk/keys/"
exit 1
fi
echo "✅ Ключи abuild успешно настроены"
else
# Если ключи не переданы, проверяем существующие или генерируем новые
@ -122,7 +152,15 @@ else
fi
echo "✅ Ключи abuild сгенерированы"
else
sudo cp -v /home/builder/.abuild/$NAME_KEY.rsa.pub /etc/apk/keys/
if [ ! -f "/home/builder/.abuild/$NAME_KEY.rsa" ] || [ ! -f "/home/builder/.abuild/$NAME_KEY.rsa.pub" ]; then
echo "🚫 Ошибка: Указанное имя ключа $NAME_KEY не соответствует существующим ключам"
exit 1
fi
sudo cp /home/builder/.abuild/$NAME_KEY.rsa.pub /etc/apk/keys/
if [ $? -ne 0 ]; then
echo "🚫 Ошибка при копировании существующего публичного ключа"
exit 1
fi
echo "✅ Использую существующие ключи abuild"
fi
fi
@ -131,6 +169,10 @@ fi
if [ "$NFS_ENABLED" -eq 1 ]; then
echo "🔌 Монтирую NFS-ресурс $NFS_SERVER:$NFS_PATH в $PACKAGES_DIR..."
sudo mkdir -p "$PACKAGES_DIR"
if [ $? -ne 0 ]; then
echo "🚫 Ошибка: Не удалось создать директорию $PACKAGES_DIR"
exit 1
fi
sudo mount -t nfs "$NFS_SERVER:$NFS_PATH" "$PACKAGES_DIR"
if [ $? -ne 0 ]; then
echo "🚫 Ошибка при монтировании NFS-ресурса"
@ -140,15 +182,20 @@ if [ "$NFS_ENABLED" -eq 1 ]; then
else
echo " NFS не указан, пакеты будут сохранены локально в $PACKAGES_DIR"
mkdir -p "$PACKAGES_DIR"
if [ $? -ne 0 ]; then
echo "🚫 Ошибка: Не удалось создать директорию $PACKAGES_DIR"
exit 1
fi
fi
# Копируем содержимое директории в рабочую директорию
echo "📂 Копирую файлы проекта в рабочую директорию..."
mkdir -p /home/builder/package
cp -r "$PACKAGE_DIR"/* /home/builder/package/
if [ $? -ne 0 ]; then
echo "🚫 Ошибка при копировании файлов проекта"
if [ "$NFS_ENABLED" -eq 1 ]; then
sudo umount "$PACKAGES_DIR"
sudo umount "$PACKAGES_DIR" || echo "🚫 Ошибка при размонтировании NFS"
fi
exit 1
fi
@ -158,7 +205,7 @@ echo "✅ Файлы успешно скопированы"
cd /home/builder/package || {
echo "🚫 Ошибка: Не удалось перейти в директорию /home/builder/package"
if [ "$NFS_ENABLED" -eq 1 ]; then
sudo umount "$PACKAGES_DIR"
sudo umount "$PACKAGES_DIR" || echo "🚫 Ошибка при размонтировании NFS"
fi
exit 1
}
@ -167,17 +214,16 @@ echo "✅ Перешел в директорию проекта"
# Проверяем зависимости и собираем пакет
echo "🔨 Проверяю зависимости и собираю APK-пакет..."
# Устанавливаем флаг NFS_ENABLED, если указаны оба флага -s и -n
# Устанавливаем REPODEST_DIR
if [ -n "$REPODEST_DIR" ]; then
REPODEST_DIR=$(echo "${REPODEST_DIR}" | sed 's|^./||;s|^/||')
fi
REPODEST="$PACKAGES_DIR/${REPODEST_DIR:=v$(cat /etc/alpine-release | awk -F. '{print $1"."$2}')}" abuild -r
if [ $? -ne 0 ]; then
echo "🚫 Ошибка при сборке APK-пакета"
if [ "$NFS_ENABLED" -eq 1 ]; then
sudo umount "$PACKAGES_DIR"
sudo umount "$PACKAGES_DIR" || echo "🚫 Ошибка при размонтировании NFS"
fi
exit 1
fi

0
edit Normal file
View file