diff --git a/enclave_build/src/docker.rs b/enclave_build/src/docker.rs index 1b27bdac..55b47b74 100644 --- a/enclave_build/src/docker.rs +++ b/enclave_build/src/docker.rs @@ -4,8 +4,9 @@ use crate::{EnclaveBuildError, Result}; use base64::{engine::general_purpose, Engine as _}; use futures::stream::StreamExt; -use log::{debug, info}; +use log::{debug, error, info}; use serde_json::{json, Value}; + use shiplift::RegistryAuth; use shiplift::{BuildOptions, Docker, PullOptions}; use std::{fs::File, io::Write, path::Path}; @@ -17,28 +18,218 @@ use url::Url; pub const DOCKER_ARCH_ARM64: &str = "arm64"; pub const DOCKER_ARCH_AMD64: &str = "amd64"; +use crate::image_manager::ImageManager; + /// Struct exposing the Docker functionalities to the EIF builder -pub struct DockerUtil { +pub struct DockerImageManager { docker: Docker, docker_image: String, } -impl DockerUtil { - /// Constructor that takes as argument a tag for the docker image to be used - pub fn new(docker_image: String) -> Self { - let mut docker_image = docker_image; +impl ImageManager for DockerImageManager { + fn image_name(&self) -> &str { + &self.docker_image + } - if !docker_image.contains(':') { - docker_image.push_str(":latest"); - } + /// Inspects the docker image and returns its description as a JSON String. + fn inspect_image(&self) -> Result { + let act = async { + match self.docker.images().get(&self.docker_image).inspect().await { + Ok(image) => Ok(json!(image)), + Err(e) => { + error!("{:?}", e); + Err(EnclaveBuildError::ImageInspectError) + } + } + }; + + let runtime = Runtime::new().map_err(|_| EnclaveBuildError::RuntimeError)?; + runtime + .block_on(act) + .map_err(|_| EnclaveBuildError::RuntimeError) + } + + /// Fetches architecture information from a docker image. + fn architecture(&self) -> Result { + let arch = async { + match self.docker.images().get(&self.docker_image).inspect().await { + Ok(image) => Ok(image.architecture), + Err(e) => { + error!("{:?}", e); + Err(EnclaveBuildError::ImageInspectError) + } + } + }; + + let runtime = Runtime::new().map_err(|_| EnclaveBuildError::RuntimeError)?; + + runtime + .block_on(arch) + .map_err(|_| EnclaveBuildError::RuntimeError) + } + + /// The main function of this struct. This needs to be called in order to + /// extract the necessary configuration values from the docker image with + /// the tag provided in the constructor. + fn extract_expressions(&self) -> Result<(NamedTempFile, NamedTempFile)> { + let (cmd, env) = self.extract_image()?; + + let cmd_file = write_config(cmd)?; + let env_file = write_config(env)?; - DockerUtil { + Ok((cmd_file, env_file)) + } +} + +impl DockerImageManager { + /// Constructor that takes as argument a tag for the docker image to be used. + pub fn new>(docker_image: S) -> Result { + let docker_image = Self::tag_image(docker_image); + + let mut docker_manager = DockerImageManager { // DOCKER_HOST environment variable is parsed inside // if docker daemon address needs to be substituted. // By default it tries to connect to 'unix:///var/run/docker.sock' docker: Docker::new(), docker_image, + }; + + docker_manager.pull_image()?; + + Ok(docker_manager) + } + + /// Builds an image locally, with the tag provided in constructor, using a + /// directory that contains a Dockerfile. Returns a manager for this image. + pub fn from_dockerfile(docker_image: &str, dockerfile_dir: &str) -> Result { + if !Path::new(&dockerfile_dir).is_dir() { + return Err(EnclaveBuildError::PathError(dockerfile_dir.to_string())); + } + + let docker_image = Self::tag_image(docker_image); + + let docker_manager = DockerImageManager { + docker: Docker::new(), + docker_image, + }; + + let act = async { + let mut stream = docker_manager.docker.images().build( + &BuildOptions::builder(dockerfile_dir) + .tag(docker_manager.docker_image.clone()) + .build(), + ); + + loop { + if let Some(item) = stream.next().await { + match item { + Ok(output) => { + let msg = &output; + + if let Some(err_msg) = msg.get("error") { + error!("{:?}", err_msg.clone()); + break Err(EnclaveBuildError::DockerError( + "Failed to build docker image".into(), + )); + } else { + info!("{}", msg); + } + } + Err(e) => { + error!("{:?}", e); + break Err(EnclaveBuildError::DockerError( + "Failed to build docker image".into(), + )); + } + } + } else { + break Ok(()); + } + } + }; + + Runtime::new() + .map_err(|_| EnclaveBuildError::RuntimeError)? + .block_on(act)?; + + Ok(docker_manager) + } + + pub fn tag_image>(docker_image: S) -> String { + let mut docker_image = docker_image.as_ref().to_string(); + + if !docker_image.contains(':') { + docker_image.push_str(":latest"); } + + docker_image + } + + /// Pull the image, with the tag provided in constructor, from the Docker registry. + fn pull_image(&mut self) -> Result<()> { + let act = async { + // Check if the Docker image is locally available. + // If available, early exit. + if self + .docker + .images() + .get(&self.docker_image) + .inspect() + .await + .is_ok() + { + eprintln!("Using the locally available Docker image..."); + return Ok(()); + } + + let mut pull_options_builder = PullOptions::builder(); + pull_options_builder.image(&self.docker_image); + + match self.get_credentials() { + Ok(auth) => { + pull_options_builder.auth(auth); + } + // It is not mandatory to have the credentials set, but this is + // the most likely reason for failure when pulling, so log the + // error. + Err(err) => { + debug!("WARNING!! Credential could not be set {:?}", err); + } + }; + + let mut stream = self.docker.images().pull(&pull_options_builder.build()); + + loop { + if let Some(item) = stream.next().await { + match item { + Ok(output) => { + let msg = &output; + + if let Some(err_msg) = msg.get("error") { + error!("{:?}", err_msg.clone()); + break Err(EnclaveBuildError::DockerError( + "Failed to pull docker image".into(), + )); + } else { + info!("{}", msg); + } + } + Err(e) => { + error!("{:?}", e); + break Err(EnclaveBuildError::DockerError( + "Failed to pull docker image".into(), + )); + } + } + } else { + break Ok(()); + } + } + }; + + let runtime = Runtime::new().map_err(|_| EnclaveBuildError::RuntimeError)?; + + runtime.block_on(act) } /// Returns the credentials by reading ${HOME}/.docker/config.json or ${DOCKER_CONFIG} @@ -154,117 +345,6 @@ impl DockerUtil { } } - /// Pull the image, with the tag provided in constructor, from the Docker registry - pub fn pull_image(&self) -> Result<()> { - let act = async { - // Check if the Docker image is locally available. - // If available, early exit. - if self - .docker - .images() - .get(&self.docker_image) - .inspect() - .await - .is_ok() - { - eprintln!("Using the locally available Docker image..."); - return Ok(()); - } - - let mut pull_options_builder = PullOptions::builder(); - pull_options_builder.image(&self.docker_image); - - match self.get_credentials() { - Ok(auth) => { - pull_options_builder.auth(auth); - } - // It is not mandatory to have the credentials set, but this is - // the most likely reason for failure when pulling, so log the - // error. - Err(err) => { - debug!("WARNING!! Credential could not be set {:?}", err); - } - }; - - let mut stream = self.docker.images().pull(&pull_options_builder.build()); - - loop { - if let Some(item) = stream.next().await { - match item { - Ok(output) => { - let msg = &output; - - if let Some(err_msg) = msg.get("error") { - break Err(EnclaveBuildError::ImagePullError(err_msg.to_string())); - } else { - info!("{}", msg); - } - } - Err(e) => { - break Err(EnclaveBuildError::ImagePullError(e.to_string())); - } - } - } else { - break Ok(()); - } - } - }; - - let runtime = Runtime::new().map_err(|_| EnclaveBuildError::RuntimeError)?; - - runtime.block_on(act) - } - - /// Build an image locally, with the tag provided in constructor, using a - /// directory that contains a Dockerfile - pub fn build_image(&self, dockerfile_dir: String) -> Result<()> { - let act = async { - let mut stream = self.docker.images().build( - &BuildOptions::builder(dockerfile_dir) - .tag(self.docker_image.clone()) - .build(), - ); - - loop { - if let Some(item) = stream.next().await { - match item { - Ok(output) => { - let msg = &output; - - if let Some(err_msg) = msg.get("error") { - break Err(EnclaveBuildError::ImageBuildError(err_msg.to_string())); - } else { - info!("{}", msg); - } - } - Err(e) => { - break Err(EnclaveBuildError::ImageBuildError(e.to_string())); - } - } - } else { - break Ok(()); - } - } - }; - - let runtime = Runtime::new().map_err(|_| EnclaveBuildError::RuntimeError)?; - - runtime.block_on(act) - } - - /// Inspect docker image and return its description as a json String - pub fn inspect_image(&self) -> Result { - let act = async { - match self.docker.images().get(&self.docker_image).inspect().await { - Ok(image) => Ok(json!(image)), - Err(e) => Err(EnclaveBuildError::ImageInspectError(e)), - } - }; - - let runtime = Runtime::new().map_err(|_| EnclaveBuildError::RuntimeError)?; - runtime.block_on(act) - } - fn extract_image(&self) -> Result<(Vec, Vec)> { // First try to find CMD parameters (together with potential ENV bindings) let act_cmd = async { @@ -333,40 +413,14 @@ impl DockerUtil { runtime.block_on(act) } - - /// The main function of this struct. This needs to be called in order to - /// extract the necessary configuration values from the docker image with - /// the tag provided in the constructor - pub fn load(&self) -> Result<(NamedTempFile, NamedTempFile)> { - let (cmd, env) = self.extract_image()?; - - let cmd_file = write_config(cmd)?; - let env_file = write_config(env)?; - - Ok((cmd_file, env_file)) - } - - /// Fetch architecture information from an image - pub fn architecture(&self) -> Result { - let arch = async { - match self.docker.images().get(&self.docker_image).inspect().await { - Ok(image) => Ok(image.architecture), - Err(e) => Err(EnclaveBuildError::ImageInspectError(e)), - } - }; - - let runtime = Runtime::new().map_err(|_| EnclaveBuildError::RuntimeError)?; - - runtime.block_on(arch) - } } pub fn write_config(config: Vec) -> Result { let mut file = NamedTempFile::new().map_err(|_| EnclaveBuildError::ConfigError)?; for line in config { - file.write_fmt(format_args!("{line}\n")) - .map_err(|_| EnclaveBuildError::ConfigError)?; + file.write_fmt(format_args!("{}\n", line)) + .map_err(EnclaveBuildError::FileError)?; } Ok(file) @@ -381,15 +435,15 @@ mod tests { #[test] fn test_config() { #[cfg(target_arch = "x86_64")] - let docker = DockerUtil::new(String::from( + let docker = DockerImageManager::new(String::from( "667861386598.dkr.ecr.us-east-1.amazonaws.com/enclaves-samples:vsock-sample-server-x86_64", )); #[cfg(target_arch = "aarch64")] - let docker = DockerUtil::new(String::from( + let mut docker = DockerImageManager::new(String::from( "667861386598.dkr.ecr.us-east-1.amazonaws.com/enclaves-samples:vsock-sample-server-aarch64", )); - let (cmd_file, env_file) = docker.load().unwrap(); + let (cmd_file, env_file) = docker.unwrap().extract_expressions().unwrap(); let mut cmd_file = File::open(cmd_file.path()).unwrap(); let mut env_file = File::open(env_file.path()).unwrap(); diff --git a/enclave_build/src/image_manager.rs b/enclave_build/src/image_manager.rs index 1da6d778..1cd7e6b9 100644 --- a/enclave_build/src/image_manager.rs +++ b/enclave_build/src/image_manager.rs @@ -7,6 +7,7 @@ use std::convert::TryFrom; use log::warn; use oci_distribution::Reference; use tempfile::NamedTempFile; +use tokio::runtime::Runtime; use crate::image::ImageDetails; use crate::storage::OciStorage; @@ -33,7 +34,7 @@ pub struct OciImageManager { impl OciImageManager { /// When calling this constructor, it also tries to initialize the storage at the default path. /// If this fails, the ImageManager is still created, but the 'storage' field is set to 'None'. - pub async fn new(image_name: &str) -> Result { + pub fn new(image_name: &str) -> Result { // Add the default ":latest" tag if the image tag is missing let image_name = normalize_tag(image_name)?; @@ -48,7 +49,12 @@ impl OciImageManager { Err(_) => None, }; - let image_details = Self::fetch_image_details(&image_name, storage).await?; + let act = Self::fetch_image_details(&image_name, storage); + + let runtime = Runtime::new().map_err(|_| EnclaveBuildError::RuntimeError)?; + let image_details = runtime + .block_on(act) + .map_err(|_| EnclaveBuildError::RuntimeError)?; Ok(Self { image_name, @@ -201,7 +207,7 @@ mod tests { #[tokio::test] async fn test_create_manager() { - let image_manager = OciImageManager::new(SAMPLE_IMAGE).await.unwrap(); + let image_manager = OciImageManager::new(SAMPLE_IMAGE).unwrap(); assert_eq!(image_manager.image_name, SAMPLE_IMAGE); @@ -220,7 +226,7 @@ mod tests { #[cfg(target_arch = "x86_64")] let image_manager = OciImageManager::new( "667861386598.dkr.ecr.us-east-1.amazonaws.com/enclaves-samples:vsock-sample-server-x86_64", - ).await.unwrap(); + ).unwrap(); #[cfg(target_arch = "aarch64")] let mut image_manager = OciImageManager::new( "667861386598.dkr.ecr.us-east-1.amazonaws.com/enclaves-samples:vsock-sample-server-aarch64", diff --git a/enclave_build/src/lib.rs b/enclave_build/src/lib.rs index b371ad7c..87f4e9b5 100644 --- a/enclave_build/src/lib.rs +++ b/enclave_build/src/lib.rs @@ -16,7 +16,6 @@ mod yaml_generator; use aws_nitro_enclaves_image_format::defs::{EifBuildInfo, EifIdentityInfo, EIF_HDR_ARCH_ARM64}; use aws_nitro_enclaves_image_format::utils::identity::parse_custom_metadata; use aws_nitro_enclaves_image_format::utils::{EifBuilder, SignEnclaveInfo}; -use docker::DockerUtil; use serde_json::json; use sha2::Digest; use std::collections::BTreeMap; @@ -27,7 +26,7 @@ pub const DEFAULT_TAG: &str = "1.0"; #[derive(Debug, Error)] pub enum EnclaveBuildError { - #[error("Docker error: `{0}`")] + #[error("Docker error: `{0:?}`")] DockerError(String), #[error("Invalid path: `{0}`")] PathError(String), @@ -85,9 +84,16 @@ pub enum EnclaveBuildError { pub type Result = std::result::Result; +#[allow(dead_code)] +enum ImageType { + Docker, + Oci, +} + pub struct Docker2Eif<'a> { - docker_image: String, - docker: DockerUtil, + /// This field can be any struct that implements the 'ImageManager' trait. + image_manager: Box, + image_type: ImageType, init_path: String, nsm_path: String, kernel_img_path: String, @@ -103,8 +109,11 @@ pub struct Docker2Eif<'a> { } impl<'a> Docker2Eif<'a> { + /// Decide on the type of image and build method of the EIF from based on build arguments. + /// The presence of `--docker-uri` alone or along `--docker-dir` prompts the usage of the Docker daemon. pub fn new( - docker_image: String, + docker_image: Option, + docker_dir: Option, init_path: String, nsm_path: String, kernel_img_path: String, @@ -119,8 +128,34 @@ impl<'a> Docker2Eif<'a> { metadata_path: Option, build_info: EifBuildInfo, ) -> Result { - let docker = DockerUtil::new(docker_image.clone()); let blob_paths = Vec::from([&init_path, &nsm_path, &kernel_img_path, &linuxkit_path]); + let image_type; + + // The flags usage was already validated by the commands parser, so now just check if the docker daemon + // should be used or not + let image_manager: Box = match (&docker_image, &docker_dir) + { + // Docker directory present so try to build from Dockerfile + (Some(docker_image), Some(docker_dir)) => { + image_type = ImageType::Docker; + Box::new(crate::docker::DockerImageManager::from_dockerfile( + docker_image, + docker_dir, + )?) + } + // If the --docker-uri flag is used then the docker client is required either for pulling the image or + // for building it locally from the supplied Dockerfile in case --docker-dir is used too + (Some(docker_image), _) => { + image_type = ImageType::Docker; + Box::new(crate::docker::DockerImageManager::new(docker_image)?) + } + // TODO: add cases for --oci-image and --oci-archive when arguments are introduced + (_, _) => { + return Err(EnclaveBuildError::ImageDetailError( + "Image directory or URI missing".to_string(), + )) + } + }; blob_paths.iter().try_for_each(|path| { if !Path::new(path).is_file() { @@ -152,8 +187,8 @@ impl<'a> Docker2Eif<'a> { }; Ok(Docker2Eif { - docker_image, - docker, + image_manager, + image_type, init_path, nsm_path, kernel_img_path, @@ -169,25 +204,10 @@ impl<'a> Docker2Eif<'a> { }) } - pub fn pull_docker_image(&self) -> Result<()> { - self.docker.pull_image()?; + fn generate_identity_info(&mut self) -> Result { + let docker_info = self.image_manager.inspect_image()?; - Ok(()) - } - - pub fn build_docker_image(&self, dockerfile_dir: String) -> Result<()> { - if !Path::new(&dockerfile_dir).is_dir() { - return Err(EnclaveBuildError::PathError(dockerfile_dir)); - } - self.docker.build_image(dockerfile_dir)?; - - Ok(()) - } - - fn generate_identity_info(&self) -> Result { - let docker_info = self.docker.inspect_image()?; - - let uri_split: Vec<&str> = self.docker_image.split(':').collect(); + let uri_split: Vec<&str> = self.image_manager.image_name().split(':').collect(); if uri_split.is_empty() { return Err(EnclaveBuildError::ImageDetailError( "Wrong image name specified".to_string(), @@ -231,11 +251,26 @@ impl<'a> Docker2Eif<'a> { }) } + fn create_ramfs(&self, args: Vec<&str>) -> Result<()> { + let output = Command::new(&self.linuxkit_path) + .args(args) + .output() + .map_err(|e| EnclaveBuildError::LinuxKitError(format!("{:?}", e)))?; + if !output.status.success() { + return Err(EnclaveBuildError::LinuxKitError(format!( + "Linuxkit reported an error while creating ramfs: {:?}", + String::from_utf8_lossy(&output.stderr) + ))); + } + + Ok(()) + } + pub fn create(&mut self) -> Result> { - let (cmd_file, env_file) = self.docker.load()?; + let (cmd_file, env_file) = self.image_manager.extract_expressions()?; let yaml_generator = YamlGenerator::new( - self.docker_image.clone(), + self.image_manager.image_name().to_string(), self.init_path.clone(), self.nsm_path.clone(), cmd_file.path().to_str().unwrap().to_string(), @@ -254,55 +289,60 @@ impl<'a> Docker2Eif<'a> { let bootstrap_ramfs = format!("{}/bootstrap-initrd.img", self.artifacts_prefix); let customer_ramfs = format!("{}/customer-initrd.img", self.artifacts_prefix); - let output = Command::new(&self.linuxkit_path) - .args([ + // Create the bootstrap ramfs + self.create_ramfs( + [ "build", "-name", &bootstrap_ramfs, "-format", "kernel+initrd", ramfs_config_file.path().to_str().unwrap(), - ]) - .output() - .map_err(|e| EnclaveBuildError::LinuxKitError(format!("{:?}", e)))?; - if !output.status.success() { - eprintln!( - "Linuxkit reported an error while creating the bootstrap ramfs: {:?}", - String::from_utf8_lossy(&output.stderr) - ); - return Err(EnclaveBuildError::LinuxKitError(format!( - "{:?}", - String::from_utf8_lossy(&output.stderr) - ))); - } - - // Prefix the docker image filesystem, as expected by init - let output = Command::new(&self.linuxkit_path) - .args([ - "build", - "-docker", - "-name", - &customer_ramfs, - "-format", - "kernel+initrd", - "-prefix", - "rootfs/", - ramfs_with_rootfs_config_file.path().to_str().unwrap(), - ]) - .output() - .map_err(|e| EnclaveBuildError::LinuxKitError(format!("{:?}", e)))?; - if !output.status.success() { - eprintln!( - "Linuxkit reported an error while creating the customer ramfs: {:?}", - String::from_utf8_lossy(&output.stderr) - ); - return Err(EnclaveBuildError::LinuxKitError(format!( - "{:?}", - String::from_utf8_lossy(&output.stderr) - ))); + ] + .to_vec(), + )?; + + // If the docker daemon should be used, then call linuxkit with the '-docker' flag, which + // makes linuxkit search the image in the docker cache first. + // Otherwise, do not add the flag and let it pull the images itself, without docker. + match self.image_type { + ImageType::Docker => { + // Prefix the docker image filesystem, as expected by init + self.create_ramfs( + [ + "build", + // Use the docker daemon to first check if the image is in the docker cache + "-docker", + "-name", + &customer_ramfs, + "-format", + "kernel+initrd", + "-prefix", + "rootfs/", + ramfs_with_rootfs_config_file.path().to_str().unwrap(), + ] + .to_vec(), + )?; + } + ImageType::OCI => { + // In this case, linuxkit pulls the image itself + self.create_ramfs( + [ + "build", + "-name", + &customer_ramfs, + "-format", + "kernel+initrd", + "-prefix", + "rootfs/", + ramfs_with_rootfs_config_file.path().to_str().unwrap(), + ] + .to_vec(), + )?; + } } - let arch = self.docker.architecture()?; + let arch = self.image_manager.architecture()?; let flags = match arch.as_str() { docker::DOCKER_ARCH_ARM64 => EIF_HDR_ARCH_ARM64, @@ -312,13 +352,15 @@ impl<'a> Docker2Eif<'a> { } }; + let eif_info = self.generate_identity_info()?; + let mut build = EifBuilder::new( Path::new(&self.kernel_img_path), self.cmdline.clone(), self.sign_info.clone(), sha2::Sha384::new(), flags, - self.generate_identity_info()?, + eif_info, ); // Linuxkit adds -initrd.img sufix to the file names. diff --git a/enclave_build/src/main.rs b/enclave_build/src/main.rs index cedc28e2..44a2fa76 100644 --- a/enclave_build/src/main.rs +++ b/enclave_build/src/main.rs @@ -17,7 +17,12 @@ fn main() { .long("tag") .help("Docker image tag") .takes_value(true) - .required(true), + ) + .arg( + Arg::with_name("docker_dir") + .long("dir") + .help("Path to directory containing a Dockerfile") + .takes_value(true) ) .arg( Arg::with_name("init_path") @@ -86,22 +91,6 @@ fn main() { .help("Specify the path to the private-key") .takes_value(true), ) - .arg( - Arg::with_name("build") - .short('b') - .long("build") - .help("Build image from Dockerfile") - .takes_value(true) - .required(false), - ) - .arg( - Arg::with_name("pull") - .short('p') - .long("pull") - .help("Pull the Docker image before generating EIF") - .required(false) - .conflicts_with("build"), - ) .arg( Arg::with_name("image_name") .long("name") @@ -122,7 +111,8 @@ fn main() { ) .get_matches(); - let docker_image = matches.value_of("docker_image").unwrap(); + let docker_image = matches.value_of("docker_image").map(|val| val.to_string()); + let docker_dir = matches.value_of("docker_dir").map(|val| val.to_string()); let init_path = matches.value_of("init_path").unwrap(); let nsm_path = matches.value_of("nsm_path").unwrap(); let kernel_img_path = matches.value_of("kernel_img_path").unwrap(); @@ -148,7 +138,8 @@ fn main() { .expect("Failed to create output file"); let mut img = Docker2Eif::new( - docker_image.to_string(), + docker_image, + docker_dir, init_path.to_string(), nsm_path.to_string(), kernel_img_path.to_string(), @@ -165,12 +156,5 @@ fn main() { ) .unwrap(); - if matches.is_present("build") { - let dockerfile_dir = matches.value_of("build").unwrap(); - img.build_docker_image(dockerfile_dir.to_string()).unwrap(); - } else if matches.is_present("pull") { - img.pull_docker_image().unwrap(); - } - img.create().unwrap(); } diff --git a/src/lib.rs b/src/lib.rs index d46686c7..b4818415 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -126,7 +126,8 @@ pub fn build_from_docker( })?; let mut docker2eif = enclave_build::Docker2Eif::new( - docker_uri.to_string(), + Some(docker_uri.to_string()), + docker_dir.clone(), format!("{}/init", blobs_path), format!("{}/nsm.ko", blobs_path), kernel_path, @@ -148,23 +149,6 @@ pub fn build_from_docker( ) })?; - if let Some(docker_dir) = docker_dir { - docker2eif - .build_docker_image(docker_dir.clone()) - .map_err(|err| { - new_nitro_cli_failure!( - &format!("Failed to build docker image: {:?}", err), - NitroCliErrorEnum::DockerImageBuildError - ) - })?; - } else { - docker2eif.pull_docker_image().map_err(|err| { - new_nitro_cli_failure!( - &format!("Failed to pull docker image: {:?}", err), - NitroCliErrorEnum::DockerImagePullError - ) - })?; - } let measurements = docker2eif.create().map_err(|err| { new_nitro_cli_failure!( &format!("Failed to create EIF image: {:?}", err),