Files
SubConverter-Extended/Dockerfile
2026-06-01 18:56:10 +08:00

235 lines
9.2 KiB
Docker
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# ========== GO BUILD STAGE ==========
# 使用 glibc (Debian) 构建 Go 共享库,避免 musl 下 Go runtime 初始化崩溃
FROM mirror.gcr.io/library/golang:latest AS go-builder
ARG TARGETARCH
ARG TARGETVARIANT
ARG MIHOMO_REF="Meta"
ARG MIHOMO_CACHE_BUST=1
ARG REFRESH_GO_DEPS=false
WORKDIR /build/bridge
# Debian 使用 apt 包管理器
RUN apt-get update && \
apt-get install -y --no-install-recommends git build-essential && \
rm -rf /var/lib/apt/lists/*
# Copy committed Go module files and source.
COPY bridge/go.mod bridge/go.sum ./
COPY bridge/converter.go ./
COPY bridge/preprocess.go ./
RUN set -xe && \
if [ "${REFRESH_GO_DEPS}" = "true" ]; then \
echo "MIHOMO_CACHE_BUST=$MIHOMO_CACHE_BUST" && \
go get github.com/metacubex/mihomo@${MIHOMO_REF} && \
go get -u all && \
go mod tidy; \
else \
go mod download; \
fi
# Copy scripts for scheme generation
COPY scripts/ ../scripts/
RUN go run ../scripts/generate_schemes.go mihomo_schemes.h
RUN go run ../scripts/generate_param_compat.go -o param_compat.h
# Build shared library (c-shared mode for musl compatibility)
# 关键修改:
# 1. 使用 c-shared 模式避免 musl 环境下 Go runtime 初始化问题
# 2. musl libc 不向构造函数传递 argc/argvc-archive 模式会导致 Segfault
# 3. c-shared 模式下 Go runtime 边界清晰,初始化更稳定
RUN echo "==> Building for $TARGETARCH with c-shared mode (musl compatible)" && \
CGO_ENABLED=1 \
go build \
-trimpath \
-buildmode=c-shared \
-o libmihomo.so \
.
# Verify build output
RUN ls -lh libmihomo.so libmihomo.h
# ========== C++ BUILD STAGE ==========
# 使用 Debian (glibc) 编译,运行时再搬运依赖到 Alpine
FROM mirror.gcr.io/library/debian:latest AS builder
ARG THREADS="4"
ARG SHA=""
ARG VERSION="dev"
ARG BUILD_DATE=""
ARG REFRESH_HEADERS=false
ARG SOURCE_DEPS_CACHE_BUST=stable
WORKDIR /
# 安装 Debian 构建依赖
RUN apt-get update && \
apt-get install -y --no-install-recommends \
git g++ build-essential cmake python3 python3-pip \
pkg-config curl \
libcurl4-openssl-dev libpcre2-dev rapidjson-dev \
libyaml-cpp-dev ca-certificates ninja-build ccache && \
rm -rf /var/lib/apt/lists/*
# quickjspp
RUN set -xe && \
echo "SOURCE_DEPS_CACHE_BUST=${SOURCE_DEPS_CACHE_BUST}" && \
git clone --depth=1 --recurse-submodules --shallow-submodules https://github.com/ftk/quickjspp.git quickjspp && \
cd quickjspp && \
cmake -DCMAKE_BUILD_TYPE=Release . && \
make quickjs -j ${THREADS} && \
install -d /usr/lib/quickjs/ && \
install -m644 quickjs/libquickjs.a /usr/lib/quickjs/ && \
install -d /usr/include/quickjs/ && \
install -m644 quickjs/quickjs.h quickjs/quickjs-libc.h /usr/include/quickjs/ && \
install -m644 quickjspp.hpp /usr/include
# libcron
RUN set -xe && \
echo "SOURCE_DEPS_CACHE_BUST=${SOURCE_DEPS_CACHE_BUST}" && \
git clone --depth=1 --recurse-submodules --shallow-submodules https://github.com/PerMalmberg/libcron.git libcron && \
cd libcron && \
cmake -DCMAKE_BUILD_TYPE=Release . && \
make libcron -j ${THREADS} && \
install -m644 libcron/out/Release/liblibcron.a /usr/lib/ && \
install -d /usr/include/libcron/ && \
install -m644 libcron/include/libcron/* /usr/include/libcron/ && \
install -d /usr/include/date/ && \
install -m644 libcron/externals/date/include/date/* /usr/include/date/
RUN set -xe && \
echo "SOURCE_DEPS_CACHE_BUST=${SOURCE_DEPS_CACHE_BUST}" && \
git clone --depth=1 https://github.com/ToruNiina/toml11.git toml11 && \
cd toml11 && \
cmake -DCMAKE_CXX_STANDARD=11 . && \
make install -j ${THREADS}
# Copy Go shared library and module files from go-builder stage
COPY --from=go-builder /build/bridge/libmihomo.so /usr/lib/
COPY --from=go-builder /build/bridge/libmihomo.h /usr/include/
COPY --from=go-builder /build/bridge/go.mod /src/bridge/go.mod
COPY --from=go-builder /build/bridge/go.sum /src/bridge/go.sum
# build SubConverter-Extended from THIS repository source
WORKDIR /src
COPY . /src
COPY --from=go-builder /build/bridge/mihomo_schemes.h /src/src/parser/mihomo_schemes.h
COPY --from=go-builder /build/bridge/param_compat.h /src/src/parser/param_compat.h
RUN set -xe && \
if [ "${REFRESH_HEADERS}" = "true" ]; then \
echo "Downloading latest cpp-httplib..." && \
curl -fsSL https://raw.githubusercontent.com/yhirose/cpp-httplib/master/httplib.h -o include/httplib.h && \
echo "Downloading latest nlohmann/json..." && \
curl -fsSL https://github.com/nlohmann/json/releases/latest/download/json.hpp -o include/nlohmann/json.hpp && \
echo "Downloading latest inja..." && \
curl -fsSL https://raw.githubusercontent.com/pantor/inja/master/single_include/inja/inja.hpp -o include/inja.hpp && \
echo "Downloading latest jpcre2..." && \
curl -fsSL https://raw.githubusercontent.com/jpcre2/jpcre2/master/src/jpcre2.hpp -o include/jpcre2.hpp && \
echo "Copying latest quickjspp from compiled source..." && \
cp /usr/include/quickjspp.hpp include/quickjspp.hpp && \
echo "Copying latest libcron headers from compiled source..." && \
rm -rf include/libcron include/date && \
cp -a /libcron/libcron/include/libcron include/libcron && \
cp -a /libcron/libcron/externals/date/include/date include/date && \
echo "Copying latest toml11 headers from compiled source..." && \
rm -rf include/toml11 && \
cp /toml11/include/toml.hpp include/toml.hpp && \
cp -a /toml11/include/toml11 include/toml11; \
else \
echo "Using committed header libraries"; \
fi
RUN set -xe && \
[ -n "${SHA}" ] && sed -i "s/#define BUILD_ID \"\"/#define BUILD_ID \"${SHA}\"/ " src/version.h || true && \
[ -n "${VERSION}" ] && sed -i "s/#define VERSION \"dev\"/#define VERSION \"${VERSION}\"/" src/version.h || true && \
[ -n "${BUILD_DATE}" ] && sed -i "s/#define BUILD_DATE \"\"/#define BUILD_DATE \"${BUILD_DATE}\"/" src/version.h || true && \
mkdir -p bridge && \
cp /usr/lib/libmihomo.so bridge/ && \
cp /usr/include/libmihomo.h bridge/ && \
export PATH="/usr/lib/ccache:$PATH" && \
export CCACHE_DIR=/tmp/ccache && \
export CCACHE_COMPILERCHECK=content && \
cmake -GNinja \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
-DCMAKE_INTERPROCEDURAL_OPTIMIZATION=OFF \
-DCMAKE_POSITION_INDEPENDENT_CODE=OFF \
. && \
ninja -j ${THREADS}
# 收集 glibc 运行时依赖(动态探测,避免固定版本)
RUN set -xe && \
mkdir -p /runtime-libs && \
ELF_LIBRARY_PATH="/usr/lib:/lib/x86_64-linux-gnu:/usr/lib/x86_64-linux-gnu:/lib/aarch64-linux-gnu:/usr/lib/aarch64-linux-gnu:/lib64" \
bash /src/scripts/ci/copy-elf-runtime-deps.sh /runtime-libs \
/src/subconverter \
/usr/lib/libmihomo.so \
libnss_dns.so.2 \
libnss_files.so.2 \
libnss_compat.so.2 \
libresolv.so.2 && \
if [ -f /etc/nsswitch.conf ]; then \
mkdir -p /runtime-libs/etc && \
cp -aL /etc/nsswitch.conf /runtime-libs/etc/nsswitch.conf; \
fi
# ========== FINAL STAGE ==========
# Alpine 运行时 + 搬运 glibc 依赖(不固定版本)
FROM mirror.gcr.io/library/alpine:latest
ARG VERSION="dev"
ARG SHA=""
ARG BUILD_DATE=""
LABEL \
org.opencontainers.image.title="SubConverter-Extended" \
org.opencontainers.image.description="A Modern Evolution of subconverter; an enhanced implementation aligned with Mihomo configuration" \
org.opencontainers.image.url="https://github.com/Aethersailor/SubConverter-Extended" \
org.opencontainers.image.source="https://github.com/Aethersailor/SubConverter-Extended" \
org.opencontainers.image.licenses="GPL-3.0" \
org.opencontainers.image.version="${VERSION}" \
org.opencontainers.image.revision="${SHA}" \
org.opencontainers.image.created="${BUILD_DATE}" \
maintainer="Aethersailor"
ENV TZ=Asia/Shanghai
RUN apk add --no-cache ca-certificates tzdata && \
ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && \
echo $TZ > /etc/timezone
COPY --from=builder /src/subconverter /usr/bin/subconverter
COPY --from=builder /src/base /base/
COPY --from=builder /runtime-libs/ /
# 确保二进制和库可执行
RUN chmod +x /usr/bin/subconverter && chmod +x /usr/lib/libmihomo.so
ENV LD_LIBRARY_PATH="/lib/x86_64-linux-gnu:/usr/lib/x86_64-linux-gnu:/lib/aarch64-linux-gnu:/usr/lib/aarch64-linux-gnu:/lib64:/usr/lib"
WORKDIR /base
RUN set -e && \
printf '%s\n' \
'#!/bin/sh' \
'set -e' \
'ARCH="$(uname -m)"' \
'case "$ARCH" in' \
' x86_64) LIB_ARCH="x86_64-linux-gnu" ;;' \
' aarch64|arm64) LIB_ARCH="aarch64-linux-gnu" ;;' \
' *) LIB_ARCH="" ;;' \
'esac' \
'if [ -n "$LIB_ARCH" ]; then' \
' export LD_LIBRARY_PATH="/lib/${LIB_ARCH}:/usr/lib/${LIB_ARCH}:/lib64:/usr/lib"' \
'fi' \
'CONF="${PREF_PATH:-/base/pref.toml}"' \
'CONF_DIR="$(dirname "$CONF")"' \
'mkdir -p "$CONF_DIR"' \
'if [ ! -f "$CONF" ] && [ -f /base/pref.example.toml ]; then' \
' cp /base/pref.example.toml "$CONF"' \
'fi' \
'exec /usr/bin/subconverter -f "$CONF"' \
> /usr/local/bin/start-subconverter && \
chmod +x /usr/local/bin/start-subconverter
CMD ["/usr/local/bin/start-subconverter"]
EXPOSE 25500/tcp