@@ -437,9 +437,17 @@ impl DockerClient {
437437 "Generated challenge container name"
438438 ) ;
439439
440- // Remove existing container if any
440+ // Remove existing container if any (same name)
441441 let _ = self . remove_container ( & container_name) . await ;
442442
443+ // Clean up old challenge containers with different suffixes (from previous server restarts)
444+ let challenge_prefix = format ! (
445+ "challenge-{}-" ,
446+ config. name. to_lowercase( ) . replace( ' ' , "-" )
447+ ) ;
448+ self . cleanup_old_challenge_containers ( & challenge_prefix, & container_name)
449+ . await ;
450+
443451 // Build port bindings - expose on a dynamic port
444452 let mut port_bindings = HashMap :: new ( ) ;
445453 port_bindings. insert (
@@ -732,6 +740,44 @@ impl DockerClient {
732740 Ok ( output)
733741 }
734742
743+ /// Clean up old challenge containers with different suffixes
744+ /// This handles the case where the server restarts with a new container ID
745+ async fn cleanup_old_challenge_containers ( & self , prefix : & str , exclude_name : & str ) {
746+ let options = ListContainersOptions :: < String > {
747+ all : true ,
748+ ..Default :: default ( )
749+ } ;
750+
751+ let containers = match self . docker . list_containers ( Some ( options) ) . await {
752+ Ok ( c) => c,
753+ Err ( e) => {
754+ warn ! ( error = %e, "Failed to list containers for cleanup" ) ;
755+ return ;
756+ }
757+ } ;
758+
759+ for container in containers {
760+ let names = container. names . unwrap_or_default ( ) ;
761+ let container_id = match container. id . as_ref ( ) {
762+ Some ( id) => id. clone ( ) ,
763+ None => continue ,
764+ } ;
765+
766+ // Check if container name matches prefix but is not the current container
767+ let should_remove = names. iter ( ) . any ( |name| {
768+ let clean_name = name. trim_start_matches ( '/' ) ;
769+ clean_name. starts_with ( prefix) && clean_name != exclude_name
770+ } ) ;
771+
772+ if should_remove {
773+ info ! ( container = ?names, "Removing old challenge container from previous server instance" ) ;
774+ if let Err ( e) = self . remove_container ( & container_id) . await {
775+ warn ! ( container = ?names, error = %e, "Failed to remove old container" ) ;
776+ }
777+ }
778+ }
779+ }
780+
735781 /// Clean up stale task containers created by challenge evaluations
736782 ///
737783 /// This removes containers that match the pattern but excludes:
0 commit comments