Running multiple dev projects in docker containers with nginx-proxy - nginx

As I understand a docker-compose file, using the docker-compose up command, loads the images and starts the containers. Conversely using a Dockerfile file with the docker build command creates the image only. I think I am missing something here as things aren't working as I'd like.
Following the bitnami/wordpress instructions I got an install running fine using docker-compose up d. Can then access via localhost:81
version: '2'
services:
mariadb:
image: bitnami/mariadb:latest
volumes:
- /path/to/mariadb-persistence:/bitnami/mariadb
wordpress:
image: bitnami/wordpress:latest
depends_on:
- mariadb
ports:
- '81:80'
- '443:443'
volumes:
- ./wordpress-persistence:/bitnami/wordpress
- ./apache-persistence:/bitnami/apache
- ./php-persistence:/bitnami/php
Because I want to be able to access this as domain.com.dev, I looked at implementing nginx-proxy. Following the instructions there, and with some inspiration from Docker nginx-proxy : proxy between containers, I came up with the following:
version: '2'
services:
nginx-proxy:
image: jwilder/nginx-proxy
container_name: nginx-proxy
restart: always
ports:
- "88:80"
volumes:
- "/var/run/docker.sock:/tmp/docker.sock:ro"
mariadb:
image: bitnami/mariadb:latest
volumes:
- //c/websites/domain_com/mariadb-persistence:/bitnami/mariadb
domain.com.dev:
image: bitnami/wordpress:latest
depends_on:
- mariadb
ports:
- '81:80'
environment:
- VIRTUAL_HOST=domain.com.dev
volumes:
- //c/websites/domain_com/wordpress-persistence:/bitnami/wordpress
- //c/websites/domain_com/apache-persistence:/bitnami/apache
- //c/websites/domain_com/php-persistence:/bitnami/php
Running docker-compose up -d with this appears to complete without error. However when I access domain.com.dev in a browser, I get a default Index of / page, which suggests I somehow got partway there but not all the way. Looking at the local folders, they get created but it seems like the wordpress-persistence does not get populated, which could explain the default view in the browser.
Any thoughts on why this isn't coming up as expected? Something obvious I missed?

1) For the first approach, you need "to finish" the configuration.
If you don't have a running webserver (nginx, apache, etc.) (on port 80) - just change the port from 81 to 80:
ports:
- '80:80'
- '443:443'
and add the record "127.0.0.1 domain.com.dev" to your hosts file (/etc/hosts in linux).
P.S. you may change port from 88 to 80 at the second approach - it will work without changing hosts file
If you have a running wevserver on port 80 - then it is needed to you proxy directives at virtualhost config file. Here is an example:
server {
listen 80 default_server;
server_name _;
include expires.conf;
location / {
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_pass http://172.17.0.1:81;
proxy_http_version 1.1;
}
}
2) The second approach is usually used with dnsmasq configuration.
Use this and this links to get more detailed information and examples of configuration.

Related

FastAPI served through NGINX with gunicorn and docker compose

I have a FastAPI API that I want to serve using gunicorn, nginx and docker compose.
I manage to make the FastApi and Gunicorn work with docker compose, now I add nginx. But I cannot manage to make it work. When I do curl http://localhost:80 I get this messsage: If you see this page, the nginx web server is successfully installed and working. Further configuration is required.
So this is my docker compose file:
version: '3.8'
services:
web:
build:
dockerfile: Dockerfile.prod
context: .
command: gunicorn main:app --bind 0.0.0.0:8000 --worker-class uvicorn.workers.UvicornWorker
expose:
- 8000
env_file:
- ./.env.prod
nginx:
build:
dockerfile: Dockerfile.prod
context: ./nginx
ports:
- 1337:80
depends_on:
- web
On this one, if I set ports to 80:80 I get an error when the image is composed: Error starting userland proxy: listen tcp4 0.0.0.0:80: bind: address already in use, which I don't know why.
If I put [some random number]:80 (e.g. 1337:80) then the docker build works, but I get the If you see this page, the nginx web server is successfully installed but... error message state before. I think 1337 is not where nginx is listening, and that's why.
This is my nginx conf file:
upstream platic_service {
server web:8000;
}
server {
listen 80;
location / {
proxy_pass http://platic_service;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_redirect off;
}
I tried to change it to listen to 8080 but does not work.
What am I doing wrong?

Properly mount Flask app at location using Nginx reverse proxy

I have a Flask app, which runs inside a Docker container and should be exposed under a specific URL: myserver.com/mylocation. I want to use another container running Nginx as a reverse proxy to achieve the routing. I am following an awesome tutorial that got me quite far already.
My Nginx-config (the relevant part) reads:
server {
server_name myserver.com;
location /mylocation {
proxy_pass http://myapp:5000;
proxy_set_header Host $host;
rewrite ^/mylocation(.*)$ $1 break;
}
}
My docker-compose.yml reads:
version: '2'
services:
nginx:
image: nginx:latest
container_name: production_nginx
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
ports:
- 80:80
- 443:443
myapp:
build: .
image: app_image
container_name: app_container
expose:
- "5000"
Now, when I run this, I successfully get my applications' index.html from myserver.com/mylocation, but subsequent requests (the CSS, JS etc) are being fired at myserver.com without the location part (/mylocation), and so Nginx does not route them to the container and they 404. The references to CSS, JS and such are all relative, they do not (and should not) contain the server name and location.
How can I achieve this? Am I missing something in my NGinx config that would let the app know it should run at /mylocation?

Issue with setting up Nginx with multiple Docker containers

Currently I want to setup one server that has a Docker WordPress and Nginx that serves as a proxy in front. I would like in future to be able have multiple WordPress, NodeJS, ROR, etc, sitting behind this Nginx proxy.
When ever I try to connect to my server on port 80 I get a 403 forbidden.
I am able to build a Docker WordPress image and can connect to it on port 8080 on a remote PC.
Here is the compose.yml for my Docker WordPress:
version: "3.1"
services:
my_wordpress:
image: wordpress
ports:
- 8080:80
environment:
WORDPRESS_DB_PASSWORD: password
WORDPRESS_DB_HOST: my_mysql_wordpress
my_mysql_wordpress:
image: mysql:5.7
environment:
MYSQL_ROOT_PASSWORD: password
This is the part when I try to build a Nginx container I am getting a 403 forbidden.
Nginx DockerFile:
FROM nginx
COPY nginx.conf /etc/nginx/nginx.conf
Nginx compose.yml:
version: "2"
services:
web:
restart: always
image: nginx
ports:
- "80:80"
volumes:
- /path/in/vm/www:/usr/share/nginx/html
external_links:
- mywordpress_wordpress_1:mywordpress
networks:
default:
external:
name: mywordpress_default
Nginx nginx.conf:
http {
#...
upstream wordpress {
server mywordpress:8080;
}
#...
server {
listen 80;
server_name 192.168.1.124 test.me;
location / {
proxy_pass http://wordpress/;
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_cache_bypass $http_upgrade;
}
}
}
Now for me it would seem that this most likely has to do with my nginx.conf as I am still able to connect to my WordPress site on port 8080. As well as I stated I am also able to connect to my Nginx proxy and I don't see any errors when it launches.
Is what I'm trying to doing even possible or do I need to have the Nginx application sitting on the OS and not inside a docker container?
You are putting Nginx and Wordpress in 2 different compose files. If you are running then on same machines then
external_links:
- mywordpress_wordpress_1:mywordpress
Above would not work if you are on different machines. Also make sure the external link you are using the correct name by checking docker ps.
Also check the logs of your nginx container to see if it is showing in any error. Because the error log will give a pointer as to why a 403 is being thrown, and it could be that the proxy_pass is not able to connect to your wordpress server because of the way you have configured it.
If you are running these compose files on different machines then instead of external_links use extra_hosts
extra_hosts:
- "mywordpress:<IP of the wordpress machine>"
If I am right, You want to run multiple wordpress docker images and use nginx to reverse proxy to the wordpress instances. In that Use-case, The nginx should sit on your OS and not inside a docker image. That way, the nginx will have the ability to proxy to ports on your OS which are tied to the wordpress containers.

Unable to load balance using Docker, Consul and nginx

What I want to achive is load balancing using this stack: Docker, Docker Compose, Registrator, Consul, Consul Template, NGINX and, finally, a tiny service that prints out "Hello world" in browser. So, at this moment I have a docker-compose.yml file. It looks like so:
version: '2'
services:
accent:
build:
context: ./accent
image: accent
container_name: accent
restart: always
ports:
- 80
consul:
image: gliderlabs/consul-server:latest
container_name: consul
hostname: ${MYHOST}
restart: always
ports:
- 8300:8300
- 8400:8400
- 8500:8500
- 8600:53/udp
command: -advertise ${MYHOST} -data-dir /tmp/consul -bootstrap -client 0.0.0.0
registrator:
image: gliderlabs/registrator:latest
container_name: registrator
hostname: ${MYHOST}
network_mode: host
restart: always
volumes:
- /var/run/docker.sock:/tmp/docker.sock
command: -ip ${MYHOST} consul://${MYHOST}:8500
nginx:
container_name: nginx
image: nginx:latest
restart: always
volumes:
- /etc/nginx
ports:
- 8181:80
consul-template:
container_name: consul-template
build:
context: ./consul-template
network_mode: host
restart: always
volumes_from:
- nginx
volumes:
- /var/run/docker.sock:/tmp/docker.sock
command: -consul=${MYHOST}:8500 -wait=5s -template="/etc/ctmpl/nginx.ctmpl:/etc/nginx/nginx.conf:docker kill -s HUP nginx"
The first service - accent - is that my web service that I need to load balance. When I run this command:
$ docker-compose up
I see that all services start to run and I see no error messages. It looks as if everything is just perfect. When I run
$ docker ps
I see this in the console:
... NAMES STATUS PORTS
consul-template Up 45 seconds
consul Up 56 seconds 0.0.0.0:8300->8300/tcp, 0.0.0.0:8400->8400/tcp, 8301-8302/tcp, 8301-8302/udp, 0.0.0.0:8500->8500/tcp, 8600/tcp, 8600/udp, 0.0.0.0:8600->53/udp
nginx Up 41 seconds 0.0.0.0:8181->80/tcp
registrator Up 56 seconds
accent Up 56 seconds 0.0.0.0:32792->80/tcp
Please, pay attention to the last row and especially to PORTS column. As you can see, this service publishes 32792 port. To check that my web service is achievable I go to 127.0.0.1:32972 on my host machine (the machine where I run docker compose up) and see this in browser:
Hello World
This is exactly what I wanted to see. However, it is not what I finally want. Please, have a look at the output of docker ps command and you will see, that my nginx service published 8181 port. So, my expectation is that when I go to this address - 127.0.0.1:8181 - I will see exactly the same "Hello world" page. However, it is not. In browser I see Bad Gateway error message and in nginx logs I see this error message
nginx | 2017/01/18 06:16:45 [error] 5#5: *5 connect() failed (111: Connection refused) while connecting to upstream, client: 172.18.0.1, server: , request: "GET /favicon.ico HTTP/1.1", upstream: "http://127.0.0.1:32792/index.php", host: "127.0.0.1:8181"
It is really interesting, because nginx does what I expect it to do - upstreams to "http://127.0.0.1:32792/index.php". But I'm not sure why does it fail. By the way, this is how nginx.conf (created automatically with Consul Template) looks like:
worker_processes 1;
events {
worker_connections 1024;
}
http {
sendfile on;
upstream app_servers {
server 127.0.0.1:32792;
}
server {
listen 80;
root /code;
index index.php index.html;
location / {
try_files $uri/ $uri/ /index.php;
}
location ~ \.php$ {
proxy_pass http://app_servers;
proxy_redirect off;
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 $server_name;
}
location ~ /\.ht {
deny all;
}
}
}
I wouldn't change anything, since this nginx.conf looks good to me. Trying to understand why it does not work, I shelled to nginx container and made a couple of commands:
$ curl accent
Hello World
$ curl 127.0.0.1:32972
curl: (7) Failed to connect to 127.0.0.1 port 32972: Connection refused
$ curl accent:32972
curl: (7) Failed to connect to accent port 32972: Connection refused
Again, it is interesting, because nginx container sees my web service under port 80 and not under its published 32972 port. Anyway, at this stage I do not know why it does not work and how to fix it. I just have a guess, that it is somehow connected to the way, how network is configured in docker-compose.yml. I tried various combinations of network_mode: host on accent and nginx service, but to no avail - either accent stops working or nginx or both. So, I need some help.
When you do port binding it publish some port from container (80 in accent e.g.) and some port on your host (random 32792 on host e.g.).Containers in same network as your accent container can access your container port 80 by accent (same as accent:80) due to docker-compose services name resolving. You can access accent:80 from your host with accent:32792. When you are requesting 127.0.0.1:32792 from your nginx container you can access only nginx container 32792 port, not accent. accent:32792 is not correct url from anyway (80 port open on accent, 32792 on host). But 127.0.0.1:32792 should work when you add nginx container to host network. But I noticed that you use incorrect port in curl call. Your accent:80 published to host 32792 but you request 32972.

How to forward upstream from nginx to upstream server

I am trying to reverse-proxy an ejabberd connection manager with nginx in docker.
Following is my docker-compose file
version: '2'
services:
nginx:
image: nginx
ports:
- "80:80"
- "443:443"
depends_on:
- ejabberd
links:
- ejabberd
ejabberd:
image: ejabberd:16.04
depends_on:
- mysql
ports:
- "5280:5280"
links:
- mysql
mysql:
image: mysql:5.6
ports:
- "3306:3306"
The images nginx, ejabberd:16.04 and mysql:5.6 are available in my local docker.
Following is my server config file which is included in the nginx.conf file
upstream ejabberd-server {
server ejabberd:5280;
}
server {
# regular silverstripe things here
# location should match your JabberPage::BOSHUrl
# with a leading slash
listen 80;
#server_name oops.hereim.co
location /http-bind {
# Local ejabberd with http-bind
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://ejabberd-server;
}
}
But when I try to access the url http://192.168.99.102/http-bind
I get the error 404 not found.
Am I missing something in the configuration above?
192.168.99.102 is the IP of my docker machine.
docker-compose exec nginx ping ejabberd
The above command returns a reply.
The upstream has to be setup to host ejabberd as nginx and ejabberd are not on the same ejabberd container.
If you see the docker-compose.yml, the ejabberd and mysql connection works fine and I am able to connect to mysql from ejabberd. But there seems to be some missing piece while connection nginx to ejabberd.
The issue is probably due to an nginx issue. nginx does not pick up .conf files under the /etc/nginx/conf.d directory.
I had to change the file /etc/nginx/sites-enabled/default and enter the location inside that file. This solved my problem for this question.
The next action item is to check why nginx does not read conf file from /etc/nginx/conf.d directory
Looks like your server part in upstream is a bit wrong.
Can you try server 127.0.0.1:5280; instead of server ejabberd:5280; ?

Resources