# Solace with testcontainers - problem with ports

**URL:** <https://community.solace.com/t/solace-with-testcontainers-problem-with-ports/1439>\
**Category:** General Discussions\
**Created:** [October 18, 2022, 9:15am UTC](https://community.solace.com/t/solace-with-testcontainers-problem-with-ports/1439 "2022-10-18T09:15:05Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![masz](https://avatars.discourse-cdn.com/v4/letter/m/9f8e36/32.png) [@masz](https://community.solace.com/u/masz)\
**Post date:** [October 18, 2022, 9:15am UTC](https://community.solace.com/t/solace-with-testcontainers-problem-with-ports/1439/1 "2022-10-18T09:15:05Z")

</div>

Hi!  
I have problem with creating Solace container via testcontainers plugin. Exception which appear:  
09:15:15.486 [main] ERROR ? [solace:1.0.0] - Could not start container  
org.testcontainers.containers.ContainerLaunchException: Timed out waiting for container port to open (localhost ports: [51600, 51601, 51492, 51493, 51494, 51495, 51596, 51597, 51599] should be listening)  
Below full log:

> 

Also here is my class for Solace container:  
import org.testcontainers.containers.GenericContainer;

> import org.testcontainers.containers.wait.strategy.Wait;  
> import org.testcontainers.utility.DockerImageName;  
> import java.util.Arrays;  
> public class PubSubPlusContainer extends GenericContainer {  
> private String adminUsername;  
> private String adminPassword;  
> public static final DockerImageName DEFAULT\_IMAGE\_NAME = DockerImageName.parse(“solace/solace-pubsub-standard”);  
> public static final String DEFAULT\_IMAGE\_TAG = “latest”;  
> private static final String DEFAULT\_ADMIN\_USERNAME = “admin”;  
> private static final String DEFAULT\_ADMIN\_PASSWORD = “admin”;  
> private static final String DEFAULT\_MAX\_CONNECTION\_COUNT = “100”;  
> private static final long DEFAULT\_SHM\_SIZE = (long) Math.pow(1024, 3); // 1 GB  
> public PubSubPlusContainer() {  
> this(DEFAULT\_IMAGE\_NAME.withTag(DEFAULT\_IMAGE\_TAG));  
> }  
> public PubSubPlusContainer(String dockerImageName) {  
> this(DockerImageName.parse(dockerImageName));  
> }  
> public PubSubPlusContainer(DockerImageName dockerImageName) {  
> super(dockerImageName);  
> dockerImageName.assertCompatibleWith(DEFAULT\_IMAGE\_NAME);  
> this.withExposedPorts(Arrays.stream(Port.values()).map(Port::getInternalPort).toArray(Integer::new));  
> this.withAdminUsername(DEFAULT\_ADMIN\_USERNAME);  
> this.withAdminPassword(DEFAULT\_ADMIN\_PASSWORD);  
> this.withMaxConnectionCount(DEFAULT\_MAX\_CONNECTION\_COUNT);  
> this.withSharedMemorySize(DEFAULT\_SHM\_SIZE);  
> this.waitingFor(Wait.forListeningPort());  
> }  
> public String getAdminUsername() {  
> return adminUsername;  
> }  
> public String getAdminPassword() {  
> return adminPassword;  
> }  
> public String getOrigin(Port port) {  
> if (port.getProtocol() == null) {  
> throw new IllegalArgumentException(String.format(“Getting origin of port %s is not supported”, port.name()));  
> }  
> return String.format(“%s://%s:%s”, port.getProtocol(), getContainerIpAddress(),  
> getMappedPort(port.getInternalPort()));  
> }  
> public Integer getSshPort() {  
> return getMappedPort(Port.SSH.getInternalPort());  
> }  
> public PubSubPlusContainer withAdminUsername(String username) {  
> adminUsername = username;  
> return withEnv(“username\_admin\_globalaccesslevel”, adminUsername);  
> }  
> public PubSubPlusContainer withAdminPassword(String password) {  
> adminPassword = password;  
> return withEnv(“username\_admin\_password”, password);  
> }  
> public PubSubPlusContainer withMaxConnectionCount(String maxConnectionCount) {  
> return withEnv(“system\_scaling\_maxconnectioncount”, maxConnectionCount);  
> }  
> public enum Port {  
> AMQP(5672, “amqp”),  
> MQTT(1883, “tcp”),  
> MQTT\_WEB(8000, “ws”),  
> REST(9000, “http”),  
> SEMP(8080, “http”),  
> SMF(55555, “tcp”),  
> SMF\_TLS(55443, “tcps”),  
> SMF\_WEB(8008, “ws”),  
> SSH(2222, null);  
> private final int containerPort;  
> private final String protocol;  
> Port(int containerPort, String protocol) {  
> this.containerPort = containerPort;  
> this.protocol = protocol;  
> }  
> public int getInternalPort() {  
> return containerPort;  
> }  
> private String getProtocol() {  
> return protocol;  
> }  
> }  
> }

I contact testcontainers team, but they responded that I need to try contact Solace whether I’m using correctly that image “solace/solace-pubsub-standard”. Could somebody help me?

[logs.txt](https://community.solace.com/uploads/short-url/iytbSoLV4meU4zSIqIqyvz7S25H.txt) (42.6 KB)

---

<div class="post-metadata">

**Author:** ![amackenzie](https://yyz1.discourse-cdn.com/solace/user_avatar/community.solace.com/amackenzie/32/1168_2.png) [@amackenzie](https://community.solace.com/u/amackenzie)\
**Post date:** [October 18, 2022, 2:19pm UTC](https://community.solace.com/t/solace-with-testcontainers-problem-with-ports/1439/2 "2022-10-18T14:19:21Z")

</div>

I am not familiar with testcontainers, but at 1st glance, it seems to be that the ports are not exposed. From reading the docs, testcontainers will map the PS+ ports to randomized ports to avoid collisions with other containers. But I think these need to be exposed to the external network.  
When doing a normal docker run, you will typically map the internal ports to an external port.  
For example, to make PubSub+ Broker Manager visible on your network, you would add -p 8080:8090 on docker run will map the internal port 8080 to the host port of 8090. Then your users would access the Manager UI via 8090 from your network.  
So, is the missing piece that the testcontainers random ports are not exposed?  
I see there is something called .withExposedPorts() in the config of the container. Perhaps you need to call that with the enum you have above? Networking and communicating with containers - Testcontainers

---

<div class="post-metadata">

**Author:** ![masz](https://avatars.discourse-cdn.com/v4/letter/m/9f8e36/32.png) [@masz](https://community.solace.com/u/masz)\
**Post date:** [October 18, 2022, 3:28pm UTC](https://community.solace.com/t/solace-with-testcontainers-problem-with-ports/1439/3 "2022-10-18T15:28:44Z")

</div>

Thanks for answer, but I’m doing that \> here:  
public PubSubPlusContainer(DockerImageName dockerImageName) {

> ```
> super(dockerImageName);
> dockerImageName.assertCompatibleWith(DEFAULT_IMAGE_NAME);
> this.withExposedPorts(Arrays.stream(Port.values()).map(Port::getInternalPort).toArray(Integer[]::new));
> this.withAdminUsername(DEFAULT_ADMIN_USERNAME);
> this.withAdminPassword(DEFAULT_ADMIN_PASSWORD);
> this.withMaxConnectionCount(DEFAULT_MAX_CONNECTION_COUNT);
> this.withSharedMemorySize(DEFAULT_SHM_SIZE);
> this.waitingFor(Wait.forListeningPort());
> }
> 
> ```
> 
> I compare my implementation with implementation of KafkaContainer (which works perfectly fine), but I couldn’t find difference :/.  
> Example of class for Kafka which work:  
> import com.github.dockerjava.api.command.InspectContainerResponse;  
> import org.testcontainers.containers.Container.ExecResult;  
> import org.testcontainers.utility.DockerImageName;  
> public class KafkaContainer extends GenericContainer {  
> private static final DockerImageName DEFAULT\_IMAGE\_NAME = DockerImageName.parse(“confluentinc/cp-kafka”);  
> private static final String DEFAULT\_TAG = “5.4.3”;  
> public static final int KAFKA\_PORT = 9093;  
> public static final int ZOOKEEPER\_PORT = 2181;  
> private static final String DEFAULT\_INTERNAL\_TOPIC\_RF = “1”;  
> protected String externalZookeeperConnect;  
> /\*\* @deprecated _/  
> @Deprecated  
> public KafkaContainer() {  
> this(DEFAULT\_IMAGE\_NAME.withTag(“5.4.3”));  
> }  
> /_\* @deprecated \*/  
> @Deprecated  
> public KafkaContainer(String confluentPlatformVersion) {  
> this(DEFAULT\_IMAGE\_NAME.withTag(confluentPlatformVersion));  
> }  
> public KafkaContainer(DockerImageName dockerImageName) {  
> super(dockerImageName);  
> this.externalZookeeperConnect = null;  
> dockerImageName.assertCompatibleWith(new DockerImageName{DEFAULT\_IMAGE\_NAME});  
> this.withExposedPorts(new Integer{9093});  
> this.withEnv(“KAFKA\_LISTENERS”, “PLAINTEXT://0.0.0.0:9093,BROKER://0.0.0.0:9092”);  
> this.withEnv(“KAFKA\_LISTENER\_SECURITY\_PROTOCOL\_MAP”, “BROKER:PLAINTEXT,PLAINTEXT:PLAINTEXT”);  
> this.withEnv(“KAFKA\_INTER\_BROKER\_LISTENER\_NAME”, “BROKER”);  
> this.withEnv(“KAFKA\_BROKER\_ID”, “1”);  
> this.withEnv(“KAFKA\_OFFSETS\_TOPIC\_REPLICATION\_FACTOR”, “1”);  
> this.withEnv(“KAFKA\_OFFSETS\_TOPIC\_NUM\_PARTITIONS”, “1”);  
> this.withEnv(“KAFKA\_TRANSACTION\_STATE\_LOG\_REPLICATION\_FACTOR”, “1”);  
> this.withEnv(“KAFKA\_TRANSACTION\_STATE\_LOG\_MIN\_ISR”, “1”);  
> this.withEnv(“KAFKA\_LOG\_FLUSH\_INTERVAL\_MESSAGES”, “9223372036854775807”);  
> this.withEnv(“KAFKA\_GROUP\_INITIAL\_REBALANCE\_DELAY\_MS”, “0”);  
> }  
> public KafkaContainer withEmbeddedZookeeper() {  
> this.externalZookeeperConnect = null;  
> return (KafkaContainer)this.self();  
> }  
> public KafkaContainer withExternalZookeeper(String connectString) {  
> this.externalZookeeperConnect = connectString;  
> return (KafkaContainer)this.self();  
> }  
> public String getBootstrapServers() {  
> return String.format(“PLAINTEXT://%s:%s”, this.getHost(), this.getMappedPort(9093));  
> }  
> protected void configure() {  
> this.withEnv(“KAFKA\_ADVERTISED\_LISTENERS”, String.format(“BROKER://%s:9092”, this.getNetwork() != null ? this.getNetworkAliases().get(0) : “localhost”));  
> String command = “#!/bin/bash\n”;  
> if (this.externalZookeeperConnect != null) {  
> this.withEnv(“KAFKA\_ZOOKEEPER\_CONNECT”, this.externalZookeeperConnect);  
> } else {  
> this.addExposedPort(2181);  
> this.withEnv(“KAFKA\_ZOOKEEPER\_CONNECT”, “localhost:2181”);  
> command = command + “echo ‘clientPort=2181’ \> zookeeper.properties\n”;  
> command = command + “echo ‘dataDir=/var/lib/zookeeper/data’ \>\> zookeeper.properties\n”;  
> command = command + “echo ‘dataLogDir=/var/lib/zookeeper/log’ \>\> zookeeper.properties\n”;  
> command = command + “zookeeper-server-start zookeeper.properties &\n”;  
> }  
> command = command + “echo ‘’ \> /etc/confluent/docker/ensure \n”;  
> command = command + “/etc/confluent/docker/run \n”;  
> this.withCommand(new String{“sh”, “-c”, command});  
> }  
> protected void containerIsStarted(InspectContainerResponse containerInfo) {  
> try {  
> String brokerAdvertisedListener = this.brokerAdvertisedListener(containerInfo);  
> ExecResult result = this.execInContainer(new String{“kafka-configs”, “–alter”, “–bootstrap-server”, brokerAdvertisedListener, “–entity-type”, “brokers”, “–entity-name”, (String)this.getEnvMap().get(“KAFKA\_BROKER\_ID”), “–add-config”, “advertised.listeners=[” + String.join(“,”, this.getBootstrapServers(), brokerAdvertisedListener) + “]”});  
> if (result.getExitCode() != 0) {  
> throw new IllegalStateException(result.toString());  
> }  
> } catch (Throwable var4) {  
> throw var4;  
> }  
> }  
> protected String brokerAdvertisedListener(InspectContainerResponse containerInfo) {  
> return String.format(“BROKER://%s:%s”, containerInfo.getConfig().getHostName(), “9092”);  
> }  
> }

---

<div class="post-metadata">

**Author:** ![masz](https://avatars.discourse-cdn.com/v4/letter/m/9f8e36/32.png) [@masz](https://community.solace.com/u/masz)\
**Post date:** [October 19, 2022, 6:03pm UTC](https://community.solace.com/t/solace-with-testcontainers-problem-with-ports/1439/4 "2022-10-19T18:03:26Z")

</div>

> Topic can be closed, problem was here:  
> public enum Port {  
> AMQP(5672, “amqp”),  
> MQTT(1883, “tcp”),  
> MQTT\_WEB(8000, “ws”),  
> REST(9000, “http”),  
> SEMP(8080, “http”),  
> SMF(55555, “tcp”),  
> SMF\_TLS(55443, “tcps”),  
> SMF\_WEB(8008, “ws”),  
> SSH(2222, null);  
> private final int containerPort;  
> private final String protocol;  
> Port(int containerPort, String protocol) {  
> this.containerPort = containerPort;  
> this.protocol = protocol;  
> }  
> public int getInternalPort() {  
> return containerPort;  
> }  
> private String getProtocol() {  
> return protocol;  
> }  
> }  
> with port 55443 (after removing that port container started).

---

<div class="post-metadata">

**Author:** ![aditya](https://avatars.discourse-cdn.com/v4/letter/a/df705f/32.png) [@aditya](https://community.solace.com/u/aditya)\
**Post date:** [March 23, 2023, 10:41pm UTC](https://community.solace.com/t/solace-with-testcontainers-problem-with-ports/1439/5 "2023-03-23T22:41:12Z")

</div>

Hi @masz \> , I am getting the similar issue as yours but from the beginning I am not using the 55443 port still I am getting the same issue.  
Please find the below code:  
private static final int SEMP\_PORT = 8080;

> private static final int REST\_PORT = 9000;  
> private static final int MQTT\_WEB\_PORT = 8000;  
> private static final int MQTT\_PORT = 1883;  
> private static final int AMQP\_PORT = 5672;  
> private static final int WEB\_TRANSPORT = 8008;  
> private static final int SMF\_PORT = 55555;  
> ﻿static {  
> LOGGER.info(“Starting Solace PubSub+ Docker Container”);  
> solace = new GenericContainer\<\>(“solace/solace-pubsub-standard:latest”)  
> .withExposedPorts(SMF\_PORT, WEB\_TRANSPORT, AMQP\_PORT, MQTT\_PORT, MQTT\_WEB\_PORT, REST\_PORT, SEMP\_PORT)  
> .withSharedMemorySize(1000000000L).withEnv(“username\_admin\_globalaccesslevel”, ADMIN\_USER)  
> .withEnv(“username\_admin\_password”, ADMIN\_PASSWORD).withEnv(“system\_scaling\_interconnection”, “1200”)  
> .waitingFor(Wait.forListeningPort());  
> solace.start();  
> Please can you check and help me out to resolve this issue.
