Nginx Rverse Proxy to Tomcat (simple yes….? NO) - docker

I have created a docker-compose file to spin up both an nginx and tomcat image. I use volumised files such /etc/nginx/nginx.conf and /etc/nginx/conf.d/app.conf
Same for Tomcat but with xml config files and webapps.
Both spin up and run fine… on their own. I can browse to Nginx and get the welcom page and the same for Tomcat on their respective ports, 81/8080.
However I cannot proxy the request to the backend tomcat. I’ll admit, I’m Apache and have been for years but I need to experiment.
My nginx.conf hasnt changed, its still default. I have an app.conf for the tomcat application (below). I do try and CMD mv the default.conf in teh tomcat Dockerfile but it still remains along side my app.conf so that maybe causing the issue?
my app.conf config is here: (apologies, couldnt get the code to output properly)
"server {
listen *:81;
set $allowOriginSite *;
proxy_pass_request_headers on;
proxy_pass_header Set-Cookie;
access_log /var/log/nginx/access.log combined;
error_log /var/log/nginx/error.log error;
# Upload size unlimited
client_max_body_size 0;
location /evf {
proxy_pass http://tomcat:8080;
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
proxy_redirect off;
proxy_buffering off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass_header Set-Cookie;
}
}
tomcat:8080 being the name of the service in my docker-compose file.
Any help would be appreciated!
Thank you,
Craig
docker-compose.yml for reference;
version: '3'
services:
nginx:
build: ./nginx
image: nginx:evf
command: nginx -g "daemon off;"
networks:
- evf
container_name: evf-nginx
volumes:
- ./volumes/config/nginx-evf.conf:/etc/nginx/conf.d/nginx-evf.conf
- ./volumes/config/default.conf.disabled:/etc/nginx/conf.d/default.conf.disabled
ports:
- "81:80"
tomcat:
image: tomcat
working_dir: /usr/local/tomcat
volumes:
- ./volumes/config/tomcat-users.xml:/usr/local/tomcat/conf/tomcat-users.xml
- ./volumes/webapps/EVF.war:/usr/local/tomcat/webapps/EVF.war
networks:
- evf
container_name: evf-tomcat
ports:
- "8080:8080" #expose 8080 externally to test connectivity.
networks:
evf:
Thanks,

In your nginx conf you have listen *:81 but you are exposing port 80 with "81:80".
So eiter expose port 81 with "81:81" or change you nginx config to listen *:80.
If the second option does not work try to replace the original nginx config by changing the volume file in your docker-compose.yml:
volumes:
- ./nginx/nginx-evf.conf:/etc/nginx/conf.d/default.conf

Related

Nginx Reverse proxy for a docker container running at port 80

My docker compose looks like this:
version: '3.2'
services:
mediawiki:
image: mediawiki:lts
nginx:
image: nginx:stable-alpine
depends_on:
- mediawiki
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
ports:
- 80:80
#...
Where mediawiki is a docker container that runs on port 80 in docker and does not appear to have a way to change the port number.
I'm trying to expose mediwiki through ngninx and the nginx config looks like this:
events {
}
http {
server {
listen 80;
location / {
client_max_body_size 2M;
real_ip_header X-Forwarded-For;
real_ip_recursive on;
proxy_pass http://mediawiki:80;
}
}
}
Since both nginx and mediawiki is running at port 80, I can't set portmap mediwiki 80:80.
I've tried mapping it to another port under mediawiki such as 7001:80 and in nginx config replace http://mediawiki:80 with http://mediawiki:7001 but this produces bad gateway error when loading the site url at port 80.
How might I fix this?
Let's have a look at reverse proxy in which case I use.
version: '3.2'
services:
mediawiki:
image: mediawiki:lts
nginx:
build: .
image: A_NEW_NAME:VERSION_TAG
depends_on:
- mediawiki
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
- ./wiki.conf:/etc/sites-available/wiki.conf
ports:
- 80:80
This should be your wiki.conf contents:
server {
listen 80;
server_name THE_DOMAIN_NAME_OF_YOUR_MEDIAWIKI;
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $http_host;
proxy_set_header X-NginX-Proxy true;
proxy_pass http://mediawiki:80;
proxy_redirect off;
# Socket.IO Support
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
And add a Dockerfile in the directory where your docker-compose file is:
FROM nginx:stable-alpine
COPY wiki.conf /etc/sites-available/
RUN cd /etc/sites-enabled/ && ln -s /etc/sites-available/wiki.conf
And keep your nginx.conf as default values, or change some values on your own but do not add any directives to serve wiki.
You can replace THE_DOMAIN_NAME_OF_YOUR_MEDIAWIKI wit the actual domain name. Like if you have media.com and your wiki wants to be accessible at wiki.media.com.
Now you can run docker-compose up -d --build and see the result.
Change the service port for media wiki to 8080, like
8080:80
and
Change the nginx port to 7001 inside the local nginx.conf and
proxy_pass http://mediawiki:8080;
./nginx.conf:/etc/nginx/nginx.conf
So, nginx will run on port 7001 and mediawiki on 80.
version: '3.2'
services:
mediawiki:
image: mediawiki:lts
nginx:
image: nginx:stable-alpine
depends_on:
- mediawiki
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
ports:
- 80:7001
#...
Then access the app at http://mediawiki:80

Nginx container doesn't use nginx.conf unless I restart the container

As the title says, my nginx container is not working as expected unless I restart it. I have several services defined in a docker-compose.yml file that looks like this: reverseproxy is my nginx container, and service-a and service-b are Node.js servers.
version: "3.4"
services:
reverseproxy:
container_name: reverseproxy
build:
context: ./proxy
ports:
- "80:80"
service-a:
container_name: service-a
build:
context: ./service-a
ports:
- "3500:3500"
command: ["yarn", "run", "watch-debug"]
service-b:
container_name: service-b
build:
context: ./service-b
ports:
- "3501:3501"
command: ["yarn", "run", "watch-debug"]
The Dockerfile used to build my reverseproxy service simply removes the default.conf file and then copies the nginx.conf file from my host to the image:
FROM nginx:alpine
RUN rm /etc/nginx/conf.d/default.conf
COPY nginx.conf /etc/nginx/nginx.conf
And my nginx.conf file that gets copied into the image looks like this:
worker_processes 1;
events { worker_connections 1024; }
http {
sendfile on;
server {
listen 80;
location /api/customers {
proxy_pass http://service-a:3500;
proxy_redirect off;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $server_name;
}
location /api/products {
proxy_pass http://service-b:3501;
proxy_redirect off;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $server_name;
}
}
}
When I docker-compose up everything spins up fine, but when I POST to one of my endpoints (for example, localhost:80/api/customers) then nginx responds with a 502. But if I docker container stop reverseproxy and then docker container start reverseproxy, then everything works as expected and I'm able to hit my endpoints with localhost:80.
I was able to docker exec -it reverseproxy /bin/sh and was able to verify that default.conf is gone and nginx.conf was copied over from my host as expected. I have followed the sample configuration from the nginx page on Docker Hub and most tutorials online show a nearly identical set up.
What may be causing this? How could make my nginx revereproxy service work as expected without restarting the container?
Edit: I am using Postman to make my requests localhost:80
#DavidMaze had the correct solution -- thank you!
reverseproxy:
container_name: reverseproxy
build:
context: ./proxy
ports:
- "80:80"
depends_on:
- "service-a"
- "service-b"
Makes sense that it only works as expected on a restarted because the other services were available by then. Just tried it out and it works as expected.

Running two Docker containers (1 reverse proxy nginx, the other a dotnetcore app)

First time using docker-compose. Attempting to set up a Nginx container as a webserver and a container that holds my dotnetcore app. The intention is for nginx to pass the call onto Kestrel. Both images build and run but getting error when accessing "http://localhost:8080":
proxy_1 | 2019/05/12 16:39:45 [error] 6#6: *1 connect() failed (111: Connection refused) while connecting to upstream, client: 172.19.0.1, server: , request: "GET / HTTP/1.1", upstream: "http://172.19.0.2:4000/", host: "localhost:8080"
The project structure is as follows:
Dockersingleproject
Dockersingleproject/ (dotnetcore app)
*app files'
DockerFile
Nginx/
nginx.conf
DockerFile
docker-compose.yml
I am under the impression that the issue is regarding the connection between the web server container and the app container is refusing but I cannot figure out why. Below is the app Dockerfile:
FROM mcr.microsoft.com/dotnet/core/aspnet:2.2-stretch-slim AS base
FROM mcr.microsoft.com/dotnet/core/sdk:2.2-stretch AS build
WORKDIR /Dockersingleproject
COPY bin/Debug/netcoreapp2.2/publish .
ENV ASPNETCORE_URLS http://+:4000
EXPOSE 4000
ENTRYPOINT ["dotnet", "Dockersingleproject.dll"]
The app docker file is exposing port 4000. The nginx.conf:
worker_processes 1;
events { worker_connections 1024; }
http {
sendfile on;
upstream docker-nginx {
server app:4000;
}
server {
listen 8080;
location / {
proxy_pass http://docker-nginx;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection keep-alive;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_cache_bypass $http_upgrade;
proxy_buffers 8 16k; # Buffer pool = 8 buffers of 16k
proxy_buffer_size 16k; # 16k of buffers from pool used for headers
}
}
}
The server is listening on port 8080 and proxies the request to port 4000 on server "app". Which is defined in the docker-compose file:
version: '2'
services:
app:
build:
context: ./Dockersingleproject
dockerfile: Dockerfile
ports:
- "4000:4000"
proxy:
build:
context: ./nginx
dockerfile: Dockerfile
ports:
- "8080:8080"
links:
- app
The app service maps port 4000 requests to 4000 and in my head this should be working.
The IP of the nginx container is: 172.19.0.3
The IP of the app container is: 172.19.0.2
Please let me know where my confusion lies. I am on the point of accusing my PC of being the issue. Any information is appreciated.
Getting Connection refused when accessing the site resulting in a nginx 502 bad gateway
This uses the Microsoft-provided ASP.NET Core sample:
docker-compose.yaml:
version: "3"
services:
app:
image: mcr.microsoft.com/dotnet/core/samples:aspnetapp
expose:
- "80"
proxy:
image: nginx
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
ports:
- "8080:80"
NB
The ASP.NET Core sample runs on :80 and is expose'd
The Nginx container also runs on :80 and is exposed on the host on :8080
nginx.conf:
events {}
http {
server {
listen 80;
location / {
proxy_pass http://app:80;
}
}
}
NB
Nginx listens on :80 because its container requires it
The proxy configuration references the service name (app) on :80
And:
curl \
--silent \
--write-out "%{http_code}" \
--output /dev/null \
http://localhost:8080
200

Docker Compose on ASP.NET Core 2.x and Nginx with HTTPS/SSL

I want to use Nginx as the web server for my ASP.NET Core 2.x project using this tutorial as base. I just omitted the server_name(for multitenancy about to be implemented in the web project). All of HTTP/80 requests will be redirected to HTTPS/443.
I created an ASP.NET Core 2.x with Angular project and enabled "Configure for HTTPS", then added Docker support which it created the default Dockerfile for the project and a project for Docker-compose.
In the Dockerfile, I removed the auto-generated port numbers, instead exposed port 80 and 443:
#EXPOSE 61876
#EXPOSE 44340
EXPOSE 80
EXPOSE 443
Then created a file and named it as nginx.conf:
worker_processes 4;
events { worker_connections 1024; }
http {
sendfile on;
server {
listen 443;
location / {
proxy_pass $scheme://erp.web;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection keep-alive;
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
}
Then modified the docker-compose.yml(version 3.4) into this:
services:
erp.web:
image: ${DOCKER_REGISTRY}erpweb
build:
context: .
dockerfile: Erp.Web/Dockerfile
proxy:
image: nginx:latest
ports:
- 80:80
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
with docker-comspoe.override.yml like this:
services:
erp.web:
environment:
- ASPNETCORE_ENVIRONMENT=Development
- ASPNETCORE_URLS=https://+:443;http://+:80
- ASPNETCORE_HTTPS_PORT=443
ports:
- "80" #"61876:80"
- "443" #"44340:443"
volumes:
- ${APPDATA}/ASP.NET/Https:/root/.aspnet/https:ro
- ${APPDATA}/Microsoft/UserSecrets:/root/.microsoft/usersecrets:ro
When I try to browse https://localhost, it says it can't reach the server. Also when I try to check the list of Docker containers, the Nginx server still uses port 80, while my web app project has these ports:
some-random-port(currently 32771)->80, some-other-random-port(32770 for now)->443

Docker nginx cannot reverse proxy within default network

I'm having problems with nginx reverse proxying as a docker container. My question is about how to correctly proxy pass nginx in a default docker network?
Here's my docker-compose.yml (unnecessary details omitted for brevity)
version: '3'
networks:
nginx_default:
external: true
services:
db:
image: postgres:10.2
ports:
- "5432:5432"
environment: ...
postgrest:
image: postgrest/postgrest
ports:
- "3000:3000"
environment: ...
nginx:
restart: always
image: nginx:latest
ports:
- "8080:80"
volumes:
- ./nginx/nginx.conf:/etc/nginx/sites-enabled/ruler
command: [nginx-debug, '-g', 'daemon off;']
webapp:
build:
context: "./"
dockerfile: Dockerfile.dev
volumes: ...
ports:
- "3001:3001"
environment: ...
Here's my nginx.conf
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
listen 80;
server_name _;
gzip on;
gzip_proxied any;
gzip_types text/plain text/xml text/css application/x-javascript;
gzip_vary on;
gzip_disable "MSIE [1-6]\.(?!.*SV1)";
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log warn;
location / {
try_files $uri #node;
}
location /api/ {
try_files $uri #postgrest;
}
location #node {
proxy_pass http://webapp:3001;
proxy_redirect off;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_cache_bypass $http_upgrade;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_cache_bypass $http_cache_control;
add_header X-Proxy-Cache $upstream_cache_status;
}
location #postgrest {
proxy_pass http://postgrest:3000;
proxy_http_version 1.1;
default_type application/json;
proxy_set_header Connection "";
proxy_hide_header Content-Location;
add_header Content-Location /api/$upstream_http_content_location;
}
}
And my Dockerfile.dev
FROM node:8.9
WORKDIR /client
CMD npm run dev -- -p 3001
When I do $ docker-compose up -d everything starts without an error. After that I can successfully do $ curl http://127.0.0.1:3001/ (webapp) and $ curl http://127.0.0.1:3000 (postgrest).
But when I try $ curl http://127.0.0.1:8080/ (nginx should handle here the proxying) I get default nginx welcome page. Also $ curl http://127.0.0.1:8080/api/ is not hitting the API :/
What may be the cause? Using $ docker inspect I see that every container is in the same default network.
Edit: Using $ docker-compose logs seems like the default network is not used at all O_o
docker-compose logs
WARNING: Some networks were defined but are not used by any service: nginx_default
Attaching to ruler_webapp_1, ruler_nginx_1
webapp_1 |
webapp_1 | > ruler# dev /client
webapp_1 | > next "-p" "3001"
webapp_1 |
webapp_1 | > Using external babel configuration
webapp_1 | > Location: "/client/.babelrc"
webapp_1 | DONE Compiled successfully in 1741ms09:04:49
webapp_1 |
My guess is you mapped your local nginx configuration file to the wrong file on the container side. The default configuration file for the nginx image is located at /etc/nginx/conf.d/default.conf so the volume of the nginx container should be:
./nginx/nginx.conf:/etc/nginx/conf.d/default.conf:ro
You can check your configuration file is used correctly by executing:
docker-compose exec nginx nginx -T
Side notes:
Never use the latest tag, because in some time you may face broken compatibility issues. Use fixed version tag 1, 1.13 etc. instead
You don't need to publish ports everywhere, eg. 3000:3000, 3001:3001. Those ports will be accessible internally by containers
Your config is a partial config and not a complete nginx config. So it needs to go inside conf.d inside the container and not on nginx.conf or sites-enabled. So change
volumes:
- ./nginx/nginx.conf:/etc/nginx/sites-enabled/ruler
to
volumes:
- ./nginx/nginx.conf:/etc/nginx/conf.d/default.conf
And now it should start working

Resources