Is it possible to configure dockercloud/haproxy with more than one backend service but listening on a different port? I'm trying to get a docker-compose config working with nginx on port 80 for a web frontend, and then a container on 8080 running a Spring Boot app.
It appears by default haproxy is seeing the linked containers for web and addressbook (see .yml file below), but by default they are both being exposed on port 80 by happroxy, and so the Spring Boot container never receives traffic on 8080.
Is this config possible, or do I need to run 2 different haproxy containers too, one for web, and one for the REST backend service?
Here's my docker-compose.yml so far:
version: '2'
#build:
# context: ./haproxy
# image: haproxy
# dockerfile: Dockerfile
services:
mongodata:
image: mongo:3.2
volumes:
- /data/db
entrypoint: /bin/bash
mongo:
image: mongo:3.2
depends_on:
- mongodata
volumes_from:
- mongodata
ports:
#only specify internal port, not external, so we can scale with docker-compose scale
- "27017"
addressbook:
image: addressbook
depends_on:
- mongo
environment:
- MONGODB_DB_NAME=addressbook
ports:
- "8080"
links:
- mongo
web:
image: docker-web-angularjs
ports:
- "80"
lb:
image: dockercloud/haproxy
#TODO: need to add an haproxy.cfg to configure for addressbook instances exposed behind 8080?
#or can be configured via container properties?
#image: haproxy
depends_on:
- addressbook
environment:
- STATS_PORT=1936
- STATS_AUTH="admin:password"
links:
- addressbook
- web
volumes:
- /var/run/docker.sock:/var/run/docker.sock
ports:
- 80:80
- 8080:8080
- 1936:1936
To me, it's easier to use Traefik to achieve the goal.
addressbook:
image: addressbook
depends_on:
- mongo
environment:
- MONGODB_DB_NAME=addressbook
labels:
- "traefik.backend=spring_boot"
- "traefik.protocol=http"
- "traefik.port=8080"
- "traefik.frontend.entryPoints=http_8080"
ports:
- "8080"
links:
- mongo
web:
image: docker-web-angularjs
labels:
- "traefik.backend=nginx"
- "traefik.protocol=http"
- "traefik.port=80"
- "traefik.frontend.entryPoints=http_80"
ports:
- "80"
lb:
image: traefik
command: "--web --web.address=8081 --docker --docker.domain=docker.localhost \
--logLevel=DEBUG \
--entryPoints='Name:http_80 Address::80' \
--entryPoints='Name:http_8080 Address::8080'"
ports:
- 80:80
- 8080:8080
- 8081:8081
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- /dev/null:/traefik.toml
You can expose the two services using two different paths, both on the same port of the haproxy container. You can do this using the environment variable VIRTUAL_HOST for the addressbook and web containers:
addressbook:
image: addressbook
depends_on:
- mongo
environment:
- MONGODB_DB_NAME=addressbook
- VIRTUALHOST="/addressbook/*"
ports:
- "8080"
links:
- mongo
web:
image: docker-web-angularjs
environment:
- VIRTUALHOST="/web/*"
ports:
- "80"
Unfortunately, haproxy doesn't remove the web or addressbook path by default, so you need to update the two apps in order to manage a "base path".
Related
I'm trying to run two separate API's on a local server, and point two different DNS A Records to the same server. Something like service1.userdomain.com => [ip address] and service2.userdomain.com => [ip address]
I thought I could use Traefik and route to two different docker images based on the host name. However this isnt working as I get a 504 Gateway timeout when trying to hit the service. The services themselves are listening to port :8080
version: '3'
services:
traefik:
image: traefik:latest
restart: always
command:
- --accesslog
- --api.insecure=true
- --providers.docker
- --providers.docker.exposedbydefault=false
volumes:
- /var/run/docker.sock:/var/run/docker.sock
ports:
- "80:80"
- "8080:8080"
service1:
image: ghcr.io/user/service1:latest
restart: always
ports:
- "8081:8080"
networks:
- fullstack
labels:
- traefik.enable=true
- traefik.http.routers.service1.rule=Host(`service1.domain.com`)
service2:
image: ghcr.io/user/serice2:latest
restart: always
ports:
- "8082:8080"
labels:
- traefik.enable=true
- traefik.http.routers.service2.rule=Host(`service2.domain.com`)
networks:
- fullstack
networks:
fullstack:
driver: bridge
I have an environment running docker containers.
This environment hosts Traefik, Nextcloud, MotionEye and Heimdall.
I also have another environment running CoreDNS in a docker container.
For some reason, I can get MotionEye to be accessible from motioneye.docker.swarm (changed the domain in here for privacy).
However, for nextcloud and Heimdall, I have to explicitly access the ports and I'm struggling to tell why.
e.g. Heimdall is gateway.docker.swarm:8091 when should be gateway.docker.swarm
When a user requests a webpage onto the local dns server X.X.X.117 it gets routed through to the traefik instance on X.X.X.106.
My traefik compose file is as follows:
version: '3'
services:
reverse-proxy:
# The official v2 Traefik docker image
image: traefik:v2.3
restart: always
# Enables the web UI and tells Traefik to listen to docker
command: --api.insecure=true --providers.docker
ports:
# The HTTP port
- "80:80"
# The Web UI (enabled by --api.insecure=true)
- "8080:8080"
volumes:
# So that Traefik can listen to the Docker events
- /var/run/docker.sock:/var/run/docker.sock
labels:
- "traefik.port=8080"
- "traefik.backend=traefik"
- "traefik.frontend.rule=Host:traefik.docker.swarm"
- "traefik.docker.network=traefik_default"
My Heimdall compose is as follows:
version: "3"
services:
heimdall:
image: ghcr.io/linuxserver/heimdall
container_name: heimdall
environment:
- PUID=1000
- PGID=1000
- TZ=Europe/London
volumes:
- /home/pi/heimdall/config:/config
ports:
- 8091:80
restart: unless-stopped
networks:
- heimdall
labels:
- "traefik.enable=true"
- "traefik.port=8091"
- "traefik.http.routers.heimdall.entrypoints=http"
- "traefik.http.routers.heimdall.rule=Host(`gateway.docker.swarm`)"
networks:
heimdall:
external:
name: heimdall
Can anyone see what I'm doing wrong here?
When you access through gateway.docker.swarm:8091 it works because you are accessing the heimdall container directly. This is possible because you defined
ports:
- 8091:80
in your docker-compose.
In order to access through traefik they must be on the same network. Also, remove the port mapping if you like this container to be only accessible through traefik. And finally correct the traefik port accordingly.
version: "3"
services:
heimdall:
image: ghcr.io/linuxserver/heimdall
container_name: heimdall
environment:
- PUID=1000
- PGID=1000
- TZ=Europe/London
volumes:
- /home/pi/heimdall/config:/config
restart: unless-stopped
labels:
- "traefik.enable=true"
- "traefik.port=80"
- "traefik.http.routers.heimdall.entrypoints=http"
- "traefik.http.routers.heimdall.rule=Host(`gateway.docker.swarm`)"
I would like to build a docker landscape. I use a container with a traefik (v2. 1) image and a mysql container for multiple databases.
traefik/docker-compose.yml
version: "3.3"
services:
traefik:
image: "traefik:v2.1"
container_name: "traefik"
restart: always
command:
- "--log.level=DEBUG"
- "--api=true"
- "--api.dashboard=true"
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
- "--providers.docker.network=proxy"
- "--entrypoints.web.address=:80"
- "--entrypoints.websecure.address=:443"
- "--entrypoints.traefik-dashboard.address=:8080"
- "--certificatesresolvers.devnik-resolver.acme.httpchallenge=true"
- "--certificatesresolvers.devnik-resolver.acme.httpchallenge.entrypoint=web"
#- "--certificatesresolvers.devnik-resolver.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory"
- "--certificatesresolvers.devnik-resolver.acme.email=####"
- "--certificatesresolvers.devnik-resolver.acme.storage=/letsencrypt/acme.json"
ports:
- "80:80"
- "443:443"
- "8080:8080"
volumes:
- "./letsencrypt:/letsencrypt"
- "./data:/etc/traefik"
- "/var/run/docker.sock:/var/run/docker.sock:ro"
networks:
- "proxy"
labels:
- "traefik.enable=true"
- "traefik.http.routers.traefik.rule=Host(`devnik.dev`)"
- "traefik.http.routers.traefik.entrypoints=traefik-dashboard"
- "traefik.http.routers.traefik.tls.certresolver=devnik-resolver"
#basic auth
- "traefik.http.routers.traefik.service=api#internal"
- "traefik.http.routers.traefik.middlewares=auth"
- "traefik.http.middlewares.auth.basicauth.usersfile=/etc/traefik/.htpasswd"
#Docker Networks
networks:
proxy:
database/docker-compose.yml
version: "3.3"
services:
#MySQL Service
mysql:
image: mysql:5.7
container_name: mysql
restart: always
ports:
- "3306:3306"
volumes:
#persist data
- ./mysqldata/:/var/lib/mysql/
- ./init:/docker-entrypoint-initdb.d
networks:
- "mysql"
environment:
MYSQL_ROOT_PASSWORD: ####
TZ: Europe/Berlin
#Docker Networks
networks:
mysql:
driver: bridge
For the structure I want to control all projects via multiple docker-compose files. These containers should run on the same network as the traefik container and some with the mysql container.
This also works for the following case (but only sometimes)
dev-releases/docker-compose.yml
version: "3.3"
services:
backend:
image: "registry.gitlab.com/devnik/dev-releases-backend/master:latest"
container_name: "dev-releases-backend"
restart: always
volumes:
#laravel logs
- "./logs/backend:/app/storage/logs"
#cron logs
- "./logs/backend/cron.log:/var/log/cron.log"
labels:
- "traefik.enable=true"
- "traefik.http.routers.dev-releases-backend.rule=Host(`dev-releases.backend.devnik.dev`)"
- "traefik.http.routers.dev-releases-backend.entrypoints=websecure"
- "traefik.http.routers.dev-releases-backend.tls.certresolver=devnik-resolver"
networks:
- proxy
- mysql
environment:
TZ: Europe/Berlin
#Docker Networks
networks:
proxy:
external:
name: "traefik_proxy"
mysql:
external:
name: "database_mysql"
As soon as I restart the containers in dev-releases/ via docker-compose up -d I get the typical error "Gateway timeout" when calling them in the browser.
As soon as I comment the network networks: #- mysql and restart the docker-compose in dev-releases/ it works again.
My guess is that I have not configured the external networks correctly. Is it not possible to use 2 external networks?
I'd like some container have access to the 'mysql' network but it should not be accessible for the whole traefik network.
Let me know if you need more information
EDIT (26.03.2020)
I make it running.
I put all my containers into one network "proxy". It seems mysql also have to be in the proxy network.
So I add following to database/docker-compose.yml
networks:
proxy:
external:
name: "traefik_proxy"
And removed the database_mysql network out of dev-releases/docker-compose.yml
based on the names of the files, your mysql network should be mysql_mysql.
you can verify this by executing
$> docker network ls
You are also missing a couple of labels for your services such as
traefik command line
- '--providers.docker.watch=true'
- '--providers.docker.swarmMode=true'
labels
- traefik.docker.network=proxy
- traefik.http.services.dev-releases-backend.loadbalancer.server.port=yourport
- traefik.http.routers.dev-releases-backend.service=mailcatcher
You can check this for more info
I've a VPS on which I want to deploy multiple web applications (for which I've already read posts and they're perfect when we have directly sub container). I want to manage each web application having its own nginx to route to its sub domains and also some static website's related to them. I've two docker compose. My network looks like the following. Image.
My NGINX Rerverse proxy should be responsible to route the domains to respective nginx container. It might be possible or not I'm not sure (that's why I asked help). If someone can provide a better understanding that I'm open to suggestions. Below is my configuration for nginx proxy container and other web apps docker yaml file code. I've used the NGINX PROXY
NGINX PROXY Docker Compose File
version: "3.7"
services:
nginx-proxy:
image: jwilder/nginx-proxy:alpine
container_name: nginx-proxy
ports:
- "80:80"
- "443:443"
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
networks:
default:
external:
name: nginx-proxy
WEB APPLICATION 1 docker-compose.yml
version: "3.7"
networks:
default:
external:
name: nginx-proxy
yoda-network:
driver: bridge
services:
adminer:
container_name: ${APP_NAME}_adminer
image: adminer
depends_on:
- mysql
expose:
- 8080
environment:
VIRTUAL_HOST: yodaledger.com
VIRTUAL_PORT: 8080
networks:
- yoda-network
python:
container_name: ${APP_NAME}_python
image: python:3.6
command: bash -c "pip3 install -r requirements.txt && python manage.py runserver 0.0.0.0:8000"
volumes:
- ${APP_PATH}var/www/api.yodaledger.com/yodaledger_backend:/app
- ${APP_PATH}var/www/static.yodaledger.com:/app/static
depends_on:
- mysql
working_dir: /app
environment:
- PYTHONUNBUFFERED=1
- MYSQL_HOST=mysql
- MYSQL_USER=${MYSQL_USER}
- MYSQL_PASSWORD=${MYSQL_PASSWORD}
- MYSQL_DATABASE=${MYSQL_DATABASE}
networks:
- yoda-network
nginx:
container_name: ${APP_NAME}_nginx
image: nginx:alpine
expose:
- 443
- 80
volumes:
- ${APP_PATH}var/www:/var/www
- ${APP_PATH}var/log:/var/log/nginx
- ${APP_PATH}var/ssl:/var/ssl
- ${APP_PATH}etc/nginx:/etc/nginx
- /tmp/${APP_NAME}/nginx:/tmp
depends_on:
- python
environment:
VIRTUAL_PORT: 443
VIRTUAL_HOST: yodaledger.com,api.yodaledger.com,app.yodaledger.com,static.yodaledger.com
networks:
- yoda-network
- default
mysql:
container_name: ${APP_NAME}_mysql
image: mariadb:latest
#ports:
# - "3306:3306"
volumes:
- ${APP_PATH}var/mysql:/var/lib/mysql
- ${APP_PATH}etc/mysql:/etc/mysql
environment:
- MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD}
- MYSQL_DATABASE=${MYSQL_DATABASE}
- MYSQL_USER=${MYSQL_USER}
- MYSQL_PASSWORD=${MYSQL_PASSWORD}
- TZ=Europe/Paris
networks:
- yoda-network
WEB APPLICATION 2
It looks the same as web application 1.
I'm using jwilder/nginx-proxy with separate docker-compose.yaml. It looks like this:
proxy:
image: jwilder/nginx-proxy
restart: always
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
- ./nginx/conf.d/proxy.conf:/etc/nginx/conf.d/proxy.conf:ro
- /Users/marcin/Docker/local_share/certificates:/etc/nginx/certs:ro
ports:
- "80:80"
- "443:443"
container_name: proxy
I'm using it for quite a long time and it's working fine when my project docker-compose.yaml looks like this:
web:
build: /Users/marcin/Docker/definitions/php-nginx/php-7.1-ubuntu
volumes:
- /Users/marcin/Docker/projects/test.local/html/:/usr/share/nginx/html/
- /Users/marcin/Docker/projects/test.local/nginx/conf.d/:/etc/nginx/conf.d/
- /Users/marcin/Docker/projects/test.local/nginx/log/:/var/log/nginx/
- /Users/marcin/Docker/projects/test.local/supervisor/conf.d/:/etc/supervisor/conf.d/
- /Users/marcin/Docker/projects/test.local/supervisor/log/:/var/log/supervisor/
- /Users/marcin/Docker/projects/test.local/cron/:/root/.cron/
- /Users/marcin/Docker/local_share/:/root/.local_share/
- /Users/marcin/Docker/local_share/certificates/:/usr/share/nginx/certificates/
working_dir: /usr/share/nginx/html/
links:
- db
container_name: test.php
hostname: test.local
ports:
- "336:22"
- "8081:80"
- "18080:443"
environment:
- VIRTUAL_HOST=test.local
- CERT_NAME=default
- HTTPS_METHOD=noredirect
db:
build: /Users/marcin/Docker/definitions/mysql/5.7
environment:
- MYSQL_ROOT_PASSWORD=pass
- MYSQL_DATABASE=
- MYSQL_USER=
- MYSQL_PASSWORD=
expose:
- 3306
volumes:
- /Users/marcin/Docker/projects/test.local/mysql/data/:/var/lib/mysql/
- /Users/marcin/Docker/projects/test.local/mysql/conf.d/:/etc/mysql/conf.d/source
- /Users/marcin/Docker/projects/test.local/mysql/log/:/var/log/mysql/
ports:
- "33060:3306"
container_name: test.db
hostname: test.local
I can access site without any problem using http://test.local or https://test.local what is expected.
However I had to update my file structure to newer version:
version: "3.2"
services:
web:
build: /Users/marcin/Docker/definitions/php-nginx/php-7.1-ubuntu
volumes:
- /Users/marcin/Docker/projects/test.local/html/:/usr/share/nginx/html/
- /Users/marcin/Docker/projects/test.local/nginx/conf.d/:/etc/nginx/conf.d/
- /Users/marcin/Docker/projects/test.local/nginx/log/:/var/log/nginx/
- /Users/marcin/Docker/projects/test.local/supervisor/conf.d/:/etc/supervisor/conf.d/
- /Users/marcin/Docker/projects/test.local/supervisor/log/:/var/log/supervisor/
- /Users/marcin/Docker/projects/test.local/cron/:/root/.cron/
- /Users/marcin/Docker/local_share/:/root/.local_share/
- /Users/marcin/Docker/local_share/certificates/:/usr/share/nginx/certificates/
working_dir: /usr/share/nginx/html/
links:
- db
container_name: test.php
hostname: test.local
ports:
- "336:22"
- "8081:80"
- "18080:443"
environment:
- VIRTUAL_HOST=test.local
- CERT_NAME=default
- HTTPS_METHOD=noredirect
db:
build: /Users/marcin/Docker/definitions/mysql/5.7
environment:
- MYSQL_ROOT_PASSWORD=pass
- MYSQL_DATABASE=
- MYSQL_USER=
- MYSQL_PASSWORD=
expose:
- 3306
volumes:
- /Users/marcin/Docker/projects/test.local/mysql/data/:/var/lib/mysql/
- /Users/marcin/Docker/projects/test.local/mysql/conf.d/:/etc/mysql/conf.d/source
- /Users/marcin/Docker/projects/test.local/mysql/log/:/var/log/mysql/
ports:
- "33060:3306"
container_name: test.db
hostname: test.local
and after that it seems not to work. I can access site using ip and port without a problem, but I cannot longer use domain to access it. When I try I'm getting:
503 Service Temporarily Unavailable
nginx/1.13.8
And this is for sure from jwilder nginx (and not the nginx in project).
So the question is - where should I put environment variables to make it work? It seems that when they are placed as they are at the moment they are not read by proxy.
The 503 indicates that the nginx-proxy container can see your container running in docker and it has the configuration needed for nginx to route traffic to it, but it is unable to connect to that container over the docker network. For container-to-container networking to work, you need to have a common docker network defined. You should first run the following to create a network:
docker network create proxy
Then update your nginx-proxy compose file to use the network (this should also be upgraded to at least a v2 syntax, I've gone with 3.2 to match your other file):
version: "3.2"
networks:
proxy:
external: true
services:
proxy:
image: jwilder/nginx-proxy
restart: always
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
- ./nginx/conf.d/proxy.conf:/etc/nginx/conf.d/proxy.conf:ro
- /Users/marcin/Docker/local_share/certificates:/etc/nginx/certs:ro
ports:
- "80:80"
- "443:443"
container_name: proxy
networks:
- proxy
And then do something similar for your application:
version: "3.2"
networks:
proxy:
external: true
services:
web:
build: /Users/marcin/Docker/definitions/php-nginx/php-7.1-ubuntu
volumes:
- /Users/marcin/Docker/projects/test.local/html/:/usr/share/nginx/html/
- /Users/marcin/Docker/projects/test.local/nginx/conf.d/:/etc/nginx/conf.d/
- /Users/marcin/Docker/projects/test.local/nginx/log/:/var/log/nginx/
- /Users/marcin/Docker/projects/test.local/supervisor/conf.d/:/etc/supervisor/conf.d/
- /Users/marcin/Docker/projects/test.local/supervisor/log/:/var/log/supervisor/
- /Users/marcin/Docker/projects/test.local/cron/:/root/.cron/
- /Users/marcin/Docker/local_share/:/root/.local_share/
- /Users/marcin/Docker/local_share/certificates/:/usr/share/nginx/certificates/
working_dir: /usr/share/nginx/html/
links:
- db
container_name: test.php
hostname: test.local
ports:
- "336:22"
- "8081:80"
- "18080:443"
environment:
- VIRTUAL_HOST=test.local
- CERT_NAME=default
- HTTPS_METHOD=noredirect
networks:
- proxy
- default
db:
build: /Users/marcin/Docker/definitions/mysql/5.7
environment:
- MYSQL_ROOT_PASSWORD=pass
- MYSQL_DATABASE=
- MYSQL_USER=
- MYSQL_PASSWORD=
expose:
- 3306
volumes:
- /Users/marcin/Docker/projects/test.local/mysql/data/:/var/lib/mysql/
- /Users/marcin/Docker/projects/test.local/mysql/conf.d/:/etc/mysql/conf.d/source
- /Users/marcin/Docker/projects/test.local/mysql/log/:/var/log/mysql/
ports:
- "33060:3306"
container_name: test.db
hostname: test.local
If you were upgrading from a v1 syntax (without a version defined), you will find that docker switches from running everything on the same network without dns to running each compose project or stack on a dedicated network with dns. To run your apps on other networks, you'll need to explicitly configure that. In the above example, only the web container was placed on the proxy network, and both are on the default network created for this project or stack.