rusty_docker_compose/
lib.rs1use std::fs::File;
2use std::path::Path;
3use std::process::{Command, Stdio};
4use std::thread;
5
6#[derive(Clone)]
7pub struct DockerComposeCmd {
8 file: String,
9 logs_dir: String,
10}
11
12impl DockerComposeCmd {
13 pub fn new(file: &str, logs_dir: &str) -> DockerComposeCmd {
14 DockerComposeCmd {
15 file: file.to_string(),
16 logs_dir: logs_dir.to_string(),
17 }
18 }
19
20 fn get_docker_compose_command() -> &'static str {
21 if Command::new("docker-compose").output().is_ok() {
22 return "docker-compose";
23 } else {
24 return "docker compose";
25 }
26 }
27
28 pub fn up(&self) {
29 let docker_compose_command = Self::get_docker_compose_command();
30
31 let output = Command::new(docker_compose_command)
32 .arg("-f")
33 .arg(self.file.clone())
34 .arg("up")
35 .arg("-d")
36 .output()
37 .expect("Failed to execute command");
38 println!("Output: {}", String::from_utf8_lossy(&output.stdout));
39 println!("Errors: {}", String::from_utf8_lossy(&output.stderr));
40 println!("Docker Compose started");
41
42 let dir = &self.logs_dir;
43 if Path::new(dir).exists() {
44 std::fs::remove_dir_all(dir).unwrap();
45 }
46 std::fs::create_dir_all(dir).unwrap();
47
48 let output = Command::new(docker_compose_command)
49 .arg("-f")
50 .arg(self.file.clone())
51 .arg("ps")
52 .arg("--services")
53 .output()
54 .unwrap();
55
56 let stdout = String::from_utf8(output.stdout).unwrap();
57 let containers: Vec<String> = stdout.lines().map(String::from).collect();
58
59 let _handles: Vec<_> = containers
60 .into_iter()
61 .map(|container| {
62 let file_name = format!("{}/{}.log", dir, container);
63 let file_path = std::path::PathBuf::from(file_name);
64 let docker_compose_file = self.file.clone();
65 thread::spawn(move || {
66 let follow_container_log =
67 |container: String, file_path: std::path::PathBuf| {
68 let file = File::create(file_path).unwrap();
69 let _ = Command::new(docker_compose_command)
70 .arg("-f")
71 .arg(docker_compose_file)
72 .arg("logs")
73 .arg("--follow")
74 .arg("--no-log-prefix")
75 .arg(&container)
76 .stdout(Stdio::from(file))
77 .spawn()
78 .unwrap();
79 };
80
81 follow_container_log(container, file_path);
82 });
83 })
84 .collect();
85 }
86
87 pub fn down(&self) {
88 println!("Gracefully shutting down...");
89
90 let docker_compose_command = Self::get_docker_compose_command();
91
92 let _output = Command::new(docker_compose_command)
93 .arg("-f")
94 .arg(self.file.clone())
95 .arg("down")
96 .output()
97 .expect("Failed to execute command");
98 }
99}
100
101pub struct DockerCompose {
102 cmd: DockerComposeCmd,
103}
104
105impl DockerCompose {
106 pub fn new(file: &str, logs_dir: &str) -> DockerCompose {
107 let cmd = DockerComposeCmd::new(file, logs_dir);
108 cmd.up();
109 DockerCompose { cmd }
110 }
111}
112
113impl Drop for DockerCompose {
114 fn drop(&mut self) {
115 self.cmd.down();
116 }
117}