@@ -261,6 +261,26 @@ List<Container> listChildContainers() {
261261 void startAmbassadorContainer () {
262262 if (!this .ambassadorPortMappings .isEmpty ()) {
263263 this .ambassadorContainer .start ();
264+ connectAmbassadorToComposeNetworks ();
265+ }
266+ }
267+
268+ private void connectAmbassadorToComposeNetworks () {
269+ Set <String > composeNetworkIds = listChildContainers ()
270+ .stream ()
271+ .filter (container ->
272+ container .getNetworkSettings () != null && container .getNetworkSettings ().getNetworks () != null
273+ )
274+ .flatMap (container -> container .getNetworkSettings ().getNetworks ().entrySet ().stream ())
275+ .filter (entry -> !Arrays .asList ("bridge" , "host" , "none" ).contains (entry .getKey ()))
276+ .map (entry -> entry .getValue ().getNetworkID ())
277+ .collect (Collectors .toSet ());
278+
279+ for (String composeNetworkId : composeNetworkIds ) {
280+ this .dockerClient .connectToNetworkCmd ()
281+ .withContainerId (this .ambassadorContainer .getContainerId ())
282+ .withNetworkId (composeNetworkId )
283+ .exec ();
264284 }
265285 }
266286
@@ -282,27 +302,25 @@ public void withExposedService(String serviceName, int servicePort, @NonNull Wai
282302 /*
283303 * For every service/port pair that needs to be exposed, we register a target on an 'ambassador container'.
284304 *
285- * The ambassador container's role is to link (within the Docker network) to one of the
286- * compose services, and proxy TCP network I/O out to a port that the ambassador container
287- * exposes.
305+ * The ambassador container's role is to proxy TCP network I/O from one of the compose
306+ * services out to a port that the ambassador container exposes.
307+ *
308+ * After Docker Compose starts, the ambassador container is connected to the compose
309+ * network so it can resolve service names via Docker's built-in DNS.
288310 *
289311 * This avoids the need for the docker compose file to explicitly expose ports on all the
290312 * services.
291- *
292- * {@link GenericContainer} should ensure that the ambassador container is on the same network
293- * as the rest of the compose environment.
294313 */
295314
296315 // Ambassador container will be started together after docker compose has started
297316 int ambassadorPort = nextAmbassadorPort .getAndIncrement ();
298317 ambassadorPortMappings
299318 .computeIfAbsent (serviceInstanceName , __ -> new ConcurrentHashMap <>())
300319 .put (servicePort , ambassadorPort );
301- ambassadorContainer .withTarget (ambassadorPort , serviceInstanceName , servicePort );
302- ambassadorContainer .addLink (
303- new FutureContainer (this .project + this .composeSeparator + serviceInstanceName ),
304- serviceInstanceName
305- );
320+ // Use the full container name as the socat target so Docker DNS can resolve it
321+ // on the compose network (e.g., "project-redis-1" instead of just "redis-1")
322+ String containerName = this .project + this .composeSeparator + serviceInstanceName ;
323+ ambassadorContainer .withTarget (ambassadorPort , containerName , servicePort );
306324 addWaitStrategy (serviceInstanceName , waitStrategy );
307325 }
308326
0 commit comments