diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 00000000..c0d5dc8b --- /dev/null +++ b/.dockerignore @@ -0,0 +1,10 @@ +.git +target/ +bench/ +docs/ +tests/ +clients/ +*.md +!LICENSE* +.DS_Store +*.swp diff --git a/Dockerfile b/Dockerfile index 2fe7cb30..0a22054d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,10 @@ FROM rust:1.93-slim AS builder +RUN apt-get update && apt-get install -y --no-install-recommends \ + pkg-config \ + libssl-dev \ + && rm -rf /var/lib/apt/lists/* + WORKDIR /usr/src/ember COPY . . @@ -11,12 +16,26 @@ FROM debian:trixie-slim RUN apt-get update && apt-get install -y --no-install-recommends \ ca-certificates \ + libssl3 \ && rm -rf /var/lib/apt/lists/* +RUN groupadd -g 65532 ember && \ + useradd -u 65532 -g ember -s /sbin/nologin -M ember + COPY --from=builder /usr/src/ember/target/release/ember-server /usr/local/bin/ember-server +RUN mkdir -p /data && chown ember:ember /data +VOLUME /data + +USER ember + +ENV EMBER_HOST=0.0.0.0 + EXPOSE 6379 -# metrics port (set via --metrics-port at runtime) EXPOSE 9100 -ENTRYPOINT ["ember-server", "--host", "0.0.0.0"] +LABEL org.opencontainers.image.title="ember" \ + org.opencontainers.image.description="low-latency distributed cache" \ + org.opencontainers.image.source="https://github.com/kacy/ember" + +ENTRYPOINT ["ember-server"] diff --git a/Makefile b/Makefile index 15e8d2d6..d6954489 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -.PHONY: build release test fmt fmt-check clippy check clean docker-build \ +.PHONY: build release test fmt fmt-check clippy check clean docker-build docker-run \ release-patch release-minor release-major github-release \ publish publish-dry-run bench bench-core bench-protocol bench-compare bench-quick @@ -31,6 +31,9 @@ clean: docker-build: docker build -t ember:latest . +docker-run: docker-build + docker run --rm -p 6379:6379 ember:latest + bench: cargo bench --workspace diff --git a/crates/ember-server/src/main.rs b/crates/ember-server/src/main.rs index b94d57ec..5c5c2add 100644 --- a/crates/ember-server/src/main.rs +++ b/crates/ember-server/src/main.rs @@ -29,80 +29,80 @@ use crate::config::{ #[command(name = "ember-server", about = "ember cache server")] struct Args { /// address to bind to - #[arg(long, default_value = "127.0.0.1")] + #[arg(long, default_value = "127.0.0.1", env = "EMBER_HOST")] host: String, /// port to listen on - #[arg(short, long, default_value_t = 6379)] + #[arg(short, long, default_value_t = 6379, env = "EMBER_PORT")] port: u16, /// maximum memory limit (e.g. "100M", "1G", "512K"). default: unlimited - #[arg(long)] + #[arg(long, env = "EMBER_MAX_MEMORY")] max_memory: Option, /// eviction policy when memory limit is reached: noeviction or allkeys-lru - #[arg(long, default_value = "noeviction")] + #[arg(long, default_value = "noeviction", env = "EMBER_EVICTION_POLICY")] eviction_policy: String, /// directory for AOF and snapshot files. required if --appendonly is set - #[arg(long)] + #[arg(long, env = "EMBER_DATA_DIR")] data_dir: Option, /// enable append-only file logging for durability - #[arg(long)] + #[arg(long, env = "EMBER_APPENDONLY")] appendonly: bool, /// fsync policy for the AOF: always, everysec, or no - #[arg(long, default_value = "everysec")] + #[arg(long, default_value = "everysec", env = "EMBER_APPENDFSYNC")] appendfsync: String, /// port for prometheus metrics HTTP endpoint. disabled when not set - #[arg(long)] + #[arg(long, env = "EMBER_METRICS_PORT")] metrics_port: Option, /// log commands slower than this many microseconds. default: 10000 (10ms). /// set to -1 to disable, 0 to log every command - #[arg(long, default_value_t = 10_000)] + #[arg(long, default_value_t = 10_000, env = "EMBER_SLOWLOG_LOG_SLOWER_THAN")] slowlog_log_slower_than: i64, /// maximum number of entries in the slow log ring buffer - #[arg(long, default_value_t = 128)] + #[arg(long, default_value_t = 128, env = "EMBER_SLOWLOG_MAX_LEN")] slowlog_max_len: usize, /// number of shards (worker threads). defaults to available CPU cores - #[arg(long)] + #[arg(long, env = "EMBER_SHARDS")] shards: Option, /// use concurrent keyspace (DashMap) instead of sharded channels. /// experimental: bypasses channel overhead for GET/SET commands. - #[arg(long)] + #[arg(long, env = "EMBER_CONCURRENT")] concurrent: bool, /// require clients to AUTH with this password before running commands. /// when set, connections must authenticate before executing any data commands. - #[arg(long)] + #[arg(long, env = "EMBER_REQUIREPASS")] requirepass: Option, // -- TLS options (matching redis) -- /// port for TLS connections. when set, enables TLS alongside plain TCP - #[arg(long)] + #[arg(long, env = "EMBER_TLS_PORT")] tls_port: Option, /// path to server certificate file (PEM format) - #[arg(long)] + #[arg(long, env = "EMBER_TLS_CERT_FILE")] tls_cert_file: Option, /// path to server private key file (PEM format) - #[arg(long)] + #[arg(long, env = "EMBER_TLS_KEY_FILE")] tls_key_file: Option, /// path to CA certificate for client verification (enables mTLS) - #[arg(long)] + #[arg(long, env = "EMBER_TLS_CA_CERT_FILE")] tls_ca_cert_file: Option, /// require client certificates when CA cert is configured. /// accepts: yes, no. default: no - #[arg(long, default_value = "no")] + #[arg(long, default_value = "no", env = "EMBER_TLS_AUTH_CLIENTS")] tls_auth_clients: String, }