@Override
    @SneakyThrows(InterruptedException.class)
    protected void waitUntilReady() {
        final Set<Integer> externalLivenessCheckPorts;
        if (this.ports == null || this.ports.length == 0) {
            externalLivenessCheckPorts = getLivenessCheckPorts();
            if (externalLivenessCheckPorts.isEmpty()) {
                if (log.isDebugEnabled()) {
                    log.debug(
                        "Liveness check ports of {} is empty. Not waiting.",
                        waitStrategyTarget.getContainerInfo().getName()
                    );
                }
                return;
            }
        } else {
            externalLivenessCheckPorts =
                Arrays
                    .stream(this.ports)
                    .mapToObj(port -> waitStrategyTarget.getMappedPort(port))
                    .collect(Collectors.toSet());
        }

        List<Integer> exposedPorts = waitStrategyTarget.getExposedPorts();

        final Set<Integer> internalPorts = getInternalPorts(externalLivenessCheckPorts, exposedPorts);

        Callable<Boolean> internalCheck = new InternalCommandPortListeningCheck(waitStrategyTarget, internalPorts);

        Callable<Boolean> externalCheck = new ExternalPortListeningCheck(
            waitStrategyTarget,
            externalLivenessCheckPorts
        );

        try {
            List<Future<Boolean>> futures = EXECUTOR.invokeAll(
                Arrays.asList(
                    // Blocking
                    () -> {
                        Instant now = Instant.now();
                        Boolean result = internalCheck.call();
                        log.debug(
                            "Internal port check {} for {} in {}",
                            Boolean.TRUE.equals(result) ? "passed" : "failed",
                            internalPorts,
                            Duration.between(now, Instant.now())
                        );
                        return result;
                    },
                    // Polling
                    () -> {
                        Instant now = Instant.now();
                        Awaitility
                            .await()
                            .pollInSameThread()
                            .pollInterval(Duration.ofMillis(100))
                            .pollDelay(Duration.ZERO)
                            .failFast("container is no longer running", () -> !waitStrategyTarget.isRunning())
                            .ignoreExceptions()
                            .forever()
                            .until(externalCheck);

                        log.debug(
                            "External port check passed for {} mapped as {} in {}",
                            internalPorts,
                            externalLivenessCheckPorts,
                            Duration.between(now, Instant.now())
                        );
                        return true;
                    }
                ),
                startupTimeout.getSeconds(),
                TimeUnit.SECONDS
            );

            for (Future<Boolean> future : futures) {
                future.get(0, TimeUnit.SECONDS);
            }
        } catch (CancellationException | ExecutionException | TimeoutException e) {
            throw new ContainerLaunchException(
                "Timed out waiting for container port to open (" +
                waitStrategyTarget.getHost() +
                " ports: " +
                externalLivenessCheckPorts +
                " should be listening)"
            );
        }
    }
Waits until a socket connection can be established on a port exposed or mapped by the container.
core/src/main/java/org/testcontainers/containers/wait/strategy/HostPortWaitStrategy.java