From 83ebcfbd8d930ccbae6064a806f923034919978b Mon Sep 17 00:00:00 2001 From: Garen Tyler Date: Wed, 4 Dec 2024 23:12:29 -0700 Subject: [PATCH] Add proxy to docker and package features --- Cargo.toml | 2 +- Dockerfile | 9 +++++---- docker-bake.hcl | 11 +++++++++-- docker-compose.yml | 27 ++++++++++++++++++++++++++- src/config.rs | 20 +++++++++++++++++++- src/proxy/config.rs | 43 ++++++++++++++++++++++++++++++++++++------- src/proxy/mod.rs | 1 + src/server/config.rs | 8 +++++--- 8 files changed, 102 insertions(+), 19 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index a13e2ff..4c6aaff 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "composition" -description = "An extremely fast Minecraft server" +description = "An extremely fast Minecraft server & proxy" build = "build.rs" version = "0.1.0" authors = ["Garen Tyler "] diff --git a/Dockerfile b/Dockerfile index e4e68ff..f6e1fa5 100644 --- a/Dockerfile +++ b/Dockerfile @@ -3,13 +3,15 @@ RUN apk add --no-cache musl-dev=1.2.5-r0 git=2.45.2-r0 RUN cargo install cargo-chef --locked --version 0.1.68 WORKDIR /app RUN git config --global --add safe.directory /app +ARG FEATURES FROM base AS dev RUN cargo install cargo-watch --locked --version 8.5.3 VOLUME /app VOLUME /app/.git EXPOSE 25565 -CMD ["cargo", "watch", "-x", "run -- server"] +ENTRYPOINT ["cargo", "watch", "-x"] +CMD ["run -- server"] FROM base AS planner COPY Cargo.toml . @@ -18,13 +20,13 @@ RUN cargo chef prepare --recipe-path recipe.json FROM base AS builder COPY --from=planner /app/recipe.json recipe.json -RUN cargo chef cook --release --recipe-path recipe.json +RUN cargo chef cook --release --recipe-path recipe.json --no-default-features --features $FEATURES COPY src src COPY build.rs . COPY Cargo.toml . COPY Cargo.lock . COPY .git .git -RUN cargo build --release +RUN cargo build --release --no-default-features --features $FEATURES RUN strip target/release/composition FROM alpine:3.20 AS prod @@ -36,4 +38,3 @@ COPY --from=builder /app/target/release/composition /app EXPOSE 25565 USER composition ENTRYPOINT ["tini", "--", "/app/composition"] -CMD [ "server" ] diff --git a/docker-bake.hcl b/docker-bake.hcl index 258a31b..17ec158 100644 --- a/docker-bake.hcl +++ b/docker-bake.hcl @@ -1,7 +1,14 @@ +variable "TAG" { + default = "latest" +} + target "default" { context = "." dockerfile = "Dockerfile" - tags = ["composition:latest", "garentyler/composition:latest"] platforms = ["linux/amd64", "linux/arm64"] + tags = ["composition:${TAG}", "garentyler/composition:${TAG}"] target = "prod" -} \ No newline at end of file + args = { + FEATURES = "server,proxy" + } +} diff --git a/docker-compose.yml b/docker-compose.yml index 026ead5..42d803f 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -4,12 +4,37 @@ services: server: container_name: composition restart: unless-stopped + profiles: [server] build: context: . dockerfile: Dockerfile target: dev + command: [ "run -- server" ] ports: - - "25565:25565" + - "25566:25565" + volumes: + - .:/app + - .git:/app/.git + reference: + container_name: reference + restart: unless-stopped + profiles: [server, proxy] + image: itzg/minecraft-server + ports: + - "25565:25565" + environment: + EULA: "TRUE" + proxy: + container_name: composition-proxy + restart: unless-stopped + profiles: [proxy] + build: + context: . + dockerfile: Dockerfile + target: dev + command: [ "run -- proxy -u reference" ] + ports: + - "25566:25565" volumes: - .:/app - .git:/app/.git diff --git a/src/config.rs b/src/config.rs index 22a40f7..815fabd 100644 --- a/src/config.rs +++ b/src/config.rs @@ -92,7 +92,11 @@ impl Config { #[cfg(feature = "server")] { - config.server.load_icon(); + config.server.load_args(); + } + #[cfg(feature = "proxy")] + { + config.proxy.load_args(); } CONFIG.set(config).expect("could not set CONFIG"); @@ -285,6 +289,20 @@ impl Args { println!("license: {}", env!("CARGO_PKG_LICENSE")); println!("authors: {}", env!("CARGO_PKG_AUTHORS")); println!("build-target: {}", env!("BUILD_TARGET")); + let mut features = Vec::new(); + if cfg!(feature = "server") { + features.push("server"); + } + if cfg!(feature = "proxy") { + features.push("proxy"); + } + if cfg!(feature = "world") { + features.push("world"); + } + if cfg!(feature = "update_1_20") { + features.push("update_1_20"); + } + println!("features: {}", features.join(", ")); } std::process::exit(0); } diff --git a/src/proxy/config.rs b/src/proxy/config.rs index eb42244..2b8cdc3 100644 --- a/src/proxy/config.rs +++ b/src/proxy/config.rs @@ -1,5 +1,10 @@ use crate::config::{Args, Config}; +use clap::Arg; +use once_cell::sync::Lazy; use serde::{Deserialize, Serialize}; +use std::ffi::OsStr; + +pub static DEFAULT_PROXY_ARGS: Lazy = Lazy::new(ProxyArgs::default); /// The main server configuration struct. #[derive(Debug, Deserialize, Serialize)] @@ -9,14 +14,14 @@ pub struct ProxyConfig { #[serde(rename = "version-string")] pub version: String, pub port: u16, - pub upstream_address: String, + pub upstream: String, } impl Default for ProxyConfig { fn default() -> Self { ProxyConfig { version: Config::get_formatted_version(crate::config::Subcommand::Proxy), port: 25565, - upstream_address: String::new(), + upstream: String::new(), } } } @@ -24,13 +29,23 @@ impl ProxyConfig { pub fn instance() -> &'static Self { &Config::instance().proxy } + pub fn load_args(&mut self) { + self.upstream = ProxyArgs::instance() + .as_ref() + .map(|p| p.upstream.clone()) + .unwrap_or(DEFAULT_PROXY_ARGS.upstream.clone()); + } } #[derive(Debug)] -pub struct ProxyArgs {} +pub struct ProxyArgs { + upstream: String, +} impl Default for ProxyArgs { fn default() -> Self { - ProxyArgs {} + ProxyArgs { + upstream: String::new(), + } } } impl ProxyArgs { @@ -38,9 +53,23 @@ impl ProxyArgs { Args::instance().proxy.as_ref() } pub fn command() -> clap::Command { - clap::Command::new("proxy").about("Run composition in proxy mode") + clap::Command::new("proxy") + .about("Run composition in proxy mode") + .arg( + Arg::new("upstream") + .short('u') + .long("upstream") + .help("Upstream server address") + .value_hint(clap::ValueHint::Hostname) + .default_value(OsStr::new(&DEFAULT_PROXY_ARGS.upstream)), + ) } - pub fn parse(_: clap::ArgMatches) -> Self { - ProxyArgs::default() + pub fn parse(m: clap::ArgMatches) -> Self { + let mut proxy_args = ProxyArgs::default(); + proxy_args.upstream = m + .get_one::("upstream") + .unwrap_or(&proxy_args.upstream) + .clone(); + proxy_args } } diff --git a/src/proxy/mod.rs b/src/proxy/mod.rs index 2d0f09b..27123e3 100644 --- a/src/proxy/mod.rs +++ b/src/proxy/mod.rs @@ -23,6 +23,7 @@ impl Proxy { "Done! Start took {:?}", crate::START_TIME.get().unwrap().elapsed() ); + info!("Upstream server: {}", config.proxy.upstream); // Spawn the ctrl-c task. let r = running.clone(); diff --git a/src/server/config.rs b/src/server/config.rs index 01949c6..ab2aa21 100644 --- a/src/server/config.rs +++ b/src/server/config.rs @@ -39,13 +39,15 @@ impl ServerConfig { pub fn instance() -> &'static Self { &Config::instance().server } - /// Load the server icon. - pub fn load_icon(&mut self) { + pub fn load_args(&mut self) { self.server_icon = ServerArgs::instance() .as_ref() .map(|s| s.server_icon.clone()) .unwrap_or(DEFAULT_SERVER_ARGS.server_icon.clone()); - + self.load_icon(); + } + /// Load the server icon. + pub fn load_icon(&mut self) { let server_icon_path = Path::new(&self.server_icon); if server_icon_path.exists() {