Port conflict in docker-compose - docker

I am trying to create the following with a reverse proxy (the webs only work) but with the mail server, it gives port conflict error in docker-compose.
What I want is that the webs coexist with the mail service. For example mail.sitea.com
Any suggestion?
version: '3.4'
services:
nginx-proxy:
image: jwilder/nginx-proxy
restart: always
ports:
- 443:443
- 80:80
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
site-a:
image: nginx
restart: always
expose:
- '80'
volumes:
- /var/www/site-a/public_html/:/usr/share/nginx/html:ro
environment:
- VIRTUAL_HOST=sitea.com
site-b:
image: nginx
restart: always
expose:
- '80'
volumes:
- /var/www/site-b/public_html/:/usr/share/nginx/html:ro
environment:
- VIRTUAL_HOST=siteb.com
poste:
image: analogic/poste.io
restart: always
network_mode: "host"
expose:
- 25
- 80
- 443
- 110
- 143
- 465
- 587
- 993
- 995
volumes:
- /docker/mail:/data
environment:
- HTTPS=ON
- DISABLE_CLAMAV=TRUE
OUTPUT
/docker# vim /docker/docker-compose.yml
root#adroconstruccion:/docker# docker-compose up -d
Removing docker_nginx-proxy_1
docker_site-b_1 is up-to-date
docker_site-a_1 is up-to-date
Starting 08fba2b58471_docker_nginx-proxy_1 ... error
Recreating docker_poste_1 ...
ERROR: for 08fba2b58471_docker_nginx-proxy_1 Cannot start service nginx-proxy: driver failed programming external connectivity on endpoint 08fba2b58471_docker_nginx-proxy_1 (095659f459c1af8c729129074520b40800e528719727061bdbc4bfa25f6c37d5)Recreating docker_poste_1 ... done
ERROR: for nginx-proxy Cannot start service nginx-proxy: driver failed programming external connectivity on endpoint 08fba2b58471_docker_nginx-proxy_1 (095659f459c1af8c729129074520b40800e528719727061bdbc4bfa25f6c37d5): Error starting userland proxy: listen tcp 0.0.0.0:443: bind: address already in use
ERROR: Encountered errors while bringing up the project.

If you run poste with network_mode: "host" it will listen on those ports on the local network. So the port 443 listener in the poste service conflicts with nginx-proxy
Depending on what you're using the poste continer for you might be able to get away with just commenting out those ports (80 and 443) and just using the mail ports. Or you could remove the network_mode: "host" and maybe proxy them through nginx?

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.

How to access a Docker container without specifying its HTTP port?

I set up a Docker network with a db container, a nextcloud container, and a nginx container. I can access the nextcloud website with 'ip-adress':8080, but I want to access it without specifying port 8080. How can I do that?
This is my docker-compose.yml:
version: '2'
volumes:
nextcloud:
db:
services:
db:
image: mariadb
restart: always
command: --transaction-isolation=READ-COMMITTED --binlog-format=ROW
volumes:
- db:/var/lib/mysql
environment:
- MYSQL_ROOT_PASSWORD=
- MYSQL_PASSWORD=
- MYSQL_DATABASE=nextcloud
- MYSQL_USER=nextcloud
app:
image: nextcloud:fpm
restart: always
links:
- db
volumes:
- nextcloud:/var/www/html
environment:
- MYSQL_PASSWORD=
- MYSQL_DATABASE=nextcloud
- MYSQL_USER=nextcloud
- MYSQL_HOST=db
web:
image: nginx
restart: always
ports:
- 8080:80
links:
- app
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
volumes_from:
- app
What you want is to avoid having to specify the port when you request a URI. One way to do that is to use the default port for the protocol you are using (80 for HTTP, 443 for https, 21 for FTP, etc). Then rely on your client to automatically fallback to the default port.
In a Docker Compose configuration file, the syntax for exposing a port is defined as such: <host_port>:<container_port> (see the documentation). That means 8080:80 exposes port 80 from the container on your docker host on port 8080.
In your case, the service is exposing an HTTP server, which means you have to change it to the default port 80 in order to omit it. Update web.services.ports[0] from 8080:80 to 80:80, and you will be able to access nextcloud from 'ip-adress'.

Is it possible to share ports between NGINX and Docker Container?

I have Ubuntu 18:04/NGINX VPS where I have a bunch of Laravel project blocks, all use ssl (certbot).
I wanted to deploy Nextcloud via Docker Compose on the same VPS:
version: "3"
services:
proxy:
image: jwilder/nginx-proxy:alpine
labels:
# labels needed by lets encrypt to identify container to generate certs in
- "com.github.jrcs.letsencrypt_nginx_proxy_companion.nginx_proxy=true"
container_name: nextcloud-proxy
networks:
- nextcloud_network
ports:
- 80:80
- 443:443
volumes:
- ./proxy/conf.d:/etc/nginx/conf.d:rw
- ./proxy/vhost.d:/etc/nginx/vhost.d:rw
- ./proxy/html:/usr/share/nginx/html:rw
- ./proxy/certs:/etc/nginx/certs:ro
- /etc/localtime:/etc/localtime:ro
- /var/run/docker.sock:/tmp/docker.sock:ro
restart: unless-stopped
letsencrypt:
image: jrcs/letsencrypt-nginx-proxy-companion:v1.12.1
container_name: nextcloud-letsencrypt
depends_on:
- proxy
networks:
- nextcloud_network
volumes:
- ./proxy/certs:/etc/nginx/certs:rw
- ./proxy/vhost.d:/etc/nginx/vhost.d:rw
- ./proxy/html:/usr/share/nginx/html:rw
- /etc/localtime:/etc/localtime:ro
- /var/run/docker.sock:/var/run/docker.sock:ro
restart: unless-stopped
db:
image: mariadb:10.5.1
container_name: nextcloud-mariadb
networks:
- nextcloud_network
volumes:
- ./db:/var/lib/mysql
- ./dbdumps:/var/dbdumps
- /etc/localtime:/etc/localtime:ro
environment:
- MYSQL_ROOT_PASSWORD=... # set me
- MYSQL_PASSWORD=... # set me
- MYSQL_DATABASE=... # set me
- MYSQL_USER=... # set me
restart: unless-stopped
redis:
container_name: nextcloud-redis
image: redis:5.0.8
restart: unless-stopped
networks:
- nextcloud_network
volumes:
- ./redis/data:/data
command: ["redis-server", "--appendonly yes"]
app:
image: nextcloud:18.0.2
container_name: nextcloud-app
networks:
- nextcloud_network
depends_on:
- letsencrypt
- proxy
- redis
- db
volumes:
- ./nextcloud:/var/www/html
- ./app/config:/var/www/html/config
- ./app/custom_apps:/var/www/html/custom_apps
- ./app/data:/var/www/html/data
- ./app/themes:/var/www/html/themes
- /etc/localtime:/etc/localtime:ro
environment:
- VIRTUAL_HOST=YOURDOMAINHERE # set me
- LETSENCRYPT_HOST=YOURDOMAINHERE # set me
- LETSENCRYPT_EMAIL=you#example.com # set me
restart: unless-stopped
networks:
nextcloud_network:
driver: bridge
When I run this I get:
ERROR: for 3f210d699b80_nextcloud-proxy Cannot start service proxy: driver failed programming
external connectivity on endpoint nextcloud-proxy
(2d76e425c94abb95da70a7d903bf8830d4e9192a512e17db1b39f76da85c7b97): Error starting userland proxy:
listen tcp 0.0.0.0:443: bind: address already in use
ERROR: for proxy Cannot start service proxy: driver failed programming external connectivity on
endpoint nextcloud-proxy (2d76e425c94abb95da70a7d903bf8830d4e9192a512e17db1b39f76da85c7b97): Error
starting userland proxy: listen tcp 0.0.0.0:443: bind: address already in use
ERROR: Encountered errors while bringing up the project.
Because this port is already in use.
If I stop NGINX on VPS and run docker-compose up -d again, everything is ok and Nextcloud service is accessible via URL.
I tried to change outside ports to
- 8080:80
- 4444:443
And rebuild it. Then I don't see the above error but everything is messed up - the url point to wrong domain...
Is it possible to tweak the proxy container settings somehow to resolve this?
2 services are unable to listen to the same port as you have found. Your laravel applications are already listening on ports 80/443, so when start your nextcloud containers, it won't be able to bind to those ports.
You'll have to have your jwilder/nginx-proxy:alpine act as a proxy to both the nextcloud container and the laravel servers. This can be done via your nginx configurations and mount it to your container (which you seem to be using the ./proxy/ directory):
https://docs.nginx.com/nginx/admin-guide/web-server/reverse-proxy/
Although, if your VPS is able to have 2 IP addresses, then you are able to bind the laravel applications to one interface and your nextcloud proxy to the other which will also solve your problem. The first method is better practice as would allow you to scale your server better without having to add another IP address per-application.
https://docs.docker.com/config/containers/container-networking/

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.

Resources