Use scratch release image and optimize build

Narrow tokio features to rt-multi-thread, macros, time and signal.
Add release profile to reduce binary size:
opt-level = s, lto = true, codegen-units = 1, strip = true, panic =
abort
Update Cargo.lock to remove unused deps and adjust Dockerfile to copy
CA certs from builder and set ENTRYPOINT for the release image
Use scratch base image and optimize release build

Add linux/ppc64le support in CI and build script
Switch Docker release stage to scratch, copy CA certificates from the
builder and use an explicit ENTRYPOINT for the binary
Tighten Cargo release profile (opt-level="s", lto, codegen-units=1,
strip, panic="abort") and reduce Tokio features to shrink the binary
Update README to reflect image size and supported platforms
This commit is contained in:
Timothy Miller
2026-03-10 02:04:30 -04:00
parent 6cad2de74c
commit a4ac4e1e1c
6 changed files with 17 additions and 58 deletions

View File

@@ -51,7 +51,7 @@ jobs:
context: . context: .
push: ${{ github.event_name != 'pull_request' }} push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta.outputs.tags }} tags: ${{ steps.meta.outputs.tags }}
platforms: linux/amd64,linux/arm64 platforms: linux/amd64,linux/arm64,linux/ppc64le
labels: | labels: |
org.opencontainers.image.source=${{ github.event.repository.html_url }} org.opencontainers.image.source=${{ github.event.repository.html_url }}
org.opencontainers.image.created=${{ steps.meta.outputs.created }} org.opencontainers.image.created=${{ steps.meta.outputs.created }}

48
Cargo.lock generated
View File

@@ -652,15 +652,6 @@ version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77" checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77"
[[package]]
name = "lock_api"
version = "0.4.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965"
dependencies = [
"scopeguard",
]
[[package]] [[package]]
name = "log" name = "log"
version = "0.4.29" version = "0.4.29"
@@ -715,29 +706,6 @@ version = "1.21.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
[[package]]
name = "parking_lot"
version = "0.12.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a"
dependencies = [
"lock_api",
"parking_lot_core",
]
[[package]]
name = "parking_lot_core"
version = "0.9.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1"
dependencies = [
"cfg-if",
"libc",
"redox_syscall",
"smallvec",
"windows-link",
]
[[package]] [[package]]
name = "percent-encoding" name = "percent-encoding"
version = "2.3.2" version = "2.3.2"
@@ -882,15 +850,6 @@ dependencies = [
"getrandom 0.3.4", "getrandom 0.3.4",
] ]
[[package]]
name = "redox_syscall"
version = "0.5.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d"
dependencies = [
"bitflags",
]
[[package]] [[package]]
name = "regex" name = "regex"
version = "1.12.3" version = "1.12.3"
@@ -1038,12 +997,6 @@ version = "1.0.23"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f" checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f"
[[package]]
name = "scopeguard"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
[[package]] [[package]]
name = "serde" name = "serde"
version = "1.0.228" version = "1.0.228"
@@ -1247,7 +1200,6 @@ dependencies = [
"bytes", "bytes",
"libc", "libc",
"mio", "mio",
"parking_lot",
"pin-project-lite", "pin-project-lite",
"signal-hook-registry", "signal-hook-registry",
"socket2", "socket2",

View File

@@ -9,13 +9,20 @@ license = "GPL-3.0"
reqwest = { version = "0.12", features = ["json", "rustls-tls"], default-features = false } reqwest = { version = "0.12", features = ["json", "rustls-tls"], default-features = false }
serde = { version = "1", features = ["derive"] } serde = { version = "1", features = ["derive"] }
serde_json = "1" serde_json = "1"
tokio = { version = "1", features = ["full"] } tokio = { version = "1", features = ["rt-multi-thread", "macros", "time", "signal"] }
regex = "1" regex = "1"
chrono = { version = "0.4", features = ["clock"] } chrono = { version = "0.4", features = ["clock"] }
url = "2" url = "2"
idna = "1" idna = "1"
if-addrs = "0.13" if-addrs = "0.13"
[profile.release]
opt-level = "s"
lto = true
codegen-units = 1
strip = true
panic = "abort"
[dev-dependencies] [dev-dependencies]
tempfile = "3.26.0" tempfile = "3.26.0"
wiremock = "0.6" wiremock = "0.6"

View File

@@ -7,7 +7,7 @@ COPY src ./src
RUN cargo build --release RUN cargo build --release
# ---- Release ---- # ---- Release ----
FROM alpine:latest AS release FROM scratch AS release
RUN apk add --no-cache ca-certificates COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
COPY --from=builder /build/target/release/cloudflare-ddns /usr/local/bin/cloudflare-ddns COPY --from=builder /build/target/release/cloudflare-ddns /cloudflare-ddns
CMD ["cloudflare-ddns", "--repeat"] ENTRYPOINT ["/cloudflare-ddns", "--repeat"]

View File

@@ -26,7 +26,7 @@ A feature-complete dynamic DNS client for Cloudflare, written in Rust. Configure
- 🎨 **Pretty output with emoji** — Configurable emoji and verbosity levels - 🎨 **Pretty output with emoji** — Configurable emoji and verbosity levels
- 🔒 **Zero-log IP detection** — Uses Cloudflare's [cdn-cgi/trace](https://www.cloudflare.com/cdn-cgi/trace) by default - 🔒 **Zero-log IP detection** — Uses Cloudflare's [cdn-cgi/trace](https://www.cloudflare.com/cdn-cgi/trace) by default
- 🏠 **CGNAT-aware local detection** — Filters out shared address space (100.64.0.0/10) and private ranges - 🏠 **CGNAT-aware local detection** — Filters out shared address space (100.64.0.0/10) and private ranges
- 🤏 **Tiny static binary**Small Docker image, zero runtime dependencies - 🤏 **Tiny static binary**~3.5 MB Docker image built from scratch, zero runtime dependencies
## 🚀 Quick Start ## 🚀 Quick Start
@@ -289,13 +289,13 @@ The binary is at `target/release/cloudflare-ddns`.
# Single architecture (linux/amd64) # Single architecture (linux/amd64)
./scripts/docker-build.sh ./scripts/docker-build.sh
# Multi-architecture (linux/amd64, linux/arm64, linux/arm/v7) # Multi-architecture (linux/amd64, linux/arm64, linux/ppc64le)
./scripts/docker-build-all.sh ./scripts/docker-build-all.sh
``` ```
## 💻 Supported Platforms ## 💻 Supported Platforms
- 🐳 [Docker](https://docs.docker.com/get-docker/) (amd64, arm64, arm/v7) - 🐳 [Docker](https://docs.docker.com/get-docker/) (amd64, arm64, ppc64le)
- 🐙 [Docker Compose](https://docs.docker.com/compose/install/) - 🐙 [Docker Compose](https://docs.docker.com/compose/install/)
- ☸️ [Kubernetes](https://kubernetes.io/docs/tasks/tools/) - ☸️ [Kubernetes](https://kubernetes.io/docs/tasks/tools/)
- 🐧 [Systemd](https://www.freedesktop.org/wiki/Software/systemd/) - 🐧 [Systemd](https://www.freedesktop.org/wiki/Software/systemd/)

View File

@@ -1,3 +1,3 @@
#!/bin/bash #!/bin/bash
BASH_DIR=$(dirname $(realpath "${BASH_SOURCE}")) BASH_DIR=$(dirname $(realpath "${BASH_SOURCE}"))
docker buildx build --platform linux/amd64,linux/arm64,linux/arm/v7 --tag timothyjmiller/cloudflare-ddns:latest ${BASH_DIR}/../ docker buildx build --platform linux/amd64,linux/arm64,linux/ppc64le --tag timothyjmiller/cloudflare-ddns:latest ${BASH_DIR}/../