153 lines
5.5 KiB
Docker
153 lines
5.5 KiB
Docker
# Alpine-based MUSL static binary builder for C-Relay-PG
|
|
# Produces truly portable binaries with zero runtime dependencies
|
|
|
|
ARG DEBUG_BUILD=false
|
|
ARG DB_BACKEND=sqlite
|
|
|
|
FROM alpine:3.19 AS builder
|
|
|
|
# Re-declare build arguments in this stage
|
|
ARG DEBUG_BUILD=false
|
|
ARG DB_BACKEND=sqlite
|
|
|
|
# Install build dependencies
|
|
RUN apk add --no-cache \
|
|
build-base \
|
|
musl-dev \
|
|
git \
|
|
cmake \
|
|
pkgconfig \
|
|
autoconf \
|
|
automake \
|
|
libtool \
|
|
openssl-dev \
|
|
openssl-libs-static \
|
|
zlib-dev \
|
|
zlib-static \
|
|
curl-dev \
|
|
curl-static \
|
|
sqlite-dev \
|
|
sqlite-static \
|
|
postgresql-dev \
|
|
linux-headers \
|
|
wget \
|
|
bash \
|
|
openssh-client
|
|
|
|
# Set working directory
|
|
WORKDIR /build
|
|
|
|
# Build libsecp256k1 static (cached layer - only rebuilds if Alpine version changes)
|
|
RUN cd /tmp && \
|
|
git clone https://github.com/bitcoin-core/secp256k1.git && \
|
|
cd secp256k1 && \
|
|
./autogen.sh && \
|
|
./configure --enable-static --disable-shared --prefix=/usr \
|
|
CFLAGS="-fPIC" && \
|
|
make -j$(nproc) && \
|
|
make install && \
|
|
rm -rf /tmp/secp256k1
|
|
|
|
# Build libwebsockets static with minimal features (cached layer)
|
|
RUN cd /tmp && \
|
|
git clone --depth 1 --branch v4.3.3 https://github.com/warmcat/libwebsockets.git && \
|
|
cd libwebsockets && \
|
|
mkdir build && cd build && \
|
|
cmake .. \
|
|
-DLWS_WITH_STATIC=ON \
|
|
-DLWS_WITH_SHARED=OFF \
|
|
-DLWS_WITH_SSL=ON \
|
|
-DLWS_WITHOUT_TESTAPPS=ON \
|
|
-DLWS_WITHOUT_TEST_SERVER=ON \
|
|
-DLWS_WITHOUT_TEST_CLIENT=ON \
|
|
-DLWS_WITHOUT_TEST_PING=ON \
|
|
-DLWS_WITH_HTTP2=OFF \
|
|
-DLWS_WITH_LIBUV=OFF \
|
|
-DLWS_WITH_LIBEVENT=OFF \
|
|
-DLWS_IPV6=ON \
|
|
-DCMAKE_BUILD_TYPE=Release \
|
|
-DCMAKE_INSTALL_PREFIX=/usr \
|
|
-DCMAKE_C_FLAGS="-fPIC" && \
|
|
make -j$(nproc) && \
|
|
make install && \
|
|
rm -rf /tmp/libwebsockets
|
|
|
|
# Submodules are provided in the local build context and copied explicitly below.
|
|
# Avoid network/SSH dependency inside Docker image build.
|
|
|
|
# Copy nostr_core_lib source files (cached unless nostr_core_lib changes)
|
|
COPY nostr_core_lib /build/nostr_core_lib/
|
|
|
|
# Copy c_utils_lib source files (cached unless c_utils_lib changes)
|
|
COPY c_utils_lib /build/c_utils_lib/
|
|
|
|
# Build c_utils_lib static library for relay logging utilities
|
|
# (build only debug.c to avoid broken/missing version header surface in submodule revision)
|
|
RUN cd c_utils_lib && \
|
|
mkdir -p build && \
|
|
gcc -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=0 -Wall -Wextra -std=c99 -O2 -g \
|
|
-Isrc -Iinclude -c src/debug.c -o build/debug.o && \
|
|
ar rcs libc_utils.a build/debug.o
|
|
|
|
# Build nostr_core_lib with required NIPs (cached unless nostr_core_lib changes)
|
|
# Disable fortification in build.sh to prevent __*_chk symbol issues
|
|
# NIPs: 001(Basic), 004(Encryption), 006(Keys), 013(PoW), 017(DMs), 019(Bech32), 044(Encryption), 059(Gift Wrap - required by NIP-17)
|
|
# NIP-04 is required by nostr_signer.c (NIP-46 bunker signer uses NIP-04 encryption)
|
|
RUN cd nostr_core_lib && \
|
|
chmod +x build.sh && \
|
|
sed -i 's/CFLAGS="-Wall -Wextra -std=c99 -fPIC -O2"/CFLAGS="-U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=0 -Wall -Wextra -std=c99 -fPIC -O2"/' build.sh && \
|
|
rm -f *.o *.a 2>/dev/null || true && \
|
|
./build.sh --nips=1,4,6,13,17,19,44,59
|
|
|
|
# Copy c-relay-pg source files LAST (only this layer rebuilds on source changes)
|
|
COPY src/ /build/src/
|
|
COPY Makefile /build/Makefile
|
|
|
|
# Build c-relay-pg with full static linking (only rebuilds when src/ changes)
|
|
# Disable fortification to avoid __*_chk symbols that don't exist in MUSL
|
|
# Use conditional compilation flags based on DEBUG_BUILD and DB_BACKEND build args
|
|
RUN if [ "$DEBUG_BUILD" = "true" ]; then \
|
|
CFLAGS="-g -O2 -DDEBUG"; \
|
|
STRIP_CMD="echo 'Keeping debug symbols'"; \
|
|
echo "Building with DEBUG symbols enabled (optimized with -O2)"; \
|
|
else \
|
|
CFLAGS="-O2"; \
|
|
STRIP_CMD="strip /build/c_relay_pg_static"; \
|
|
echo "Building optimized production binary (symbols stripped)"; \
|
|
fi && \
|
|
if [ "$DB_BACKEND" = "postgres" ]; then \
|
|
DB_FLAGS="-DDB_BACKEND_POSTGRES -DHAVE_LIBPQ"; \
|
|
DB_LIBS="-lpq -lpgcommon -lpgport"; \
|
|
echo "Compiling with PostgreSQL backend"; \
|
|
else \
|
|
DB_FLAGS=""; \
|
|
DB_LIBS=""; \
|
|
echo "Compiling with SQLite backend"; \
|
|
fi && \
|
|
gcc -static $CFLAGS $DB_FLAGS -Wall -Wextra -std=c99 \
|
|
-U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=0 \
|
|
-I. -Ic_utils_lib/src -Inostr_core_lib -Inostr_core_lib/nostr_core \
|
|
-Inostr_core_lib/cjson -Inostr_core_lib/nostr_websocket -I/usr/include/postgresql \
|
|
src/main.c src/config.c src/dm_admin.c src/request_validator.c \
|
|
src/nip009.c src/nip011.c src/nip013.c src/nip040.c src/nip042.c \
|
|
src/websockets.c src/subscriptions.c src/api.c src/embedded_web_content.c src/ip_ban.c \
|
|
src/caching_inbox_poller.c src/caching_service_launcher.c \
|
|
src/db_ops.c src/db_ops_sqlite.c src/db_ops_postgres.c src/thread_pool.c \
|
|
-o /build/c_relay_pg_static \
|
|
c_utils_lib/libc_utils.a \
|
|
nostr_core_lib/libnostr_core_x64.a \
|
|
-lwebsockets -lssl -lcrypto -lsqlite3 -lsecp256k1 \
|
|
-lcurl -lz -lpthread -lm -ldl $DB_LIBS && \
|
|
eval "$STRIP_CMD"
|
|
|
|
# Verify it's truly static
|
|
RUN echo "=== Binary Information ===" && \
|
|
file /build/c_relay_pg_static && \
|
|
ls -lh /build/c_relay_pg_static && \
|
|
echo "=== Checking for dynamic dependencies ===" && \
|
|
(ldd /build/c_relay_pg_static 2>&1 || echo "Binary is static") && \
|
|
echo "=== Build complete ==="
|
|
|
|
# Output stage - just the binary
|
|
FROM scratch AS output
|
|
COPY --from=builder /build/c_relay_pg_static /c_relay_pg_static |