Configuring nginx and docker on EC2 (Jetbrains) - amazon-web-services

I have setup Jetbrains Upsource and Teamcity on the same EC2 instance for evalution purposes. If I expose each container on port 80 seperately, I can reach it from the outside world. I want to know how to setup nginx so that I can reach each container over a subdomain like eg. "upsource.example.aws.com" and "teamcity.example.aws.com". I exposed the containers on ports 8080 and 8111 to the host. Is it even possible to achieve this ? If so, I dont know how to start. I read on ways to host multiple domains on one machine for a node web app though exposing the static context. But i have no idea how to make it work with the preconfigured docker images.
Can this be achieved via nginx conf file ?
If not, do I have to use two instances or is there another possibility within aws ?

Its possible with nginx. You have to use something called reverse proxy.
You can expose both the containers in different ports and redirect to these with the help of the nginx configuration.
For example if you have some containers running in port 8000 and 8001 in 127.0.0.1 you can redirect like this:
location /1 {
proxy_pass http://127.0.0.1:8000;
}
location /2 {
proxy_pass http://127.0.0.1:8001;
}
Updated Answer
You need to have 3 containers. The nginx server should be running in port 80. The other two containers will host the sites in say port 8000 (upsource.example.aws.com) and port 8111(teamcity.example.aws.com).
Update the configuration file with the location settings as shown above. Make sure that location / forwards to port 8000 and location /teamcity forwards to port 8111 in your host. More details on how to configure nginx is on the docker hub.
Working
When you go to blabla.com the nginx sever forwards it to port 8000 and when you go to blabla.com/teamcity its goes to port 8111.

Related

Nginx Proxy Manager and django with nginx

I have a stack Django+Gunicorn+nginx running in docker containers. It is accessible from outside by domain and Port, like web.example.com:1300 . Also, there is Nginx Proxy Manager (NPM) running (uses ports 80 and 443) and succesfully managing some other resources (for example nextcloud). But it doesn't proxy to my django project at port 1300, shows "502 Bad Gateway".
In the Proxy Hosts of NPM I've added config:
domain names: web.example.com
Forward Hostname / IP: nginx_docker_container_name (this way it works with other resources)
Forward Port: 1300
Other settings: tried multiple combinations without success (like with and without SSL certificates etc.)
Is it possible to proxy using NPM?
Sorry if I missed to write some information, actually I do not know what else to state.
I managed to solve the problem myself.
So, nginx in docker container serves web-site with static pages. Nginx proxy manager proxying htpp protocol to nginx and secures communication (and also works from docker container in my set-up).
My mistake was that I didn't connect those docker containers by virtual network.
Ones I put them into one network - everything works.
Then I unpublished nginx port (1300).
NPM proxy settings are "standard", e.g. no "custom location" and nothing in "Advanced" tab. Just "Forward Hostname / IP" is docker container tag and "Forward Port" is nginx port it listens to (80 by default).
With WhiteNoise , you don't need to configure nginx for django static files
❤️❤️❤️

Using an Nginx container to proxy to a React container on Elastic Beanstalk with docker-compose: is that a valid approach?

I'm hoping for some general feedback on my approach to trying to get a multi-container app up on Elastic Beanstalk via docker-compose (choosing "docker running on 64bit amazon linux 2" as the platform). Two main questions:
`
Am I right that Elastic Beanstalk listens on port 80 by default when we use docker-compose, and so we need to treat port 80 as the entry point to our application? (reasons for thinking so below)
I'm using an nginx container (listening on port 80 of the host machine) to route traffic to my front end container (which talks to a back end container). Is that approach approach to getting multiple containers running on EB valid? Or is there some other much more common/straighforward way of doing this, with docker-compose? (Something like, "yes! that's a valid way to do this," or "no, you are going about this the totally wrong way, go in this other direction" would be helpful)
Why Elastic Beanstalk instead of ECS? I'm just trying to understand the basic functionality of Elastic Beanstalk first.
More context:
I have three containers: 1) a react front end, 2) an express back end, and 3) an nginx proxy. Why did I add nginx? Because it's my understanding that Elastic Beanstalk sets the proxy server configuration to none when you use docker-compose (see here, under "Environments with Docker Compose"), so what we have to do is get nginx to listen on the default point of entry for an Elastic Beanstalk app, port 80, and then forward requests to other containers on the bridge network created by docker-compose. In other words, when you go to the link associated with an EB app, it will default to whatever is listening on port 80. And if that's an Nginx server, you will be routed according to the configuration of the Nginx server.
I'll paste my docker-compose.yml file below, along with my nginx Dockerfile and its default.conf file. At this point, it mostly runs on my local machine (I can get to the front and back end directly on their respective ports), but I still get an error Invalid Host header when I go to localhost:80/, where I should be proxied (by Nginx) to the React app homepage. Any errors noticed would be helpful. But I'm not necessarily looking for a solution to that specific problem. Rather, my main two questions are up above, looking for some confirmation/correction about my general approach.
Thank you!
docker-compose.yml
version: "3"
services:
nginx:
image: mfatigati/shop-proxy
ports:
- "80:80"
depends_on:
- client
server:
image: mfatigati/shop-server-amd
container_name: shop-server
ports:
- "4001:4000"
client:
image: mfatigati/shop-client-amd
container_name: shop-client
depends_on:
- server
ports:
- "3001:3000"
Dockerfile for nginx
FROM nginx
EXPOSE 80
RUN rm -r /usr/share/nginx/html*
COPY configs/default.conf /etc/nginx/conf.d/default.conf
CMD ["nginx", "-g", "daemon off;"]
default.conf for nginx
upstream shop-client {
server shop-client:3001;
}
server {
listen 80;
location / {
proxy_pass http://shop-client;
}
}
I think it might be fine. I have a similar approach on ecs. However, you will need to use nginx to serve as a reverse proxy otherwise you will run into CORS issues as soon as you run it anywhere else then on localhost.
On ecs you have options to run all containers in the same pod or in different ones. If you choose the latter (for better scalabilty, amongst other reasons), you will need to set up discovery service as well.
On Beanstalk there might be options I do not know about, but at least using nginx should be fine.
You can set beanstalk to different ports if you want, but for reverse proxy you will still need something, so I'd just leave it at 80.
EDIT: addition on reverse proxy:
The problem to solve is CORS issues you encounter.
The directive upstream is used for loadbalancing/routing. (see this question and it's answers)
To the general mechanism is to have several locations in your nginx conf that point specific requests to other servers. This way the requests can be done to the same origin (domain, port, scheme), and then nginx will forward it to the servers who then can happily reply.
Something like:
server {
listen 80;
listen [::]:80;
server_name my-app.com;
location /api/ {
proxy_pass http://api-service:8080;
}
location / {
root /usr/share/nginx/html;
index index.html index.htm;
try_files $uri $uri/ /index.html;
}
}
You can have as many locations as necessary. This is very basic, and you might want to look into some other features, but this should be the basic setup.

django-uWSGI-nginx deployment issue: No public access behind VPN and proxy

I am trying to deploy a django application with uWSGI & nginx.
I followed this tutorial to the end and everything seems to be working fine, but for accessing the app from an external IP.
I do not own a domain name yet so my relevant nginx settings look like:
server {
listen 80;
server_name "";
}
Also, I have disabled the firewall:
iptables -S gives:
-P INPUT ACCEPT
-P FORWARD ACCEPT
-P OUTPUT ACCEPT
Now the CentOs 6.7 machine I am deploying on, has no direct access to the internet as it is behind a proxy (i.e. I need to do pip install django --http_proxy=myproxy.mynet:myport for it to work).
Among other things I have tried to use proxy_pass in my nginx configuration. One attempt:
http {
upstream corporate_proxy {
server myproxy.mynet:myport;
}
server {
listen 80;
rewrite_log on;
location / {
proxy_set_header Host "";
proxy_pass http://corporate_proxy;
}
}
}
Finally, let me add that I cannot access the machine from outside the network either, as it is inside a VPN. So in order to ssh onto it, I first need to connect to the VPN (through FortiClient console).
It is not quite clear to me how all this VPN/proxying really works and how it affects the communication between nginx and external requests. Any solutions or ways to further troubleshoot more than welcome!

How to use nginx with docker as a reverse proxy

I have a django app and running it with gunicorn on localhost:8000
I have configs for nginx to use it as a reverse proxy.
upstream django {
# fail_timeout=0 means we always retry an upstream even if it failed
# to return a good HTTP response (in case the Unicorn master nukes a
# single worker for timing out).
server localhost:8000 fail_timeout=0;
}
I know how to expose 80 port and run nginx in container, but I don't understand how to connect gunicorn running on localhost and nginx in container.
You'll need to utilize the IP of the bridge created by docker. There is a good article on Docker explaining this:
https://docs.docker.com/v1.6/articles/networking/
When Docker starts, it creates a virtual interface named docker0 on
the host machine. It randomly chooses an address and subnet from the
private range defined by RFC 1918 that are not in use on the host
machine, and assigns it to docker0.
If we take a look at the IP address assigned to docker0 (sudo ip addr show docker0) we could use this as the IP address to communicate with the host from within a docker container.
upstream django {
# fail_timeout=0 means we always retry an upstream even if it failed
# to return a good HTTP response (in case the Unicorn master nukes a
# single worker for timing out).
server IP_OF_DOCKER0:8000 fail_timeout=0;
}
I haven't tested the above but I believe it should work. If not you may need to bind gunicorn to the docker0 IP as well.
This answer has some good insight into this process as well...
From inside of a Docker container, how do I connect to the localhost of the machine?
A better approach might be "dokerize" the django application too, build a
network between the dokerized nginx and the dockerized django application
then expose the http port from the dockerized nginx to all interfaces.
Here is a good post about this, maybe you can take some hints from it :)

Why does Gunicorn use port 8000/8001 instead of 80?

I busy setting up a development environment for Django Framework using Gunicorn (as Django service) and NGINX (as a Reverse Proxy).
When I look at several tutorials like this one and this one, I see that they use port 8000 and port 8001 (http://127.0.0.1:8000 and http://127.0.0.1:8001). Is there a special reason not to use port 80, like any other webserver?
Port 8000 is often used for radio streaming and malware, so why?
BTW: I am running it using Virtualenv on a Ubuntu 12.04 system.
All ports under 1024 are privileged ports. To bind to a privileged port requires root user permissions and typically you don't want to run gunicorn with root level permissions.
What's done instead is to allow nginx to bind to 127.0.0.1:80 and then proxy requests to port 80 to a non-privileged port like 8000 using an nginx configuration like:
server {
location / {
proxy_pass http://127.0.0.1:8000;
}
}
NGINX listens on port 80 and forwards to Gunicorn. Gunicorn operates on the 127.0.0.1 IP rather than 0.0.0.0, so it isn't listening publicly, and therefore the only way to access the site externally is through port 80.