Nginx Reverse Proxy with Dynamic Containers - docker

I have a reverse proxy with nginx set up using docker compose. It is fully working when I run all services together with docker-compose up. However, I want to be able to run individual containers, and start (docker-compose up service1) and stop them independently from the proxy container. Here is a snippet from my current nginx config:
server {
listen 80;
location /service1/ {
proxy_pass http://service1/;
}
location /service2/ {
proxy_pass http://service2/;
}
}
Right now if I run service1, service2, and the proxy together all is well. However, if I run the proxy and only service2, for example, I get the following error: host not found in upstream "service1" in /etc/nginx/conf.d/default.conf:13. The behavior I want here is to just throw some HTTP error, and when that service does come up to route to it appropriately.
Is there any way to get this behavior?

Your issue is with nginx. It will fail to start if it cannot resolve one of the upstream hostnames.
In your case the docker service name will be unresolvable if the service is not up.
Try one of the solutions here, such as resolving at the location level.
(edit) The below example works for me:
events {
worker_connections 4096;
}
http {
server {
location /service1 {
resolver 127.0.0.11;
set $upstream http://service1:80;
proxy_pass $upstream;
}
location /service2 {
resolver 127.0.0.11;
set $upstream2 http://service2:80;
proxy_pass $upstream2;
}
}
}

Sounds like you need to use load balancing. I believe with load balancing it will attempt to share the load across servers/services. If one goes down, it should automatically use the others.
Example
http {
upstream myapp1 {
server srv1.example.com;
server srv2.example.com;
server srv3.example.com;
}
server {
listen 80;
location / {
proxy_pass http://myapp1;
}
}
}
Docs: http://nginx.org/en/docs/http/load_balancing.html

Related

Docker nginx reverse proxy not load static file

I am working on a project with AWS LIghtsail container and I am facing with the following problem.
I created 3 docker containers:
-NGINX port 80
-NodeJs port 5000
-Cadvisor port 8080
Lightsail container service allows you to have only one port open from which you can reach your resources, for this reason I used nginx proxy pass to make all my containers reachable on port 80.
My problem is that when I try to reach $host/containers it does not load static resources (CSS, JS, images....).
These are my nginx configs
events {}
http {
upstream node {
server ${NODE_HOST}:${NODE_PORT};
}
upstream cad {
server ${CAD_HOST}:${CAD_PORT};
}
server {
listen 80;
#proxy pass nodejs works
location / {
proxy_pass http://node;
}
#proxy pass cadvisor port8080 not work
location /containers/ {
proxy_pass http://cad;
}
}
}
#EV VAR
NGINX_ENVSUBST_OUTPUT_DIR=/etc/nginx
NODE_HOST=node
NODE_PORT=5000
CAD_HOST=cad
CAD_PORT=8080
I was following this AWS official guide (step 5): https://aws.amazon.com/it/getting-started/hands-on/setup-an-nginx-reverse-proxy/
Screenshot
Try:
http {
upstream node {
server ${NODE_HOST}:${NODE_PORT};
}
upstream cad {
server ${CAD_HOST}:${CAD_PORT};
}
server {
listen 80;
location / {
proxy_pass http://node;
}
location #cad {
proxy_pass http://cad;
}
location /docker/ {
alias /cadvisor/docker/;
}
location /containers/ {
alias /cadvisor/containers/;
try_files $uri $uri/ #cad;
}
}
}
and check your logs after

nginx and docker hide port from url

I have a droplet with nginx and docker container that works on port 4001.
I managed to implement only redirect from the main URL to my working container
events {}
http {
server {
listen 80;
server_name 1.1.1.1;
port_in_redirect off;
location / {
return 200 'This is nginx stroke';
}
location ~ /cv {
rewrite ^/cv(.*) http://1.1.1.1:4001;
}
}
}
And when url is http://1.1.1.1/cv me redirects to http://1.1.1.1:4001. How to fix it without port :4001
If i use
location /cv {
proxy_pass http://localhost:4001;
}
In inspect manager i see an empty react project, without my components:
But head is relevant

Docker swarm reverse proxy+load balancing with Nginx

I have a docker compose file with 2 services: joomla and phpmyadmin.
I need a reverse proxy which behaves like below:
path: / --> joomla service
path: /managedb --> phpmyadmin service
server {
listen 80;
server_name localhost;
location / {
proxy_pass http://joomla;
}
location /managedb {
proxy_pass http://phpmyadmin;
}
}
Everthing works well, however I'd need to add load balancing to balance work between my 3 machines in docker swarm.
They all are VM on the same LAN with static IP 192.168.75.11/12/13.
The Nginx way to add load balancing should be the follow:
upstream joomla_app {
server 192.168.75.11;
server 192.168.75.12;
server 192.168.75.13;
}
upstream phpmyadmin_app {
server 192.168.75.11;
server 192.168.75.12;
server 192.168.75.13;
}
server {
listen 80;
server_name localhost;
location / {
proxy_pass http://joomla_app;
}
location /managedb {
proxy_pass http://phpmyadmin_app;
}
}
However, since the only exposed port is the Ngxinx 80 one because i need it as reverse proxy too, the code above is obviously not working.
So how can I add the load balancing in this scenario?
Thank you in advance!
In docker swarm, you don't need own load balancer, it has a built in one. Simply scale your services and that's all. Swarm name resolver will resolve joomla and phpmyadmin either to a virtual ip that will be a swarm lb for that service or if you configure service to work in dnsrr mode, will use a dns round-robin method when resolving servicename-hostname to container ip.
However, if you want to distribute services across nodes in swarm, that's a different thing. In this case, you can set placement restrictions for each service or set them to be "global" instead replicated - see https://docs.docker.com/engine/swarm/services/#control-service-placement

Dockercompose, Nginx, Resolver not working

I use an nginx container with this config:
set $ui http://ui:9000/backend;
resolver 127.0.0.11 valid=5m;
proxy_pass $ui;
This is needed, because the "ui" container wont necessarly be up when nginx starts. This avoids the "host not found in upstream..." error.
But now I get a 404 even when the ui-container is up and running (they are both in the same network defined in the docker-compose.yml). When I proxy pass without the variable, without the resolver and start the ui container first, everything works.
Now I am looking for why docker is failing to resolve it. Could I maybe manually add a fake route to http://ui which gets replaced when the ui-container starts? Where would that be? Or can I fix the resolver?
The answer is like in this post:
https://stackoverflow.com/a/52319161/3093499
Only change is putting the resolver and set variable into the server-body instead of the location.
First you need to make sure that you have the port in the ui backend Dockerfile with EXPOSE 9000. Then you're going to want to have this as your config:
http {
upstream ui {
server ui:9000;
}
server {
# whatever port your nginx reverse proxy is listening on.
listen 80;
location / {
proxy_pass http://ui/backend;
}
}
http
{
server {
ssl_certificate /etc/tls/tls.crt;
ssl_certificate_key /etc/tls/tls.key;
resolver 127.0.0.11;
resolver_timeout 10s;
access_log /var/log/nginx/access_log.log;
location / {
set $upstream_app homer;
set $upstream_port 8080;
set $upstream_proto http;
proxy_pass http://localhost:7001;
}
}
}
i worked too

two docker app container on one nginx

I try to serve 2 web applications that should be powered by hhvm. It is easy to build up one docker image that includes nginx and the default.conf. But now where I will get n apps as microservices I want to test them and share the nginx container as I proceed with others like DB e.g.
So when nginx is externally accessed with hhvm do I have to provide hhvm on this image too? Or can I refer it to the debian where hhvm is already provided? Then, I could store the nginx.conf with something like this:
upstream api.local.io {
server 127.0.0.1:3000;
}
upstream booking.local.io {
server 127.0.0.1:5000;
}
How can I set up a proper nginx container for this?
Yeah, you can create another nginx container with an nginx.conf that is configured similarly to this:
upstream api {
# Assuming this nginx container can access 127.0.0.1:5000
server 127.0.0.1:3000;
server server2.local.io:3000;
}
upstream booking {
# Assuming this nginx container can access 127.0.0.1:5000
server 127.0.0.1:5000;
server server2.local.io:5000;
}
server {
name api.local.io;
location / {
proxy_pass http://api;
}
}
server {
name booking.local.io;
location / {
proxy_pass http://booking;
}
}

Resources