Run Camunda Operate dockerized behind an nginx reverse proxy - docker

I've successfully deployed dockerized versions camunda operate, zeebe broker, and elasticsearch. I can access the web ui for camunda operate at localhost:8080. I need to put these behind an existing nginx reverse proxy. My first attempt was to do:
location /operate/ {
proxy_pass http://operate:8080/;
}
Operate is the name of the docker container, and the nginx container is running within the same network. Navigating to https://localhost/operate shows me a blank page with the Camunda Operate title showing. What seems to be happening is the initial /operate call is proxied successfully, but subsequent calls to static resources go to https://localhost/static/some-script.js instead of https://localhost/operate/static/some-script.js
I thought specifying /operate/ instead of /operate in the nginx location would do the trick, but no luck. Any clarification would be appreciated!

Related

Varnish in Docker change backend with no downtime

Setup: [Varnish] <-> [Nginx] <-> [PHP FPM] <-> [PostgreSQL] Varnish, Nginx and PHP FPM run as Docker containers.
When we push new code, we need to update at least the PHP container with the new build. Our CI/CD pipeline also triggers Nginx to restart docker exec -i $CONTAINER_ID_API_NGINX nginx -s reload so it will fetch the (internal) ip of the newly created PHP Container.
However sometimes the Nginx container has to be restarted as well, for example if there are new static assets. In this case we also need to restart Varnish and this is where our troubles lie, and where we have some downtime on our API.
Things we've tried:
1. Starting second Nginx
2. Starting second Varnish
3. Killing first Nginx
4. Killing first Varnish
Problem: The second Varnish Container complains that there are 2 IPs for the backend and goes in a restart cycle until the first Nginx container is shut down.
1. Starting second Nginx
2. Killing first Nginx
3. Starting second Varnish
4. Killing first Varnish
Problem: Before the second varnish is accepting connections, API request still go to the first Varnish instance, it tries to forward them to the first (now killed) Nginx instance
Question: Is there a way to get Varnish to switch it's backend host to the new Nginx container, with or without a restart?
Our VCL file currently contains
backend default {
.host = "api-api";
.port = "80";
}
In an ideal world, we would start a second Nginx instance, Varnish still has the DNS cached to the first Nginx instance, we kill the first Nginx instance and trigger a DNS refresh on the Varnish instance without needing to kill the Varnish container itself.
varnishreload
Reloading the VCL can be done using the varnishreload command.
This command will load a new VCL, compile it, deactivate the previous VCL and activate the newly added one.
Any backend DNS resolution will happen while the new VCL file is parsed and compiled.
The varnishreload command runs multiple varnishadm commands. See https://github.com/varnishcache/pkg-varnish-cache/blob/master/systemd/varnishreload for more information on the code.
You can choose to either run varnishreload inside your container to automate the VCL reload, which also resolves the DNS of your backend endpoint.
varnishadm remote calls
You can also call varnishadm remotely, but that requires some extra measures.
See http://varnish-cache.org/docs/6.0/reference/varnishadm.html for varnishadm docs.
See http://varnish-cache.org/docs/6.0/reference/varnish-cli.html for more information about the Varnish CLI which varnishadm wraps around.

how to deal with changing ips of docker compose containers?

I've setup an app where a nodejs backend has to communicate with a rasa chatbot backend through a react frontend. All services are running through the same docker-compose. Being a docker beginner there are some things I'm not sure about:
communication between host and container is done using the container's ip
browser opening the local react server running on localhost:3000 or 172.22.0.1:3000
browser sending a request to the express backend on localhost:4000 172.22.0.2:4000
however communication between two docker containers is done is the container's name:
rasa server conmmunicating with the rasa custom action server through http://action_server:5055/webhooks
rasa custom action server communicating with the express backend through http://backend_name:4000/users/
my problem is that when I need to contact the rasa backend from my react front end I need to put the rasa docker container's ip which (sometimes) changes upon docker-compose reinitialization. To workaround this I do a docker inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' app_rasa_1 to get the ip and manually change it into the react frontend.
is there a way to avoid changing the ip alltogether and using the container name (or an alias/link) or what would be a way to automate the change of the container's ip in the react frontend (are environment variables updated via a script an option?)
Completely ignore the container-private IP addresses. They're implementation details that have several practical problems, including (as you note) them changing when a container is recreated. (They're also unreachable on non-Linux hosts, or if the browser isn't on the same host as the containers.)
You show the correct patterns in your question. For calls between containers, use the container names as host names (this setup is described more in Networking in Compose. For calls from outside containers, including from browser-based applications, use the host's DNS name or IP address and the first number from the ports: you publish.
If the browser application needs to contact a back-end server, it needs a path to do this. This could be via published ports:, or one of your other components could proxy the request to the service (maybe using the express-http-proxy middleware).
A dedicated container that only proxies to other backend services is also a useful pattern (Docker Nginx Proxy: how to route traffic to different container using path and not hostname includes some examples), particularly since this will let you use path-only URLs like /api or /rasa in your browser application. If the React application is served from http://localhost:8080/, and the main backend is http://localhost:8080/api, then you can just make HTTP requests to /api and they will be interpreted relative to the page's URL. This avoids the hostname problem completely, so long as your reverse proxy has path-based routes to every container you need to directly contact.

Nginx: Proxy to another nginx instance: Gateway time-out

I have two nginx instances that I will call application and main. I have many reasons to do this.
The main instance running in front is reachable. If I replace its proxy_pass directive with return 200;, I get a 200 response. However, whether I return 200; in application, or I try to make it do what it's actually supposed to do (proxy again to a third app), it never receives the request.
The request eventually fails with 504 Gateway Time-out.
There's nothing out of the ordinary in any logs. The docker logs show the exact same output as when it was working just a few days ago, except there is no output for when I made the request, because the request is never received/registered. It basically stops at "startup complete; waiting for requests". So the app never receives the request in the first place when going through the reverse proxy. There's nothing at all in the nginx logs in either of the nginx containers.
Here's a minimal, reproducible example: https://github.com/Audiopolis/MultiServerRepro
I am not able to get the above example working. I randomly did for a little bit on Windows 10 (but not on Ubuntu 20.04), but it's not working any more. Can you see anything wrong with the configuration in the example?
The end goal is to easily add several applications to the same server using non-standard ports being proxied to by one "main" instance of nginx, which selects the appropriate app based on the host name. Note that each application must be capable of running on its own with its own nginx instance as well.
Thanks.
Both your application and main nginx are running in different docker networks. main is mapping ports 80:80 and application is mapping ports 10000:80. The mapping is to the host machine so main can't proxy_pass to application.
There are a lot of ways to solve it but I will suggest 2:
Run main with network: host and remove the port forwarding from main (since it's not needed anymore). NOTE: Network host is working only on linux machines (No windows)
Run both nginx servers on the same docker network and then main can proxy_pass to application using docker network address, which is also mapped to it's docker container name (e.g: proxy_pass application_container_name:80).

AWS Service discovery, nginx and node issue

I am running 2 services in AWS ECS fargate. One is with nginx containers running behind the application load balancer. And the other is running with a node.js application. Node application is running with service discovery and Nginx containers proxy to the "service discovery endpoint" of node application containers.
My issue is :
After scaling up node application containers from 1 to 2. Nginx is unable to send the requests to the newly spawned container. It only sends the request to old containers. After restart/redploy of nginx containers it is able to send the requests to new containers.
I tried with "0" DNS ttl for service discovery endpoint. But facing the same issue.
Nginx does not resolve resolve at runtime if your server is specified as part of an upstream group or in certain other situations, see this SF post for more details. This means that Nginx never becomes aware of new containers being registered for service discovery.
You haven't posted your Nginx config so it's hard to say what you can do there. For proxy_pass directives, some people suggest using variables to force runtime resolution.
Another idea might be to expose a http endpoint from the Nginx container that listens to connections and reloads Nginx config. This endpoint can then be triggered by a lambda when new containers are registered (Lambda is in it's turn triggered by CloudWatch events). Disclaimer: I haven't tried this in practice, but it might work.

Looking for an example docker-compose file to have traefik to reverse proxy both a container and non container service

I want to be able to use traefik so that I can reverse proxy both container and non-container services. And I’d like to be able to use a docker-compose file so it is easily setup and torn down. I thought this would be a common request, but I can’t find a unified example. And since I’m still really new to docker, this is a little outside of my wheelhouse. Ideally the docker-compose file would:
install the traefik container, including authentication so that traefik can be managed with a WebUI
Have traefik use Let’s encrypt to generate and maintain SSL certificates that traefik will use to reverse proxy both docker and non-docker services
install a sample container (like Apache) that will be tagged so traefik will reverse proxy to https://apache.example.com (http automatically redirects)
reverse-proxy a non-container service at http://192.168.1.15:8085 to https://foobar.example.com (http automatically redirects)
I’ve seen plenty of examples on how to use traefik and to tag new containers so that they are reversed proxied, but precious few on how to reverse proxy non-docker services. I’m sure I’m not the only one who would appreciate an example that does both at the same time.

Resources