forked from bitcoinafterlife/bal-server
docker: add release Dockerfile, fix build deps and feature-split builds
- Add Dockerfile.release: downloads latest release from Gitea, verifies SHA-256 - Fix Dockerfile: remove unused libsodium/cmake, add libsqlite3-dev - Split build per binary with --no-default-features --features server/pusher - Remove Cargo.lock from .dockerignore for reproducible builds - Update README and knowledge base with Dockerfile.release docs
This commit is contained in:
@@ -16,7 +16,6 @@ target/
|
|||||||
*.pem
|
*.pem
|
||||||
*.key
|
*.key
|
||||||
!public_key.pem
|
!public_key.pem
|
||||||
!data/public_key.pem
|
|
||||||
|
|
||||||
# Database files
|
# Database files
|
||||||
*.db
|
*.db
|
||||||
@@ -51,7 +50,6 @@ update_codebase.txt
|
|||||||
.idea/
|
.idea/
|
||||||
|
|
||||||
# Misc
|
# Misc
|
||||||
Cargo.lock
|
|
||||||
generate_random_ascii.sh
|
generate_random_ascii.sh
|
||||||
test/
|
test/
|
||||||
invalid_txs/
|
invalid_txs/
|
||||||
|
|||||||
12
Dockerfile
12
Dockerfile
@@ -11,9 +11,8 @@ FROM rust:1.95-bookworm AS builder
|
|||||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||||
pkg-config \
|
pkg-config \
|
||||||
libssl-dev \
|
libssl-dev \
|
||||||
libsodium-dev \
|
|
||||||
libzmq5-dev \
|
libzmq5-dev \
|
||||||
cmake \
|
libsqlite3-dev \
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
WORKDIR /build
|
WORKDIR /build
|
||||||
@@ -27,12 +26,14 @@ RUN mkdir -p src/bin && \
|
|||||||
echo '' > src/db.rs && \
|
echo '' > src/db.rs && \
|
||||||
echo '' > src/xpub.rs && \
|
echo '' > src/xpub.rs && \
|
||||||
echo '' > src/validation.rs && \
|
echo '' > src/validation.rs && \
|
||||||
cargo build --release --bin bal-server --bin bal-pusher 2>/dev/null || true && \
|
cargo build --release --bin bal-server --no-default-features --features server 2>/dev/null || true && \
|
||||||
|
cargo build --release --bin bal-pusher --no-default-features --features pusher 2>/dev/null || true && \
|
||||||
rm -rf src target/release/.fingerprint target/release/deps/*bal_server*
|
rm -rf src target/release/.fingerprint target/release/deps/*bal_server*
|
||||||
|
|
||||||
# Copy real source and build
|
# Copy real source and build each binary with only its required features
|
||||||
COPY src/ src/
|
COPY src/ src/
|
||||||
RUN cargo build --release --bin bal-server --bin bal-pusher && \
|
RUN cargo build --release --bin bal-server --no-default-features --features server && \
|
||||||
|
cargo build --release --bin bal-pusher --no-default-features --features pusher && \
|
||||||
strip target/release/bal-server target/release/bal-pusher
|
strip target/release/bal-server target/release/bal-pusher
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
@@ -43,7 +44,6 @@ FROM debian:bookworm-slim AS runtime
|
|||||||
# Install runtime dependencies + tini for PID 1
|
# Install runtime dependencies + tini for PID 1
|
||||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||||
libssl3 \
|
libssl3 \
|
||||||
libsodium23 \
|
|
||||||
libzmq5 \
|
libzmq5 \
|
||||||
libsqlite3-0 \
|
libsqlite3-0 \
|
||||||
ca-certificates \
|
ca-certificates \
|
||||||
|
|||||||
100
Dockerfile.release
Normal file
100
Dockerfile.release
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
# =============================================================================
|
||||||
|
# Dockerfile.release — Downloads the latest pre-built release from Gitea
|
||||||
|
# No Rust toolchain needed. Fast builds, minimal image.
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
FROM debian:bookworm-slim AS runtime
|
||||||
|
|
||||||
|
ARG GITEA_API="https://bitcoin-after.life/gitea/api/v1/repos/bitcoinafterlife/bal-server"
|
||||||
|
ARG BAL_VERSION=""
|
||||||
|
|
||||||
|
# Install runtime dependencies
|
||||||
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||||
|
libssl3 \
|
||||||
|
libzmq5 \
|
||||||
|
libsqlite3-0 \
|
||||||
|
ca-certificates \
|
||||||
|
curl \
|
||||||
|
jq \
|
||||||
|
tini \
|
||||||
|
&& rm -rf /var/lib/apt/lists/* \
|
||||||
|
&& apt-get clean
|
||||||
|
|
||||||
|
WORKDIR /tmp/bal-install
|
||||||
|
|
||||||
|
# Download and verify release
|
||||||
|
# If BAL_VERSION is set, fetch that specific tag; otherwise fetch latest
|
||||||
|
RUN set -eux; \
|
||||||
|
if [ -n "$BAL_VERSION" ]; then \
|
||||||
|
URL="${GITEA_API}/releases/tags/${BAL_VERSION}"; \
|
||||||
|
else \
|
||||||
|
URL="${GITEA_API}/releases/latest"; \
|
||||||
|
fi; \
|
||||||
|
echo "==> Fetching release metadata from $URL"; \
|
||||||
|
RELEASE_JSON=$(curl -sfL "$URL") || { echo "ERROR: Failed to fetch release metadata"; exit 1; }; \
|
||||||
|
TAG=$(echo "$RELEASE_JSON" | jq -r '.tag_name // empty'); \
|
||||||
|
if [ -z "$TAG" ]; then echo "ERROR: Could not determine release tag"; exit 1; fi; \
|
||||||
|
echo "==> Release tag: $TAG"; \
|
||||||
|
TARBALL_URL=$(echo "$RELEASE_JSON" | jq -r \
|
||||||
|
'.assets[] | select(.name | test("\\.tar\\.gz$")) | .browser_download_url' | head -1); \
|
||||||
|
if [ -z "$TARBALL_URL" ]; then echo "ERROR: No .tar.gz asset found"; exit 1; fi; \
|
||||||
|
ASSET_NAME=$(basename "$TARBALL_URL"); \
|
||||||
|
echo "==> Downloading $ASSET_NAME"; \
|
||||||
|
curl -sfL -o "$ASSET_NAME" "$TARBALL_URL" || { echo "ERROR: Download failed"; exit 1; }; \
|
||||||
|
echo "==> Downloading checksum"; \
|
||||||
|
curl -sfL -o "${ASSET_NAME}.sha256" "${TARBALL_URL}.sha256" 2>/dev/null || true; \
|
||||||
|
if [ -f "${ASSET_NAME}.sha256" ]; then \
|
||||||
|
echo "==> Verifying SHA-256 checksum"; \
|
||||||
|
sha256sum -c "${ASSET_NAME}.sha256" || { echo "ERROR: SHA-256 verification failed"; exit 1; }; \
|
||||||
|
echo "==> Checksum OK"; \
|
||||||
|
else \
|
||||||
|
echo "WARNING: No .sha256 file available — skipping checksum verification"; \
|
||||||
|
fi; \
|
||||||
|
echo "==> Extracting tarball"; \
|
||||||
|
tar -xzf "$ASSET_NAME"; \
|
||||||
|
EXTRACTED="$(basename "$ASSET_NAME" .tar.gz)"; \
|
||||||
|
for bin in bal-server bal-pusher; do \
|
||||||
|
if [ ! -f "$EXTRACTED/$bin" ]; then \
|
||||||
|
echo "ERROR: Binary '$bin' not found in archive"; \
|
||||||
|
exit 1; \
|
||||||
|
fi; \
|
||||||
|
echo "==> Installing $bin"; \
|
||||||
|
install -m 0755 -o root -g root "$EXTRACTED/$bin" /usr/local/bin/; \
|
||||||
|
done; \
|
||||||
|
echo "==> Cleanup"; \
|
||||||
|
rm -rf /tmp/bal-install
|
||||||
|
|
||||||
|
# Create dedicated non-root user
|
||||||
|
RUN groupadd -g 1000 bal && \
|
||||||
|
useradd -u 1000 -g bal -s /usr/sbin/nologin -M bal && \
|
||||||
|
mkdir -p /var/bal /var/bal/.bitcoin && \
|
||||||
|
chown -R bal:bal /var/bal && \
|
||||||
|
chmod 700 /var/bal
|
||||||
|
|
||||||
|
# Copy entrypoint
|
||||||
|
COPY docker/entrypoint.sh /usr/local/bin/entrypoint.sh
|
||||||
|
RUN chmod +x /usr/local/bin/entrypoint.sh
|
||||||
|
|
||||||
|
# Use tini as PID 1 for proper signal handling
|
||||||
|
ENTRYPOINT ["/usr/bin/tini", "--"]
|
||||||
|
CMD ["/usr/local/bin/entrypoint.sh"]
|
||||||
|
|
||||||
|
# Data directory (mount as volume)
|
||||||
|
VOLUME ["/var/bal"]
|
||||||
|
|
||||||
|
# bal-server port
|
||||||
|
EXPOSE 9137
|
||||||
|
|
||||||
|
# Default environment (override at runtime)
|
||||||
|
ENV RUST_LOG=info \
|
||||||
|
BAL_SERVER_BIND_ADDRESS=127.0.0.1 \
|
||||||
|
BAL_SERVER_BIND_PORT=9137 \
|
||||||
|
BAL_SERVER_DB_FILE=/var/bal/bal.db \
|
||||||
|
BAL_PUSHER_DB_FILE=/var/bal/bal.db \
|
||||||
|
BAL_SERVER_URL=http://127.0.0.1:9137 \
|
||||||
|
BAL_SERVER_PUB_KEY_PATH=/var/bal/public_key.pem \
|
||||||
|
SSL_KEY_PATH=/var/bal/private_key.pem
|
||||||
|
|
||||||
|
# Health check
|
||||||
|
HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
|
||||||
|
CMD curl -sf http://127.0.0.1:9137/ || exit 1
|
||||||
19
README.md
19
README.md
@@ -13,7 +13,15 @@ sudo cp target/release/bal-server target/release/bal-pusher /usr/local/bin
|
|||||||
|
|
||||||
## Docker
|
## Docker
|
||||||
|
|
||||||
### Build
|
### Quick Start (release download)
|
||||||
|
|
||||||
|
Download the latest pre-built release — no Rust toolchain needed:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker build -f Dockerfile.release -t bal-server .
|
||||||
|
```
|
||||||
|
|
||||||
|
### Build from source
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker build -t bal-server .
|
docker build -t bal-server .
|
||||||
@@ -37,6 +45,12 @@ docker run -d \
|
|||||||
bal-server
|
bal-server
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Pin a specific version
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker build -f Dockerfile.release --build-arg BAL_VERSION=v0.3.2 -t bal-server:0.3.2 .
|
||||||
|
```
|
||||||
|
|
||||||
### Docker environment variables
|
### Docker environment variables
|
||||||
|
|
||||||
| Variable | Description | Default |
|
| Variable | Description | Default |
|
||||||
@@ -48,6 +62,7 @@ docker run -d \
|
|||||||
> **Note:** The container runs as a non-root `bal` user (uid 1000) with `tini` as PID 1.
|
> **Note:** The container runs as a non-root `bal` user (uid 1000) with `tini` as PID 1.
|
||||||
> The `/var/bal` volume stores the database. Mount Bitcoin Core's cookie file as read-only.
|
> The `/var/bal` volume stores the database. Mount Bitcoin Core's cookie file as read-only.
|
||||||
> When using `--network host`, ensure only `127.0.0.1` is used for internal services.
|
> When using `--network host`, ensure only `127.0.0.1` is used for internal services.
|
||||||
|
> `Dockerfile.release` fetches the latest release from the Gitea server and verifies its SHA-256 checksum.
|
||||||
|
|
||||||
## Configuration (bal-server)
|
## Configuration (bal-server)
|
||||||
|
|
||||||
@@ -111,7 +126,7 @@ The `bal-server` application can be configured using environment variables.
|
|||||||
zmqpubhashblock=tcp://127.0.0.1:28332
|
zmqpubhashblock=tcp://127.0.0.1:28332
|
||||||
```
|
```
|
||||||
- **Rust and Cargo**: [Rust Installation](https://www.rust-lang.org/tools/install)
|
- **Rust and Cargo**: [Rust Installation](https://www.rust-lang.org/tools/install)
|
||||||
- **Libraries**: `libssl-dev`, `libsodium-dev`, `libzmq5-dev`, `libsqlite3-dev`
|
- **Libraries**: `libssl-dev`, `libzmq5-dev`, `libsqlite3-dev`
|
||||||
|
|
||||||
## Running
|
## Running
|
||||||
|
|
||||||
|
|||||||
@@ -39,7 +39,12 @@ The project uses Cargo feature flags to build each binary independently:
|
|||||||
|
|
||||||
## Docker Support
|
## Docker Support
|
||||||
|
|
||||||
The project includes a multi-stage `Dockerfile` using `rust:1.95-bookworm` as the builder and `debian:bookworm-slim` as the runtime. The container runs as a non-root `bal` user (uid 1000) with `tini` as PID 1 and includes a healthcheck endpoint.
|
Two Dockerfiles are provided:
|
||||||
|
|
||||||
|
- **`Dockerfile.release`** (recommended for production): Downloads the latest pre-built release from the Gitea server. No Rust toolchain needed. Verifies SHA-256 checksum. Supports pinning a specific version via `BAL_VERSION` build arg.
|
||||||
|
- **`Dockerfile`** (for development/custom builds): Multi-stage build using `rust:1.95-bookworm` as the builder and `debian:bookworm-slim` as the runtime. Each binary is compiled with only its required features (`--no-default-features --features server` / `--features pusher`).
|
||||||
|
|
||||||
|
Both run as a non-root `bal` user (uid 1000) with `tini` as PID 1 and include a healthcheck endpoint.
|
||||||
|
|
||||||
## Mapping to Existing Documentation
|
## Mapping to Existing Documentation
|
||||||
|
|
||||||
|
|||||||
@@ -93,17 +93,38 @@ Default ports per network:
|
|||||||
|
|
||||||
## Docker
|
## Docker
|
||||||
|
|
||||||
The project includes a multi-stage `Dockerfile`:
|
The project provides two Dockerfiles:
|
||||||
|
|
||||||
- **Builder stage:** `rust:1.95-bookworm` with full build.
|
### `Dockerfile.release` — Download pre-built release (recommended for production)
|
||||||
|
|
||||||
|
Downloads the latest release from the Gitea server. No Rust toolchain needed. Fast builds.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Latest release
|
||||||
|
docker build -f Dockerfile.release -t bal-server .
|
||||||
|
|
||||||
|
# Specific version
|
||||||
|
docker build -f Dockerfile.release --build-arg BAL_VERSION=v0.3.2 -t bal-server:0.3.2 .
|
||||||
|
```
|
||||||
|
|
||||||
|
- Fetches `.tar.gz` from `https://bitcoin-after.life/gitea/api/v1/repos/bitcoinafterlife/bal-server/releases/latest`.
|
||||||
|
- Verifies SHA-256 checksum if available.
|
||||||
|
- Single-stage image (`debian:bookworm-slim`), minimal size.
|
||||||
|
- `BAL_VERSION` build arg: set to a tag (e.g., `v0.3.2`) to pin a specific release.
|
||||||
|
|
||||||
|
### `Dockerfile` — Build from source
|
||||||
|
|
||||||
|
Multi-stage build with the Rust toolchain. Use for development or custom builds.
|
||||||
|
|
||||||
|
- **Builder stage:** `rust:1.95-bookworm` with full build. Each binary is compiled with only its required features (`--no-default-features --features server` / `--features pusher`).
|
||||||
- **Runtime stage:** `debian:bookworm-slim` with minimal runtime.
|
- **Runtime stage:** `debian:bookworm-slim` with minimal runtime.
|
||||||
- **User:** Non-root `bal` user (uid 1000).
|
- **User:** Non-root `bal` user (uid 1000).
|
||||||
- **PID 1:** `tini` for proper signal handling.
|
- **PID 1:** `tini` for proper signal handling.
|
||||||
- **Healthcheck:** `curl -f http://localhost:9137/ || exit 1`.
|
- **Healthcheck:** `curl -f http://localhost:9137/ || exit 1`.
|
||||||
|
|
||||||
Build and run:
|
### Run (both Dockerfiles)
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker build -t bal-server .
|
|
||||||
docker run -d \
|
docker run -d \
|
||||||
--name bal-server \
|
--name bal-server \
|
||||||
-v /var/bal:/var/bal \
|
-v /var/bal:/var/bal \
|
||||||
|
|||||||
@@ -29,7 +29,8 @@
|
|||||||
| Contrib (install bitcoind) | `contrib/download_and_install_bitcoincore.sh` | Bitcoind download, GPG verify, systemd, config |
|
| Contrib (install bitcoind) | `contrib/download_and_install_bitcoincore.sh` | Bitcoind download, GPG verify, systemd, config |
|
||||||
| Contrib (install Tor) | `contrib/install_tor.sh` | Tor repository, `ControlPort 9051` |
|
| Contrib (install Tor) | `contrib/install_tor.sh` | Tor repository, `ControlPort 9051` |
|
||||||
| Nginx template | `contrib/nginx/bal-server.conf` | TLS termination, security headers, rate limiting |
|
| Nginx template | `contrib/nginx/bal-server.conf` | TLS termination, security headers, rate limiting |
|
||||||
| Dockerfile | `Dockerfile` | Multi-stage build, non-root user, tini, healthcheck |
|
| Dockerfile | `Dockerfile` | Multi-stage build from source, non-root user, tini, healthcheck |
|
||||||
|
| Dockerfile.release | `Dockerfile.release` | Download latest release from Gitea, SHA-256 verification |
|
||||||
|
|
||||||
| Systemd Service | File | Purpose |
|
| Systemd Service | File | Purpose |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
|
|||||||
Reference in New Issue
Block a user