Use runtime base to break gateway build cycle
Some checks failed
Build and Deploy Gateway / build-and-push (push) Has been cancelled
Build and Deploy Gateway / deploy (push) Has been cancelled

This commit is contained in:
2026-05-09 10:46:13 +03:00
parent e16f401dc5
commit d12b0c01fc
8 changed files with 90 additions and 18 deletions

View File

@@ -1,6 +1,8 @@
PORT=3456
BASE_IMAGE=debian:bookworm-slim
SINGBOX_VERSION=1.12.13
INSTALL_RUNTIME_DEPS=true
INSTALL_SINGBOX=true
PROXY_PORT=8080
PROXY_BIND_IP=0.0.0.0
TPROXY_PORT=7895

View File

@@ -7,7 +7,7 @@ on:
env:
DEPLOY_PATH: /opt/vpn-proxy
BASE_IMAGE: mirror.gcr.io/library/debian:bookworm-slim
BASE_IMAGE: vpn-proxy-runtime-base:bookworm-slim
SINGBOX_VERSION: 1.12.13
jobs:
@@ -39,6 +39,11 @@ jobs:
echo "Base image: ${{ env.BASE_IMAGE }}"
echo "Docker context: $(docker context show 2>/dev/null || true)"
docker info 2>/dev/null | sed -n '/HTTP Proxy:/p;/HTTPS Proxy:/p;/Name:/p'
docker image inspect "${{ env.BASE_IMAGE }}" >/dev/null || {
echo "Runtime base image ${{ env.BASE_IMAGE }} is missing on lxc-107."
echo "Seed it once on 107 with: ./scripts/build-runtime-base.sh"
exit 1
}
echo "${{ secrets.REGISTRY_TOKEN }}" | docker login "$REGISTRY_HOST" -u "${{ gitea.actor }}" --password-stdin
DOCKER_BUILDKIT=1 docker build \
@@ -46,6 +51,8 @@ jobs:
--pull=false \
--build-arg BASE_IMAGE="${{ env.BASE_IMAGE }}" \
--build-arg SINGBOX_VERSION="${{ env.SINGBOX_VERSION }}" \
--build-arg INSTALL_RUNTIME_DEPS=false \
--build-arg INSTALL_SINGBOX=false \
-t "${IMAGE}:latest" \
-t "${IMAGE}:${{ gitea.sha }}" \
.

View File

@@ -1,24 +1,37 @@
ARG BASE_IMAGE=debian:bookworm-slim
FROM ${BASE_IMAGE}
ARG SINGBOX_VERSION=1.12.13
ARG INSTALL_RUNTIME_DEPS=true
ARG INSTALL_SINGBOX=true
COPY dist /app/dist
RUN apt-get update \
&& apt-get install -y --no-install-recommends ca-certificates curl iptables ipset iproute2 nodejs dumb-init \
&& rm -rf /var/lib/apt/lists/*
RUN if [ "${INSTALL_RUNTIME_DEPS}" = "true" ]; then \
apt-get update \
&& apt-get install -y --no-install-recommends ca-certificates curl iptables ipset iproute2 nodejs dumb-init \
&& rm -rf /var/lib/apt/lists/*; \
else \
command -v dumb-init >/dev/null \
&& command -v node >/dev/null \
&& command -v iptables >/dev/null \
&& command -v ipset >/dev/null; \
fi
RUN set -eux; \
arch="$(dpkg --print-architecture)"; \
case "$arch" in \
amd64) sb_arch="amd64" ;; \
arm64) sb_arch="arm64" ;; \
*) echo "Unsupported architecture: $arch" >&2; exit 1 ;; \
esac; \
curl -fsSL "https://github.com/SagerNet/sing-box/releases/download/v${SINGBOX_VERSION}/sing-box-${SINGBOX_VERSION}-linux-${sb_arch}.tar.gz" -o /tmp/sing-box.tgz; \
tar -xzf /tmp/sing-box.tgz -C /tmp; \
mv "/tmp/sing-box-${SINGBOX_VERSION}-linux-${sb_arch}/sing-box" /usr/local/bin/sing-box; \
chmod +x /usr/local/bin/sing-box; \
rm -rf /tmp/sing-box*
RUN if [ "${INSTALL_SINGBOX}" = "true" ]; then \
set -eux; \
arch="$(dpkg --print-architecture)"; \
case "$arch" in \
amd64) sb_arch="amd64" ;; \
arm64) sb_arch="arm64" ;; \
*) echo "Unsupported architecture: $arch" >&2; exit 1 ;; \
esac; \
curl -fsSL "https://github.com/SagerNet/sing-box/releases/download/v${SINGBOX_VERSION}/sing-box-${SINGBOX_VERSION}-linux-${sb_arch}.tar.gz" -o /tmp/sing-box.tgz; \
tar -xzf /tmp/sing-box.tgz -C /tmp; \
mv "/tmp/sing-box-${SINGBOX_VERSION}-linux-${sb_arch}/sing-box" /usr/local/bin/sing-box; \
chmod +x /usr/local/bin/sing-box; \
rm -rf /tmp/sing-box*; \
else \
command -v sing-box >/dev/null; \
fi
WORKDIR /app
COPY package.json /app/package.json

20
Dockerfile.runtime-base Normal file
View File

@@ -0,0 +1,20 @@
ARG BASE_IMAGE=mirror.gcr.io/library/debian:bookworm-slim
FROM ${BASE_IMAGE}
ARG SINGBOX_VERSION=1.12.13
RUN apt-get update \
&& apt-get install -y --no-install-recommends ca-certificates curl iptables ipset iproute2 nodejs dumb-init \
&& rm -rf /var/lib/apt/lists/*
RUN set -eux; \
arch="$(dpkg --print-architecture)"; \
case "$arch" in \
amd64) sb_arch="amd64" ;; \
arm64) sb_arch="arm64" ;; \
*) echo "Unsupported architecture: $arch" >&2; exit 1 ;; \
esac; \
curl -fsSL "https://github.com/SagerNet/sing-box/releases/download/v${SINGBOX_VERSION}/sing-box-${SINGBOX_VERSION}-linux-${sb_arch}.tar.gz" -o /tmp/sing-box.tgz; \
tar -xzf /tmp/sing-box.tgz -C /tmp; \
mv "/tmp/sing-box-${SINGBOX_VERSION}-linux-${sb_arch}/sing-box" /usr/local/bin/sing-box; \
chmod +x /usr/local/bin/sing-box; \
rm -rf /tmp/sing-box*

View File

@@ -288,6 +288,14 @@ BUILD_HOST=107 DEPLOY_HOST=111 ./scripts/build-on-107-deploy-111.sh
Скрипт собирает image на `BUILD_HOST`, переносит его на `DEPLOY_HOST` через `docker save | docker load` и запускает без `docker pull`. Если `107`/`111` не являются SSH-алиасами, укажите реальные адреса, например `BUILD_HOST=root@192.168.1.107 DEPLOY_HOST=root@192.168.1.111`.
Чтобы не получать циклическую зависимость "собрать gateway можно только через уже работающий gateway", подготовьте runtime base на `107` один раз:
```bash
./scripts/build-runtime-base.sh
```
После этого CI и `build-on-107-deploy-111.sh` используют локальный `vpn-proxy-runtime-base:bookworm-slim`: основная сборка gateway больше не делает `apt-get`, не качает sing-box и не обращается к Docker Hub за base image.
UI доступен на `http://<gateway-ip>:3456`.
На роутере указать шлюз по умолчанию (или нужные подсети) на IP контейнера.
@@ -301,6 +309,8 @@ UI доступен на `http://<gateway-ip>:3456`.
| `PORT` | `3456` | Порт веб-интерфейса |
| `BASE_IMAGE` | `debian:bookworm-slim` | Базовый Docker image для сборки; можно заменить на mirror |
| `SINGBOX_VERSION` | `1.12.13` | Версия sing-box для Docker build |
| `INSTALL_RUNTIME_DEPS` | `true` | Устанавливать runtime-пакеты в Docker build; `false` для подготовленного runtime base |
| `INSTALL_SINGBOX` | `true` | Скачивать sing-box в Docker build; `false` для подготовленного runtime base |
| `PROXY_PORT` | `8080` | HTTP/SOCKS mixed inbound |
| `TPROXY_PORT` | `7895` | TProxy inbound sing-box |
| `DATA_DIR` | `/var/lib/vpn-proxy` | Директория данных (volume) |

View File

@@ -6,6 +6,8 @@ services:
args:
BASE_IMAGE: ${BASE_IMAGE:-debian:bookworm-slim}
SINGBOX_VERSION: ${SINGBOX_VERSION:-1.12.13}
INSTALL_RUNTIME_DEPS: ${INSTALL_RUNTIME_DEPS:-true}
INSTALL_SINGBOX: ${INSTALL_SINGBOX:-true}
container_name: vpn-proxy-gateway
network_mode: host
cap_add:

View File

@@ -9,9 +9,11 @@ IMAGE_NAME="${IMAGE_NAME:-vpn-proxy-gateway}"
GIT_REF="$(git rev-parse --short HEAD 2>/dev/null || echo manual)"
IMAGE_TAG="${IMAGE_TAG:-${GIT_REF}-$(date +%Y%m%d%H%M%S)}"
GATEWAY_IMAGE="${GATEWAY_IMAGE:-${IMAGE_NAME}:${IMAGE_TAG}}"
BASE_IMAGE="${BASE_IMAGE:-mirror.gcr.io/library/debian:bookworm-slim}"
BASE_IMAGE="${BASE_IMAGE:-vpn-proxy-runtime-base:bookworm-slim}"
SINGBOX_VERSION="${SINGBOX_VERSION:-1.12.13}"
DOCKER_BUILD_PULL="${DOCKER_BUILD_PULL:-false}"
INSTALL_RUNTIME_DEPS="${INSTALL_RUNTIME_DEPS:-false}"
INSTALL_SINGBOX="${INSTALL_SINGBOX:-false}"
echo "Build host: ${BUILD_HOST}"
echo "Deploy host: ${DEPLOY_HOST}"
@@ -29,7 +31,7 @@ rsync -az --delete \
echo "Building image on ${BUILD_HOST}"
ssh "${BUILD_HOST}" \
"set -e; echo 'Docker context:' \$(docker context show 2>/dev/null || true); docker info 2>/dev/null | sed -n '/HTTP Proxy:/p;/HTTPS Proxy:/p;/Name:/p'; cd '${BUILD_PATH}' && npm ci && npm run build && docker build --pull='${DOCKER_BUILD_PULL}' --build-arg BASE_IMAGE='${BASE_IMAGE}' --build-arg SINGBOX_VERSION='${SINGBOX_VERSION}' -t '${GATEWAY_IMAGE}' ."
"set -e; echo 'Docker context:' \$(docker context show 2>/dev/null || true); docker info 2>/dev/null | sed -n '/HTTP Proxy:/p;/HTTPS Proxy:/p;/Name:/p'; docker image inspect '${BASE_IMAGE}' >/dev/null || { echo 'Runtime base image ${BASE_IMAGE} is missing on ${BUILD_HOST}.'; echo 'Seed it once with: ./scripts/build-runtime-base.sh'; exit 1; }; cd '${BUILD_PATH}' && npm ci && npm run build && docker build --pull='${DOCKER_BUILD_PULL}' --build-arg BASE_IMAGE='${BASE_IMAGE}' --build-arg SINGBOX_VERSION='${SINGBOX_VERSION}' --build-arg INSTALL_RUNTIME_DEPS='${INSTALL_RUNTIME_DEPS}' --build-arg INSTALL_SINGBOX='${INSTALL_SINGBOX}' -t '${GATEWAY_IMAGE}' ."
echo "Loading image into ${DEPLOY_HOST}"
ssh "${BUILD_HOST}" "docker save '${GATEWAY_IMAGE}'" | ssh "${DEPLOY_HOST}" "docker load"

16
scripts/build-runtime-base.sh Executable file
View File

@@ -0,0 +1,16 @@
#!/usr/bin/env bash
set -euo pipefail
BASE_IMAGE="${BASE_IMAGE:-mirror.gcr.io/library/debian:bookworm-slim}"
RUNTIME_BASE_IMAGE="${RUNTIME_BASE_IMAGE:-vpn-proxy-runtime-base:bookworm-slim}"
SINGBOX_VERSION="${SINGBOX_VERSION:-1.12.13}"
echo "Building runtime base: ${RUNTIME_BASE_IMAGE}"
echo "Source base image: ${BASE_IMAGE}"
docker build \
--build-arg BASE_IMAGE="${BASE_IMAGE}" \
--build-arg SINGBOX_VERSION="${SINGBOX_VERSION}" \
-f Dockerfile.runtime-base \
-t "${RUNTIME_BASE_IMAGE}" \
.