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

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 #!/bin/sh
usage() { usage() {
echo "✏️ Использование: $0 -n <имя> -v <версия> [-a <адрес>] [-p <порт>] [-r]" echo "✏️ Использование: $0 -n <имя> -v <версия> -d <версия_docker> -b <версия_базового_образа> [-r <адрес_registry>] [-p <порт>]"
echo "🔧 Опции:" echo "🔧 Опции:"
echo " -n, --name Имя образа (обязательно)" echo " -n, --name Имя образа (обязательно)"
echo " -v, --version Версия образа в формате X.Y.Z (обязательно)" echo " -v, --version Версия образа в формате X.Y.Z (обязательно)"
echo " -a, --address Адрес registry (требуется с -r)" echo " -d, --docker-version Версия Docker для сборки (обязательно)"
echo " -p, --port Порт registry (опционально)" echo " -b, --base-image-version Версия базового образа (обязательно)"
echo " -r, --push-to-registry Создать теги и отправить образы в registry" echo " -r, --push-to-registry Адрес registry для отправки образов (например, registry.example.com)"
echo " -p, --port Порт registry (по умолчанию 5000)"
echo "" echo ""
echo "📌 Примеры:" echo "📌 Примеры:"
echo " Только сборка: $0 -n myapp -v 2.5.7" echo " Только сборка: $0 -n myapp -v 2.5.7 -d 20.10 -b 3.8"
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 -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 exit 1
} }
@ -24,9 +26,9 @@ validate_version() {
validate_address() { validate_address() {
if [ -z "$1" ]; then if [ -z "$1" ]; then
echo "❌ Ошибка: Адрес не может быть пустым" echo "❌ Ошибка: Адрес registry не может быть пустым"
exit 1 exit 1
fi }
} }
validate_port() { validate_port() {
@ -38,53 +40,68 @@ validate_port() {
fi fi
} }
check_dockerfile() {
if [ ! -f "Dockerfile.$1" ]; then
echo "❌ Ошибка: Файл Dockerfile.$1 не найден в директории docker"
exit 1
fi
}
push_to_registry=false push_to_registry=false
name="" name=""
version="" version=""
address="" docker_version=""
port="" 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 case $opt in
n) name="$OPTARG" ;; n) name="$OPTARG" ;;
v) version="$OPTARG" ;; v) version="$OPTARG" ;;
a) address="$OPTARG" ;; d) docker_version="$OPTARG" ;;
b) base_image_version="$OPTARG" ;;
p) port="$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 ;;
:) echo "❌ Опция -$OPTARG требует аргумент" >&2; usage ;; :) echo "❌ Опция -$OPTARG требует аргумент" >&2; usage ;;
esac esac
done done
if [ -z "$name" ] || [ -z "$version" ]; then if [ -z "$name" ] || [ -z "$version" ] || [ -z "$docker_version" ] || [ -z "$base_image_version" ]; then
echo "❌ Ошибка: Не указаны обязательные аргументы (-n и -v)" echo "❌ Ошибка: Не указаны обязательные аргументы (-n, -v, -d и -b)"
usage usage
fi fi
validate_version "$version" validate_version "$version"
if [ "$push_to_registry" = true ]; then if [ "$push_to_registry" = true ]; then
if [ -z "$address" ]; then if [ -z "$registry_address" ]; then
echo "❌ Ошибка: Для отправки в registry необходимо указать адрес (-a)" echo "❌ Ошибка: Для отправки в registry необходимо указать адрес с -r"
usage usage
fi fi
validate_address "$address" validate_address "$registry_address"
validate_port "$port" validate_port "$port"
fi fi
echo "🐳 Сборка образа $name:$version..." echo "📂 Переход в директорию docker..."
docker build . -t "${name}:${version}" || { 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 "❌ Ошибка при сборке образа" echo "❌ Ошибка при сборке образа"
exit 1 exit 1
} }
if [ "$push_to_registry" = true ]; then if [ "$push_to_registry" = true ]; then
if [ -z "$port" ]; then registry="$registry_address:$port"
registry="$address"
else
registry="$address:$port"
fi
echo "🏷 Создание тегов для registry..." 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 # Метаданные для CI/CD
LABEL maintainer="Alexander Zhirov <alexander@zhirov.kz>" LABEL maintainer="Alexander Zhirov <alexander@zhirov.kz>"
@ -16,7 +17,7 @@ ENV USER=builder \
NAME_KEY=builder NAME_KEY=builder
# Копируем скрипт запуска в контейнер # Копируем скрипт запуска в контейнер
COPY apk-build /usr/bin/apk-build COPY build-apk /usr/bin/build-apk
# Устанавливаем необходимые пакеты для сборки APK и NFS # Устанавливаем необходимые пакеты для сборки APK и NFS
RUN echo "http://mirror.yandex.ru/mirrors/alpine/v3.16/main" > /etc/apk/repositories && \ 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 && \ adduser -D builder && \
addgroup builder abuild && \ addgroup builder abuild && \
echo "builder ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/builder && \ 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 && \ mkdir /home/builder/package && \
chown builder:builder /home/builder/package chown builder:builder /home/builder/package
@ -38,7 +39,7 @@ USER builder
WORKDIR /home/builder/package WORKDIR /home/builder/package
# Указываем точку входа для CI/CD # Указываем точку входа для CI/CD
ENTRYPOINT ["/usr/bin/apk-build"] ENTRYPOINT ["/usr/bin/build-apk"]
# Указываем команду по умолчанию с переменными окружения # Указываем команду по умолчанию с переменными окружения
CMD ["-p", "/package"] 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 # Метаданные для CI/CD
LABEL maintainer="Alexander Zhirov <alexander@zhirov.kz>" LABEL maintainer="Alexander Zhirov <alexander@zhirov.kz>"
@ -16,7 +17,7 @@ ENV USER=builder \
NAME_KEY=builder NAME_KEY=builder
# Копируем скрипт запуска в контейнер # Копируем скрипт запуска в контейнер
COPY --chmod=0755 apk-build /usr/bin/apk-build COPY --chmod=0755 build-apk /usr/bin/build-apk
# Устанавливаем необходимые пакеты для сборки APK и NFS # Устанавливаем необходимые пакеты для сборки APK и NFS
RUN <<EOF RUN <<EOF
@ -37,7 +38,7 @@ USER builder
WORKDIR /home/builder/package WORKDIR /home/builder/package
# Указываем точку входа для CI/CD # Указываем точку входа для CI/CD
ENTRYPOINT ["/usr/bin/apk-build"] ENTRYPOINT ["/usr/bin/build-apk"]
# Указываем команду по умолчанию с переменными окружения # Указываем команду по умолчанию с переменными окружения
CMD ["-p", "/package"] CMD ["-p", "/package"]

View file

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

0
edit Normal file
View file