Multi port cantainers with nginx-proxy - docker

I'm currently running a container with my web application and it communicates through two ports, for the frontend and backend.
I'm using jwilder/nginx-proxy to serve the applictions.
When I run the docker compose file (which starts the app and the proxy) it gives me a 502 Bad gateway
when I run with only one port it serves that part of the app.
Im passing the port with the "VIRTUAL_PORT=80" is there a way to pass more than one port or if I make a separate container for the Frontend how would I get the proxy to speak to both containers with one request?
In short does jwilder/nginx-proxy support multiport containers, and if not what's the workaround?
Thank in advance!
Docker-compose.yml
reverseproxy:
image: jwilder/nginx-proxy
ports:
- "80:80"
- "8080:8080"
volumes:
- /var/run/docker.sock:/tmp/docker.sock
myapp:
depends_on:
- reverseproxy
build: ./app-files
environment:
- "VIRTUAL_HOST=my-domain.com"
- "VIRTUAL_PORT=80,8080"
expose:
- 80
- 8080

Related

docker-compose Nextcloud Instance behind reverse proxy Bad gateway 502

I want to switch from using the docker run-command to a docker-compose file with my nextcloud instance that runs behind a reverse proxy (jwilder/nginx-proxy).
This is the run command I used to use:
sudo docker run -d -p 8080:80 --expose 80 --expose 443 -e VIRTUAL_HOST=nextcloud.example.com -v nextcloud:/var/www/html --restart=always --name=nextcloud nextcloud:24.0.8
I installed the mariaDB later in the container so that I didn't have to struggle with networking. Also I use the Port 8080 only in my internal network for fast up- and downloading.
This worked quite well, but now I want to create a similar environment with docker-compose:
version: '3.8'
volumes:
nextcloud:
db:
services:
db:
image: mariadb:10.5
restart: always
command: --transaction-isolation=READ-COMMITTED --binlog-format=ROW
volumes:
- db:/var/lib/mysql
environment:
- MYSQL_ROOT_PASSWORD=my-super-strong-password
- MYSQL_PASSWORD=my-other-super-strong-password
- MYSQL_DATABASE=nextcloud
- MYSQL_USER=nextcloud
app:
image: nextcloud:24.0.8
restart: always
ports:
- 8080:80
expose:
- 80
- 443
links:
- db
volumes:
- nextcloud:/var/www/html
environment:
- MYSQL_PASSWORD=my-other-super-strong-password
- MYSQL_DATABASE=nextcloud
- MYSQL_USER=nextcloud
- MYSQL_HOST=db
- PHP_MEMORY_LIMIT=1G
- PHP_UPLOAD_LIMIT=128M
- VIRTUAL_HOST=nextcloud.example.com
The containers are starting successfully and I can use nextcloud in my internal network. But I cannot reach them from my domain. Instead I get a 502 Bad request. The VIRTUAL_HOST redirection seems to work since I'd get a 503 Service Temporarily Unavailable instead.
I think exposing the ports 80 and 443 doesn't work.
I've tried to add a proxy network:
networks:
proxy:
driver: bridge
external: true
and added
networks:
- default
to the db service and
networks:
- default
- proxy
to the app service.
That didn't fixed the problem. Does any of you have an idea what I can try next?
I've tried different ways to expose the ports and tried to create different networks
Nevermind found the problem.
Instead of simply creating an network named proxy, I had to create a new jwilder reverse-proxy service via docker compose with a name, as an example myreverseproxy. In each service I want to make public I needed to name this proxy as:
networks:
- default
- myreverseproxy
Also I had to use the name in the networks service area:
networks:
myreverseproxy:
external: true

Why I can not start proxy service? Bind for 0.0.0.0:8000 failed: port is already allocated

This is my docker-compose-proxy.yml
version: "3.7"
services:
app:
build:
context: .
ports:
- "8000:8000"
volumes:
- ./app:/app
- static_data:/vol/web
environment:
- DB_HOST=db
- DB_NAME=app
- DB_USER=postgres
- DB_PASS=supersecretpassword
- ALLOWED_HOSTS=127.0.0.1
depends_on:
- db
proxy:
image : proxy:latest
depends_on:
- app
ports:
- "8000:8000"
volumes:
- static_data:/vol/static_data
db:
image: postgres:10-alpine
environment:
- POSTGRES_DB=app
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=supersecretpassword
volumes:
static_data:
I checked the port before I run my command
netstat -ltnp | grep ':8000'
and port was not occupied.
when I go for
docker-compose -f docker-compose-proxy.yml up
I got error
ERROR: for 9bac48e03668_recipe-app-api-devops_proxy_1 Cannot start service proxy: driver failed programming external connectivity on endpoint recipe-app-api-devops_proxy_1 (af5860c135cb37026dcac6ce27151cd4e8448eaddc542d50dcd009c0e24c09fa): Bind for 0.0.0.0:8000 failed: port is already allocated
Why? How to resolve this issue?
You specified port 8000 at
ports:
- "8000:8000"
Since this port is already used for something, you get the error that it's already allocated. So, you will need to find out what is using port 8000 and either change the port of your container, stop the other process, or change the other process's port.
You're trying to bind host port 8000 to two different things:
services:
app:
ports:
- "8000:8000"
proxy:
ports:
- "8000:8000"
So this tells Compose to try to route host port 8000 to the app container, and also to route host port 8000 to the proxy container, and it can't do both. That's essentially the error you're getting.
If you want all requests to your system to go through the proxy container, you can just delete the ports: block from the app container. It will still be visible from other containers in the same Compose file via http://app:8000 but it won't be reachable from outside Docker.
If you need both containers to be accessible, you need to change the first ports: number, but not the second, on one or the other of the containers.
ports:
- '8001:8000' # host port 8001 -> container port 8000
This won't affect connections between containers at all; regardless of what ports: are or aren't present, they will always use the "standard" port number for the container they're trying to connect to.

Docker: nginx-proxy with ssl backend

I am currently in the process of containerizing wordpress apps for development. And that has been going reasonably well so far :)
At the moment I am using one docker-compose.yml file (and some configs) per app. Each app consists of an nginx-webserver, a database and wordpress with fpm. (example docker-compose.yml below). Each app handles it's ssl on it's own and I have confirmed, that it works.
The next step in my masterplan is to use an nginx reverse proxy to have all app containers up at the same time without the need to use different ports on the host.
As I understand jwilder/nginx-proxy is the best tool for the job. So I was thinking - and please correct me if that is not best practice - that I could create a compose.yml file for the nginx-proxy that could run all the time and that would expose ports 80 and 443 to the host while automatically generating the nginx-configs for every container I' spin up afterwards.
version: '3.6'
services:
nginx-proxy:
image: jwilder/nginx-proxy
container_name: nginx_proxy
ports:
- '80:80'
- '443:443'
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
networks:
default:
external:
name: nginx-proxy
I tried that with an nginx-proxy which exposed port 80 to the host and a wordpress app setup in its own docker-compose.yml file using the mariadb:latest and wordpress:latest images. That did indeed work simply by adding the expose: \ -80 and the VIRTUAL_HOST environment variable.
But I don't quite get how to use the reverse proxy in front of my aforementioned wordpress apps. The documentation states this:
SSL Backends
If you would like the reverse proxy to connect to your backend using HTTPS instead of HTTP, set VIRTUAL_PROTO=https on the backend container.
Note: If you use VIRTUAL_PROTO=https and your backend container exposes port 80 and 443, nginx-proxy will use HTTPS on port 80. This is almost certainly not what you want, so you should also include VIRTUAL_PORT=443.
so I tried adding these environment variables to the app's docker-compose.yml file. Specifically on the nginx service inside and added exposed ports 80 and 443.
version: '3.6'
services:
wordpress:
image: wordpress:4.7.2-php7.1-fpm
volumes:
- ../public:/var/www/html
environment:
- WORDPRESS_DB_NAME=${WORDPRESS_DB_NAME:-wordpress}
- WORDPRESS_TABLE_PREFIX=${WORDPRESS_TABLE_PREFIX:-wp_}
- WORDPRESS_DB_HOST=${WORDPRESS_DB_HOST:-mysql}
- WORDPRESS_DB_USER=${WORDPRESS_DB_USER:-root}
- WORDPRESS_DB_PASSWORD=${WORDPRESS_DB_PASSWORD:-password}
depends_on:
- db
restart: always
db:
image: mariadb:${MARIADB_VERSION:-latest}
volumes:
- tss-data:/var/lib/mysql
# - ./db:/docker-entrypoint-initdb.d/
environment:
- MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD:-password}
- MYSQL_USER=${MYSQL_USER:-root}
- MYSQL_PASSWORD=${MYSQL_PASSWORD:-password}
- MYSQL_DATABASE=${MYSQL_DATABASE:-wordpress}
restart: always
nginx:
image: nginx:${NGINX_VERSION:-latest}
container_name: nginx
volumes:
- ${NGINX_CONF_DIR:-./nginx}:/etc/nginx/conf.d
- ${NGINX_LOG_DIR:-./logs/nginx}:/var/log/nginx
- ${WORDPRESS_DATA_DIR:-./wordpress}:/var/www/html
- ${SSL_CERTS_DIR:-./certs}:/etc/letsencrypt
- ${SSL_CERTS_DATA_DIR:-./certs-data}:/data/letsencrypt
environment:
- VIRTUAL_HOST:local.my-app.com
- VIRTUAL_PROTO:https
- VIRTUAL_PORT:443
expose:
- 80
- 443
depends_on:
- wordpress
restart: always
volumes:
tss-data:
networks:
default:
external:
name: nginx-proxy
Alas, if I try to browse to local.my-app.com on port 80 I get
503 Service Temporarily Unavailable
If I try on port 443 the nginx reverse proxy does not respond at all. I feel like I am missing something fairly obvious but I can't seem to find it and I would really appreciate any thoughts on the matter.
In the end, I opted to not handle the SSL encryption in each individual app. But instead I changed the reverse proxy to
version: '3.6'
services:
nginx-proxy:
image: jwilder/nginx-proxy:alpine
container_name: nginx_proxy
ports:
- '80:80'
- '443:443'
volumes:
- ./certs:/etc/nginx/certs
- /var/run/docker.sock:/tmp/docker.sock:ro
restart: unless-stopped
networks:
default:
external:
name: nginx-proxy
So now I can reach each app on Port 80 until I add a cert for it in which case it becomes reachable on port 443.

docker-compose.yml nginx with php link

I tried this in the docker-compose.yml file but can't get php working in the nginx server. What I try to do is simply have nginx with php working
web:
image: nginx:latest
ports:
- "8080:80"
volumes:
- ./docker-nginx-php/html:/usr/share/nginx/html
links:
- php
php:
image: php:7-fpm
volumes:
- ./docker-nginx-php/html:/usr/share/nginx/html
Hope someone knows how to get it working!
I have on my host system apache2 installed which serves some of my apps but I want to have nginx with php server another domain so port 80 is currently in use by apache2 listener that's why I use port 8080:80 instead in this example above
You also need to specify the environment variable VIRTUAL_HOST on the php container as well as opening the port within docker for connection with other containers, like:
php:
image: php:7-fpm
environment:
- VIRTUAL_HOST=domain.example.com
ports:
- 80
volumes:
- ./docker-nginx-php/html:/usr/share/nginx/html

docker and jwilder/nginx-proxy http/https issue

I'm using docker on osx via boot2docker.
I have 2 hosts: site1.loc.test.com and site2.loc.test.com pointed to ip address of docker host.
Both should be available via 80 and 443 ports.
So I'm using jwilder/nginx-proxy for reverse proxy purposes.
But in fact when I'm running all of them via docker-compose every time I try to open via 80 port I get redirect to 443 (301 Moved Permanently).
May be I've missed something in jwilder/nginx-proxy configuration?
docker-compose.yml
proxy:
image: jwilder/nginx-proxy
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
- certs:/etc/nginx/certs
ports:
- "80:80"
- "443:443"
site1:
image: httpd:2.4
volumes:
- site1:/usr/local/apache2/htdocs
environment:
VIRTUAL_HOST: site1.loc.test.com
expose:
- "80"
site2:
image: httpd:2.4
volumes:
- site2:/usr/local/apache2/htdocs
environment:
VIRTUAL_HOST: site2.loc.test.com
expose:
- "80"
Just to keep this topic up to date, the jwilder/nginx-proxy meanwhile introduced a flag for that: HTTPS_METHOD=noredirect; To be set as environment variable.
Further reading on github
I think your configuration should be correct, but it seems that this is the intended behaviour of jwilder/nginx-proxy. See these lines in the file nginx.tmpl: https://github.com/jwilder/nginx-proxy/blob/master/nginx.tmpl#L89-L94
It seems that if a certificate is found, you will always be redirected to https.
EDIT: I found the confirmation in the documentation
The behavior for the proxy when port 80 and 443 are exposed is as
follows:
If a container has a usable cert, port 80 will redirect to 443 for that container so that HTTPS is always preferred when available.
You can still use a custom configuration. You could also try to override the file nginx.tmpl in a new Dockefile .
To serve traffic in both SSL and non-SSL modes without redirecting to SSL, you can include the environment variable HTTPS_METHOD=noredirect (the default is HTTPS_METHOD=redirect).
HTTPS_METHOD must be specified on each container for which you want to override the default behavior.
Here is an example Docker Compose file:
version: '3'
services:
nginx-proxy:
image: jwilder/nginx-proxy
ports:
- '80:80'
- '443:443'
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
- ./config/certs:/etc/nginx/certs
environment:
DEFAULT_HOST: my.example.com
app:
build:
context: .
dockerfile: ./Dockerfile
environment:
HTTPS_METHOD: noredirect
VIRTUAL_HOST: my.example.com
Note: As in this example, environment variable HTTPS_METHOD must be set on the app container, not the nginx-proxy container.
Ref: How SSL Support Works section for the jwilder/nginx-proxy Docker image.

Resources