diff --git a/modules/kafka/src/main/java/org/testcontainers/kafka/KafkaContainer.java b/modules/kafka/src/main/java/org/testcontainers/kafka/KafkaContainer.java index 375fd132f6c..36118d0092c 100644 --- a/modules/kafka/src/main/java/org/testcontainers/kafka/KafkaContainer.java +++ b/modules/kafka/src/main/java/org/testcontainers/kafka/KafkaContainer.java @@ -72,6 +72,12 @@ protected void containerIsStarting(InspectContainerResponse containerInfo) { command += "/etc/kafka/docker/run \n"; copyFileToContainer(Transferable.of(command, 0777), STARTER_SCRIPT); + // Marker file: created after the starter script copy has fully released its + // writer, so the wait loop in KafkaHelper.COMMAND only proceeds when the + // script is safe to execve. Without this, on busy hosts the loop can see the + // starter script entry before docker-cp has closed it and fail with + // "Text file busy" (exit 126). + copyFileToContainer(Transferable.of(""), KafkaHelper.STARTER_SCRIPT_READY_FLAG); } /** diff --git a/modules/kafka/src/main/java/org/testcontainers/kafka/KafkaHelper.java b/modules/kafka/src/main/java/org/testcontainers/kafka/KafkaHelper.java index 61e790d474f..766554dd1cf 100644 --- a/modules/kafka/src/main/java/org/testcontainers/kafka/KafkaHelper.java +++ b/modules/kafka/src/main/java/org/testcontainers/kafka/KafkaHelper.java @@ -25,10 +25,12 @@ class KafkaHelper { static final String STARTER_SCRIPT = "/tmp/testcontainers_start.sh"; + static final String STARTER_SCRIPT_READY_FLAG = "/tmp/testcontainers_start.ready"; + static final String[] COMMAND = { "sh", "-c", - "while [ ! -f " + STARTER_SCRIPT + " ]; do sleep 0.1; done; " + STARTER_SCRIPT, + "while [ ! -f " + STARTER_SCRIPT_READY_FLAG + " ]; do sleep 0.1; done; " + STARTER_SCRIPT, }; static final WaitStrategy WAIT_STRATEGY = Wait.forLogMessage(".*Transitioning from RECOVERY to RUNNING.*", 1);