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.
Related
I am trying to set up docker + gunicorn + angular + nginx environment:
The Angular app should be accessed at http://localhost:4200 - works as expected
the Flask API should be accessed on the same port at http://localhost:4200/api - (111: Connection refused) error
All /api/* requests should be handled by gunicorn, however, for some reason, nginx refuses the connection with error 111.
Nginx cannot connect with gunicorn, see below docker logs:
docker-compose -f docker-compose-prod.yml up --build
...
api_1 | [2022-03-18 18:02:46 +0000] [1] [INFO] Starting gunicorn 20.0.4
api_1 | [2022-03-18 18:02:46 +0000] [1] [DEBUG] Arbiter booted
api_1 | [2022-03-18 18:02:46 +0000] [1] [INFO] Listening at: http://0.0.0.0:5000 (1)
api_1 | [2022-03-18 18:02:46 +0000] [1] [INFO] Using worker: sync
api_1 | [2022-03-18 18:02:46 +0000] [9] [INFO] Booting worker with pid: 9
api_1 | [2022-03-18 18:02:46 +0000] [1] [DEBUG] 1 workers
client_1 | 192.168.32.1 - - [18/Mar/2022:18:03:20 +0000] "GET /api/checkmongo HTTP/1.1" 502 559 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.74 Safari/537.36" "-"
client_1 | 2022/03/18 18:03:20 [error] 23#23: *1 connect() failed (111: Connection refused) while connecting to upstream, client: 192.168.32.1, server: api, request: "GET /api/checkmongo HTTP/1.1", upstream: "http://173.37.145.221:5000/api/checkmongo", host: "localhost:4200"
docker-compose-prod.yml
version: '3.7'
services:
client:
build:
context: ./frontend
dockerfile: Dockerfile-prod
volumes:
- ./frontend:/app
- ./frontend/src:/app/src # for watching files
ports:
- "4200:80"
networks:
- frontend
mongodb:
image: mongo
container_name: mongo
restart: unless-stopped
command: mongod --auth
environment:
MONGO_INITDB_ROOT_USERNAME: "admin"
MONGO_INITDB_ROOT_PASSWORD: "password"
MONGO_INITDB_DATABASE: webapp
MONGODB_DATA_DIR: /data/db
volumes:
- mongodbdata:/data/db
networks:
- backend
api:
build:
context: ./backend
dockerfile: Dockerfile
command: gunicorn --log-level=debug --bind 0.0.0.0:5000 main:app
ports:
- "5000:5000"
environment:
MONGODB_HOST: mongodb
MONGODB_USERNAME: "admin"
MONGODB_PASSWORD: "password"
volumes:
- appdata:/var/www/
depends_on:
- mongodb
networks:
- frontend
- backend
networks:
frontend:
driver: bridge
backend:
driver: bridge
volumes:
mongodbdata:
driver: local
appdata:
driver: local
frontend/Dockerfile-prod
#stage 1
FROM node:17.6.0 as node
WORKDIR /app
COPY . /app
RUN npm install
RUN npm run build --prod
#stage 2
FROM nginx:alpine
COPY --from=node /app/dist/automation /usr/share/nginx/html
RUN rm /etc/nginx/conf.d/default.conf
COPY nginx.conf /etc/nginx/conf.d
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
frontend/nginx.conf
upstream web-app_api {
server api:5000;
}
server {
listen 80;
server_name api;
location /api {
proxy_pass http://web-app_api;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_redirect off;
}
location / {
root /usr/share/nginx/html;
index index.html index.htm;
try_files $uri $uri/ /index.html;
}
}
backend/Dockerfile
# Create our image based on Python 3.8
FROM python:3.8
# Expose ports
EXPOSE 5000
# Tell Python to not generate .pyc
ENV PYTHONDONTWRITEBYTECODE 1
# Turn off buffering
ENV PYTHONUNBUFFERED 1
# Install requirements using pip
ADD req .
RUN python -m pip install -r req
# Set working directory and add our Flask API files
WORKDIR /app
ADD . /app
I have been struggling with this error for many hours - trying to change nginx, gunicorn conf - without success.
EDIT:
Once, I have removed following lines from docker-compose-prod.yml, the error is gone (I don't know why):
depends_on:
- mongodb
It sounds like (at least part of) your problem is that Nginx doesn't strip /api/ from the requests before passing them on. To achieve that, you add a / at the end of the location so it becomes /api/ rather that /api like this
upstream web-app_api {
server api:5000;
}
server {
listen 80;
server_name api;
location /api/ {
proxy_pass http://web-app_api;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_redirect off;
}
location / {
root /usr/share/nginx/html;
index index.html index.htm;
try_files $uri $uri/ /index.html;
}
}
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>
I am trying to create a docker deployable django site with a seperate static Nginx server. This used to work fine, but suddenly stopped working. I now keep getting 502 errors when trying to access the static folder. The Django app is running on a gunicorn server.
This is my nginx.conf
# nginx.default
upstream staticserver {
ip_hash;
server staticserver:9010;
}
server {
location / {
proxy_pass http://127.0.0.1:8010;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location /static {
proxy_pass http://staticserver;
}
listen 9000;
server_name localhost;
}
My docker compose is this
version: '3'
services:
staticserver:
build:
context: .
dockerfile: ./staticserver/Dockerfile
ports:
- "9010:80"
djangoserver:
build:
context: .
dockerfile: Dockerfile
ports:
- "9000:9000"
depends_on:
- staticserver
If I go to 127.0.0.1:9000 I get the django site
If I go to 127.0.0.1:9010 I get the root of the static server
But, if I go to 127.0.0.1/static I get a 502 error.
The logs show entries like these
[error] 10#10: *25 connect() failed (111: Connection refused) while connecting to upstream, client: 172.21.0.1, server: localhost, request: "GET /static HTTP/1.1", upstream: "http://172.21.0.2:9010/static", host: "127.0.0.1:9000"
This seems counterintuitive, as I'd expect it to be http://172.21.0.2:9010/ with the static folder names stripped.
I've tried some of the other answers on relating topics, but so far, it seems it just stopped working. I suspect some issue in the config files that I am simply not aware of, but I can't seem to find my mistake.
Referring to a port on the inner network solved the issue;
upstream staticserver {
ip_hash;
server staticserver;
}
instead of
upstream staticserver {
ip_hash;
server staticserver:9010;
}
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
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. ^____^