From e466f14d497dd62ce6fdb4f5399cea4ccc6cb964 Mon Sep 17 00:00:00 2001 From: Sergey Antropoff Date: Wed, 29 Oct 2025 14:25:38 +0300 Subject: [PATCH] =?UTF-8?q?=D0=92=D1=82=D0=BE=D1=80=D0=B0=D1=8F=20=D0=B2?= =?UTF-8?q?=D0=B5=D1=80=D1=81=D0=B8=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 3 - dockerfile | 58 ++++++++ makefile | 410 +++++++++++++++++++++++++++++++++++++++++++++++++++++ readme.txt | 403 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 871 insertions(+), 3 deletions(-) delete mode 100644 README.md create mode 100644 dockerfile create mode 100644 makefile create mode 100644 readme.txt diff --git a/README.md b/README.md deleted file mode 100644 index 979f6c9..0000000 --- a/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# Dockerfile - -Этот Makefile предназначен для автоматизации сборки, проверки, публикации и архивирования Docker-образов. Подходит как для обычного Docker, так и для Buildx (мультиплатформенная сборка). Поддерживает офлайн-режим (работу без доступа к интернету) через .tar / .tar.gz архивы. \ No newline at end of file diff --git a/dockerfile b/dockerfile new file mode 100644 index 0000000..a8af847 --- /dev/null +++ b/dockerfile @@ -0,0 +1,58 @@ +# ========================================== +# Universal Ubuntu Dockerfile +# Author: Sergey Antropov +# https://devops.org.ru +# ========================================== + +# Базовый образ Ubuntu (можно переопределить при сборке) +ARG BASE_IMAGE=ubuntu:22.04 +FROM ${BASE_IMAGE} + +LABEL maintainer="Sergey Antropov " \ + description="Универсальный базовый образ на Ubuntu 22.04 для приложений" \ + version="1.0" + +# --- Настройки окружения --- +ENV DEBIAN_FRONTEND=noninteractive \ + TZ=Etc/UTC \ + LANG=C.UTF-8 \ + LC_ALL=C.UTF-8 \ + TERM=xterm + +# --- Обновление системы и установка минимальных утилит --- +RUN apt-get update && \ + apt-get install -y --no-install-recommends \ + ca-certificates \ + curl \ + wget \ + bash \ + tzdata \ + nano \ + mc \ + tar \ + gzip \ + unzip \ + net-tools \ + iputils-ping \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* + +# --- Рабочая директория --- +WORKDIR /app + +# --- Копирование файлов проекта (по желанию) --- +# COPY . /app + +# --- Переменные окружения для приложений --- +ENV APP_HOME=/app +ENV PATH="$PATH:/app/bin" + +# --- Пользователь (опционально, для безопасности) --- +# RUN useradd -ms /bin/bash appuser && chown -R appuser:appuser /app +# USER appuser + +# --- Открываем порт (если приложение сетевое) --- +# EXPOSE 8080 + +# --- Команда по умолчанию --- +CMD ["bash"] \ No newline at end of file diff --git a/makefile b/makefile new file mode 100644 index 0000000..822dec1 --- /dev/null +++ b/makefile @@ -0,0 +1,410 @@ +# ========================== +# Universal Makefile (namespaced only) +# Author: Sergey Antropov +# https://devops.org.ru +# ========================== + +# Замена пробелов на табы в консоли (фикс ошибок) +# sed -i 's/^ /\t/' makefile + +# ---- Предустановленные значения под вашу сборку ---- +REGISTRY ?= hub.cism-ms.ru/library +IMAGE ?= +TAG ?= latest +CONTEXT ?= . +DOCKERFILE ?= Dockerfile + +# ---- Режимы сборки ---- +USE_BUILDX ?= 0 # 1 -> использовать docker buildx +PLATFORMS ?= linux/amd64 # например: linux/amd64,linux/arm64 +PUSH ?= 0 # 1 -> пушить образ в buildx (в рамках build) +LOAD ?= 1 # 1 -> загрузить образ в локальный докер (buildx) +NO_CACHE ?= 0 # 1 -> без кэша +PULL ?= 0 # 1 -> принудительно тянуть base-образы +QUIET ?= 0 # 1 -> тихий билд (минимум вывода) + +# ---- Build args ---- +BUILD_ARGS ?= # строка с доп. флагами: --build-arg FOO=bar --build-arg BAZ=qux +ARG_FILE ?= # путь к файлу KEY=VAL; будет превращён в --build-arg KEY=VAL + +# ---- Проверка контейнера ---- +RUN_CMD ?= lsb_release -a # Что проверить после сборки (docker check) + +# ---- Buildx ---- +BUILDER ?= universal-builder + +# ---- Логи ---- +LOG_DIR ?= logs +LOG_FILE ?= $(LOG_DIR)/build_$(shell date +%Y%m%d_%H%M%S).log + +# --- Настройки Git --- +GIT_BRANCH ?= $(shell git rev-parse --abbrev-ref HEAD 2>/dev/null || echo "unknown") +GIT_REMOTE ?= origin +GIT_MSG ?= + +# ====================== +# OFFLINE LOAD/RETAG/PUSH +# ====================== +ARCHIVE ?= image.tar # путь к docker save архиву +LOGIN ?= 1 # 1 -> docker login в REGISTRY перед push +PUSH_OFFLINE ?= 1 # 1 -> docker push после load +KEEP_SRC_TAG ?= 1 # 1 -> если IMAGE пуст, взять тег из архива + +OFFLINE_DIR ?= .offline +LOAD_LOG := $(OFFLINE_DIR)/load.log +SRC_FILE := $(OFFLINE_DIR)/src_image.txt +DST_FILE := $(OFFLINE_DIR)/dst_image.txt +LAST_SAVE := $(OFFLINE_DIR)/last_save.txt + +# ====================== +# Universal save (local) +# ====================== +IMAGES_DIR ?= images # куда сохраняем архивы +SRC_IMAGE ?= # образ-источник; если пусто — $(FULL_IMAGE) +COMPRESS ?= 0 # 1 -> gzip архив +SPLIT_SIZE ?= # размер чанка, напр.: 2G (пусто = не резать) + +# ---- Полное имя образа ---- +ifneq ($(strip $(REGISTRY)),) + FULL_IMAGE := $(REGISTRY)/$(IMAGE):$(TAG) +else + FULL_IMAGE := $(IMAGE):$(TAG) +endif + +# ---- Цвета ---- +COLOR_RESET := \033[0m +COLOR_INFO := \033[1;34m +COLOR_OK := \033[1;32m +COLOR_ERR := \033[1;31m +COLOR_WARN := \033[1;33m + +# ---- Флаги сборки ---- +ifeq ($(NO_CACHE),1) + CACHE_FLAG := --no-cache +else + CACHE_FLAG := +endif + +ifeq ($(PULL),1) + PULL_FLAG := --pull +else + PULL_FLAG := +endif + +ifeq ($(QUIET),1) + QUIET_FLAG := --quiet +else + QUIET_FLAG := +endif + +# Аргументы из файла KEY=VALUE -> --build-arg KEY=VALUE +ifneq ($(strip $(ARG_FILE)),) + ARG_FILE_FLAGS := $(shell sed -n 's/^\([A-Za-z_][A-Za-z0-9_]*\)=\(.*\)/--build-arg \1=\2/p' $(ARG_FILE)) +else + ARG_FILE_FLAGS := +endif + +# ====================== +# Help +# ====================== +.PHONY: help +help: + @echo "Namespaces:" + @echo " make docker [build|check|push|save|load|load-raw|inspect|retag|create-builder|use-builder|login|clean|print-config]" + @echo " make git [status|pull|commit|push|sync]" + @echo "" + @echo "Key vars (override via make VAR=value):" + @echo " REGISTRY=$(REGISTRY) IMAGE=$(IMAGE) TAG=$(TAG) CONTEXT=$(CONTEXT) DOCKERFILE=$(DOCKERFILE)" + @echo " USE_BUILDX=$(USE_BUILDX) PLATFORMS=$(PLATFORMS) PUSH=$(PUSH) LOAD=$(LOAD) NO_CACHE=$(NO_CACHE) PULL=$(PULL) QUIET=$(QUIET)" + @echo " BUILD_ARGS=$(BUILD_ARGS) ARG_FILE=$(ARG_FILE) RUN_CMD=$(RUN_CMD)" + @echo " ARCHIVE=$(ARCHIVE) LOGIN=$(LOGIN) PUSH_OFFLINE=$(PUSH_OFFLINE) KEEP_SRC_TAG=$(KEEP_SRC_TAG)" + @echo " IMAGES_DIR=$(IMAGES_DIR)" + @echo "" + @echo "Examples:" + @echo " make docker build IMAGE=myapp TAG=1.0.0" + @echo " make docker push REGISTRY=registry.local/library IMAGE=myapp TAG=1.0.0" + @echo " make docker save IMAGE=myapp TAG=1.0.0 COMPRESS=1" + @echo " make docker load ARCHIVE=images/myapp_1.0.0.tar.gz LOGIN=1 PUSH_OFFLINE=1" + @echo " make git commit # спросит сообщение" + @echo " make git push # commit+push с запросом сообщения" + +# ====================== +# Служебные директории +# ====================== +$(LOG_DIR): + @mkdir -p $(LOG_DIR) + +$(IMAGES_DIR): + @mkdir -p $(IMAGES_DIR) + +$(OFFLINE_DIR): + @mkdir -p $(OFFLINE_DIR) + +# ====================== +# Docker: реализация +# ====================== +# Внутренние цели (не вызывать напрямую) +.PHONY: __docker_build __docker_check __docker_push __docker_login __docker_retag __docker_save __docker_load __docker_load_raw __docker_inspect __docker_create_builder __docker_use_builder __docker_clean __docker_print_config + +# --- Команды сборки --- +define DOCKER_BUILD_CLASSIC + docker build $(CACHE_FLAG) $(PULL_FLAG) $(QUIET_FLAG) \ + -f $(DOCKERFILE) -t "$(FULL_IMAGE)" \ + $(BUILD_ARGS) $(ARG_FILE_FLAGS) \ + "$(CONTEXT)" +endef + +define DOCKER_BUILD_BUILDX + docker buildx build $(CACHE_FLAG) $(PULL_FLAG) $(QUIET_FLAG) \ + $(if $(filter 1,$(PUSH)),--push,) \ + $(if $(filter 1,$(LOAD)),--load,) \ + --platform $(PLATFORMS) \ + -f $(DOCKERFILE) -t "$(FULL_IMAGE)" \ + $(BUILD_ARGS) $(ARG_FILE_FLAGS) \ + "$(CONTEXT)" +endef + +__docker_build: $(LOG_DIR) + @echo "$(COLOR_INFO)[INFO] Build: $(FULL_IMAGE)$(COLOR_RESET)" + @echo "$(COLOR_INFO)[INFO] Log: $(LOG_FILE)$(COLOR_RESET)" + @{ \ + echo "=== Build started: $$(date) ==="; \ + if [ "$(USE_BUILDX)" = "1" ]; then \ + $(DOCKER_BUILD_BUILDX); \ + else \ + $(DOCKER_BUILD_CLASSIC); \ + fi; \ + echo "=== Build finished: $$(date) ==="; \ + } | tee $(LOG_FILE) + @echo "$(COLOR_OK)[OK] Build success$(COLOR_RESET)" + +__docker_check: + @echo "$(COLOR_INFO)[INFO] Check (RUN_CMD) for $(FULL_IMAGE): $(RUN_CMD)$(COLOR_RESET)" + @docker run --rm --entrypoint /bin/sh "$(FULL_IMAGE)" -lc "$(RUN_CMD)" + +__docker_push: + @if [ "$(USE_BUILDX)" != "1" ]; then \ + echo "$(COLOR_INFO)[INFO] Pushing: $(FULL_IMAGE)$(COLOR_RESET)"; \ + docker push "$(FULL_IMAGE)"; \ + else \ + echo "$(COLOR_WARN)[WARN] USE_BUILDX=1: push выполняется при buildx (PUSH=1).$(COLOR_RESET)"; \ + echo "$(COLOR_WARN)[WARN] Пересоберите с PUSH=1 или выполните docker push вручную.$(COLOR_RESET)"; \ + fi + @echo "$(COLOR_OK)[OK] Push done$(COLOR_RESET)" + +__docker_login: + @if [ -z "$(REGISTRY)" ]; then \ + echo "$(COLOR_ERR)[ERR] REGISTRY не задан. Пример: make docker login REGISTRY=registry.local$(COLOR_RESET)"; \ + exit 1; \ + fi + @echo "$(COLOR_INFO)[INFO] docker login $(REGISTRY)$(COLOR_RESET)" + @docker login $(REGISTRY) + +__docker_retag: + @if [ -z "$(NEW_TAG)" ]; then \ + echo "$(COLOR_ERR)[ERR] Укажи NEW_TAG: make docker retag NEW_TAG=vX.Y.Z$(COLOR_RESET)"; \ + exit 1; \ + fi + @echo "$(COLOR_INFO)[INFO] Retag: $(FULL_IMAGE) -> $(IMAGE):$(NEW_TAG)$(COLOR_RESET)" + @docker tag "$(FULL_IMAGE)" "$(IMAGE):$(NEW_TAG)" + @echo "$(COLOR_OK)[OK] Retag done$(COLOR_RESET)" + +__docker_save: | $(IMAGES_DIR) $(OFFLINE_DIR) + @src="$(SRC_IMAGE)"; \ + if [ -z "$$src" ]; then \ + if [ -n "$(IMAGE)" ]; then src="$(FULL_IMAGE)"; else echo "$(COLOR_ERR)[ERR] Укажи SRC_IMAGE или IMAGE/TAG$(COLOR_RESET)"; exit 1; fi; \ + fi; \ + docker image inspect "$$src" >/dev/null 2>&1 || { echo "$(COLOR_ERR)[ERR] Образ не найден: $$src$(COLOR_RESET)"; exit 1; }; \ + safe="$${src//\//_}"; safe="$${safe//:/_}"; out="$(IMAGES_DIR)/$$safe.tar"; \ + echo "$(COLOR_INFO)[INFO] Сохранение $$src -> $$out$(COLOR_RESET)"; \ + docker save -o "$$out" "$$src"; \ + if [ "$(COMPRESS)" = "1" ]; then \ + echo "$(COLOR_INFO)[INFO] Gzip $$out$(COLOR_RESET)"; gzip -f "$$out"; out="$$out.gz"; \ + fi; \ + if [ -n "$(SPLIT_SIZE)" ]; then \ + echo "$(COLOR_INFO)[INFO] Резка архива на чанки по $(SPLIT_SIZE)$(COLOR_RESET)"; \ + split -b $(SPLIT_SIZE) -d -a 3 "$$out" "$$out.part."; \ + fi; \ + { sha256sum "$$out" 2>/dev/null || shasum -a 256 "$$out"; } > "$$out.sha256" 2>/dev/null || true; \ + echo "$$out" > "$(LAST_SAVE)"; \ + echo "$(COLOR_OK)[OK] Образ сохранён: $$out$(COLOR_RESET)"; \ + ls -lh "$$out"* + +__docker_load_raw: + @if [ -z "$(FILE)" ]; then \ + echo "$(COLOR_ERR)[ERR] Укажи FILE: make docker load-raw FILE=img.tar$(COLOR_RESET)"; \ + exit 1; \ + fi + @echo "$(COLOR_INFO)[INFO] Loading image from $(FILE)$(COLOR_RESET)" + @docker load -i "$(FILE)" + @echo "$(COLOR_OK)[OK] Load done$(COLOR_RESET)" + +__docker_load: | $(OFFLINE_DIR) + @if [ ! -f "$(ARCHIVE)" ]; then \ + echo "$(COLOR_ERR)[ERR] Не найден архив: $(ARCHIVE) (ARCHIVE=... )$(COLOR_RESET)"; exit 1; \ + fi + @echo "$(COLOR_INFO)[INFO] docker load -i $(ARCHIVE)$(COLOR_RESET)" + @docker load -i "$(ARCHIVE)" | tee "$(LOAD_LOG)" + @awk '/Loaded image:/ { last=$$0 } END { gsub(/^.*Loaded image: /,"",last); print last }' "$(LOAD_LOG)" > "$(SRC_FILE)" + @src="$$(cat "$(SRC_FILE)" 2>/dev/null || true)"; \ + if [ -z "$$src" ]; then \ + echo "$(COLOR_ERR)[ERR] Не удалось определить repo:tag из docker load. Укажи IMAGE/TAG вручную.$(COLOR_RESET)"; \ + exit 1; \ + fi; \ + echo "$(COLOR_OK)[OK] Загружен исходный образ: $$src$(COLOR_RESET)"; \ + repo="$${src%:*}"; srctag="$${src#*:}"; [ "$$repo" = "$$srctag" ] && srctag="latest"; \ + src_name="$${repo##*/}"; \ + dst_image="$(IMAGE)"; [ -z "$$dst_image" ] && dst_image="$$src_name"; \ + if [ -z "$(IMAGE)" ] && [ "$(KEEP_SRC_TAG)" = "1" ]; then dst_tag="$$srctag"; else dst_tag="$(TAG)"; fi; \ + if [ -z "$(REGISTRY)" ]; then echo "$(COLOR_ERR)[ERR] REGISTRY пуст$(COLOR_RESET)"; exit 1; fi; \ + full_dst="$(REGISTRY)/$$dst_image:$$dst_tag"; echo "$$full_dst" > "$(DST_FILE)"; \ + echo "$(COLOR_INFO)[INFO] Тегируем: $$src -> $$full_dst$(COLOR_RESET)"; \ + docker tag "$$src" "$$full_dst"; \ + if [ "$(LOGIN)" = "1" ]; then echo "$(COLOR_INFO)[INFO] docker login $(REGISTRY)$(COLOR_RESET)"; docker login "$(REGISTRY)"; fi; \ + if [ "$(PUSH_OFFLINE)" = "1" ]; then echo "$(COLOR_INFO)[INFO] docker push $$full_dst$(COLOR_RESET)"; docker push "$$full_dst"; echo "$(COLOR_OK)[OK] Пуш завершён$(COLOR_RESET)"; else echo "$(COLOR_WARN)[WARN] PUSH_OFFLINE=0: пуш пропущен$(COLOR_RESET)"; fi + +__docker_inspect: + @docker image inspect "$(FULL_IMAGE)" || true + +__docker_create_builder: + @docker buildx create --name $(BUILDER) --use --bootstrap || docker buildx use $(BUILDER) + @echo "$(COLOR_OK)[OK] Builder ready: $(BUILDER)$(COLOR_RESET)" + +__docker_use_builder: + @docker buildx use $(BUILDER) + @docker buildx inspect --bootstrap + @echo "$(COLOR_OK)[OK] Using builder: $(BUILDER)$(COLOR_RESET)" + +__docker_clean: + @echo "$(COLOR_WARN)[WARN] Removing logs and .offline$(COLOR_RESET)" + @rm -rf "$(LOG_DIR)" "$(OFFLINE_DIR)" + @echo "$(COLOR_OK)[OK] Clean done$(COLOR_RESET)" + +__docker_print_config: + @echo "FULL_IMAGE : $(FULL_IMAGE)" + @echo "REGISTRY : $(REGISTRY)" + @echo "IMAGE : $(IMAGE)" + @echo "TAG : $(TAG)" + @echo "CONTEXT : $(CONTEXT)" + @echo "DOCKERFILE : $(DOCKERFILE)" + @echo "USE_BUILDX : $(USE_BUILDX)" + @echo "PLATFORMS : $(PLATFORMS)" + @echo "PUSH : $(PUSH)" + @echo "LOAD : $(LOAD)" + @echo "NO_CACHE : $(NO_CACHE)" + @echo "PULL : $(PULL)" + @echo "QUIET : $(QUIET)" + @echo "BUILD_ARGS : $(BUILD_ARGS)" + @echo "ARG_FILE : $(ARG_FILE)" + @echo "RUN_CMD : $(RUN_CMD)" + @echo "BUILDER : $(BUILDER)" + @echo "LOG_DIR : $(LOG_DIR)" + @echo "LOG_FILE : $(LOG_FILE)" + +# ====================== +# Docker dispatcher +# ====================== +.PHONY: docker +docker: + @sub="$(word 2,$(MAKECMDGOALS))"; \ + case "$$sub" in \ + build) $(MAKE) __docker_build ;; \ + check) $(MAKE) __docker_check ;; \ + push) $(MAKE) __docker_build __docker_check __docker_push ;; \ + save) $(MAKE) __docker_save ;; \ + load) $(MAKE) __docker_load ;; \ + load-raw) $(MAKE) __docker_load_raw ;; \ + inspect) $(MAKE) __docker_inspect ;; \ + retag) $(MAKE) __docker_retag ;; \ + create-builder) $(MAKE) __docker_create_builder ;; \ + use-builder) $(MAKE) __docker_use_builder ;; \ + login) $(MAKE) __docker_login ;; \ + clean) $(MAKE) __docker_clean ;; \ + print-config) $(MAKE) __docker_print_config ;; \ + "") \ + echo "$(COLOR_INFO)[INFO] Docker commands:$(COLOR_RESET)"; \ + echo " make docker build — собрать образ"; \ + echo " make docker check — проверить контейнер (RUN_CMD)"; \ + echo " make docker push — build + check + push"; \ + echo " make docker save — сохранить образ в ./images/"; \ + echo " make docker load — загрузить из архива и (опц.) запушить"; \ + echo " make docker load-raw — чистый docker load -i FILE"; \ + echo " make docker inspect — docker image inspect"; \ + echo " make docker retag — перетегировать локальный образ"; \ + echo " make docker create-builder — создать buildx builder"; \ + echo " make docker use-builder — выбрать buildx builder"; \ + echo " make docker login — docker login в REGISTRY"; \ + echo " make docker clean — удалить логи и .offline"; \ + echo " make docker print-config — показать конфигурацию"; \ + ;; \ + *) echo "$(COLOR_ERR)[ERR] Unknown docker subcommand: $$sub$(COLOR_RESET)"; exit 1 ;; \ + esac + +# ====================== +# Git: реализация +# ====================== +.PHONY: __git_status __git_pull __git_commit __git_push __git_sync + +__git_status: + @echo "$(COLOR_INFO)[INFO] Git status ($(GIT_BRANCH))$(COLOR_RESET)" + @git status -sb || echo "$(COLOR_WARN)[WARN] Not a git repository$(COLOR_RESET)" + +__git_pull: + @echo "$(COLOR_INFO)[INFO] Pulling from $(GIT_REMOTE)/$(GIT_BRANCH)$(COLOR_RESET)" + @git pull $(GIT_REMOTE) $(GIT_BRANCH) || echo "$(COLOR_ERR)[ERR] git pull failed$(COLOR_RESET)" + +__git_commit: + @echo "$(COLOR_INFO)[INFO] Preparing commit$(COLOR_RESET)" + @if [ -z "$(GIT_MSG)" ]; then \ + read -p "Введите сообщение коммита: " msg; \ + GIT_MSG="$$msg"; \ + else \ + GIT_MSG="$(GIT_MSG)"; \ + fi; \ + git add -A; \ + if git diff --cached --quiet; then \ + echo "$(COLOR_WARN)[WARN] Нет изменений для коммита$(COLOR_RESET)"; \ + else \ + git commit -m "$$GIT_MSG" && echo "$(COLOR_OK)[OK] Commit created: $$GIT_MSG$(COLOR_RESET)"; \ + fi + +__git_push: + @echo "$(COLOR_INFO)[INFO] Preparing push for $(GIT_BRANCH)$(COLOR_RESET)" + @$(MAKE) __git_commit + @echo "$(COLOR_INFO)[INFO] Pushing to $(GIT_REMOTE)/$(GIT_BRANCH)$(COLOR_RESET)" + @git push $(GIT_REMOTE) $(GIT_BRANCH) || echo "$(COLOR_ERR)[ERR] git push failed$(COLOR_RESET)" + +__git_sync: + @echo "$(COLOR_INFO)[INFO] Git sync (pull + commit + push)$(COLOR_RESET)" + @$(MAKE) __git_pull + @$(MAKE) __git_push + @echo "$(COLOR_OK)[OK] Git sync complete for branch $(GIT_BRANCH)$(COLOR_RESET)" + +# ====================== +# Git dispatcher +# ====================== +.PHONY: git +git: + @sub="$(word 2,$(MAKECMDGOALS))"; \ + case "$$sub" in \ + status) $(MAKE) __git_status ;; \ + pull) $(MAKE) __git_pull ;; \ + commit) $(MAKE) __git_commit ;; \ + push) $(MAKE) __git_push ;; \ + sync) $(MAKE) __git_sync ;; \ + "") \ + echo "$(COLOR_INFO)[INFO] Git commands:$(COLOR_RESET)"; \ + echo " make git status — показать статус"; \ + echo " make git pull — получить изменения"; \ + echo " make git commit — коммит (со вводом сообщения)"; \ + echo " make git push — commit + push (со вводом сообщения)"; \ + echo " make git sync — pull + commit + push"; \ + ;; \ + *) echo "$(COLOR_ERR)[ERR] Unknown git subcommand: $$sub$(COLOR_RESET)"; exit 1 ;; \ + esac + +.PHONY: status pull commit push sync \ + build check save load load-raw inspect retag create-builder use-builder login clean print-config +status pull commit push sync \ +build check save load load-raw inspect retag create-builder use-builder login clean print-config: + @: \ No newline at end of file diff --git a/readme.txt b/readme.txt new file mode 100644 index 0000000..1f7be25 --- /dev/null +++ b/readme.txt @@ -0,0 +1,403 @@ +========================================================= +UNIVERSAL MAKEFILE FOR DOCKER AND GIT +========================================================= + +Автор: Sergey Antropov +Версия: 2.0 +Описание: Универсальный Makefile для управления Docker-образами, +их сборкой, сохранением, загрузкой, публикацией, а также +интеграцией с Git. + +========================================================= +РАЗДЕЛ 1. ОБЩЕЕ ОПИСАНИЕ +========================================================= + +Makefile предназначен для автоматизации типовых задач DevOps: +- сборка Docker-образов (включая Buildx) +- сохранение и загрузка архивов образов (save/load) +- оффлайн публикация (ретег и push) +- логирование всех операций +- Git-команды (commit, push, pull, sync) +- быстрая проверка сборки через RUN_CMD + +Все сценарии универсальны, не требуют внешних зависимостей +кроме установленного Docker и Git. + +========================================================= +РАЗДЕЛ 2. ОСНОВНЫЕ КОМАНДЫ +========================================================= + +Формат вызова: + make <группа> <действие> [переменные] + +--------------------------------------------------------- +ГРУППА: docker +--------------------------------------------------------- +make docker build + Собрать Docker-образ. + Примеры: + make docker build IMAGE=myapp TAG=latest + make docker build NO_CACHE=1 + make docker build USE_BUILDX=1 PLATFORMS="linux/amd64,linux/arm64" + +make docker check + Проверить образ, запустив RUN_CMD внутри контейнера. + Пример: + make docker check RUN_CMD="java -version" + +make docker push + Собрать, проверить и отправить образ в registry. + Пример: + make docker push IMAGE=myapp TAG=v1.0 + +make docker login + Авторизация в Docker Registry. + Пример: + make docker login REGISTRY=hub.cism-ms.ru + +make docker save + Сохранить локальный образ в архив (tar или tar.gz). + Поддерживает разбиение на части. + Пример: + make docker save SRC_IMAGE=myapp:latest COMPRESS=1 SPLIT_SIZE=2G + +make docker load + Загрузить архив, ретегнуть и (опционально) запушить. + Пример: + make docker load ARCHIVE=images/myapp.tar LOGIN=1 PUSH_OFFLINE=1 + +make docker retag + Перетегировать образ. + Пример: + make docker retag NEW_TAG=v2.0 + +make docker inspect + Просмотреть метаданные Docker-образа. + +make docker clean + Очистить временные каталоги logs/ и .offline/. + +make docker print-config + Показать текущие значения всех переменных. + +make docker create-builder + Создать buildx builder для мультиплатформенной сборки. + +make docker use-builder + Активировать ранее созданный builder. + +--------------------------------------------------------- +ГРУППА: git +--------------------------------------------------------- +make git status + Показать текущее состояние репозитория. + +make git pull + Получить последние изменения из origin. + +make git commit + Добавить и закоммитить изменения. + Если GIT_MSG не задана — запросит ввод вручную. + +make git push + Создать коммит (если есть изменения) и отправить в origin. + +make git sync + Выполнить pull, commit и push последовательно. + +========================================================= +РАЗДЕЛ 3. ПЕРЕМЕННЫЕ ОКРУЖЕНИЯ (ПОДРОБНО) +========================================================= + +Любая переменная может быть переопределена при вызове make: + make docker build IMAGE=myapp TAG=v1.0 NO_CACHE=1 + +--------------------------------------------------------- +DOCKER-ПЕРЕМЕННЫЕ +--------------------------------------------------------- + +REGISTRY + Адрес Docker Registry без протокола. + Пример: hub.cism-ms.ru/library + +IMAGE + Имя Docker-образа (обязательное поле при сборке). + +TAG + Тег образа. По умолчанию: latest. + +CONTEXT + Папка контекста сборки. По умолчанию — текущая директория. + +DOCKERFILE + Имя Dockerfile, используемого при сборке. + +USE_BUILDX + 1 — использовать Docker Buildx (для мультиплатформенной сборки). + 0 — обычный docker build. + +PLATFORMS + Целевые платформы для buildx. Пример: linux/amd64,linux/arm64. + +PUSH + 1 — выполнить docker push после buildx. + 0 — не выполнять. + +LOAD + 1 — загрузить образ в локальный docker после сборки. + 0 — не загружать (актуально для CI/CD). + +NO_CACHE + 1 — сборка без кэша. + 0 — использовать кэш. + +PULL + 1 — принудительно обновить базовые образы. + 0 — использовать локальные. + +QUIET + 1 — минимальный вывод в консоль. + 0 — стандартный. + +BUILD_ARGS + Дополнительные аргументы docker build. + Пример: BUILD_ARGS="--build-arg VERSION=1.0 --build-arg DEBUG=1" + +ARG_FILE + Путь к файлу KEY=VALUE. Все пары превращаются в --build-arg KEY=VALUE. + +RUN_CMD + Команда для проверки контейнера после сборки. + По умолчанию: lsb_release -a + +BUILDER + Имя buildx builder'а (по умолчанию universal-builder). + +LOG_DIR + Каталог для логов сборок (по умолчанию logs/). + +LOG_FILE + Файл лога, формируется автоматически с датой и временем. + +--------------------------------------------------------- +ОФФЛАЙН-ПЕРЕМЕННЫЕ (SAVE / LOAD) +--------------------------------------------------------- + +ARCHIVE + Путь к архиву образа (tar или gz). + +LOGIN + 1 — выполнить docker login перед push. + 0 — пропустить. + +PUSH_OFFLINE + 1 — выполнить docker push после загрузки архива. + 0 — только загрузить. + +KEEP_SRC_TAG + 1 — использовать тег из архива. + 0 — использовать TAG из Makefile. + +IMAGES_DIR + Каталог для сохранения архивов Docker-образов (по умолчанию images/). + +OFFLINE_DIR + Временная служебная папка (.offline). + +SRC_IMAGE + Имя исходного образа для сохранения. + +COMPRESS + 1 — сжать gzip. + 0 — оставить tar. + +SPLIT_SIZE + Размер чанка для split (например 2G). + +LAST_SAVE + Путь к последнему сохранённому архиву. + +--------------------------------------------------------- +GIT-ПЕРЕМЕННЫЕ +--------------------------------------------------------- + +GIT_REMOTE + Имя удалённого репозитория (по умолчанию origin). + +GIT_BRANCH + Текущая ветка (определяется автоматически). + +GIT_MSG + Сообщение коммита. Если не задано — будет запрошено вручную. + +--------------------------------------------------------- +ПРОЧИЕ +--------------------------------------------------------- + +FULL_IMAGE + Полное имя образа REGISTRY/IMAGE:TAG (формируется автоматически). + +Цвета (COLOR_INFO, COLOR_OK, COLOR_ERR, COLOR_WARN) + ANSI-коды для форматирования вывода. + Можно обнулить, чтобы отключить цвет в CI. + +========================================================= +РАЗДЕЛ 4. ПРИМЕРЫ +========================================================= + +1. Сборка без кэша: + make docker build NO_CACHE=1 + +2. Сборка и пуш мультиплатформенного образа: + make docker build USE_BUILDX=1 PUSH=1 LOAD=0 PLATFORMS="linux/amd64,linux/arm64" + +3. Проверка образа: + make docker check RUN_CMD="java -version" + +4. Сохранение и сжатие: + make docker save SRC_IMAGE=myapp:latest COMPRESS=1 + +5. Загрузка и пуш: + make docker load ARCHIVE=images/myapp.tar LOGIN=1 PUSH_OFFLINE=1 + +6. Коммит и пуш в git: + make git push GIT_MSG="Обновлены зависимости" + +7. Быстрое обновление ветки: + make git sync + +========================================================= +РАЗДЕЛ 5. ВОЗМОЖНЫЕ ПРОБЛЕМЫ И РЕШЕНИЯ +========================================================= + +--------------------------------------------------------- +1. Ошибка: "missing separator. Stop." +--------------------------------------------------------- +Причина: + В Makefile должны быть табы, а не пробелы. + +Решение: + Преобразовать пробелы в табы: + sed -i 's/^ /\t/' Makefile + +--------------------------------------------------------- +2. Ошибка: "unknown instruction: yum (did you mean RUN?)" +--------------------------------------------------------- +Причина: + В Dockerfile после инструкции `RUN < + +--------------------------------------------------------- +5. Ошибка: "docker: command not found" +--------------------------------------------------------- +Причина: + Docker не установлен или не добавлен в PATH. + +Решение: + Установи Docker и проверь: + docker version + +--------------------------------------------------------- +6. Ошибка при push: "unauthorized: authentication required" +--------------------------------------------------------- +Причина: + Не выполнен docker login в registry. + +Решение: + Выполни: + make docker login REGISTRY=hub.cism-ms.ru + или авторизуйся вручную: + docker login hub.cism-ms.ru + +--------------------------------------------------------- +7. Ошибка: "Образ не найден" +--------------------------------------------------------- +Причина: + Указан неверный SRC_IMAGE или IMAGE не собран. + +Решение: + Убедись, что образ существует: + docker images + Или собери его: + make docker build + +--------------------------------------------------------- +8. Ошибка checksum при загрузке архива +--------------------------------------------------------- +Причина: + Повреждён файл tar.gz. + +Решение: + Проверить хеш-сумму: + sha256sum images/*.sha256 + Пересобрать архив: + make docker save SRC_IMAGE=myapp:latest COMPRESS=1 + +--------------------------------------------------------- +9. Ошибка "Git push failed" +--------------------------------------------------------- +Причина: + Нет прав на запись в репозиторий или неверная ветка. + +Решение: + Проверь текущую ветку: + git branch + Выполни повторно push: + make git push GIT_MSG="Обновление" + +--------------------------------------------------------- +10. Ошибка Buildx: "no builder instance" +--------------------------------------------------------- +Причина: + Buildx не инициализирован. + +Решение: + Создай builder: + make docker create-builder + Затем используй: + make docker use-builder + +========================================================= +РАЗДЕЛ 6. СОВЕТЫ ПО ИСПОЛЬЗОВАНИЮ +========================================================= + +- Всегда задавай REGISTRY и IMAGE при сборке. +- Для CI/CD добавь NO_CACHE=1 и QUIET=1. +- Для оффлайн-деплоя используй SAVE/LOAD. +- Git-команды можно вызывать без аргументов — Makefile запросит сообщение сам. +- Если часто работаешь с конкретными параметрами — создай файл `.env` или `Makefile.local`. + +========================================================= + ЛИЦЕНЗИЯ +========================================================= + + MIT License + Свободно для использования в любых проектах. + +=========================================================