diff --git a/.gitignore b/.gitignore index 7f354826e..0ec486600 100644 --- a/.gitignore +++ b/.gitignore @@ -45,3 +45,6 @@ /tmp /src/api-umbrella/example-website/.hugo_build.lock + +# Added by cargo +/target diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 000000000..f086a16a0 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "api-umbrella-postgres" +version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 000000000..66810ea9e --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "api-umbrella-postgres" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] + +[[bin]] +name = "envoy-config-wrapper" +path = "src/api-umbrella/bin/envoy-config-wrapper.rs" + +[profile.release] +panic = "abort" +strip = true diff --git a/Dockerfile b/Dockerfile index ce05b58e5..f25a50cbe 100644 --- a/Dockerfile +++ b/Dockerfile @@ -177,14 +177,38 @@ EXPOSE 80 443 CMD ["api-umbrella", "run"] +### +# Build - envoy-config-wrapper +### +FROM rust:1-slim-bookworm AS envoy-config-wrapper-build + +# Use the musl target for static binaries that will work in the distroless +# image. +RUN rustup target add "$(arch)-unknown-linux-musl" + +COPY Cargo.toml ./ +COPY src/api-umbrella/bin/envoy-config-wrapper.rs ./src/api-umbrella/bin/ + +RUN cargo build --release --target "$(arch)-unknown-linux-musl" + ### # Runtime - Egress Only # https://github.com/envoyproxy/envoy/blob/release/v1.27/ci/Dockerfile-envoy#L60-L69 ### FROM gcr.io/distroless/base-nossl-debian12:nonroot AS runtime-egress +# Create the needed directories as the non-root user, and then switch back to +# the defalt workdir. +WORKDIR /etc/envoy +WORKDIR /var/run/enovy +WORKDIR /home/nonroot + +# Copy Envoy and our config wrapper binary in so that's all that's present in +# this distroless image. +COPY --from=envoy-config-wrapper-build --chown=0:0 --chmod=755 ./target/*/release/envoy-config-wrapper /usr/local/bin/ COPY --from=build --chown=0:0 --chmod=755 /app/build/work/stage/opt/api-umbrella/embedded/bin/envoy /usr/local/bin/ EXPOSE 14001 -CMD ["/usr/local/bin/envoy", "-c", "/etc/envoy/envoy.yaml", "--use-dynamic-base-id", "--base-id-path", "/var/run/envoy/base-id"] +ENTRYPOINT ["/usr/local/bin/envoy-config-wrapper"] +CMD ["-c", "/etc/envoy/envoy.yaml", "--use-dynamic-base-id", "--base-id-path", "/var/run/envoy/base-id"] diff --git a/src/api-umbrella/bin/envoy-config-wrapper.rs b/src/api-umbrella/bin/envoy-config-wrapper.rs new file mode 100644 index 000000000..cf40cbf99 --- /dev/null +++ b/src/api-umbrella/bin/envoy-config-wrapper.rs @@ -0,0 +1,24 @@ +use std::env; +use std::fs; +use std::os::unix::process::CommandExt; +use std::process::Command; + +// A minimal binary that writes the Envoy config file based on YAML in an +// environment variable, and then replaces the process with the real envoy +// process (passing all arguments along). +// +// The driver of this is to have a statically compiled binary that will work in +// our "distroless" envoy egress image in a way that makes it easier to +// integrate our configuration from environment variables in Cloud Foundry +// (since it can't mount files into the container). +fn main() { + let config_yaml = env::var("ENVOY_CONFIG_YAML"); + if config_yaml.is_ok() { + fs::write("/etc/envoy/envoy.yaml", config_yaml.unwrap()) + .expect("Error writing '/etc/envoy/envoy.yaml' file"); + } + + let args: Vec<_> = env::args_os().skip(1).collect(); + let err = Command::new("/usr/local/bin/envoy").args(&args).exec(); + println!("Error: {}", err); +}