|
2 | 2 | // SPDX-License-Identifier: Apache-2.0 |
3 | 3 |
|
4 | 4 | use crate::RemoteOptions; |
5 | | -use crate::constants::{NETWORK_NAME, container_name, volume_name}; |
| 5 | +use crate::constants::{container_name, volume_name}; |
6 | 6 | use crate::image::{ |
7 | 7 | self, DEFAULT_IMAGE_REPO_BASE, DEFAULT_REGISTRY, DEFAULT_REGISTRY_USERNAME, parse_image_ref, |
8 | 8 | }; |
9 | 9 | use bollard::API_DEFAULT_VERSION; |
10 | 10 | use bollard::Docker; |
11 | 11 | use bollard::errors::Error as BollardError; |
12 | 12 | use bollard::models::{ |
13 | | - ContainerCreateBody, DeviceRequest, HostConfig, NetworkCreateRequest, NetworkDisconnectRequest, |
14 | | - PortBinding, VolumeCreateRequest, |
| 13 | + ContainerCreateBody, DeviceRequest, HostConfig, PortBinding, VolumeCreateRequest, |
15 | 14 | }; |
16 | 15 | use bollard::query_parameters::{ |
17 | | - CreateContainerOptions, CreateImageOptions, InspectContainerOptions, InspectNetworkOptions, |
| 16 | + CreateContainerOptions, CreateImageOptions, InspectContainerOptions, |
18 | 17 | ListContainersOptionsBuilder, RemoveContainerOptions, RemoveImageOptions, RemoveVolumeOptions, |
19 | 18 | StartContainerOptions, |
20 | 19 | }; |
@@ -186,53 +185,6 @@ pub async fn find_gateway_container(docker: &Docker, port: Option<u16>) -> Resul |
186 | 185 | } |
187 | 186 | } |
188 | 187 |
|
189 | | -pub async fn ensure_network(docker: &Docker) -> Result<()> { |
190 | | - // Always remove and recreate the network to guarantee a clean state. |
191 | | - // Stale Docker networks (e.g., from a previous interrupted destroy or |
192 | | - // Docker Desktop restart) can leave broken routing that causes the |
193 | | - // container to fail with "no default routes found". |
194 | | - force_remove_network(docker).await?; |
195 | | - |
196 | | - // Docker may return a 409 conflict if the previous network teardown has |
197 | | - // not fully completed in the daemon. Retry a few times with back-off, |
198 | | - // re-attempting the removal before each create. |
199 | | - let mut last_err = None; |
200 | | - for attempt in 0u64..5 { |
201 | | - if attempt > 0 { |
202 | | - tokio::time::sleep(std::time::Duration::from_millis(500 * attempt)).await; |
203 | | - // Re-attempt removal in case the previous teardown has now settled. |
204 | | - force_remove_network(docker).await?; |
205 | | - } |
206 | | - match docker |
207 | | - .create_network(NetworkCreateRequest { |
208 | | - name: NETWORK_NAME.to_string(), |
209 | | - driver: Some("bridge".to_string()), |
210 | | - attachable: Some(true), |
211 | | - ..Default::default() |
212 | | - }) |
213 | | - .await |
214 | | - { |
215 | | - Ok(_) => return Ok(()), |
216 | | - Err(err) if is_conflict(&err) => { |
217 | | - tracing::debug!( |
218 | | - "Network create conflict (attempt {}/5), retrying: {}", |
219 | | - attempt + 1, |
220 | | - err, |
221 | | - ); |
222 | | - last_err = Some(err); |
223 | | - } |
224 | | - Err(err) => { |
225 | | - return Err(err) |
226 | | - .into_diagnostic() |
227 | | - .wrap_err("failed to create Docker network"); |
228 | | - } |
229 | | - } |
230 | | - } |
231 | | - Err(last_err.expect("at least one retry attempt")) |
232 | | - .into_diagnostic() |
233 | | - .wrap_err("failed to create Docker network after retries (network still in use)") |
234 | | -} |
235 | | - |
236 | 188 | pub async fn ensure_volume(docker: &Docker, name: &str) -> Result<()> { |
237 | 189 | match docker.inspect_volume(name).await { |
238 | 190 | Ok(_) => return Ok(()), |
@@ -376,7 +328,6 @@ pub async fn ensure_container( |
376 | 328 | privileged: Some(true), |
377 | 329 | port_bindings: Some(port_bindings), |
378 | 330 | binds: Some(vec![format!("{}:/var/lib/rancher/k3s", volume_name(name))]), |
379 | | - network_mode: Some(NETWORK_NAME.to_string()), |
380 | 331 | // Add host.docker.internal mapping for DNS resolution |
381 | 332 | // This allows the entrypoint script to configure CoreDNS to use the host gateway |
382 | 333 | extra_hosts: Some(vec!["host.docker.internal:host-gateway".to_string()]), |
@@ -678,20 +629,6 @@ pub async fn destroy_gateway_resources(docker: &Docker, name: &str) -> Result<() |
678 | 629 | .ok() |
679 | 630 | .and_then(|info| info.image); |
680 | 631 |
|
681 | | - // Explicitly disconnect the container from the cluster network before |
682 | | - // removing it. This ensures Docker tears down the network endpoint |
683 | | - // synchronously so port bindings are released immediately and the |
684 | | - // subsequent network cleanup sees zero connected containers. |
685 | | - let _ = docker |
686 | | - .disconnect_network( |
687 | | - NETWORK_NAME, |
688 | | - NetworkDisconnectRequest { |
689 | | - container: container_name.clone(), |
690 | | - force: Some(true), |
691 | | - }, |
692 | | - ) |
693 | | - .await; |
694 | | - |
695 | 632 | let _ = stop_container(docker, &container_name).await; |
696 | 633 |
|
697 | 634 | let remove_container = docker |
@@ -763,50 +700,9 @@ pub async fn destroy_gateway_resources(docker: &Docker, name: &str) -> Result<() |
763 | 700 | return Err(err).into_diagnostic(); |
764 | 701 | } |
765 | 702 |
|
766 | | - // Force-remove the network during a full destroy. First disconnect any |
767 | | - // stale endpoints that Docker may still report (race between container |
768 | | - // removal and network bookkeeping), then remove the network itself. |
769 | | - force_remove_network(docker).await?; |
770 | 703 | Ok(()) |
771 | 704 | } |
772 | 705 |
|
773 | | -/// Forcefully remove the gateway network, disconnecting any remaining |
774 | | -/// containers first. This ensures that stale Docker network endpoints |
775 | | -/// cannot prevent port bindings from being released. |
776 | | -async fn force_remove_network(docker: &Docker) -> Result<()> { |
777 | | - let network = match docker |
778 | | - .inspect_network(NETWORK_NAME, None::<InspectNetworkOptions>) |
779 | | - .await |
780 | | - { |
781 | | - Ok(info) => info, |
782 | | - Err(err) if is_not_found(&err) => return Ok(()), |
783 | | - Err(err) => return Err(err).into_diagnostic(), |
784 | | - }; |
785 | | - |
786 | | - // Disconnect any containers still attached to the network. |
787 | | - if let Some(containers) = network.containers { |
788 | | - for (id, _) in containers { |
789 | | - let _ = docker |
790 | | - .disconnect_network( |
791 | | - NETWORK_NAME, |
792 | | - NetworkDisconnectRequest { |
793 | | - container: id, |
794 | | - force: Some(true), |
795 | | - }, |
796 | | - ) |
797 | | - .await; |
798 | | - } |
799 | | - } |
800 | | - |
801 | | - match docker.remove_network(NETWORK_NAME).await { |
802 | | - Ok(()) => Ok(()), |
803 | | - Err(err) if is_not_found(&err) => Ok(()), |
804 | | - Err(err) => Err(err) |
805 | | - .into_diagnostic() |
806 | | - .wrap_err("failed to remove Docker network"), |
807 | | - } |
808 | | -} |
809 | | - |
810 | 706 | fn is_not_found(err: &BollardError) -> bool { |
811 | 707 | matches!( |
812 | 708 | err, |
|
0 commit comments