This commit is contained in:
@@ -112,17 +112,7 @@ impl DevContainer {
|
||||
),
|
||||
working_dir: Some(workspace_folder.clone()),
|
||||
host_config: Some(HostConfig {
|
||||
binds: Some(vec![format!(
|
||||
"{}:{workspace_folder}",
|
||||
workspace_dir.display()
|
||||
)]),
|
||||
network_mode: Some(network.clone()),
|
||||
// Le clone est monté depuis un chemin de l'hôte. Sur une distribution
|
||||
// à SELinux enforcing, ce chemin n'a pas le label attendu et l'accès
|
||||
// est refusé (EACCES), ce qui fait échouer tous les outils de la
|
||||
// sandbox. C'est le compromis inverse de l'alternative `:Z` sur le
|
||||
// montage, qui re-labellise le clone et garde le confinement SELinux.
|
||||
security_opt: Some(vec![String::from("label=disable")]),
|
||||
..Default::default()
|
||||
}),
|
||||
..Default::default()
|
||||
@@ -141,6 +131,20 @@ impl DevContainer {
|
||||
return Err(err);
|
||||
}
|
||||
|
||||
// Le clone est copié dans le container par le socket, pas monté depuis un
|
||||
// chemin de l'hôte : le daemon n'a pas besoin de voir le clone pour le rendre
|
||||
// visible dans la sandbox, ce qui permet à Herald de tourner dans un container
|
||||
// (avec le socket monté) sans partager de dossier avec l'hôte.
|
||||
if let Err(err) = runtime
|
||||
.upload_directory(&name, &workspace_folder, workspace_dir)
|
||||
.await
|
||||
{
|
||||
let _ = runtime.remove_container(&name).await;
|
||||
let _ = runtime.remove_network(&network).await;
|
||||
let _ = runtime.remove_image(&image_tag).await;
|
||||
return Err(err);
|
||||
}
|
||||
|
||||
let container = Container::new(
|
||||
runtime.clone(),
|
||||
name,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
//! Primitives de cycle de vie de container pour un [`DevContainer`] analysé.
|
||||
//!
|
||||
//! Cette crate pilote l'API du daemon de containers pour construire l'image
|
||||
//! devcontainer, démarrer un container avec le workspace monté, exécuter les
|
||||
//! devcontainer, démarrer un container et y copier le workspace, exécuter les
|
||||
//! hooks `postCreateCommand` / `postStartCommand` et lancer des commandes à
|
||||
//! l'intérieur du container en cours d'exécution.
|
||||
//!
|
||||
|
||||
@@ -10,7 +10,7 @@ use bollard::{
|
||||
models::{BuildInfo, ContainerCreateBody, NetworkCreateRequest, NetworkDisconnectRequest},
|
||||
query_parameters::{
|
||||
BuildImageOptions, CreateContainerOptions, RemoveContainerOptions, RemoveImageOptions,
|
||||
StartContainerOptions, StopContainerOptions,
|
||||
StartContainerOptions, StopContainerOptions, UploadToContainerOptions,
|
||||
},
|
||||
};
|
||||
use futures_util::StreamExt;
|
||||
@@ -153,6 +153,30 @@ impl ContainerRuntime {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) async fn upload_directory(
|
||||
&self,
|
||||
container: &str,
|
||||
destination: &str,
|
||||
directory: &Path,
|
||||
) -> Result<(), ContainerError> {
|
||||
let options = UploadToContainerOptions {
|
||||
path: String::from(destination),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
self.request(
|
||||
"upload workspace",
|
||||
self.docker.upload_to_container(
|
||||
container,
|
||||
Some(options),
|
||||
body_try_stream(tar_directory_stream(directory)),
|
||||
),
|
||||
)
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) async fn start_container(&self, name: &str) -> Result<(), ContainerError> {
|
||||
self.request(
|
||||
"start container",
|
||||
|
||||
Reference in New Issue
Block a user