Split gateway control and dataplane into separate services
All checks were successful
Build and Deploy Gateway / build-and-push (push) Successful in 13s
Build and Deploy Gateway / deploy (push) Successful in 12s

This commit is contained in:
2026-07-11 17:52:48 +03:00
parent 4b326c5e99
commit b0b9da51b6
15 changed files with 479 additions and 117 deletions

View File

@@ -2,17 +2,29 @@
set -euo pipefail
DEPLOY_PATH="${DEPLOY_PATH:-/opt/vpn-proxy}"
GATEWAY_IMAGE="${GATEWAY_IMAGE:?GATEWAY_IMAGE is required}"
CONTROL_IMAGE="${CONTROL_IMAGE:-${GATEWAY_IMAGE:-}}"
DATAPLANE_IMAGE="${DATAPLANE_IMAGE:-${GATEWAY_IMAGE:-}}"
CONTROL_IMAGE="${CONTROL_IMAGE:?CONTROL_IMAGE or GATEWAY_IMAGE is required}"
DATAPLANE_IMAGE="${DATAPLANE_IMAGE:?DATAPLANE_IMAGE or GATEWAY_IMAGE is required}"
UPDATE_DATAPLANE="${UPDATE_DATAPLANE:-false}"
PULL_IMAGE="${PULL_IMAGE:-true}"
echo "Preparing deploy directory: ${DEPLOY_PATH}"
mkdir -p "${DEPLOY_PATH}"
EXISTING_DATAPLANE_IMAGE="$(docker inspect --format '{{.Config.Image}}' vpn-proxy-dataplane 2>/dev/null || true)"
FIRST_SPLIT_DEPLOY=false
if [ -z "${EXISTING_DATAPLANE_IMAGE}" ]; then
FIRST_SPLIT_DEPLOY=true
elif [ "${UPDATE_DATAPLANE}" != "true" ]; then
DATAPLANE_IMAGE="${EXISTING_DATAPLANE_IMAGE}"
fi
cat > "${DEPLOY_PATH}/docker-compose.server.yml" <<EOF
services:
vpn-proxy-gateway:
image: ${GATEWAY_IMAGE}
container_name: vpn-proxy-gateway
vpn-proxy-dataplane:
image: ${DATAPLANE_IMAGE}
container_name: vpn-proxy-dataplane
network_mode: host
cap_add:
- NET_ADMIN
@@ -20,11 +32,42 @@ services:
env_file:
- .env
environment:
APP_COMPONENT: dataplane
DATA_DIR: /var/lib/vpn-proxy
SING_BOX_CONFIG: /var/lib/vpn-proxy/sing-box-config.json
SING_BOX_CACHE: /var/lib/sing-box/cache.db
DATAPLANE_SOCKET: /run/vpn-proxy/dataplane.sock
volumes:
- vpn-proxy-data:/var/lib/vpn-proxy
- sing-box-cache:/var/lib/sing-box
- vpn-proxy-runtime:/run/vpn-proxy
restart: unless-stopped
healthcheck:
test: ["CMD", "curl", "--unix-socket", "/run/vpn-proxy/dataplane.sock", "-fsS", "http://localhost/status"]
interval: 5s
timeout: 3s
retries: 12
start_period: 5s
vpn-proxy-control:
image: ${CONTROL_IMAGE}
container_name: vpn-proxy-gateway
env_file:
- .env
environment:
APP_COMPONENT: control
DATA_DIR: /var/lib/vpn-proxy
SING_BOX_CONFIG: /var/lib/vpn-proxy/sing-box-config.json
SING_BOX_CACHE: /var/lib/sing-box/cache.db
DATAPLANE_SOCKET: /run/vpn-proxy/dataplane.sock
ports:
- "\${PORT:-3456}:\${PORT:-3456}"
volumes:
- vpn-proxy-data:/var/lib/vpn-proxy
- vpn-proxy-runtime:/run/vpn-proxy
depends_on:
vpn-proxy-dataplane:
condition: service_healthy
restart: unless-stopped
healthcheck:
test: ["CMD", "curl", "-fsS", "http://127.0.0.1:\${PORT:-3456}/api/state"]
@@ -36,6 +79,7 @@ services:
volumes:
vpn-proxy-data:
sing-box-cache:
vpn-proxy-runtime:
EOF
if [ ! -f "${DEPLOY_PATH}/.env" ]; then
@@ -59,15 +103,29 @@ fi
cd "${DEPLOY_PATH}"
echo "Pulling image: ${GATEWAY_IMAGE}"
echo "Control image: ${CONTROL_IMAGE}"
echo "Dataplane image: ${DATAPLANE_IMAGE}"
if [ "${PULL_IMAGE}" = "true" ]; then
docker compose -f docker-compose.server.yml pull
docker compose -f docker-compose.server.yml pull vpn-proxy-control
if [ "${FIRST_SPLIT_DEPLOY}" = "true" ] || [ "${UPDATE_DATAPLANE}" = "true" ]; then
docker compose -f docker-compose.server.yml pull vpn-proxy-dataplane
fi
else
echo "Skipping image pull; using local image ${GATEWAY_IMAGE}"
echo "Skipping image pull"
fi
echo "Starting gateway..."
docker compose -f docker-compose.server.yml up -d
if [ "${FIRST_SPLIT_DEPLOY}" = "true" ]; then
echo "Migrating the legacy combined gateway to split services..."
docker stop vpn-proxy-gateway 2>/dev/null || true
docker rm vpn-proxy-gateway 2>/dev/null || true
docker compose -f docker-compose.server.yml up -d --wait --wait-timeout 90
elif [ "${UPDATE_DATAPLANE}" = "true" ]; then
echo "Updating control and dataplane..."
docker compose -f docker-compose.server.yml up -d --wait --wait-timeout 90
else
echo "Updating control; keeping dataplane running..."
docker compose -f docker-compose.server.yml up -d --no-deps --wait --wait-timeout 90 vpn-proxy-control
fi
echo "Current container:"
docker ps --filter "name=vpn-proxy-gateway"
echo "Current containers:"
docker ps --filter "name=vpn-proxy-gateway" --filter "name=vpn-proxy-dataplane"