We have a docker setup (Windows 10, native docker, compose V3) with multiple containers one of which is running Wildfly 10 with JMS subsystem (ActiveMQ). Everything works fine inside the docker NAT (various services use JMS via in-vm or http connectors) but we also need to connect to JMS from the outside docker. We realize JMS connectivity with remote JNDI lookup on JMSConnectionFactory exposed by wildfly. The issue is the connection factory advertises internal IP address of the docker container which is not accessible from the outside.
We have the right ports (actually only one port for http is needed) exposed and accessible via localhost.
Here are some solutions I tried:
- Adding container IP as a second address to Hosts Loopback interface. This in theory should work but it didn't and also feels like a lame solution.
- Make JMS connection factory use host IP as a socket binding. This would be also fine in theory however wildfly needs to actually bind to a given IP and it failed since it couldn’t do it
- Set the network driver for container to host mode but compose complained that there can be only one host network. Not sure what exactly it meant but I didn’t like the idea of losing network separation anyway so I didn’t dig deeper into that
- Make JMS factory advertise a hostname and than play with DNS or /etc/hosts. Whatever I put into standalone.xml as socket binding it anyway gets translated into IP.
Ideally I'd like an elegant, "golden bullet" solution that works on both Windows and Linux but I understand that this might not be achievable.
UPDATE: I found a solution (bit hacky) but I think it should do unless anyone proposes something better.
I created additional JMSConnectionFactory in wildfly (configured in standalone.xml):
<connection-factory name="ExternalConnectionFactory" entries="java:jboss/exported/jms/ExternalConnectionFactory" connectors="external-http-connector"/>
It uses it's own connector
<http-connector name="external-http-connector" socket-binding="external-http" endpoint="http-acceptor"/>
and I use the outbound socket binding, this part is bit hacky by allows me to specify any network address.
<outbound-socket-binding name="external-http">
<remote-destination host="localhost" port="8080"/>
</outbound-socket-binding>
This way if I use ExternalConnectionFactory it advertises the IP accessible from the outside the docker. Obviously the localhost in my example only allows to connect from the host machine but with little scripting magic I should be able to replace it with docker host IP at container creation time.
<socket-binding>
element can contain one or more<client-mapping>
element(s) that seems to be what you want. – Hillard