Using Dockerized Apache as a Reverse Proxy for Java

I recently was working on a project in an effort to replace a legacy development environment. Our dev environment had simply grown to require a multitude of items including ElasticSearch, DynamoDB, Apache, and MySQL. For Apache and MySQL the old environment was using a XAMPP stack which I’ve commonly used in other development environments in the past. The other components were previously installed using homebrew and required at least half a day for a dev to get their environment ready to run the application. Docker with Docker Compose seemed liked an easy enough solution for this as there are supported containers for each of the services listed above that make this easy to setup with minimal effort. Creating scripts within repos to load development data would also greatly decrease the setup time for a developer to be setup and productive on a project.

One of the biggest sticking points though was the Apache reverse proxy to Tomcat. During application development the Java application is run from within IntelliJ so that the code can be live edited and there are other services and reasons outside the scope of this blog for needing to use Apache to proxy calls on 80 and 443 back to the application on 8080. The challenge is you can map localhost 80 and localhost 443 to the container no problem, but getting back from the Apache container to Java proved to be somewhat of a challenge as the localhost or referred to the container itself not the host.

Please note the solution below may not be optimal for everyone, relies on the users being on MacOS and using the interface en0 (this should be whatever your default network connection is).

To get around this my teammate and I discovered that you can map back using your host machine’s private IPv4 address however this is problematic as it would require modifying the container and it can change from time to time. After some experimenting we found that the simplest way to to get this to work was to add the following environemnt variable to your docker-compose.yml

Next you will need to make sure your Apache container’s vhost file has a ProxyPass directive that includes this environment variable, this may look something like this:
ProxyPass / http://${MYIP}:8080/
ProxyPassReverse / http://${MYIP}:8080/

Next you will need to create a build script that sets the value to something. Then you’ll need a startup script that starts the docker-compose with a valid IP address.
The build script looks something like this:
MYIP=x docker-compose build --no-cache

The startup script looks something like this:
MYIP=$(ifconfig | grep -C5 en0 | grep inet | grep -v inet6 | awk ‘{print $2}’) docker-compose up -d ${1}