linera_service/cli_wrappers/
docker.rs1use std::path::PathBuf;
5
6use anyhow::{Context, Result};
7use linera_base::command::{current_binary_parent, CommandExt};
8use pathdiff::diff_paths;
9use tokio::process::Command;
10
11use crate::cli_wrappers::local_kubernetes_net::BuildMode;
12
13pub enum Dockerfile {
14 Main,
15 Indexer,
16 Explorer,
17}
18
19impl Dockerfile {
20 pub fn path(&self) -> &'static str {
21 match self {
22 Dockerfile::Main => "docker/Dockerfile",
23 Dockerfile::Indexer => "docker/Dockerfile.indexer",
24 Dockerfile::Explorer => "docker/Dockerfile.explorer",
25 }
26 }
27}
28
29pub struct DockerImage {
30 name: String,
31}
32
33impl DockerImage {
34 pub fn name(&self) -> &String {
35 &self.name
36 }
37
38 pub async fn build(
39 name: String,
40 binaries: BuildArg,
41 github_root: PathBuf,
42 build_mode: BuildMode,
43 dual_store: bool,
44 dockerfile: Dockerfile,
45 ) -> Result<Self> {
46 let docker_image = Self {
47 name: name.to_owned(),
48 };
49 let mut command = Command::new("docker");
50 command
51 .current_dir(github_root.clone())
52 .arg("build")
53 .args(["-f", dockerfile.path()]);
54
55 if let Dockerfile::Main = dockerfile {
56 let build_arg = match binaries {
57 BuildArg::Directory(bin_path) => {
58 let bin_path = diff_paths(bin_path, github_root)
60 .context("Getting relative path failed")?;
61 let bin_path_str = bin_path.to_str().context("Getting str failed")?;
62 format!("binaries={bin_path_str}")
63 }
64 BuildArg::ParentDirectory => {
65 let parent_path = current_binary_parent()
67 .expect("Fetching current binaries path should not fail");
68 let bin_path = diff_paths(parent_path, github_root)
69 .context("Getting relative path failed")?;
70 let bin_path_str = bin_path.to_str().context("Getting str failed")?;
71 format!("binaries={bin_path_str}")
72 }
73 BuildArg::Build => {
74 let arch = std::env::consts::ARCH;
76 let docker_arch = match arch {
78 "arm" => "aarch",
79 _ => arch,
80 };
81 format!("target={}-unknown-linux-gnu", docker_arch)
82 }
83 };
84
85 command.args(["--build-arg", &build_arg]);
86
87 match build_mode {
88 BuildMode::Release => {}
90 BuildMode::Debug => {
91 command.args(["--build-arg", "build_folder=debug"]);
92 command.args(["--build-arg", "build_flag="]);
93 }
94 }
95
96 if dual_store {
97 command.args(["--build-arg", "build_features=rocksdb,scylladb,metrics"]);
98 }
99
100 #[cfg(not(with_testing))]
101 command
102 .args([
103 "--build-arg",
104 &format!(
105 "git_commit={}",
106 linera_version::VersionInfo::get()?.git_commit
107 ),
108 ])
109 .args([
110 "--build-arg",
111 &format!(
112 "build_date={}",
113 chrono::Utc::now().format("%a %b %d %T UTC %Y")
115 ),
116 ]);
117 }
118
119 command
120 .arg(".")
121 .args(["-t", &name])
122 .spawn_and_wait()
123 .await?;
124 Ok(docker_image)
125 }
126}
127
128#[derive(Clone)]
130pub enum BuildArg {
131 Build,
133 ParentDirectory,
135 Directory(PathBuf),
137}
138
139impl From<Option<Option<PathBuf>>> for BuildArg {
140 fn from(arg: Option<Option<PathBuf>>) -> Self {
141 match arg {
142 None => BuildArg::Build,
143 Some(None) => BuildArg::ParentDirectory,
144 Some(Some(path)) => BuildArg::Directory(path),
145 }
146 }
147}