Add proxy to docker and package features

This commit is contained in:
Garen Tyler 2024-12-04 23:12:29 -07:00
parent 7b63542810
commit 83ebcfbd8d
Signed by: garentyler
SSH Key Fingerprint: SHA256:G4ke7blZMdpWPbkescyZ7IQYE4JAtwpI85YoJdq+S7U
8 changed files with 102 additions and 19 deletions

View File

@ -1,6 +1,6 @@
[package] [package]
name = "composition" name = "composition"
description = "An extremely fast Minecraft server" description = "An extremely fast Minecraft server & proxy"
build = "build.rs" build = "build.rs"
version = "0.1.0" version = "0.1.0"
authors = ["Garen Tyler <garentyler@garen.dev>"] authors = ["Garen Tyler <garentyler@garen.dev>"]

View File

@ -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 RUN cargo install cargo-chef --locked --version 0.1.68
WORKDIR /app WORKDIR /app
RUN git config --global --add safe.directory /app RUN git config --global --add safe.directory /app
ARG FEATURES
FROM base AS dev FROM base AS dev
RUN cargo install cargo-watch --locked --version 8.5.3 RUN cargo install cargo-watch --locked --version 8.5.3
VOLUME /app VOLUME /app
VOLUME /app/.git VOLUME /app/.git
EXPOSE 25565 EXPOSE 25565
CMD ["cargo", "watch", "-x", "run -- server"] ENTRYPOINT ["cargo", "watch", "-x"]
CMD ["run -- server"]
FROM base AS planner FROM base AS planner
COPY Cargo.toml . COPY Cargo.toml .
@ -18,13 +20,13 @@ RUN cargo chef prepare --recipe-path recipe.json
FROM base AS builder FROM base AS builder
COPY --from=planner /app/recipe.json recipe.json 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 src src
COPY build.rs . COPY build.rs .
COPY Cargo.toml . COPY Cargo.toml .
COPY Cargo.lock . COPY Cargo.lock .
COPY .git .git COPY .git .git
RUN cargo build --release RUN cargo build --release --no-default-features --features $FEATURES
RUN strip target/release/composition RUN strip target/release/composition
FROM alpine:3.20 AS prod FROM alpine:3.20 AS prod
@ -36,4 +38,3 @@ COPY --from=builder /app/target/release/composition /app
EXPOSE 25565 EXPOSE 25565
USER composition USER composition
ENTRYPOINT ["tini", "--", "/app/composition"] ENTRYPOINT ["tini", "--", "/app/composition"]
CMD [ "server" ]

View File

@ -1,7 +1,14 @@
variable "TAG" {
default = "latest"
}
target "default" { target "default" {
context = "." context = "."
dockerfile = "Dockerfile" dockerfile = "Dockerfile"
tags = ["composition:latest", "garentyler/composition:latest"]
platforms = ["linux/amd64", "linux/arm64"] platforms = ["linux/amd64", "linux/arm64"]
tags = ["composition:${TAG}", "garentyler/composition:${TAG}"]
target = "prod" target = "prod"
} args = {
FEATURES = "server,proxy"
}
}

View File

@ -4,12 +4,37 @@ services:
server: server:
container_name: composition container_name: composition
restart: unless-stopped restart: unless-stopped
profiles: [server]
build: build:
context: . context: .
dockerfile: Dockerfile dockerfile: Dockerfile
target: dev target: dev
command: [ "run -- server" ]
ports: 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: volumes:
- .:/app - .:/app
- .git:/app/.git - .git:/app/.git

View File

@ -92,7 +92,11 @@ impl Config {
#[cfg(feature = "server")] #[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"); CONFIG.set(config).expect("could not set CONFIG");
@ -285,6 +289,20 @@ impl Args {
println!("license: {}", env!("CARGO_PKG_LICENSE")); println!("license: {}", env!("CARGO_PKG_LICENSE"));
println!("authors: {}", env!("CARGO_PKG_AUTHORS")); println!("authors: {}", env!("CARGO_PKG_AUTHORS"));
println!("build-target: {}", env!("BUILD_TARGET")); 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); std::process::exit(0);
} }

View File

@ -1,5 +1,10 @@
use crate::config::{Args, Config}; use crate::config::{Args, Config};
use clap::Arg;
use once_cell::sync::Lazy;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::ffi::OsStr;
pub static DEFAULT_PROXY_ARGS: Lazy<ProxyArgs> = Lazy::new(ProxyArgs::default);
/// The main server configuration struct. /// The main server configuration struct.
#[derive(Debug, Deserialize, Serialize)] #[derive(Debug, Deserialize, Serialize)]
@ -9,14 +14,14 @@ pub struct ProxyConfig {
#[serde(rename = "version-string")] #[serde(rename = "version-string")]
pub version: String, pub version: String,
pub port: u16, pub port: u16,
pub upstream_address: String, pub upstream: String,
} }
impl Default for ProxyConfig { impl Default for ProxyConfig {
fn default() -> Self { fn default() -> Self {
ProxyConfig { ProxyConfig {
version: Config::get_formatted_version(crate::config::Subcommand::Proxy), version: Config::get_formatted_version(crate::config::Subcommand::Proxy),
port: 25565, port: 25565,
upstream_address: String::new(), upstream: String::new(),
} }
} }
} }
@ -24,13 +29,23 @@ impl ProxyConfig {
pub fn instance() -> &'static Self { pub fn instance() -> &'static Self {
&Config::instance().proxy &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)] #[derive(Debug)]
pub struct ProxyArgs {} pub struct ProxyArgs {
upstream: String,
}
impl Default for ProxyArgs { impl Default for ProxyArgs {
fn default() -> Self { fn default() -> Self {
ProxyArgs {} ProxyArgs {
upstream: String::new(),
}
} }
} }
impl ProxyArgs { impl ProxyArgs {
@ -38,9 +53,23 @@ impl ProxyArgs {
Args::instance().proxy.as_ref() Args::instance().proxy.as_ref()
} }
pub fn command() -> clap::Command { 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 { pub fn parse(m: clap::ArgMatches) -> Self {
ProxyArgs::default() let mut proxy_args = ProxyArgs::default();
proxy_args.upstream = m
.get_one::<String>("upstream")
.unwrap_or(&proxy_args.upstream)
.clone();
proxy_args
} }
} }

View File

@ -23,6 +23,7 @@ impl Proxy {
"Done! Start took {:?}", "Done! Start took {:?}",
crate::START_TIME.get().unwrap().elapsed() crate::START_TIME.get().unwrap().elapsed()
); );
info!("Upstream server: {}", config.proxy.upstream);
// Spawn the ctrl-c task. // Spawn the ctrl-c task.
let r = running.clone(); let r = running.clone();

View File

@ -39,13 +39,15 @@ impl ServerConfig {
pub fn instance() -> &'static Self { pub fn instance() -> &'static Self {
&Config::instance().server &Config::instance().server
} }
/// Load the server icon. pub fn load_args(&mut self) {
pub fn load_icon(&mut self) {
self.server_icon = ServerArgs::instance() self.server_icon = ServerArgs::instance()
.as_ref() .as_ref()
.map(|s| s.server_icon.clone()) .map(|s| s.server_icon.clone())
.unwrap_or(DEFAULT_SERVER_ARGS.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); let server_icon_path = Path::new(&self.server_icon);
if server_icon_path.exists() { if server_icon_path.exists() {