build using bollard, not CLI

This commit is contained in:
tahahawa 2025-07-09 00:13:51 -04:00
parent a9aa989b66
commit de6969f824

View File

@ -1,14 +1,19 @@
use std::fs; use std::fs;
use std::io::Read;
use std::path::PathBuf; use std::path::PathBuf;
use std::process; use std::process;
use std::sync::Arc; use std::sync::Arc;
use async_trait::async_trait; use async_trait::async_trait;
use bollard::{Docker, body_full};
use dockerfile_builder::Dockerfile; use dockerfile_builder::Dockerfile;
use dockerfile_builder::instruction::{CMD, COPY, ENV, EXPOSE, FROM, RUN, USER, WORKDIR}; use dockerfile_builder::instruction::{CMD, COPY, ENV, EXPOSE, FROM, RUN, USER, WORKDIR};
use dockerfile_builder::instruction_builder::CopyBuilder; use dockerfile_builder::instruction_builder::CopyBuilder;
use futures_util::StreamExt;
use log::{debug, error, info}; use log::{debug, error, info};
use serde::Serialize; use serde::Serialize;
use tar::Archive;
use tempfile::tempfile;
use crate::config::{REGISTRY_PROJECT, REGISTRY_URL}; use crate::config::{REGISTRY_PROJECT, REGISTRY_URL};
use crate::{ use crate::{
@ -108,6 +113,7 @@ impl OCICompliant for RustWebapp {
// 1. Build the local image by calling the synchronous helper function. // 1. Build the local image by calling the synchronous helper function.
let local_image_name = self.local_image_name(); let local_image_name = self.local_image_name();
self.build_docker_image(&local_image_name) self.build_docker_image(&local_image_name)
.await
.map_err(|e| format!("Failed to build Docker image: {}", e))?; .map_err(|e| format!("Failed to build Docker image: {}", e))?;
info!( info!(
"Successfully built local Docker image: {}", "Successfully built local Docker image: {}",
@ -153,31 +159,46 @@ impl RustWebapp {
} }
/// Builds the Docker image using the generated Dockerfile. /// Builds the Docker image using the generated Dockerfile.
pub fn build_docker_image( pub async fn build_docker_image(
&self, &self,
image_name: &str, image_name: &str,
) -> Result<String, Box<dyn std::error::Error>> { ) -> Result<String, Box<dyn std::error::Error>> {
info!("Generating Dockerfile for '{}'", self.name); info!("Generating Dockerfile for '{}'", self.name);
let dockerfile_path = self.build_dockerfile()?; let _dockerfile_path = self.build_dockerfile()?;
info!( let docker = Docker::connect_with_socket_defaults().unwrap();
"Building Docker image with file {} from root {}",
dockerfile_path.to_string_lossy(), let build_image_options = bollard::query_parameters::BuildImageOptionsBuilder::default()
self.project_root.to_string_lossy() .dockerfile("Dockerfile.harmony")
.t(image_name)
.q(false)
.version(bollard::query_parameters::BuilderVersion::BuilderV1)
.platform("linux/x86_64");
let mut temp_tar_builder = tar::Builder::new(Vec::new());
let _ = temp_tar_builder
.append_dir_all("", self.project_root.clone())
.unwrap();
let archive = temp_tar_builder
.into_inner()
.expect("couldn't finish creating tar");
let archived_files = Archive::new(archive.as_slice())
.entries()
.unwrap()
.map(|entry| entry.unwrap().path().unwrap().into_owned())
.collect::<Vec<_>>();
debug!("files in docker tar: {:#?}", archived_files);
let mut image_build_stream = docker.build_image(
build_image_options.build(),
None,
Some(body_full(archive.into())),
); );
let output = process::Command::new("docker")
.args([
"build",
"--file",
dockerfile_path.to_str().unwrap(),
"-t",
&image_name,
self.project_root.to_str().unwrap(),
])
.spawn()?
.wait_with_output()?;
self.check_output(&output, "Failed to build Docker image")?; while let Some(msg) = image_build_stream.next().await {
println!("Message: {msg:?}");
}
Ok(image_name.to_string()) Ok(image_name.to_string())
} }