diff --git a/Cargo.toml b/Cargo.toml index ebfeac2..54d5aca 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,3 +1,7 @@ [workspace] members = ["crates/x-media", "crates/xmedia-bot"] resolver = "3" + +# Smaller production binary; debug symbols are not shipped anyway. +[profile.release] +strip = true diff --git a/Dockerfile b/Dockerfile index 8dadec8..b44ff8b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -11,6 +11,11 @@ ARG APP_NAME=telegram-twitter-media-bot # runners. `/redirect/latest/` floats to the newest release build; each build # also ships a .sha256. Swap `amd64` for `arm64` when building arm64 images. ARG FFMPEG_URL=https://ffmpeg.martin-riedl.de/redirect/latest/linux/amd64/release/ffmpeg.zip +# Optional sha256 of ffmpeg.zip (pinned releases only): set to verify the +# download. The mirror publishes .sha256 sidecars next to pinned builds, e.g. +# https://ffmpeg.martin-riedl.de/download/linux/amd64/_9.0/ffmpeg.zip.sha256 +# (the /redirect/latest/ URL itself has no sidecar — pin the effective URL). +ARG FFMPEG_SHA256= WORKDIR /build @@ -30,19 +35,20 @@ RUN mkdir -p crates/x-media/src crates/xmedia-bot/src \ # root. `unzip -t` verifies the archive before extraction so a bad # download fails loudly here instead of a cryptic later error. RUN wget -q -O /tmp/ffmpeg.zip "$FFMPEG_URL" \ + && if [ -n "$FFMPEG_SHA256" ]; then echo "$FFMPEG_SHA256 /tmp/ffmpeg.zip" | sha256sum -c -; fi \ && unzip -tq /tmp/ffmpeg.zip \ && unzip -q /tmp/ffmpeg.zip -d /usr/local/bin \ && chmod +x /usr/local/bin/ffmpeg \ && rm /tmp/ffmpeg.zip \ && /usr/local/bin/ffmpeg -version >/dev/null -# 3. Real sources last: only our crates recompile on source changes. The -# COPY preserves host mtimes, which predate the stub artifacts from step 1; -# cargo's mtime-based freshness check would otherwise treat the stub build -# as up-to-date and never compile the real sources. `touch` forces cargo to -# see the real files as newer. +# 3. Real sources last: only our crates recompile on source changes. +# `cargo clean -p` drops the two crates' artifacts while keeping the +# compiled dependency layer, forcing a deterministic rebuild of the real +# sources. (The previous `touch`-mtimes hack silently shipped the stub +# binary when host files carried future timestamps.) COPY crates/ ./crates/ -RUN find crates -type f -name '*.rs' -exec touch {} + \ +RUN cargo clean -p xmedia-bot -p x-media \ && cargo build --release -p xmedia-bot # ---------- runtime stage ---------- @@ -56,10 +62,9 @@ LABEL org.opencontainers.image.title="${APP_NAME}" # Everything is copied in — no apt in the runtime stage. Privilege dropping is # done by docker-entrypoint.sh with setpriv (util-linux, already in -# bookworm-slim), so no gosu needed. +# bookworm-slim), so no gosu needed. (libssl3/libcrypto are already in +# bookworm-slim; only ca-certificates and ffmpeg need copying.) COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt -COPY --from=builder /usr/lib/x86_64-linux-gnu/libssl.so.3* /usr/lib/x86_64-linux-gnu/ -COPY --from=builder /usr/lib/x86_64-linux-gnu/libcrypto.so.3* /usr/lib/x86_64-linux-gnu/ COPY --from=builder /usr/local/bin/ffmpeg /usr/local/bin/ffmpeg WORKDIR /app diff --git a/docker-compose.yml.example b/docker-compose.yml.example index 1e7075a..add0ec8 100644 --- a/docker-compose.yml.example +++ b/docker-compose.yml.example @@ -55,6 +55,14 @@ services: depends_on: - nginx-proxy container_name: tgxmb + # Webhook mode only: the bot listens on WEBHOOK_PORT; nginx-proxy shows + # 502s while this is down, so surface it to the orchestrator. + healthcheck: + test: ["CMD-SHELL", "bash -c 'exec 3<>/dev/tcp/127.0.0.1/8443'"] + interval: 30s + timeout: 5s + retries: 3 + start_period: 10s volumes: certs: diff --git a/docker-entrypoint.sh b/docker-entrypoint.sh index 19e0ae3..8ec5576 100644 --- a/docker-entrypoint.sh +++ b/docker-entrypoint.sh @@ -16,7 +16,6 @@ then else usermod -u ${USER_ID} -o user > /dev/null 2>&1 || true fi - usermod -a -G root user > /dev/null 2>&1 || true # Bind-mounted volumes may not support chown; a failure here must not kill # the container either. chown -R `id -u user`:`id -u user` /app > /dev/null 2>&1 || true