Nginx reverse proxy for Docker containers - docker

I have a problem with reverse proxy to my Docker services. I have a local machine with IP 10.0.0.163 and with Docker stack running on it with nginx and portainer (for this question only they matter).
docker-compose.yml:
...
portainer:
image: portainer/portainer
ports:
- "9000:9000"
volumes:
- "/var/run/docker.sock:/var/run/docker.sock"
- "/mnt/StorageDrive/Portainer:/data"
deploy:
placement:
constraints: [node.role == manager]
networks:
...
- proxy
reverse-proxy:
image: reverseproxy:latest
ports:
- "80:80"
networks:
- proxy
networks:
...
proxy:
nginx.conf:
worker_processes 1; ## Default: 1
events { worker_connections 1024; }
http {
sendfile on;
server {
listen 80;
allow all;
location / {
proxy_pass http://10.0.0.163:9000;
}
}
}
Dockerfile for reverseproxy image:
FROM nginx:alpine
COPY nginx.conf /etc/nginx/nginx.conf
When trying to access 10.0.0.163 I get error 502 and logs from reverseproxy show this:
2017/10/09 07:43:02 [error] 5#5: *1 connect() failed (113: Host is unreachable) while connecting to upstream, client: 10.255.0.2, server: , request: "GET / HTTP/1.1", upstream: "http://10.0.0.163:9000/", host: "10.0.0.163"
10.255.0.2 - - [09/Oct/2017:07:43:02 +0000] "GET / HTTP/1.1" 502 575 "-" "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36"
When typing 10.0.0.163:9000/ into browser - everything works fine. What is the problem? And how can I make it work with this URL
10.0.0.163/portainer/... -> 10.0.0.163:9000/...

Try to change nginx configuration
server {
listen 80;
allow all;
location / {
proxy_pass http://portainer:9000/;
resolver 127.0.0.11;
}
}
portainer is container name defined into your docker-compose.yml file
127.0.0.11 is embedded docker DNS server
Also. Alternative way. You can use jwilder/nginx-proxy instead of your reverse-proxy.

The problem same me.
I resolve below,
# Docker run command
docker run --name portainer --network devops-net -d -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer
# Nginx
location /portainer/ {
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_pass http://portainer:9000/;
}
location /portainer/api/websocket/ {
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_http_version 1.1;
proxy_pass http://portainer:9000/api/websocket/;
}
# Notice
Portainer default port 9000
Open brower >> https://domain-name.dev/portainer
Read more: https://portainer.readthedocs.io/en/stable/faq.html
Work for me. ^____^

Related

Nginx can't find specific location

I'm trying to run django + gunicorn + nginx by using docker-compose.
django and gunicorn now are working correctly and response to request, but, when I try to access to project within nginx (port 80), it can't find my project location.
following are nginx Dockerfile and nginx.conf:
FROM nginx:1.17.4-alpine
RUN rm /etc/nginx/conf.d/default.conf
COPY nginx.conf /etc/nginx/conf.d/
and nginx.conf:
upstream back {
# in docker-compose.yml file, (django+gunicorn) service name is `backend` and is listening on port 8000.
server backend:8000;
}
server {
listen 80;
location /backend {
proxy_pass http://back;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_redirect off;
}
}
Now, gunicorn is listening on port 8000 and responses to requestes. if I go to 127.0.0.1, I see nginx default page. But if I go to 127.0.0.1/backend/, nginx shows me 404 page.
in docker-compose logs it shows me following line:
[error] 6#6: *1 open() "/usr/share/nginx/html/backend" failed (2: No such file or directory), client: 192.168.176.1, server: localhost, request: "GET /backend HTTP/1.1", host: "127.0.0.1" <br>
It seems, nginx are searching for /backend in his folders in usr/share and does not pass request to port 8000.
How can I solve this problem?
UPDATE
this is docker-compose.yml file:
version: '3'
services:
db:
...
redis:
...
backend:
hostname: backend
depends_on:
- db
- redis
volumes:
- ./backend/app/:/opt/
build:
context: .
dockerfile: ./backend/Dockerfile
working_dir: /opt/app/project
command: gunicorn config.wsgi:application --bind 0.0.0.0:8000
env_file:
- ./backend/.env
ports:
- 8000:8000
nginx:
image: nginx
build:
context: .
dockerfile: ./nginx/Dockerfile
ports:
- 80:80
depends_on:
- backend
I'm not very familiar with gunicorn, but your configuration looks basically correct.
When nginx does the proxy_pass, the path /backend is also proxy_pass'ed to your backend-service.
I assume, that your gunicorn does not know how to handle the /backend-path?
Maybe it would help, if you rewrite everything to /:
nginx.conf:
upstream back {
# in docker-compose.yml file, (django+gunicorn) service name is `backend` and is listening on port 8000.
server backend:8000;
}
server {
listen 80;
location /backend {
# # # this rewrites all requests to '/backend' to '/' ...
# # # ... before passing them to your backend-service
rewrite /backend.* / break;
# # #
proxy_pass http://back;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_redirect off;
}
}
I've adapted your docker-compose.yml for easy testing purposes:
docker-compose.yml:
version: '3'
services:
backend:
image: nginx:alpine
hostname: backend
expose:
- 80
nginx:
image: nginx:alpine
ports:
- 8080:80
volumes:
- ./default.conf:/etc/nginx/conf.d/default.conf
default.conf:
upstream back {
# in docker-compose.yml file, (django+gunicorn) service name is `backend` and is listening on port 8000.
server backend:80;
}
server {
listen 80;
location /backend {
rewrite /backend.* / break;
proxy_pass http://back;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_redirect off;
}
}
docker-compose up:
╰─❯ docker-compose up
Starting test_backend_1 ... done
Starting test_nginx_1 ... done
Attaching to test_backend_1, test_nginx_1
backend_1 | 172.21.0.3 - - [03/Apr/2020:11:53:52 +0000] "GET / HTTP/1.0" 200 612 "-" "curl/7.64.1" "172.21.0.1"
nginx_1 | 172.21.0.1 - - [03/Apr/2020:11:53:52 +0000] "GET /backend HTTP/1.1" 200 612 "-" "curl/7.64.1" "-"
curl:
╰─❯ curl localhost:8080/backend
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
body {
width: 35em;
margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif;
}
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
nginx.org.<br/>
Commercial support is available at
nginx.com.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>

Local subdomains using Nginx and Docker Compose

I want to test different subdomains locally, using nginx and docker-compose.
docker-compose.yml:
version: '2'
services:
...
phpmyadmin:
depends_on:
- db
image: phpmyadmin/phpmyadmin
restart: unless-stopped
ports:
- 8081:80
environment:
PMA_HOST: db
MYSQL_ROOT_PASSWORD: p4ssw0rd!
...
nginx:
build: ./backend/nginx
links:
- phpmyadmin
ports:
- "4000:80"
volumes:
- "./backend/nginx/nginx.conf:/etc/nginx/nginx.conf"
nginx.conf:
worker_processes 1;
events { worker_connections 1024; }
http {
sendfile on;
upstream docker-phpmyadmin {
server phpmyadmin:8081;
}
server {
listen 80;
server_name api.example.com;
location / {
proxy_pass http://docker-phpmyadmin;
proxy_redirect 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_set_header X-Forwarded-Host $server_name;
}
}
}
Nginx Dockerfile:
FROM nginx:alpine
COPY ./nginx.conf /etc/nginx/nginx.conf
etc/hosts:
127.0.0.1 example.com
127.0.0.1 api.example.com
127.0.0.1 admin.example.com
When I run my nginx container and I navigate to api.example.com:4000 on my browser I see a 502 Bad Gateway page, and inside the container I get this message:
nginx_1 | 2019/07/27 12:17:00 [error] 6#6: *1 connect() failed (111: Connection refused) while connecting to upstream, client: 172.21.0.1, server: api.example.com, request: "GET / HTTP/1.1", upstream: "http://172.21.0.4:8081/", host: "api.example.com:4000"
I guess that it should work using the port 80 instead of the 4000 but how can I test my configuration locally?
Thanks
I was able to fix it by changing my upstream server port to 80:
upstream docker-phpmyadmin {
server phpmyadmin;
}

Docker Compose with Express.js and Nginx - 502 response

I'm trying to use express.js and nginx as a reverse proxy with Docker. The express app works fine with docker on its own, but when I add nginx I get 502 response. It prints this:
nginx_1 | 2019/03/30 21:14:04 [error] 6#6: *3 connect() failed (111: Connection refused) while connecting to upstream, client: 172.20.0.1, server: localhost, request: "GET / HTTP/1.1", upstream: "http://127.0.0.1:20000/", host: "localhost:21000"
docker-compose.yml
version: '3.3'
services:
app:
image: node:latest
volumes:
- ./app:/usr/src/service/app
working_dir: /usr/src/service/app
command: ["node", "app"]
ports:
- 20000:18000
nginx:
image: nginx:latest
volumes:
- ./nginx/nginx.conf:/etc/nginx/nginx.conf
- ./nginx/error.log:/etc/nginx/error_log.log
- ./nginx/cache/:/etc/nginx/cache
ports:
- 21000:80
nginx.conf
events {
}
http {
upstream upstream_server {
server localhost:20000;
}
server {
listen 127.0.0.1;
listen 80;
server_name localhost;
location / {
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://upstream_server;
break;
}
}
}
Your nginx container & app container are on the same network but not on the same host - hence localhost is not where you'll find your app running.
Try app as the server parameter in upstream - this should resolve to the IP of the app container in the compose network.

Can't access Docker container containing Vue JS front-end app

I'm really hoping that someone can help me as I've been stuck with this issue for over a week. I'm a Docker and Nginx beginner and just can't seem to get my configuration right.
Basically I have 3 Docker containers running - Nginx reverse proxy, Node JS back-end and Vue JS front-end. I have the following vision for the 3-container-system:
localhost/ should send requests to the front-end container
localhost/api/email should send requests to the back-end container (These requests would obviously come from the front-end)
At a later stage, we'd like to add more websites and api's to be served by the reverse proxy
At the moment when I use Postman to send a request to the back-end via localhost/api/email/send, it works 100% and the e-mail is sent as expected but I'm unable to reach my front-end in a browser via localhost.
The error reads:
reverse-proxy | 2018/07/12 14:35:55 [error] 5#5: *4 connect() failed (111: Connection refused) while connecting to upstream, client: 172.18.0.1, server: localhost,
request: "GET / HTTP/1.1", upstream: "http://172.18.0.2:8080/", host: "localhost"
reverse-proxy | 172.18.0.1 - - [12/Jul/2018:14:35:55 +0000] "GET / HTTP/1.1" 502 575 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like
Gecko) Chrome/67.0.3396.99 Safari/537.36"
I'm very desperate and eager to learn at this stage. Please see the attached files and configuration for more information.
Reverse proxy Dockerfile:
FROM nginx:alpine
COPY nginx.conf /etc/nginx/nginx.conf
Back-end Dockerfile:
FROM node:7
WORKDIR /email-api
COPY package.json /e-mail-api
RUN npm install
COPY . .
CMD node server.js
EXPOSE 8082
Front-end Dockerfile:
FROM alpine:3.7
RUN apk add --update nodejs
RUN mkdir -p /var/www/html
WORKDIR /those-devs-website
COPY . .
RUN npm install
RUN npm run build
RUN cp -r dist/* /var/www/html
EXPOSE 8080
nginx.conf:
worker_processes 1;
events { worker_connections 1024; }
http {
sendfile on;
upstream email-api {
server email-api:8082;
}
upstream those-devs-website {
server those-devs-website:8080;
}
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-Host $server_name;
server {
listen 80;
server_name localhost;
location / {
proxy_pass http://those-devs-website;
}
location /api/email/ {
proxy_pass http://email-api;
}
}
}
docker-compose.yml
version: '3'
services:
email-api:
container_name: email-api
ports:
- '8082:80'
image: email-api
those-devs-website:
container_name: those-devs-website
ports:
- '8080:80'
image: those-devs-website
reverse-proxy:
container_name: reverse-proxy
image: reverse-proxy
ports:
- '80:80'
restart: always
Any help, recommendations or input would be greatly appreciated.
If you are hitting the container IP from within other container so you should use port it actually listens to, so use 80 in your nginx.conf instead of 8080.
Published ports will work on interface\s docker interface bridges to.

Dockerized Nginx redirect different subdomains to the same page

Background
I am trying to set up a home server with a bunch of webapps. For now, I am focusing on seafile and a static html page. The server uses Docker and Nginx.
I want to achieve the following behavior:
The address domain-name.eu redirects to the static pages, saying "Welcome to Domain Name".
The address seafile.domain-name.eu redirects to the seafile container.
Problem description
I followed various tutorials on the web on how to set up a docker-compose.yml and the nginx conf to allow nginx to serve different website. I manage to have my seafile working alone behind nginx on the right address, and I manage to have the static page working alone behind nginx on the right address. When I try to mix both, both domain-name.eu and seafile.domain-name.eu serve the static page "Welcome to Domain Name".
Here is my docker-compose.yml:
nginx:
image: nginx
ports:
- 80:80
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
- ./html/:/usr/share/nginx/html
links:
- seafile
seafile:
image: seafileltd/seafile:latest
expose:
- 80
volumes:
- /home/docker/seafile-data:/shared
And my nginx.conf:
http {
upstream seafile {
server seafile;
}
server {
listen 80;
server_name seafile.domain-name.eu;
location /{
proxy_pass http://seafile/;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_cache_bypass $http_upgrade;
}
}
server {
listen 80;
server_name domain-name.eu;
root /usr/share/nginx/html;
index index.html index.htm;
}
}
events {}
When I try to access seafile.domain-name.eu, I receive this log from the nginx container:
nginx_1 | xxx.xxx.xxx.xxx - - [05/Jun/2018:09:44:24 +0000] "GET / HTTP/1.1" 200 22 "http://seafile.domain-name.eu/" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:60.0) Gecko/20100101 Firefox/60.0"
And when I try to access domain-name.eu, I receive this:
nginx_1 | xxx.xxx.xxx.xxx - - [05/Jun/2018:10:07:11 +0000] "GET / HTTP/1.1" 200 22 "-" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:60.0) Gecko/20100101 Firefox/60.0"
So the address is indeed recognized for the seafile, which helped me eliminating a bad configuration of my DNS as a possible cause. Or am I mistaken?
Can anyone help me troubleshooting the problem? 
Thanks.
EDIT: Adding docker ps output:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
b6d018169d76 nginx "nginx -g 'daemon of…" About an hour ago Up About an hour 0.0.0.0:80->80/tcp jarvis-compose_nginx_1
7e701ce7650d seafileltd/seafile:latest "/sbin/my_init -- /s…" About an hour ago Up About an hour 80/tcp jarvis-compose_seafile_1
EDIT 2 : the problem was due to a configuration error (see accepted answer) + a residual redirection from my old registrar that was causing weird behavior. Thanks for the help! 
Have trying this to run on my local. Found that you've mount wrong nginx config file in the container. nginx.conf should mounted on /etc/nginx/conf.d/default.conf, it's the default config to supporting vhost on nginx. Below are the correct setups:
nginx.conf
upstream seafile {
server seafile;
}
server {
listen 80;
server_name seafile.domain-name.eu;
location /{
proxy_pass http://seafile/;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_cache_bypass $http_upgrade;
}
}
server {
listen 80;
server_name domain-name.eu;
root /usr/share/nginx/html;
index index.html index.htm;
}
docker-compose.yml
version: '3'
services:
nginx:
image: nginx
ports:
- 80:80
volumes:
- ./nginx.conf:/etc/nginx/conf.d/default.conf
- ./html/:/usr/share/nginx/html
links:
- seafile
container_name: web
seafile:
image: seafileltd/seafile:latest
expose:
- 80
volumes:
- /home/docker/seafile-data:/shared
container_name: seafile_server

Resources