Nginx as reverse proxy for Docker-contained Tomcat
Consider the following diagram:
I have a Debian droplet from Digital Ocean where I need to deploy N Java applications inside individual Docker containers running a Tomcat instance.
Each image has the following Dockerfile configuration:
FROM tomcat:jdk8-openjdk
LABEL maintainer="[email protected]"
ADD webapp1.war /usr/local/tomcat/webapps/ #webapp1, webapp2,... webappN
EXPOSE 8080
CMD ["catalina.sh", "run"]
And is built with:
docker build -t webapp1 .
docker build -t webapp2 .
...
Each container is started with the command:
docker run -it -d -p 8081:8080 webapp1
docker run -it -d -p 8082:8080 webapp2
...
Every application works correctly and is accesible through the droplet IP address, port and application name:
http://123.123.123.123:8081/webapp1
http://123.123.123.123:8082/webapp2
...
But I need to use a domain name (without SSL for now):
http://example.com/webapp1
http://example.com/webapp2
...
So I'm using Nginx as reverse proxy to achieve this. The following is the Nginx configuration in sites-available
folder I'm using:
default file:
# Default server configuration
#
server {
listen 80 default_server;
listen [::]:80 default_server;
root /var/www/html;
# Add index.php to the list if you are using PHP
index index.html index.htm index.nginx-debian.html;
server_name _;
location / {
try_files $uri $uri/ =404;
}
}
webapp1 file:
# webapp1 configuration
#
server {
listen 80;
server_name example.com;
access_log /var/log/nginx/tomcat-access.log;
error_log /var/log/nginx/tomcat-error.log;
location / {
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://123.123.123.123:8081/;
}
}
webapp2 file:
# webapp2 configuration
#
server {
listen 80;
server_name example.com;
access_log /var/log/nginx/tomcat-access.log;
error_log /var/log/nginx/tomcat-error.log;
location / {
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://123.123.123.123:8082/;
}
}
Here's the problem, when I deployed the first application and made it accesible through the domain name (example.com/webapp1
) it was working fine but an 404 error was produced when I try to access example.com
(my landing page). I decided to solve this problem later and better to try to deploy a second application. It worked, webapp2 was successfully deployed and was accesible through example.com/webapp2
but now both example.com
and example.com/webapp1
are giving an 404 error.
I'm a Nginx and Docker newbie. Please, help.
Solution 1:
In Nginx a server
configuration block defines a single named virtual host. If you define multiple server
blocks for the same domain, there should be a warning in the logs, but a single server
block will be chosen, the others will be ignored.
What you need is multiple location
blocks. So you need a single sites-available/example.com
configuration (symlinked from sites-enabled/example.com
) like this:
server {
listen 80 default_server;
listen [::]:80 default_server;
root /var/www/html;
server_name example.com;
location / {
try_files $uri $uri/ =404;
}
# For each web application
location /webapp1/ {
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass http://192.0.2.1:8081;
}
}
Remark: the X-Forwarded-For
and X-Forwarded-Proto
headers have no effect on Tomcat, unless you add:
<Valve className="org.apache.catalina.valves.RemoteIpValve" />
to the Tomcat <Host>
configuration.