multiple site on localhost served by nginx without domain name - nginx

I'm on ubuntu 20.04 rpi4 and I like to write some www site for testing.
Is quite simple configure nginx using some server blocks and server_name inside the server blocs to point to some virtual domain not existing and then set this domain to point to localhost in /etc/hosts:
# /etc/hosts
127.0.0.1 adminer
127.0.0.1 pippo
127.0.0.1 pluto
to have some site like this:
http://adminer
http://pippo
http://pluto
But I like to avoid /etc/hosts setting.
what I like is:
http://localhost/adminer
http://localhost/pippo
http://localhost/pluto
...
to point to 3 different site adminer, pippo and pluto.
It is possible?
what configuration have to use?
can I use one server block for one site or have I to use one server block to all 3 sites?
I'm new on nginx ...
best regards,
Leonardo

I just came across the same issue and I used ports to achieve that.
This solution worked for me on a local machine and home network and probably works on any VPS without domain.
WEB SERVER 1
Open your firewall, example port 81
sudo ufw allow 81
Create your 1st web directory
sudo mkdir -p /var/www/web-folder-name1
Create test content in your web-folder
sudo nano /var/www/web-folder-name1/index.html
and paste any content here to test
Hello World 1!
Create a virtual host file in Nginx
sudo nano /etc/nginx/sites-available/web-folder-name1
and paste the following content
server {
listen 81; # the port is important
server_name _; # underscore is ok as you don't have a domain
root /var/www/web-folder-name1;
index index.html;
}
Enable your web server
sudo ln -s /etc/nginx/sites-available/web-folder-name1 /etc/nginx/sites-enabled/
WEB SERVER 2
Open your firewall, example port 82
sudo ufw allow 82
Create your 2nd web directory
sudo mkdir -p /var/www/web-folder-name2
Create test content in your web-folder
sudo nano /var/www/web-folder-name2/index.html
and paste any content here to test
Hello World 2!
Create a virtual host file in Nginx
sudo nano /etc/nginx/sites-available/web-folder-name2
and paste the following content
server {
listen 82;
server_name _;
root /var/www/web-folder-name2;
index index.html;
}
Enable your web server
sudo ln -s /etc/nginx/sites-available/web-folder-name2 /etc/nginx/sites-enabled/
Restart Nginx
sudo systemctl restart nginx
Test in your browser
127.0.0.1:81
127.0.0.1:82
# or
localhost:81
localhost:82
# or if you're on a network
static-ip:81
static-ip:82

Thanks #lotfio.
if server_name is the same cannot be other server blocks using the same server_name, I suppose.
to avoid setting on /etc/hosts we can be do:
on /etc/nginx/sites-available/default:
server {
#... normal default stuff conf
include /etc/nginx/sites-avilable/localhost_adminer.inc;
incluse /etc/nginx/sites-avilable/localhost_pippo.inc;
#...
#... normal default stuff conf
}
if you like to do a reverse proxy on apache2 for adminer like my first try to move from apache2 to nginx you have to configure apache2 to Listen on other port (I choose 8181):
in /etc/nginx/sites-avilable/localhost_adminer.inc
location /adminer/ {
index conf.php;
alias /etc/adminer/;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $host;
proxy_pass http://127.0.0.1:8181/adminer/;
}
(I'm on ubuntu so adminer package is configured to start on /etc/adminer/)
and so on for pippo, pluto sites etc.
best regards,
Leonardo

Related

Nginx Gunicorn socket issue? Unresponsive

I'm trying to deploy a Django project to a AWS Lightsail server.
I followed mostly this tutorial. I added some SSL protocols for additional security.
This projects runs perfectly on my Ubuntu 18.04 VirtualBox with exact same setup and exact same components, same SSL protocols. However on the Lightsail it doesn't respond to the browser request. It will redirect me to https but then will die... I wasn't able to identify any errors in any of the logs. Which leaves me guessing
/etc/systemd/system/webrock.socket:
[Unit]
Description=gunicorn socket
[Socket]
ListenStream=/run/webrock.sock
[Install]
WantedBy=sockets.target
/etc/systemd/system/webrock.service:
[Unit]
Description=gunicorn daemon
Requires=webrock.socket
After=network.target
[Service]
User=ubuntu
Group=www-data
WorkingDirectory=/home/ubuntu/django/webrock
ExecStart=/home/ubuntu/django/webrock/venv/bin/gunicorn \
--access-logfile - \
--workers 3 \
--bind unix:/run/webrock.sock \
core.wsgi:application
[Install]
WantedBy=multi-user.target
/etc/nginx/sites-available/webrock:
server {
listen 443 ssl http2;
listen [::]:443 ssl http2 ipv6only=on;
include snippets/signed.conf; # path to certs
include snippets/params.conf; # cert related params
index index.html index.htm index.nginx-debian.html;
server_name mydomain.com www.mydomain.com; #changed this line by replacing domain name with dummy
location = /favicon.ico {access_log off; log_not_found off;}
location /static/ {
root /home/ubuntu/django/webrock;
}
location / {
include proxy_params;
proxy_pass http://unix:/run/webrock.sock;
try_files $uri $uri/ =404;
}
}
server {
listen 80;
listen [::]:80;
server_name mydomain.com www.mydomain.com; #changed this line by replacing domain name with dummy
return 302 https://$server_name$request_uri;
}
I left the nginx default file alone. Now every time I visit the page by punching in the server IP, I see the nginx default page. When I use the domain name I get redirected to HTTPS, but then... nothing. I assume that there is some disruption between gunicorn and nginx, but I'm not experienced enough to troubleshoot there or solve to solve it.
As I mentioned above, exact the same setup runs flawless on the similar system in my VirtualBox.
I'm very thankful for suggestions and hints.
Update:
I disabled the redirect portion in nginx and made it listen to port 80. It worked. Now I'm trying to figure out how to introduce HTTP2 and port 443 back to the setup. BTW my ufw looks like this:
After two days banging my head against this issue here is the solution.
So Amazon Lightsail has an additional firewall in front of the UFW on the actual server.
You can access Lightsail firewall by clicking on...
Menue of your instance > Manage > Networking
You will see a summarized networking for your instance like IP addresses, Firewall, Loadbalancer. In that firewall you need to add an additional port (In my case HTTPS).
Why would they put an additional firewall in front of UFW beats me.

Error when creating a NGINX reverse proxy on docker and sending a request to website in another container

I am currently trying to create a NGINX reverse proxy server using docker that will accept a request from the web to the proxy server, then redirect the request to a container with the website I want to be online. So i currently have 2 containers, one for the Nginx reverse proxy, and another that contains Nginx with LEMP and my website files. For some reason I am continuously getting a 502 Bad Gateway Error. I've tested the website container separately (directly connecting to the web rather than passing through the proxy) and the website properly showed. In addition I've used 'wget' to test for connectivity in the terminal, and the website container connects properly from everywhere, but when trying to access the Nginx proxy container using 'wget' it also displays a 502 Bad Gateway Error. I'm pretty new to web dev so I appreciate any help, as I might have just missed something simple.
Nginx Reverse Proxy Configuration file
server {
listen 80 default_server;
listen [::]:80 default_server;
# include snippets/snakeoil.conf;
root /var/www/html;
index index.html index.php index.htm index.nginx-debian.html;
server_name 138.197.67.44;
location / {
# First attempt to serve request as file, then
# as directory, then fall back to displaying a 404.
try_files $uri $uri/ =404;
proxy_set_header X-Real-IP $remote_addr;
proxy_pass http://172.17.0.2:80;
}
}
DockerFile for Reverse Proxy
#############################################################
#Dockerfile for creating and configuring a Nginx Reverse Proxy
#Based in Ubuntu 16.04
##############################################################
#Set base image as existing image with nginx configuration (one shown above)
FROM nginxproxyr
#FileName + Author
MAINTAINER NginxProxy Javier
# Update the repository sources lsit RUN apt-get update
#NOTE EVERYTHING IS ALREADY INSTALLED IN BASE IMAGE USED; just required to configure the image
#EXPOSE AND ASSIGN PORTS
#Expose default port
EXPOSE 80
#Give access to the system to reach the script that runs the entrypoint
RUN chmod +x /usr/bin/startup.sh
#Default port to excecute entrypoint
CMD service nginx start
Command to run a container from image created by Dockerfile
sudo docker run -it -p 80:80 -d NginxReverseProxy
When you have two containers I advise you to use docker-compose and make references through service not by ip. Now if you want to make a redirection you are advised to use this image which is quite simple to see how it works.
https://github.com/jwilder/nginx-proxy

nginx proxy_pass and docker - I don't want port number in address bar

On mywebsite.com, I have running docker container with wordpress.
I started it as
docker run -p 8000:80 --name docker-wordpress-nginx -d
and
docker ps
shows
0.0.0.0:8000->80/tcp
and on my host I have nginx running with
server {
listen 80;
...
server_name mywebsite.com www.mywebsite.com;
...
location / {
proxy_pass http://localhost:8000/;
proxy_set_header Host $host;
}
when i go here
mywebsite.com
It brings wordpress index page of my site, but address in browser is now
mywebsite.com:8000
instead of
mywebsite.com
which I expected.
Everything looks as i wanted except that I always get that port number in address
http://mywebsite.com:8000/2015/08/01/hello-world/
Instead, I wanted
http://mywebsite.com/2015/08/01/hello-world/
i mean, in general, instead of
http://mywebsite.com:8000/some_blog/
i want
http://mywebsite.com/some_blog/
Any ideas?

How to configure Docker port mapping to use Nginx as an upstream proxy?

Update II
It's now July 16th, 2015 and things have changed again. I've discovered this automagical container from Jason Wilder: https://github.com/jwilder/nginx-proxy and it solves this problem in about as long as it takes to docker run the container. This is now the solution I'm using to solve this problem.
Update
It's now July of 2015 and things have change drastically with regards to networking Docker containers. There are now many different offerings that solve this problem (in a variety of ways).
You should use this post to gain a basic understanding of the docker --link approach to service discovery, which is about as basic as it gets, works very well, and actually requires less fancy-dancing than most of the other solutions. It is limited in that it's quite difficult to network containers on separate hosts in any given cluster, and containers cannot be restarted once networked, but does offer a quick and relatively easy way to network containers on the same host. It's a good way to get an idea of what the software you'll likely be using to solve this problem is actually doing under the hood.
Additionally, you'll probably want to also check out Docker's nascent network, Hashicorp's consul, Weaveworks weave, Jeff Lindsay's progrium/consul & gliderlabs/registrator, and Google's Kubernetes.
There's also the CoreOS offerings that utilize etcd, fleet, and flannel.
And if you really want to have a party you can spin up a cluster to run Mesosphere, or Deis, or Flynn.
If you're new to networking (like me) then you should get out your reading glasses, pop "Paint The Sky With Stars — The Best of Enya" on the Wi-Hi-Fi, and crack a beer — it's going to be a while before you really understand exactly what it is you're trying to do. Hint: You're trying to implement a Service Discovery Layer in your Cluster Control Plane. It's a very nice way to spend a Saturday night.
It's a lot of fun, but I wish I'd taken the time to educate myself better about networking in general before diving right in. I eventually found a couple posts from the benevolent Digital Ocean Tutorial gods: Introduction to Networking Terminology and Understanding ... Networking. I suggest reading those a few times first before diving in.
Have fun!
Original Post
I can't seem to grasp port mapping for Docker containers. Specifically how to pass requests from Nginx to another container, listening on another port, on the same server.
I've got a Dockerfile for an Nginx container like so:
FROM ubuntu:14.04
MAINTAINER Me <me#myapp.com>
RUN apt-get update && apt-get install -y htop git nginx
ADD sites-enabled/api.myapp.com /etc/nginx/sites-enabled/api.myapp.com
ADD sites-enabled/app.myapp.com /etc/nginx/sites-enabled/app.myapp.com
ADD nginx.conf /etc/nginx/nginx.conf
RUN echo "daemon off;" >> /etc/nginx/nginx.conf
EXPOSE 80 443
CMD ["service", "nginx", "start"]
And then the api.myapp.com config file looks like so:
upstream api_upstream{
server 0.0.0.0:3333;
}
server {
listen 80;
server_name api.myapp.com;
return 301 https://api.myapp.com/$request_uri;
}
server {
listen 443;
server_name api.mypp.com;
location / {
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
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_pass http://api_upstream;
}
}
And then another for app.myapp.com as well.
And then I run:
sudo docker run -p 80:80 -p 443:443 -d --name Nginx myusername/nginx
And it all stands up just fine, but the requests are not getting passed-through to the other containers/ports. And when I ssh into the Nginx container and inspect the logs I see no errors.
Any help?
#T0xicCode's answer is correct, but I thought I would expand on the details since it actually took me about 20 hours to finally get a working solution implemented.
If you're looking to run Nginx in its own container and use it as a reverse proxy to load balance multiple applications on the same server instance then the steps you need to follow are as such:
Link Your Containers
When you docker run your containers, typically by inputting a shell script into User Data, you can declare links to any other running containers. This means that you need to start your containers up in order and only the latter containers can link to the former ones. Like so:
#!/bin/bash
sudo docker run -p 3000:3000 --name API mydockerhub/api
sudo docker run -p 3001:3001 --link API:API --name App mydockerhub/app
sudo docker run -p 80:80 -p 443:443 --link API:API --link App:App --name Nginx mydockerhub/nginx
So in this example, the API container isn't linked to any others, but the
App container is linked to API and Nginx is linked to both API and App.
The result of this is changes to the env vars and the /etc/hosts files that reside within the API and App containers. The results look like so:
/etc/hosts
Running cat /etc/hosts within your Nginx container will produce the following:
172.17.0.5 0fd9a40ab5ec
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.17.0.3 App
172.17.0.2 API
ENV Vars
Running env within your Nginx container will produce the following:
API_PORT=tcp://172.17.0.2:3000
API_PORT_3000_TCP_PROTO=tcp
API_PORT_3000_TCP_PORT=3000
API_PORT_3000_TCP_ADDR=172.17.0.2
APP_PORT=tcp://172.17.0.3:3001
APP_PORT_3001_TCP_PROTO=tcp
APP_PORT_3001_TCP_PORT=3001
APP_PORT_3001_TCP_ADDR=172.17.0.3
I've truncated many of the actual vars, but the above are the key values you need to proxy traffic to your containers.
To obtain a shell to run the above commands within a running container, use the following:
sudo docker exec -i -t Nginx bash
You can see that you now have both /etc/hosts file entries and env vars that contain the local IP address for any of the containers that were linked. So far as I can tell, this is all that happens when you run containers with link options declared. But you can now use this information to configure nginx within your Nginx container.
Configuring Nginx
This is where it gets a little tricky, and there's a couple of options. You can choose to configure your sites to point to an entry in the /etc/hosts file that docker created, or you can utilize the ENV vars and run a string replacement (I used sed) on your nginx.conf and any other conf files that may be in your /etc/nginx/sites-enabled folder to insert the IP values.
OPTION A: Configure Nginx Using ENV Vars
This is the option that I went with because I couldn't get the
/etc/hosts file option to work. I'll be trying Option B soon enough
and update this post with any findings.
The key difference between this option and using the /etc/hosts file option is how you write your Dockerfile to use a shell script as the CMD argument, which in turn handles the string replacement to copy the IP values from ENV to your conf file(s).
Here's the set of configuration files I ended up with:
Dockerfile
FROM ubuntu:14.04
MAINTAINER Your Name <you#myapp.com>
RUN apt-get update && apt-get install -y nano htop git nginx
ADD nginx.conf /etc/nginx/nginx.conf
ADD api.myapp.conf /etc/nginx/sites-enabled/api.myapp.conf
ADD app.myapp.conf /etc/nginx/sites-enabled/app.myapp.conf
ADD Nginx-Startup.sh /etc/nginx/Nginx-Startup.sh
EXPOSE 80 443
CMD ["/bin/bash","/etc/nginx/Nginx-Startup.sh"]
nginx.conf
daemon off;
user www-data;
pid /var/run/nginx.pid;
worker_processes 1;
events {
worker_connections 1024;
}
http {
# Basic Settings
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 33;
types_hash_max_size 2048;
server_tokens off;
server_names_hash_bucket_size 64;
include /etc/nginx/mime.types;
default_type application/octet-stream;
# Logging Settings
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
# Gzip Settings
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 3;
gzip_buffers 16 8k;
gzip_http_version 1.1;
gzip_types text/plain text/xml text/css application/x-javascript application/json;
gzip_disable "MSIE [1-6]\.(?!.*SV1)";
# Virtual Host Configs
include /etc/nginx/sites-enabled/*;
# Error Page Config
#error_page 403 404 500 502 /srv/Splash;
}
NOTE: It's important to include daemon off; in your nginx.conf file to ensure that your container doesn't exit immediately after launching.
api.myapp.conf
upstream api_upstream{
server APP_IP:3000;
}
server {
listen 80;
server_name api.myapp.com;
return 301 https://api.myapp.com/$request_uri;
}
server {
listen 443;
server_name api.myapp.com;
location / {
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
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_pass http://api_upstream;
}
}
Nginx-Startup.sh
#!/bin/bash
sed -i 's/APP_IP/'"$API_PORT_3000_TCP_ADDR"'/g' /etc/nginx/sites-enabled/api.myapp.com
sed -i 's/APP_IP/'"$APP_PORT_3001_TCP_ADDR"'/g' /etc/nginx/sites-enabled/app.myapp.com
service nginx start
I'll leave it up to you to do your homework about most of the contents of nginx.conf and api.myapp.conf.
The magic happens in Nginx-Startup.sh where we use sed to do string replacement on the APP_IP placeholder that we've written into the upstream block of our api.myapp.conf and app.myapp.conf files.
This ask.ubuntu.com question explains it very nicely:
Find and replace text within a file using commands
GOTCHA
On OSX, sed handles options differently, the -i flag specifically.
On Ubuntu, the -i flag will handle the replacement 'in place'; it
will open the file, change the text, and then 'save over' the same
file.
On OSX, the -i flag requires the file extension you'd like the resulting file to have. If you're working with a file that has no extension you must input '' as the value for the -i flag.
GOTCHA
To use ENV vars within the regex that sed uses to find the string you want to replace you need to wrap the var within double-quotes. So the correct, albeit wonky-looking, syntax is as above.
So docker has launched our container and triggered the Nginx-Startup.sh script to run, which has used sed to change the value APP_IP to the corresponding ENV variable we provided in the sed command. We now have conf files within our /etc/nginx/sites-enabled directory that have the IP addresses from the ENV vars that docker set when starting up the container. Within your api.myapp.conf file you'll see the upstream block has changed to this:
upstream api_upstream{
server 172.0.0.2:3000;
}
The IP address you see may be different, but I've noticed that it's usually 172.0.0.x.
You should now have everything routing appropriately.
GOTCHA
You cannot restart/rerun any containers once you've run the initial instance launch. Docker provides each container with a new IP upon launch and does not seem to re-use any that its used before. So api.myapp.com will get 172.0.0.2 the first time, but then get 172.0.0.4 the next time. But Nginx will have already set the first IP into its conf files, or in its /etc/hosts file, so it won't be able to determine the new IP for api.myapp.com. The solution to this is likely to use CoreOS and its etcd service which, in my limited understanding, acts like a shared ENV for all machines registered into the same CoreOS cluster. This is the next toy I'm going to play with setting up.
OPTION B: Use /etc/hosts File Entries
This should be the quicker, easier way of doing this, but I couldn't get it to work. Ostensibly you just input the value of the /etc/hosts entry into your api.myapp.conf and app.myapp.conf files, but I couldn't get this method to work.
UPDATE:
See #Wes Tod's answer for instructions on how to make this method work.
Here's the attempt that I made in api.myapp.conf:
upstream api_upstream{
server API:3000;
}
Considering that there's an entry in my /etc/hosts file like so: 172.0.0.2 API I figured it would just pull in the value, but it doesn't seem to be.
I also had a couple of ancillary issues with my Elastic Load Balancer sourcing from all AZ's so that may have been the issue when I tried this route. Instead I had to learn how to handle replacing strings in Linux, so that was fun. I'll give this a try in a while and see how it goes.
I tried using the popular Jason Wilder reverse proxy that code-magically works for everyone, and learned that it doesn't work for everyone (ie: me). And I'm brand new to NGINX, and didn't like that I didn't understand the technologies I was trying to use.
Wanted to add my 2 cents, because the discussion above around linking containers together is now dated since it is a deprecated feature. So here's an explanation on how to do it using networks. This answer is a full example of setting up nginx as a reverse proxy to a statically paged website using Docker Compose and nginx configuration.
TL;DR;
Add the services that need to talk to each other onto a predefined network. For a step-by-step discussion on Docker networks, I learned some things here:
https://technologyconversations.com/2016/04/25/docker-networking-and-dns-the-good-the-bad-and-the-ugly/
Define the Network
First of all, we need a network upon which all your backend services can talk on. I called mine web but it can be whatever you want.
docker network create web
Build the App
We'll just do a simple website app. The website is a simple index.html page being served by an nginx container. The content is a mounted volume to the host under a folder content
DockerFile:
FROM nginx
COPY default.conf /etc/nginx/conf.d/default.conf
default.conf
server {
listen 80;
server_name localhost;
location / {
root /var/www/html;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
docker-compose.yml
version: "2"
networks:
mynetwork:
external:
name: web
services:
nginx:
container_name: sample-site
build: .
expose:
- "80"
volumes:
- "./content/:/var/www/html/"
networks:
default: {}
mynetwork:
aliases:
- sample-site
Note that we no longer need port mapping here. We simple expose port 80. This is handy for avoiding port collisions.
Run the App
Fire this website up with
docker-compose up -d
Some fun checks regarding the dns mappings for your container:
docker exec -it sample-site bash
ping sample-site
This ping should work, inside your container.
Build the Proxy
Nginx Reverse Proxy:
Dockerfile
FROM nginx
RUN rm /etc/nginx/conf.d/*
We reset all the virtual host config, since we're going to customize it.
docker-compose.yml
version: "2"
networks:
mynetwork:
external:
name: web
services:
nginx:
container_name: nginx-proxy
build: .
ports:
- "80:80"
- "443:443"
volumes:
- ./conf.d/:/etc/nginx/conf.d/:ro
- ./sites/:/var/www/
networks:
default: {}
mynetwork:
aliases:
- nginx-proxy
Run the Proxy
Fire up the proxy using our trusty
docker-compose up -d
Assuming no issues, then you have two containers running that can talk to each other using their names. Let's test it.
docker exec -it nginx-proxy bash
ping sample-site
ping nginx-proxy
Set up Virtual Host
Last detail is to set up the virtual hosting file so the proxy can direct traffic based on however you want to set up your matching:
sample-site.conf for our virtual hosting config:
server {
listen 80;
listen [::]:80;
server_name my.domain.com;
location / {
proxy_pass http://sample-site;
}
}
Based on how the proxy was set up, you'll need this file stored under your local conf.d folder which we mounted via the volumes declaration in the docker-compose file.
Last but not least, tell nginx to reload it's config.
docker exec nginx-proxy service nginx reload
These sequence of steps is the culmination of hours of pounding head-aches as I struggled with the ever painful 502 Bad Gateway error, and learning nginx for the first time, since most of my experience was with Apache.
This answer is to demonstrate how to kill the 502 Bad Gateway error that results from containers not being able to talk to one another.
I hope this answer saves someone out there hours of pain, since getting containers to talk to each other was really hard to figure out for some reason, despite it being what I expected to be an obvious use-case. But then again, me dumb. And please let me know how I can improve this approach.
Using docker links, you can link the upstream container to the nginx container. An added feature is that docker manages the host file, which means you'll be able to refer to the linked container using a name rather than the potentially random ip.
#gdbj's answer is a great explanation and the most up to date answer. Here's however a simpler approach.
So if you want to redirect all traffic from nginx listening to 80 to another container exposing 8080, minimum configuration can be as little as:
nginx.conf:
server {
listen 80;
location / {
proxy_pass http://client:8080; # this one here
proxy_redirect off;
}
}
docker-compose.yml
version: "2"
services:
entrypoint:
image: some-image-with-nginx
ports:
- "80:80"
links:
- client # will use this one here
client:
image: some-image-with-api
ports:
- "8080:8080"
Docker docs
AJB's "Option B" can be made to work by using the base Ubuntu image and setting up nginx on your own. (It didn't work when I used the Nginx image from Docker Hub.)
Here is the Docker file I used:
FROM ubuntu
RUN apt-get update && apt-get install -y nginx
RUN ln -sf /dev/stdout /var/log/nginx/access.log
RUN ln -sf /dev/stderr /var/log/nginx/error.log
RUN rm -rf /etc/nginx/sites-enabled/default
EXPOSE 80 443
COPY conf/mysite.com /etc/nginx/sites-enabled/mysite.com
CMD ["nginx", "-g", "daemon off;"]
My nginx config (aka: conf/mysite.com):
server {
listen 80 default;
server_name mysite.com;
location / {
proxy_pass http://website;
}
}
upstream website {
server website:3000;
}
And finally, how I start my containers:
$ docker run -dP --name website website
$ docker run -dP --name nginx --link website:website nginx
This got me up and running so my nginx pointed the upstream to the second docker container which exposed port 3000.
Just found an article from Anand Mani Sankar wich shows a simple way of using nginx upstream proxy with docker composer.
Basically one must configure the instance linking and ports at the docker-compose file and update upstream at nginx.conf accordingly.

How to test nginx subdomains on localhost

I want to test nginx subdomains before uploading config to the server. Can i test it on localhost? I try
server {
listen 80;
server_name localhost;
location / {
proxy_pass http://localhost:8080;
}
}
server {
listen 80;
server_name sub.localhost;
location / {
proxy_pass http://localhost:8080/sub;
}
}
And it does not work. Shoulld i change my hosts file in order to make it work? Also, after uploading site to the server should i change DNS records and add sub.mydomain.com?
Yes, add '127.0.0.1 sub.localhost' to your hosts file. That sub has to be resolved somehow. That should work.
Then once you're ready to go to the net, yes, add an a or cname record for the subdomain sub.
When I use proxy_pass I also include the proxy.conf from nginx.
http://wiki.nginx.org/HttpProxyModule
In Linux based OS just to edit as sudo /etc/hosts file and change 127.0.0.1 localhost to 127.0.0.1 *.localhost.
So at /etc/nginx/sites-enabled/<environment>/<your_project_name> edit server_name key as <subdomain>.localhost.
Reload nginx and networking service.
$ sudo service nginx reload
$ sudo service networking reload
And then try http://<subdomain>.localhost at url bar.
It works for me.
UPDATE
In my opinion, a better solution is creating a virtual server that only responds if subdomain doesn’t exist, at /etc/nginx/sites-enabled/development/default, as default server (remember that you can define only one server as default).
server {
listen 80 default_server;
root /var/www/html/errors/404;
server_name *.localhost *.<host-name>;
location / {
index subdomain.html;
}
}
Make sure that in nginx.conf (generally at /etc/nginx/nginx.conf) contain include /etc/nginx/sites-enabled/**/*; to this virtual server work. If not, put it and then run $ sudo service nginx reload.
In this case isn't necessary put *.localhost in /etc/hosts, but only localhost.
For your public webserver with its own domain name, you just need to add a Canonical name using a CNAME record in your DNS configuration:
CNAME * example.com.
Once this is done, set your nginx setting
server_name *.example.com example.com;
In your local setup you can keep the same configuration for nginx but unless you have a local DNS setup, you will have to edit your /etc/hosts file and add each subdomain manually. wildcards don't work in the /etc/hosts file.
127.0.0.1 abc.example.com def.example.com ghi.example.com
It is generally recommended to use .local as the namespace for your local domains.
With an Nginx configuration like shown by the OP, all that is needed is to configure the local DNS resolution. I run Linux containers on a VM with a local DHCP IP but test them on Windows 10 browsers.
The DNS configuration can be done by editing "C:\Windows\System32\drivers\etc\hosts" as Administrator.
192.168.100.50 sub.example.local
192.168.100.50 example.local
Of course, use 127.0.0.1 or other appropriate IP as needed.

Resources