Files
didactyl/Dockerfile.alpine-musl

117 lines
3.7 KiB
Docker

# Alpine-based MUSL static binary builder for Didactyl
# Produces truly portable binaries with zero runtime dependencies
ARG DEBUG_BUILD=false
FROM alpine:3.19 AS builder
# Re-declare build argument in this stage
ARG DEBUG_BUILD=false
# 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 \
nghttp2-dev \
nghttp2-static \
c-ares-dev \
c-ares-static \
libpsl-dev \
libpsl-static \
libidn2-dev \
libidn2-static \
libunistring-dev \
libunistring-static \
brotli-dev \
brotli-static \
zstd-dev \
zstd-static \
sqlite-dev \
sqlite-static \
linux-headers \
wget \
bash
# 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
# Copy nostr_core_lib source files (cached unless nostr_core_lib changes)
# NOTE: nostr_core_lib currently compiles request_validator, which includes <sqlite3.h>,
# so sqlite-dev/sqlite-static are required in this image even if didactyl does not use sqlite directly.
COPY nostr_core_lib /build/nostr_core_lib/
# Build nostr_core_lib with all NIPs
# Disable fortification in build.sh to prevent __*_chk symbol issues
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=all
# Copy didactyl source files LAST (only this layer rebuilds on source changes)
COPY src/ /build/src/
COPY Makefile /build/Makefile
# Build didactyl 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 argument
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/didactyl_static"; \
echo "Building optimized production binary (symbols stripped)"; \
fi && \
CURL_LIBS="$(pkg-config --static --libs libcurl)" && \
OPENSSL_LIBS="$(pkg-config --static --libs openssl)" && \
gcc -static $CFLAGS -Wall -Wextra -std=c99 \
-U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=0 \
-I. -Isrc -Inostr_core_lib -Inostr_core_lib/nostr_core \
-Inostr_core_lib/cjson -Inostr_core_lib/nostr_websocket \
src/main.c src/config.c src/context.c src/llm.c \
src/nostr_handler.c src/agent.c src/tools.c src/debug.c \
-o /build/didactyl_static \
nostr_core_lib/libnostr_core_x64.a \
-lsecp256k1 \
$OPENSSL_LIBS \
$CURL_LIBS \
-lpthread -lm -ldl && \
eval "$STRIP_CMD"
# Verify it's truly static
RUN echo "=== Binary Information ===" && \
file /build/didactyl_static && \
ls -lh /build/didactyl_static && \
echo "=== Checking for dynamic dependencies ===" && \
(ldd /build/didactyl_static 2>&1 || echo "Binary is static") && \
echo "=== Build complete ==="
# Output stage - just the binary
FROM scratch AS output
COPY --from=builder /build/didactyl_static /didactyl_static