dev_container: Detect actual buildx availability instead of assuming Docker has it (#53910)
`supports_compose_buildkit()` returned `!self.is_podman()`, assuming every Docker install has buildx. On setups like Colima where the buildx CLI plugin isn't installed, this causes builds to fail with "classic builder doesn't support additional contexts" since `DOCKER_BUILDKIT=1` alone isn't enough without the plugin. Now probes for `docker buildx version` at construction time and caches the result. When buildx isn't found, the existing scratch-image fallback path (same one Podman uses) kicks in instead. Closes #53890 Release Notes: - Fixed dev container builds failing on Docker installations without the buildx plugin. --------- Co-authored-by: krisswee <krisswee@users.noreply.github.com> Co-authored-by: KyleBarton <kjb@initialcapacity.io>
This commit is contained in:
1 parent
191333351e
commit
8efe882ef2
2 files changed
+29
-8
No files matched your search
@@ -2108,9 +2108,9 @@ pub(crate) async fn read_devcontainer_configuration(
|
||||
environment: HashMap<String, String>,
|
||||
) -> Result<DevContainer, DevContainerError> {
|
||||
let docker = if context.use_podman {
|
||||
Docker::new("podman")
|
||||
Docker::new("podman").await
|
||||
} else {
|
||||
Docker::new("docker")
|
||||
Docker::new("docker").await
|
||||
};
|
||||
let mut dev_container = DevContainerManifest::new(
|
||||
context,
|
||||
@@ -2132,9 +2132,9 @@ pub(crate) async fn spawn_dev_container(
|
||||
local_project_path: &Path,
|
||||
) -> Result<DevContainerUp, DevContainerError> {
|
||||
let docker = if context.use_podman {
|
||||
Docker::new("podman")
|
||||
Docker::new("podman").await
|
||||
} else {
|
||||
Docker::new("docker")
|
||||
Docker::new("docker").await
|
||||
};
|
||||
let mut devcontainer_manifest = DevContainerManifest::new(
|
||||
context,
|
||||
@@ -4784,12 +4784,14 @@ FROM docker.io/hexpm/elixir:1.21-erlang-28.4.1-debian-trixie-20260316-slim AS de
|
||||
pub(crate) struct FakeDocker {
|
||||
exec_commands_recorded: Mutex<Vec<RecordedExecCommand>>,
|
||||
podman: bool,
|
||||
has_buildx: bool,
|
||||
}
|
||||
|
||||
impl FakeDocker {
|
||||
pub(crate) fn new() -> Self {
|
||||
Self {
|
||||
podman: false,
|
||||
has_buildx: true,
|
||||
exec_commands_recorded: Mutex::new(Vec::new()),
|
||||
}
|
||||
}
|
||||
@@ -5029,7 +5031,7 @@ FROM docker.io/hexpm/elixir:1.21-erlang-28.4.1-debian-trixie-20260316-slim AS de
|
||||
}))
|
||||
}
|
||||
fn supports_compose_buildkit(&self) -> bool {
|
||||
!self.podman
|
||||
!self.podman && self.has_buildx
|
||||
}
|
||||
fn docker_cli(&self) -> String {
|
||||
if self.podman {
|
||||
|
||||
@@ -175,6 +175,7 @@ pub(crate) struct DockerComposeConfig {
|
||||
|
||||
pub(crate) struct Docker {
|
||||
docker_cli: String,
|
||||
has_buildx: bool,
|
||||
}
|
||||
|
||||
impl DockerInspect {
|
||||
@@ -184,9 +185,24 @@ impl DockerInspect {
|
||||
}
|
||||
|
||||
impl Docker {
|
||||
pub(crate) fn new(docker_cli: &str) -> Self {
|
||||
pub(crate) async fn new(docker_cli: &str) -> Self {
|
||||
let has_buildx = if docker_cli == "podman" {
|
||||
false
|
||||
} else {
|
||||
let output = Command::new(docker_cli)
|
||||
.args(["buildx", "version"])
|
||||
.output()
|
||||
.await;
|
||||
output.map(|o| o.status.success()).unwrap_or(false)
|
||||
};
|
||||
if !has_buildx && docker_cli != "podman" {
|
||||
log::info!(
|
||||
"docker buildx not found; dev container builds will use the scratch-image fallback"
|
||||
);
|
||||
}
|
||||
Self {
|
||||
docker_cli: docker_cli.to_string(),
|
||||
has_buildx,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -372,7 +388,7 @@ impl DockerClient for Docker {
|
||||
}
|
||||
|
||||
fn supports_compose_buildkit(&self) -> bool {
|
||||
!self.is_podman()
|
||||
self.has_buildx
|
||||
}
|
||||
}
|
||||
|
||||
@@ -595,7 +611,10 @@ mod test {
|
||||
|
||||
#[test]
|
||||
fn should_create_docker_inspect_command() {
|
||||
let docker = Docker::new("docker");
|
||||
let docker = Docker {
|
||||
docker_cli: "docker".to_string(),
|
||||
has_buildx: false,
|
||||
};
|
||||
let given_id = "given_docker_id";
|
||||
|
||||
let command = docker.create_docker_inspect(given_id);
|
||||
|
||||
Reference in new issue
Block a user