@@ -70,11 +70,112 @@ impl DockerClient {
7070
7171 self . docker . create_network ( config) . await ?;
7272 info ! ( network = %self . network_name, "Created Docker network" ) ;
73+ } else {
74+ debug ! ( network = %self . network_name, "Docker network already exists" ) ;
7375 }
7476
7577 Ok ( ( ) )
7678 }
7779
80+ /// Connect the current container to the platform network
81+ /// This allows the validator to communicate with challenge containers via hostname
82+ pub async fn connect_self_to_network ( & self ) -> anyhow:: Result < ( ) > {
83+ // Get our container ID from the hostname or cgroup
84+ let container_id = self . get_self_container_id ( ) ?;
85+
86+ // Check if already connected
87+ let inspect = self . docker . inspect_container ( & container_id, None ) . await ?;
88+ let networks = inspect
89+ . network_settings
90+ . as_ref ( )
91+ . and_then ( |ns| ns. networks . as_ref ( ) ) ;
92+
93+ if let Some ( nets) = networks {
94+ if nets. contains_key ( & self . network_name ) {
95+ debug ! (
96+ container = %container_id,
97+ network = %self . network_name,
98+ "Container already connected to network"
99+ ) ;
100+ return Ok ( ( ) ) ;
101+ }
102+ }
103+
104+ // Connect to the network
105+ use bollard:: models:: EndpointSettings ;
106+ use bollard:: network:: ConnectNetworkOptions ;
107+
108+ let config = ConnectNetworkOptions {
109+ container : container_id. clone ( ) ,
110+ endpoint_config : EndpointSettings :: default ( ) ,
111+ } ;
112+
113+ self . docker
114+ . connect_network ( & self . network_name , config)
115+ . await ?;
116+
117+ info ! (
118+ container = %container_id,
119+ network = %self . network_name,
120+ "Connected validator container to platform network"
121+ ) ;
122+
123+ Ok ( ( ) )
124+ }
125+
126+ /// Get the container ID of the current process (if running in Docker)
127+ fn get_self_container_id ( & self ) -> anyhow:: Result < String > {
128+ // Method 1: Check hostname (Docker sets hostname to container ID by default)
129+ if let Ok ( hostname) = std:: env:: var ( "HOSTNAME" ) {
130+ // Docker container IDs are 12+ hex characters
131+ if hostname. len ( ) >= 12 && hostname. chars ( ) . all ( |c| c. is_ascii_hexdigit ( ) ) {
132+ return Ok ( hostname) ;
133+ }
134+ }
135+
136+ // Method 2: Parse from cgroup (works on Linux)
137+ if let Ok ( cgroup) = std:: fs:: read_to_string ( "/proc/self/cgroup" ) {
138+ for line in cgroup. lines ( ) {
139+ // Docker cgroup format: .../docker/<container_id>
140+ if let Some ( docker_pos) = line. rfind ( "/docker/" ) {
141+ let id = & line[ docker_pos + 8 ..] ;
142+ if id. len ( ) >= 12 {
143+ return Ok ( id[ ..12 ] . to_string ( ) ) ;
144+ }
145+ }
146+ // Kubernetes/containerd format: .../cri-containerd-<container_id>
147+ if let Some ( containerd_pos) = line. rfind ( "cri-containerd-" ) {
148+ let id = & line[ containerd_pos + 15 ..] ;
149+ if id. len ( ) >= 12 {
150+ return Ok ( id[ ..12 ] . to_string ( ) ) ;
151+ }
152+ }
153+ }
154+ }
155+
156+ // Method 3: Check /.dockerenv file exists
157+ if std:: path:: Path :: new ( "/.dockerenv" ) . exists ( ) {
158+ // If we're in Docker but can't get ID, try the mountinfo
159+ if let Ok ( mountinfo) = std:: fs:: read_to_string ( "/proc/self/mountinfo" ) {
160+ for line in mountinfo. lines ( ) {
161+ if line. contains ( "/docker/containers/" ) {
162+ if let Some ( start) = line. find ( "/docker/containers/" ) {
163+ let rest = & line[ start + 19 ..] ;
164+ if let Some ( end) = rest. find ( '/' ) {
165+ let id = & rest[ ..end] ;
166+ if id. len ( ) >= 12 {
167+ return Ok ( id[ ..12 ] . to_string ( ) ) ;
168+ }
169+ }
170+ }
171+ }
172+ }
173+ }
174+ }
175+
176+ anyhow:: bail!( "Not running in a Docker container or unable to determine container ID" )
177+ }
178+
78179 /// Check if a Docker image is from an allowed registry
79180 /// SECURITY: This prevents pulling/running malicious containers
80181 fn is_image_allowed ( image : & str ) -> bool {
0 commit comments