Use runtime base to break gateway build cycle
This commit is contained in:
@@ -1,6 +1,8 @@
|
|||||||
PORT=3456
|
PORT=3456
|
||||||
BASE_IMAGE=debian:bookworm-slim
|
BASE_IMAGE=debian:bookworm-slim
|
||||||
SINGBOX_VERSION=1.12.13
|
SINGBOX_VERSION=1.12.13
|
||||||
|
INSTALL_RUNTIME_DEPS=true
|
||||||
|
INSTALL_SINGBOX=true
|
||||||
PROXY_PORT=8080
|
PROXY_PORT=8080
|
||||||
PROXY_BIND_IP=0.0.0.0
|
PROXY_BIND_IP=0.0.0.0
|
||||||
TPROXY_PORT=7895
|
TPROXY_PORT=7895
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ on:
|
|||||||
|
|
||||||
env:
|
env:
|
||||||
DEPLOY_PATH: /opt/vpn-proxy
|
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
|
SINGBOX_VERSION: 1.12.13
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
@@ -39,6 +39,11 @@ jobs:
|
|||||||
echo "Base image: ${{ env.BASE_IMAGE }}"
|
echo "Base image: ${{ env.BASE_IMAGE }}"
|
||||||
echo "Docker context: $(docker context show 2>/dev/null || true)"
|
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 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
|
echo "${{ secrets.REGISTRY_TOKEN }}" | docker login "$REGISTRY_HOST" -u "${{ gitea.actor }}" --password-stdin
|
||||||
DOCKER_BUILDKIT=1 docker build \
|
DOCKER_BUILDKIT=1 docker build \
|
||||||
@@ -46,6 +51,8 @@ jobs:
|
|||||||
--pull=false \
|
--pull=false \
|
||||||
--build-arg BASE_IMAGE="${{ env.BASE_IMAGE }}" \
|
--build-arg BASE_IMAGE="${{ env.BASE_IMAGE }}" \
|
||||||
--build-arg SINGBOX_VERSION="${{ env.SINGBOX_VERSION }}" \
|
--build-arg SINGBOX_VERSION="${{ env.SINGBOX_VERSION }}" \
|
||||||
|
--build-arg INSTALL_RUNTIME_DEPS=false \
|
||||||
|
--build-arg INSTALL_SINGBOX=false \
|
||||||
-t "${IMAGE}:latest" \
|
-t "${IMAGE}:latest" \
|
||||||
-t "${IMAGE}:${{ gitea.sha }}" \
|
-t "${IMAGE}:${{ gitea.sha }}" \
|
||||||
.
|
.
|
||||||
|
|||||||
21
Dockerfile
21
Dockerfile
@@ -1,13 +1,23 @@
|
|||||||
ARG BASE_IMAGE=debian:bookworm-slim
|
ARG BASE_IMAGE=debian:bookworm-slim
|
||||||
FROM ${BASE_IMAGE}
|
FROM ${BASE_IMAGE}
|
||||||
ARG SINGBOX_VERSION=1.12.13
|
ARG SINGBOX_VERSION=1.12.13
|
||||||
|
ARG INSTALL_RUNTIME_DEPS=true
|
||||||
|
ARG INSTALL_SINGBOX=true
|
||||||
COPY dist /app/dist
|
COPY dist /app/dist
|
||||||
|
|
||||||
RUN apt-get update \
|
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 \
|
&& apt-get install -y --no-install-recommends ca-certificates curl iptables ipset iproute2 nodejs dumb-init \
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
&& 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; \
|
RUN if [ "${INSTALL_SINGBOX}" = "true" ]; then \
|
||||||
|
set -eux; \
|
||||||
arch="$(dpkg --print-architecture)"; \
|
arch="$(dpkg --print-architecture)"; \
|
||||||
case "$arch" in \
|
case "$arch" in \
|
||||||
amd64) sb_arch="amd64" ;; \
|
amd64) sb_arch="amd64" ;; \
|
||||||
@@ -18,7 +28,10 @@ RUN set -eux; \
|
|||||||
tar -xzf /tmp/sing-box.tgz -C /tmp; \
|
tar -xzf /tmp/sing-box.tgz -C /tmp; \
|
||||||
mv "/tmp/sing-box-${SINGBOX_VERSION}-linux-${sb_arch}/sing-box" /usr/local/bin/sing-box; \
|
mv "/tmp/sing-box-${SINGBOX_VERSION}-linux-${sb_arch}/sing-box" /usr/local/bin/sing-box; \
|
||||||
chmod +x /usr/local/bin/sing-box; \
|
chmod +x /usr/local/bin/sing-box; \
|
||||||
rm -rf /tmp/sing-box*
|
rm -rf /tmp/sing-box*; \
|
||||||
|
else \
|
||||||
|
command -v sing-box >/dev/null; \
|
||||||
|
fi
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
COPY package.json /app/package.json
|
COPY package.json /app/package.json
|
||||||
|
|||||||
20
Dockerfile.runtime-base
Normal file
20
Dockerfile.runtime-base
Normal 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*
|
||||||
10
README.md
10
README.md
@@ -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`.
|
Скрипт собирает 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`.
|
UI доступен на `http://<gateway-ip>:3456`.
|
||||||
|
|
||||||
На роутере указать шлюз по умолчанию (или нужные подсети) на IP контейнера.
|
На роутере указать шлюз по умолчанию (или нужные подсети) на IP контейнера.
|
||||||
@@ -301,6 +309,8 @@ UI доступен на `http://<gateway-ip>:3456`.
|
|||||||
| `PORT` | `3456` | Порт веб-интерфейса |
|
| `PORT` | `3456` | Порт веб-интерфейса |
|
||||||
| `BASE_IMAGE` | `debian:bookworm-slim` | Базовый Docker image для сборки; можно заменить на mirror |
|
| `BASE_IMAGE` | `debian:bookworm-slim` | Базовый Docker image для сборки; можно заменить на mirror |
|
||||||
| `SINGBOX_VERSION` | `1.12.13` | Версия sing-box для Docker build |
|
| `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 |
|
| `PROXY_PORT` | `8080` | HTTP/SOCKS mixed inbound |
|
||||||
| `TPROXY_PORT` | `7895` | TProxy inbound sing-box |
|
| `TPROXY_PORT` | `7895` | TProxy inbound sing-box |
|
||||||
| `DATA_DIR` | `/var/lib/vpn-proxy` | Директория данных (volume) |
|
| `DATA_DIR` | `/var/lib/vpn-proxy` | Директория данных (volume) |
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ services:
|
|||||||
args:
|
args:
|
||||||
BASE_IMAGE: ${BASE_IMAGE:-debian:bookworm-slim}
|
BASE_IMAGE: ${BASE_IMAGE:-debian:bookworm-slim}
|
||||||
SINGBOX_VERSION: ${SINGBOX_VERSION:-1.12.13}
|
SINGBOX_VERSION: ${SINGBOX_VERSION:-1.12.13}
|
||||||
|
INSTALL_RUNTIME_DEPS: ${INSTALL_RUNTIME_DEPS:-true}
|
||||||
|
INSTALL_SINGBOX: ${INSTALL_SINGBOX:-true}
|
||||||
container_name: vpn-proxy-gateway
|
container_name: vpn-proxy-gateway
|
||||||
network_mode: host
|
network_mode: host
|
||||||
cap_add:
|
cap_add:
|
||||||
|
|||||||
@@ -9,9 +9,11 @@ IMAGE_NAME="${IMAGE_NAME:-vpn-proxy-gateway}"
|
|||||||
GIT_REF="$(git rev-parse --short HEAD 2>/dev/null || echo manual)"
|
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)}"
|
IMAGE_TAG="${IMAGE_TAG:-${GIT_REF}-$(date +%Y%m%d%H%M%S)}"
|
||||||
GATEWAY_IMAGE="${GATEWAY_IMAGE:-${IMAGE_NAME}:${IMAGE_TAG}}"
|
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}"
|
SINGBOX_VERSION="${SINGBOX_VERSION:-1.12.13}"
|
||||||
DOCKER_BUILD_PULL="${DOCKER_BUILD_PULL:-false}"
|
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 "Build host: ${BUILD_HOST}"
|
||||||
echo "Deploy host: ${DEPLOY_HOST}"
|
echo "Deploy host: ${DEPLOY_HOST}"
|
||||||
@@ -29,7 +31,7 @@ rsync -az --delete \
|
|||||||
|
|
||||||
echo "Building image on ${BUILD_HOST}"
|
echo "Building image on ${BUILD_HOST}"
|
||||||
ssh "${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}"
|
echo "Loading image into ${DEPLOY_HOST}"
|
||||||
ssh "${BUILD_HOST}" "docker save '${GATEWAY_IMAGE}'" | ssh "${DEPLOY_HOST}" "docker load"
|
ssh "${BUILD_HOST}" "docker save '${GATEWAY_IMAGE}'" | ssh "${DEPLOY_HOST}" "docker load"
|
||||||
|
|||||||
16
scripts/build-runtime-base.sh
Executable file
16
scripts/build-runtime-base.sh
Executable 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}" \
|
||||||
|
.
|
||||||
Reference in New Issue
Block a user