diff --git a/Cargo.lock b/Cargo.lock index 43e5649..2c675d9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -170,6 +170,12 @@ version = "0.2.153" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" +[[package]] +name = "log" +version = "0.4.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" + [[package]] name = "memchr" version = "2.7.1" @@ -246,6 +252,7 @@ dependencies = [ "assert_cmd", "clap", "predicates", + "users", ] [[package]] @@ -326,6 +333,16 @@ version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +[[package]] +name = "users" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24cc0f6d6f267b73e5a2cadf007ba8f9bc39c6a6f9666f8cf25ea809a153b032" +dependencies = [ + "libc", + "log", +] + [[package]] name = "utf8parse" version = "0.2.1" diff --git a/Cargo.toml b/Cargo.toml index ea8ae4f..730f630 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,6 +8,8 @@ edition = "2021" [dependencies] clap = { version = "4.5.1", features = ["derive"] } +[target.'cfg(unix)'.dependencies] +users = "0.11.0" [dev-dependencies] assert_cmd = "2.0.14" diff --git a/Dockerfile b/Dockerfile index eb09298..773cd8c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,9 @@ ARG RUBY_VERSION=3.2.3 FROM ruby:${RUBY_VERSION} +ARG USER_ID=1000 +ARG GROUP_ID=1000 +RUN groupadd -g $GROUP_ID app && useradd -u $USER_ID -g app -m app +USER app ARG RAILS_VERSION # Install Rails based on the version specified but if not specified, install the latest version. RUN if [ -z "$RAILS_VERSION" ] ; then gem install rails ; else gem install rails -v $RAILS_VERSION ; fi diff --git a/Dockerfile.windows b/Dockerfile.windows new file mode 100644 index 0000000..eb09298 --- /dev/null +++ b/Dockerfile.windows @@ -0,0 +1,5 @@ +ARG RUBY_VERSION=3.2.3 +FROM ruby:${RUBY_VERSION} +ARG RAILS_VERSION +# Install Rails based on the version specified but if not specified, install the latest version. +RUN if [ -z "$RAILS_VERSION" ] ; then gem install rails ; else gem install rails -v $RAILS_VERSION ; fi diff --git a/src/docker_client.rs b/src/docker_client.rs index 84188e9..0ed7f6e 100644 --- a/src/docker_client.rs +++ b/src/docker_client.rs @@ -3,7 +3,12 @@ use std::process::{Command, Stdio}; pub struct DockerClient {} impl DockerClient { - pub fn build_image(ruby_version: &str, rails_version: &str) -> Command { + pub fn build_image( + ruby_version: &str, + rails_version: &str, + user_id: Option, + group_id: Option, + ) -> Command { let mut command = Command::new("docker"); command @@ -11,7 +16,12 @@ impl DockerClient { .arg("--build-arg") .arg(format!("RUBY_VERSION={}", ruby_version)) .arg("--build-arg") - .arg(format!("RAILS_VERSION={}", rails_version)) + .arg(format!("RAILS_VERSION={}", rails_version)); + + user_id.map(|id| command.args(["--build-arg", &format!("USER_ID={}", id)])); + group_id.map(|id| command.args(["--build-arg", &format!("GROUP_ID={}", id)])); + + command .arg("-t") .arg(format!("rails-new-{}-{}", ruby_version, rails_version)) .arg("-") diff --git a/src/main.rs b/src/main.rs index 91084e9..e018574 100644 --- a/src/main.rs +++ b/src/main.rs @@ -10,24 +10,30 @@ use clap::Parser; use crate::docker_client::DockerClient; +#[cfg_attr(unix, path = "unix.rs")] +#[cfg_attr(windows, path = "windows.rs")] +mod os_specific; + fn main() { let cli = Cli::parse(); - // read the content of the DOCKERFILE and store it in a variable - let dockerfile = include_bytes!("../Dockerfile"); - let ruby_version = cli.ruby_version; let rails_version = cli.rails_version; // Run docker build --build-arg RUBY_VERSION=$RUBY_VERSION --build-arg RAILS_VERSION=$RAILS_VERSION -t rails-new-$RUBY_VERSION-$RAILS_VERSION // passing the content of DOCKERFILE to the command stdin - let mut child = DockerClient::build_image(&ruby_version, &rails_version) - .spawn() - .expect("Failed to execute process"); + let mut child = DockerClient::build_image( + &ruby_version, + &rails_version, + os_specific::get_user_id(), + os_specific::get_group_id(), + ) + .spawn() + .expect("Failed to execute process"); let mut stdin = child.stdin.take().expect("Failed to open stdin"); std::thread::spawn(move || { - stdin.write_all(dockerfile).unwrap(); + stdin.write_all(os_specific::dockerfile_content()).unwrap(); }); let status = child.wait().expect("failed to wait on child"); diff --git a/src/unix.rs b/src/unix.rs new file mode 100644 index 0000000..e24e232 --- /dev/null +++ b/src/unix.rs @@ -0,0 +1,11 @@ +pub fn dockerfile_content() -> &'static [u8] { + include_bytes!("../Dockerfile") +} + +pub fn get_user_id() -> Option { + Some(users::get_current_uid()) +} + +pub fn get_group_id() -> Option { + Some(users::get_current_gid()) +} diff --git a/src/windows.rs b/src/windows.rs new file mode 100644 index 0000000..a9a3c49 --- /dev/null +++ b/src/windows.rs @@ -0,0 +1,11 @@ +pub fn dockerfile_content() -> &'static [u8] { + include_bytes!("../Dockerfile.windows") +} + +pub fn get_user_id() -> Option { + None +} + +pub fn get_group_id() -> Option { + None +}