I'm using a nginx container with docker lihe proxy server. The real function is redirect the request from http://127.0.0.1:7003 to my asp .net rest app with expose port in 5000.
So I have been investigating where is the sintaxys error and what is happening.
nginx-container | 2020/01/28 08:34:06 [emerg] 1#1: unknown directive "events" in /etc/nginx/conf.d/Local.Project.Core.conf:1
nginx-container | nginx: [emerg] unknown directive "server" in /etc/nginx/conf.d/Local.Project.Core.conf:1
So there is my nginx Dockerfile:
FROM nginx:latest
# Copy virtual hosts config
RUN rm /etc/nginx/conf.d/default.conf
COPY ./wwwroot/config/Local.Project.Core.conf /etc/nginx/conf.d/
My docker compose where I put the connexions:
local-project:
image: project-mysql-image
container_name: project-mysql-container
ports:
- 127.0.0.1:7000:80
- 127.0.0.1:7001:433
- 127.0.0.1:7002:5000
expose:
- "5000"
environment:
ASPNETCORE_ENVIRONMENT: Production
ASPNETCORE_URLS: http://+:80;http//+:433;http:+:5000 # Is going to use Kestrel standard 5000 port, only http connection
ASPNETCORE_Kestrel__Certificates__Default__Path: /etc/ssl/certs/Local.Proyect.Core.pfx
ASPNETCORE_Kestrel__Certificates__Default__Password: local
volumes:
- .\wwwroot\cer\Local.Proyect.Core.cer:/etc/ssl/certs/Local.Proyect.Core.pfx
nginx:
image: nginx-image
container_name: nginx-container
ports:
- 127.0.0.1:7003:80
And the most important, the file.conf:
events {
worker_connections 1024;
multi_accept on;
use epoll;
}
http {
include /etc/nginx/sites-enabled/*;
upstrem project-mysql-container { server project-mysql-container:5000; }
server {
listen 80;
root /;
index index.html index.htm index.nginx-debian.html;
server_name *.Local.Project.Core;
location / {
proxy_pass http://project-mysql-container:5000;
}
location /ws/ {
proxy_pass http://project-mysql-container:5000/ws/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
}
}
}
In your nginx configuration, you have upstrem project-mysql-container .... That upstrem should be upstream.
Related
I have a Docker compose file running an application that utilizes NGIX as a reverse proxy. The proxy is running on HTTPS for STIG Manager and Keycloak but the additional container I wish to add is running on a different port that is non-HTTPS.
#1 I want to add additional docker containers behind the proxy.
#2 I want to call the app using a DNS name.
Environment: (The server hosting docker)
gsil-docker1.gsil.mil
Compose File:
version: '3.7'
services:
nginx:
# image: nginx:1.23.1
# alternative image from Ironbank
image: registry1.dso.mil/ironbank/opensource/nginx/nginx:1.23.1
volumes:
- ./nginx/nginx.conf:/etc/nginx/nginx.conf
- ./certs/localhost/localhost.crt:/etc/nginx/cert.pem
- ./certs/localhost/localhost.key:/etc/nginx/privkey.pem
- ./certs/dod/Certificates_PKCS7_v5.9_DoD.pem.pem:/etc/nginx/dod-certs.pem
- ./nginx/index.html:/usr/share/nginx/html/index.html
ports:
- "443:443"
keycloak:
# image: quay.io/keycloak/keycloak:19.0.2
# alternative image from Ironbank
image: registry1.dso.mil/ironbank/opensource/keycloak/keycloak:19.0.2
environment:
- KEYCLOAK_ADMIN=admin
- KEYCLOAK_ADMIN_PASSWORD=Pa55w0rd
- KC_PROXY=edge
- KC_HOSTNAME_URL=https://localhost/kc/
- KC_HOSTNAME_ADMIN_URL=https://localhost/kc/
- KC_SPI_X509CERT_LOOKUP_PROVIDER=nginx
- KC_SPI_X509CERT_LOOKUP_NGINX_SSL_CLIENT_CERT=SSL-CLIENT-CERT
- KC_SPI_TRUSTSTORE_FILE_FILE=/tmp/truststore.p12
- KC_SPI_TRUSTSTORE_FILE_PASSWORD=password
command: start --import-realm
volumes:
- ./certs/dod/Certificates_PKCS7_v5.9_DoD.pem.p12:/tmp/truststore.p12
- ./kc/stigman_realm.json:/opt/keycloak/data/import/stigman_realm.json
- ./kc/create-x509-user.jar:/opt/keycloak/providers/create-x509-user.jar
# uncomment below to persist Keycloak data
# - ./kc/h2:/opt/keycloak/data/h2
stigman:
# image: nuwcdivnpt/stig-manager:1.2.20
# alternative image based on Ironbank Node.js
image: nuwcdivnpt/stig-manager:latest-ironbank
environment:
- STIGMAN_OIDC_PROVIDER=http://keycloak:8080/realms/stigman
- STIGMAN_CLIENT_OIDC_PROVIDER=https://localhost/kc/realms/stigman
- STIGMAN_CLASSIFICATION=U
- STIGMAN_DB_HOST=mysql
- STIGMAN_DB_USER=stigman
- STIGMAN_DB_PASSWORD=stigmanpw
# uncomment below to fetch current STIG library from DISA and import it
# - STIGMAN_INIT_IMPORT_STIGS=true
init: true
mysql:
# image: mysql:8.0.21
# alternative image from Ironbank
image: registry1.dso.mil/ironbank/opensource/mysql/mysql8:8.0.31
environment:
- MYSQL_ROOT_PASSWORD=rootpw
- MYSQL_USER=stigman
- MYSQL_DATABASE=stigman
- MYSQL_PASSWORD=stigmanpw
# uncomment below to persist MySQL data
volumes:
- ./mysql-data:/var/lib/mysql
Nginx Config:
events {
worker_connections 4096; ## Default: 1024
}
pid /var/cache/nginx/nginx.pid;
http {
server {
listen 443 ssl;
server_name localhost;
root /usr/share/nginx/html;
client_max_body_size 100M;
ssl_certificate /etc/nginx/cert.pem;
ssl_certificate_key /etc/nginx/privkey.pem;
ssl_prefer_server_ciphers on;
ssl_client_certificate /etc/nginx/dod-certs.pem;
ssl_verify_client optional;
ssl_verify_depth 4;
error_log /var/log/nginx/error.log debug;
if ($return_unauthorized) { return 496; }
location / {
autoindex on;
ssi on;
}
location /stigman/ {
proxy_pass http://stigman:54000/;
}
location /kc/ {
proxy_pass http://keycloak: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 $host;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-Port $server_port;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header ssl-client-cert $ssl_client_escaped_cert;
proxy_buffer_size 128k;
proxy_buffers 4 256k;
proxy_busy_buffers_size 256k;
}
}
# define which endpoints require mTLS
map_hash_bucket_size 128;
map $uri $secured_url {
default false;
"/kc/realms/stigman/protocol/openid-connect/auth" true;
}
map "$secured_url:$ssl_client_verify" $return_unauthorized {
default 0;
"true:FAILED" 1;
"true:NONE" 1;
"true:" 1;
}
}
I have tried adding settings to my docker-compose and nginx but I was unable to make it work.
docker-compose addition:
networks:
default:
name: grafana_default
external: true
nginx addtion:
server {
listen 80;
server_name grafana.gsil.mil;
location / {
proxy_pass http://grafana.gsil.smil:3000/;
}
}
Additionally, I have created a CNAME DNS entry for grafana.gsil.mil and pointed it to gsil-docker1.gsil.mil
The containers app are all running and I can reach all of them respectively by going to:
gsil-docker1.gsil.mil/stigman
gsil-docker1.gsil.mil/kc
gsil-docker1.gsil.mil:3000
The docker-compose file for grafana:
version: '3.0'
volumes:
grafana-data:
services:
grafana:
container_name: grafana
image: registry1.dso.mil/ironbank/opensource/grafana/grafana:9.3.2
environment:
- grafana.config
restart: always
volumes:
- grafana-data:/var/lib/grafana
ports:
- 3000:3000/tcp
I have done a lot of searching but examples I found tended to show http on nginx with http backend apps. I was struggling to find something that would help pull this all together. Can you have an https proxy with a http backend app or do I need to create certs and make all my backend apps run https?
The issue was simple to fix. I needed to add port 80 to my nginx config in my docker-compose file. NGINX cannot proxy http traffic when listening on https only (so add http).
version: '3.7'
services:
nginx:
ports:
- "443:443"
- "80:80"
My presumptions about these specific items were all correct:
-making docker aware of external networks (when the container you want to add/proxy is not part of the same network)
networks:
default:
name: grafana_default
external: true
-adding DNS CNAME entries was correct.
I have created a CNAME DNS entry for grafana.gsil.mil and pointed it to gsil-docker1.gsil.mil
-the appropriate lines had to be added to nginx.conf for each additional container that you need to add.
server {
listen 80;
server_name grafana.gsil.mil;
location / {
proxy_pass http://grafana.gsil.smil:3000/;
}
}
I created a Github repo weeks ago with Docker Compose, Odoo, PostgreSQL, Certbot, Nginx as a proxy server, and a little bit of PHP stuff (Symfony) -> https://github.com/Inushin/dockerOdooSymfonySSL When I was trying the config I found that NGINX worked as it was supposed to and you get the correct HHTP -> HTTPS redirect, BUT if you put the port 8069, the browser goes to HTTP. One of the solutions should be configured de another VPC, but I was thinking about using this repo for other "minimal VPS services" and not needing another VPC, so... how could I solve this? Maybe from Odoo config? Is something missing in the NGINX conf?
NGINX
#FOR THE ODOO DOMAIN
server {
listen 80;
server_name DOMAIN_ODOO;
server_tokens off;
location / {
return 301 https://$server_name$request_uri;
}
location /.well-known/acme-challenge/ {
root /var/www/certbot;
}
}
server {
listen 443 ssl;
server_name DOMAIN_ODOO;
server_tokens off;
location / {
proxy_pass http://web:8069;
proxy_set_header Host DOMAIN_ODOO;
proxy_set_header X-Forwarded-For $remote_addr;
}
ssl_certificate /etc/letsencrypt/live/DOMAIN_ODOO/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/DOMAIN_ODOO/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
}
docker-compose.yml
nginx:
image: nginx:1.15-alpine
expose:
- "80"
- "443"
ports:
- "80:80"
- "443:443"
networks:
- default
volumes:
- ./data/nginx:/etc/nginx/conf.d/:rw
- ./data/certbot/conf:/etc/letsencrypt/:rw
- ./data/certbotSymfony/conf:/etc/letsencrypt/symfony/:rw
- ./data/certbotSymfony/www:/var/www/certbot/:rw
command: "/bin/sh -c 'while :; do sleep 6h & wait $${!}; nginx -s reload; done & nginx -g \"daemon off;\"'"
web:
image: odoo:13.0
depends_on:
- db
ports:
- "8069:8069/tcp"
volumes:
- web-data:/var/lib/odoo
- ./data/odoo/config:/etc/odoo
- ./data/odoo/addons:/mnt/extra-addons
I am using docker-compose to build containers and to serve the frontend of my website at https:// example.com and the backend at a subdomain, https:// api.example.com. The SSL certificates for both the root and subdomain are working properly, and I can access the live site (static files served by Nginx) at https:// example.com so at least half of the configuration is working properly. The problem occurs when the frontend tries to communicate with the backend. All calls are met with a "No 'Access-Control-Allow-Origin'" 502 Error in the console logs. In the logs of the docker container, this is the error response.
Docker Container Error
2022/03/09 19:01:21 [error] 30#30: *7 connect() failed (111: Connection refused) while connecting
to upstream, client: xxx.xx.xxx.xxx, server: api.example.com, request: "GET /api/services/images/
HTTP/1.1", upstream: "http://127.0.0.1:8000/api/services/images/",
host: "api.example.com", referrer: "https://example.com/"
I think it's likely that something is wrong with my Nginx or docker-compose configuration. When setting the SECURE_SSL_REDIRECT, SECURE_HSTS_INCLUDE_SUBDOMAINS, and the SECURE_HSTS_SECONDS to False or None (in the Django settings) I am able to hit http:// api.example.com:8000/api/services/images/ and get the data I am looking for. So it is running and hooked up, just not taking requests from where I want it to be. I've attached the Nginx configuration and the docker-compose.yml. Please let me know if you need more info, I would greatly appreciate any input, and thanks in advance for the help.
Nginx-custom.conf
# Config for the frontend application under example.com
server {
listen 80;
server_name example.com www.example.com;
if ($host = www.example.com) {
return 301 https://$host$request_uri;
}
if ($host = example.com) {
return 301 https://$host$request_uri;
}
return 404;
}
server {
server_name example.com www.example.com;
index index.html index.htm;
add_header Access-Control-Allow-Origin $http_origin;
add_header Access-Control-Allow-Credentials true;
add_header Access-Control-Allow-Headers $http_access_control_request_headers;
add_header Access-Control-Allow-Methods $http_access_control_request_method;
location / {
root /usr/share/nginx/html;
try_files $uri /index.html =404;
}
listen 443 ssl;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
}
##### Config for the backend server at api.example.com
server {
listen 80;
server_name api.example.com;
return 301 https://$host$request_uri;
}
server {
server_name api.example.com;
add_header Access-Control-Allow-Origin $http_origin;
add_header Access-Control-Allow-Credentials true;
add_header Access-Control-Allow-Headers $http_access_control_request_headers;
add_header Access-Control-Allow-Methods $http_access_control_request_method;
location / {
proxy_pass http://127.0.0.1:8000/; #API Server
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Forwarded-Proto https;
proxy_redirect off;
}
listen 443 ssl;
ssl_certificate /etc/letsencrypt/live/api.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/api.example.com/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
}
Docker-Compose File
version: '3.9'
# services that make up the development env
services:
# DJANGO BACKEND
backend:
container_name: example-backend
restart: unless-stopped
image: example-backend:1.0.1
build:
context: ./backend/src
dockerfile: Dockerfile
command: gunicorn example.wsgi:application --bind 0.0.0.0:8000
ports:
- 8000:8000
environment:
- SECRET_KEY=xxx
- DEBUG=0
- ALLOWED_HOSTS=example.com,api.example.com,xxx.xxx.xxx.x
- DB_HOST=postgres-db
- DB_NAME=xxx
- DB_USER=xxx
- DB_PASS=xxx
- EMAIL_HOST_PASS=xxx
# sets a dependency on the db container and there should be a network connection between the two
networks:
- db-net
- shared-network
links:
- postgres-db:postgres-db
depends_on:
- postgres-db
# POSTGRES DATABASE
postgres-db:
container_name: postgres-db
image: postgres
restart: always
volumes:
- example-data:/var/lib/postgresql/data
ports:
- 5432:5432
environment:
- POSTGRES_DB=exampledb
- POSTGRES_USER=user
- POSTGRES_PASSWORD=pass
networks:
- db-net
# ANGULAR & NGINX FRONTEND
frontend:
container_name: example-frontend
build:
context: ./frontend
ports:
- "80:80"
- "443:443"
networks:
- shared-network
links:
- backend
depends_on:
- backend
networks:
shared-network:
driver: bridge
db-net:
volumes:
example-data:
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'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