Docker + traefik proxy routing wildcard subdomain not working - docker

Can you help me understand why the below rule doesn't match abc123.phppointofsale.com (404 from proxy)
"traefik.http.routers.production_php_point_of_sale_app.rule=Host(*.phppointofsale.com,*.phppos.com)"
production_php_point_of_sale_app:
logging:
driver: "local"
deploy:
mode: global
labels:
- "traefik.http.routers.production_php_point_of_sale_app.rule=Host(`*.phppointofsale.com`,`*.phppos.com`)"
- "traefik.http.services.production_php_point_of_sale_app.loadbalancer.server.port=80"
image: phppointofsale/production-app
build:
context: "production_php_point_of_sale_app"
restart: always
env_file:
- production_php_point_of_sale_app/.env
- .env
networks:
- app_network
- mail

Related

Docker swarm with reverse proxy, run requests based on request uri path to certain node

I have the following nodes with hostnames docker-php-pos-web-1,docker-php-pos-web-2,docker-php-pos-web-3,and docker-php-pos-web-4 in a docker swarm cluster with caddy proxy configured on distributed mode
I want requests with cron anywhere in the url path to run on docker-php-pos-web-4. An example request would be demo.phppointofsale.com/index.php/ecommerce/cron. If "cron" is not in the url, it would route as normal.
I want to avoid having 2 copies of production_php_point_of_sale_app just for this.
I am already routing to docker-php-pos-web-4 from my load balancer for "cron" in request path, BUT since in docker swarm the mesh network can decide on which node actually "runs" it. I always want docker-php-pos-web-4 to run these tasks
Below is my docker-compose.yml file
version: '3.9'
services:
production_php_point_of_sale_app:
logging:
driver: "local"
deploy:
restart_policy:
condition: any
mode: global
labels:
caddy: "http://*.phppointofsale.com, http://*.phppos.com"
caddy.reverse_proxy.trusted_proxies: "private_ranges"
caddy.reverse_proxy: "{{upstreams}}"
image: phppointofsale/production-app
build:
context: "production_php_point_of_sale_app"
restart: always
env_file:
- production_php_point_of_sale_app/.env
- .env
networks:
- app_network
- mail
caddy_server:
image: lucaslorentz/caddy-docker-proxy:ci-alpine
ports:
- 80:80
networks:
- caddy_controller
- app_network
environment:
- CADDY_DOCKER_MODE=server
- CADDY_CONTROLLER_NETWORK=10.200.200.0/24
volumes:
- caddy_data:/data
deploy:
restart_policy:
condition: any
mode: global
labels:
caddy_controlled_server:
caddy_controller:
image: lucaslorentz/caddy-docker-proxy:ci-alpine
networks:
- caddy_controller
- app_network
environment:
- CADDY_DOCKER_MODE=controller
- CADDY_CONTROLLER_NETWORK=10.200.200.0/24
volumes:
- /var/run/docker.sock:/var/run/docker.sock
deploy:
restart_policy:
condition: any
placement:
constraints: [node.role == manager]
networks:
caddy_controller:
driver: overlay
ipam:
driver: default
config:
- subnet: "10.200.200.0/24"
app_network:
driver: overlay
mail:
driver: overlay
volumes:
caddy_data: {}

How to map specific port inside docker container when using traefik?

Here's my docker-compose.yml:
version: '3'
services:
website:
build: ./website
expose: [3000]
labels:
- "traefik.frontend.rule=Host:localhost"
blog:
build: ./blog
expose: [4000]
labels:
- "traefik.frontend.rule=Host:localhost;PathPrefix:/blog"
docs:
build: ./docs
expose: [3000]
labels:
- "traefik.frontend.rule=Host:localhost;PathPrefix:/docs"
proxy:
image: traefik
command: --api.insecure=true --providers.docker
networks:
- webgateway
ports:
- "80:80"
- "8080:8080"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
networks:
webgateway:
driver: bridge
What I want is access three different node.js websites via different routes. But these three node.js websites actually expose different ports. Now my treafik is running. I can config via localhost:8080 But localhost localhost/blog and localhost/docs are all 404 page not found
P.S: I'm not sure whether port is the issue I should investigate, because changing one node.js service to port 80 doesn't solve the puzzle. And I saw on traefik dashboard the rule is Host(blog-dev)
PathPrefix:/blog
When you have this as a routing rule, traefix won't automatically remove the prefix when sending to the container.
So unless you have a route /blog inside your container you will get a 404.
So what you normally do is also add a middleware to strip this ->
https://docs.traefik.io/middlewares/stripprefix/
Also you appear not to be setting your rules based on your service.
So as an example for your first service blog,
try->
labels:
- "traefik.http.routers.blog.rule=Host(`localhost`) && PathPrefix(`/blog`)"
- "traefik.http.routers.blog.middlewares=strip-blog"
- "traefik.http.middlewares.strip-blog.stripprefix.prefixes=/blog"
And then do the same for your other routes, don't forget to replace routers.blog with routers.docs etc..
labels:
- traefik.http.services.<YOUR-SERVICE-NAME>.loadbalancer.server.port=9763
EG:
services:
wso:
image: "my-custom-wso-image"
volumes:
- .....
labels:
- "traefik.enable=true"
- "traefik.http.routers.wso.tls=true"
- "traefik.http.routers.wso.rule=Host(`my.nice.url`)"
- "traefik.http.services.wso.loadbalancer.server.port=9763" #<-----
Thanks to #Keith I found the solution
version: '3'
services:
website:
build: ./website
expose: [3000]
networks: # It's essential to specify the same network in every service
- webgateway
labels:
- "traefik.http.routers.website.rule=Host(`localhost`)" # Use the right format
- "traefik.port=3000" # Let traefik find the right port
blog:
build: ./blog
expose: [4000]
networks:
- webgateway
labels:
- "traefik.http.routers.blog.rule=Host(`localhost`) && PathPrefix(`/blog`)" # blog has a root as `/blog` so no need to strip otherwise too many redirects
- "traefik.port=4000"
docs:
build: ./docs
expose: [3000]
networks:
- webgateway
labels:
- "traefik.http.routers.docs.rule=Host(`localhost`) && PathPrefix(`/docs`)"
- "traefik.http.routers.docs.middlewares=strip-docs" # Necessary as Keith mentioned
- "traefik.http.middlewares.strip-docs.stripprefix.prefixes=/docs"
- "traefik.port=3000"
proxy:
image: traefik
command: --api.insecure=true --providers.docker
networks:
- webgateway
ports:
- "80:80"
- "8080:8080"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
networks:
webgateway:
driver: bridge

Combining Traefik frontend redirect replacement with PathPrefixStrip

I am encountering some conflicts between the traefik.frontend.redirect and PathPrefixStrip. the docker-compose.yml file below always routes www.mysite.nl/adminer to the wordpress container. If I omit the redirect rules it works correctly and i get routed to the adminer instance. How can I make these rules work together?
Drilled down docker-comose.yml:
version: '3'
services:
wordpress:
image: wordpress:latest
restart: $RESTART
container_name: ${COMPOSE_PROJECT_NAME}_wp
depends_on:
- mysql
networks:
- web
labels:
- 'traefik.backend=$COMPOSE_PROJECT_NAME'
- 'traefik.entrypoint=https'
- 'traefik.enable=true'
- 'traefik.frontend.rule=Host:mysite.nl, www.mysite.nl, cdn.mysite.net'
# omitting these rules make the adminer instance reachable
- 'traefik.frontend.redirect.regex=^https?://mysite.nl/(.*)'
- 'traefik.frontend.redirect.replacement=https://www.mysite.nl/$${1}'
mysql:
image: mysql:latest
restart: $RESTART
container_name: ${COMPOSE_PROJECT_NAME}_db
networks:
- web
adminer:
image: adminer:4.6.2
restart: $RESTART
container_name: ${COMPOSE_PROJECT_NAME}
depends_on:
- mysql
networks:
- web
labels:
- 'traefik.backend=${COMPOSE_PROJECT_NAME}_adminer'
- 'traefik.entrypoint=https'
- 'traefik.enable=true'
- 'traefik.frontend.rule=Host:www.mysite.nl;PathPrefixStrip:/adminer'
networks:
web:
external:
name: traefik_${COMPOSE_PROJECT_NAME}_web
The issue you are running into is due to overlapping rules.
The request www.mysite.nl/adminer
Matches both:
traefik.frontend.rule=Host:mysite.nl, www.mysite.nl, cdn.mysite.net
and traefik.frontend.rule=Host:www.mysite.nl;PathPrefixStrip:/adminer
Therefore Traefik does not know which to route requests to.
Use the traefik.frontend.priority label to set an order for matching (from https://docs.traefik.io/configuration/backends/docker/#on-containers)
With help from Daniel Tomcej i came to the following working docker-compose.yml. You have to set the priority explicitly on both containers.
version: '3'
services:
wordpress:
image: wordpress:latest
restart: $RESTART
container_name: ${COMPOSE_PROJECT_NAME}_wp
depends_on:
- mysql
networks:
- web
labels:
- 'traefik.backend=$COMPOSE_PROJECT_NAME'
- 'traefik.entrypoint=https'
- 'traefik.enable=true'
- 'traefik.frontend.rule=Host:mysite.nl, www.mysite.nl, cdn.mysite.net'
- 'traefik.frontend.redirect.regex=^https?://mysite.nl/(.*)'
- 'traefik.frontend.redirect.replacement=https://www.mysite.nl/$${1}'
- 'traefik.frontend.priority=5'
mysql:
image: mysql:latest
restart: $RESTART
container_name: ${COMPOSE_PROJECT_NAME}_db
networks:
- web
adminer:
image: adminer:4.6.2
restart: $RESTART
container_name: ${COMPOSE_PROJECT_NAME}
depends_on:
- mysql
networks:
- web
labels:
- 'traefik.backend=${COMPOSE_PROJECT_NAME}_adminer'
- 'traefik.entrypoint=https'
- 'traefik.enable=true'
- 'traefik.frontend.rule=Host:www.mysite.nl;PathPrefixStrip:/adminer'
- 'traefik.frontend.priority=20'
networks:
web:
external:
name: traefik_${COMPOSE_PROJECT_NAME}_web

Handling server redirection with traefik

I have a http server running in a docker. Accessing the server at / redirects it to /web. This works fine locally. I have setup traefik to connect to the docker through xxxxxxx.com domain. However, this results in a 404 page not found but when I try xxxxxxxx.com/web it works. How does traefik handle this kind of redirects? Thanks in advance.
Here's my docker-compose.yml file:
version: "3"
networks:
proxy:
external: true
internal:
external: false
services:
web:
restart: always
image: odoo:10.0
labels:
- traefik.backend=web
- traefik.frontend.rule=Host:portal.sironirestaurant.com
- traefik.docker.network=proxy
- traefik.port=8069
networks:
- internal
- proxy
depends_on:
- db
ports:
- 8069:8069
volumes:
- odoo-web-data:/var/lib/odoo
- ./config:/etc/odoo
- ./addons:/mnt/extra-addons
db:
restart: always
image: postgres:9.4
networks:
- internal
labels:
- traefik.enable=false
environment:
- POSTGRES_PASSWORD=xxxxxxx
- POSTGRES_USER=xxxxxx
- PGDATA=/var/lib/postgresql/data/pgdata
volumes:
- odoo-db-data:/var/lib/postgresql/data/pgdata
volumes:
odoo-web-data:
odoo-db-data:

Connection refused when making curl request inside docker

I have a nginx webserver with docker compose with the following web apps:
example.com
api.example.com
I can curl both sides from outside, but I need to curl from one web page to the other one.
curl example.com -> host not found
curl nginx -> returns exmaple.com app
I tried to set the servername to api.nginx and curling this, but then it says host not found
So how do I have to set the configuration so both apps can communicate?
docker-compose:
version: '2'
services:
### Applications Code Container #############################
applications:
image: tianon/true
volumes:
- ${APPLICATION}:/var/www
### Workspace Utilities Container ###########################
workspace:
build:
context: ./workspace
args:
- INSTALL_XDEBUG=${WORKSPACE_INSTALL_XDEBUG}
- INSTALL_SOAP=${WORKSPACE_INSTALL_SOAP}
- INSTALL_MSSQL=${WORKSPACE_INSTALL_MSSQL}
- INSTALL_NODE=${WORKSPACE_INSTALL_NODE}
- INSTALL_YARN=${WORKSPACE_INSTALL_YARN}
- INSTALL_DRUSH=${WORKSPACE_INSTALL_DRUSH}
- INSTALL_AEROSPIKE=${WORKSPACE_INSTALL_AEROSPIKE}
- INSTALL_V8JS=${WORKSPACE_INSTALL_V8JS}
- COMPOSER_GLOBAL_INSTALL=${WORKSPACE_COMPOSER_GLOBAL_INSTALL}
- INSTALL_WORKSPACE_SSH=${WORKSPACE_INSTALL_WORKSPACE_SSH}
- INSTALL_LARAVEL_ENVOY=${WORKSPACE_INSTALL_LARAVEL_ENVOY}
- INSTALL_DEPLOYER=${WORKSPACE_INSTALL_DEPLOYER}
- INSTALL_LINUXBREW=${WORKSPACE_INSTALL_LINUXBREW}
- INSTALL_MC=${WORKSPACE_INSTALL_MC}
- PUID=${WORKSPACE_PUID}
- PGID=${WORKSPACE_PGID}
- NODE_VERSION=${WORKSPACE_NODE_VERSION}
- YARN_VERSION=${WORKSPACE_YARN_VERSION}
- TZ=${WORKSPACE_TIMEZONE}
dockerfile: "Dockerfile-${PHP_VERSION}"
volumes_from:
- applications
extra_hosts:
- "dockerhost:${DOCKER_HOST_IP}"
ports:
- "${WORKSPACE_SSH_PORT}:22"
tty: true
networks:
- frontend
- backend
### PHP-FPM Container #######################################
php-fpm:
build:
context: ./php-fpm
args:
- INSTALL_XDEBUG=${PHP_FPM_INSTALL_XDEBUG}
- INSTALL_SOAP=${PHP_FPM_INSTALL_SOAP}
- INSTALL_MONGO=${PHP_FPM_INSTALL_MONGO}
- INSTALL_MSSQL=${PHP_FPM_INSTALL_MSSQL}
- INSTALL_ZIP_ARCHIVE=${PHP_FPM_INSTALL_ZIP_ARCHIVE}
- INSTALL_BCMATH=${PHP_FPM_INSTALL_BCMATH}
- INSTALL_PHPREDIS=${PHP_FPM_INSTALL_PHPREDIS}
- INSTALL_MEMCACHED=${PHP_FPM_INSTALL_MEMCACHED}
- INSTALL_OPCACHE=${PHP_FPM_INSTALL_OPCACHE}
- INSTALL_EXIF=${PHP_FPM_INSTALL_EXIF}
- INSTALL_AEROSPIKE=${PHP_FPM_INSTALL_AEROSPIKE}
- INSTALL_MYSQLI=${PHP_FPM_INSTALL_MYSQLI}
- INSTALL_TOKENIZER=${PHP_FPM_INSTALL_TOKENIZER}
- INSTALL_INTL=${PHP_FPM_INSTALL_INTL}
- INSTALL_GHOSTSCRIPT=${PHP_FPM_INSTALL_GHOSTSCRIPT}
- INSTALL_LDAP=${PHP_FPM_INSTALL_LDAP}
- INSTALL_SWOOLE=${PHP_FPM_INSTALL_SWOOLE}
dockerfile: "Dockerfile-${PHP_VERSION}"
volumes_from:
- applications
volumes:
- ./php-fpm/php${PHP_VERSION}.ini:/usr/local/etc/php/php.ini
expose:
- "9000"
depends_on:
- workspace
extra_hosts:
- "dockerhost:${DOCKER_HOST_IP}"
environment:
- PHP_IDE_CONFIG=${PHP_IDE_CONFIG}
networks:
- backend
### PHP Worker Container #####################################
php-worker:
build:
context: ./php-worker
volumes_from:
- applications
depends_on:
- workspace
extra_hosts:
- "dockerhost:${DOCKER_HOST_IP}"
networks:
- backend
### MySQL Container #########################################
mysql:
build:
context: ./mysql
environment:
- MYSQL_DATABASE=${MYSQL_DATABASE}
- MYSQL_USER=${MYSQL_USER}
- MYSQL_PASSWORD=${MYSQL_PASSWORD}
- MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD}
volumes:
- ${DATA_SAVE_PATH}/mysql:/var/lib/mysql
- ./mysql/docker-entrypoint-initdb.d:/docker-entrypoint-initdb.d
ports:
- "${MYSQL_PORT}:3306"
networks:
- backend
- frontend
### Redis Container #########################################
redis:
build: ./redis
volumes:
- ${DATA_SAVE_PATH}/redis:/data
ports:
- "6379:6379"
networks:
- backend
### Caddy Server Container ##################################
caddy:
build: ./caddy
volumes_from:
- applications
volumes:
- ${CADDY_CUSTOM_CADDYFILE}:/etc/Caddyfile
- ${CADDY_HOST_LOG_PATH}:/var/log/caddy
- ${DATA_SAVE_PATH}:/root/.caddy
ports:
- "${CADDY_HOST_HTTP_PORT}:80"
- "${CADDY_HOST_HTTPS_PORT}:443"
depends_on:
- php-fpm
networks:
- frontend
- backend
### Adminer Container ####################################
adminer:
build:
context: ./adminer
args:
- INSTALL_MSSQL=${ADM_INSTALL_MSSQL}
ports:
- "${ADM_PORT}:8080"
depends_on:
- php-fpm
networks:
- frontend
- backend
### Laravel Echo Server #######################################
laravel-echo-server:
build:
context: ./laravel-echo-server
volumes:
- ./laravel-echo-server/laravel-echo-server.json:/app/laravel-echo-server.json:ro
ports:
- "${LARAVEL_ECHO_SERVER_PORT}:6001"
links:
- redis
networks:
- frontend
- backend
### Networks Setup ############################################
networks:
frontend:
driver: "bridge"
backend:
driver: "bridge"
### Volumes Setup #############################################
volumes:
mysql:
driver: "local"
percona:
driver: "local"
mssql:
driver: "local"
postgres:
driver: "local"
memcached:
driver: "local"
redis:
driver: "local"
neo4j:
driver: "local"
mariadb:
driver: "local"
mongo:
driver: "local"
minio:
driver: "local"
rethinkdb:
driver: "local"
phpmyadmin:
driver: "local"
adminer:
driver: "local"
aerospike:
driver: "local"
caddy:
driver: "local"
elasticsearch-data:
driver: "local"
elasticsearch-plugins:
driver: "local"
I had to add the extra hosts to the extra_hosts in my php-fpm service:
https://github.com/laradock/laradock/issues/435
php-fpm:
build:
context: ./php-fpm
args:
- INSTALL_XDEBUG=${PHP_FPM_INSTALL_XDEBUG}
- INSTALL_SOAP=${PHP_FPM_INSTALL_SOAP}
- INSTALL_MONGO=${PHP_FPM_INSTALL_MONGO}
- INSTALL_MSSQL=${PHP_FPM_INSTALL_MSSQL}
- INSTALL_ZIP_ARCHIVE=${PHP_FPM_INSTALL_ZIP_ARCHIVE}
- INSTALL_BCMATH=${PHP_FPM_INSTALL_BCMATH}
- INSTALL_PHPREDIS=${PHP_FPM_INSTALL_PHPREDIS}
- INSTALL_MEMCACHED=${PHP_FPM_INSTALL_MEMCACHED}
- INSTALL_OPCACHE=${PHP_FPM_INSTALL_OPCACHE}
- INSTALL_EXIF=${PHP_FPM_INSTALL_EXIF}
- INSTALL_AEROSPIKE=${PHP_FPM_INSTALL_AEROSPIKE}
- INSTALL_MYSQLI=${PHP_FPM_INSTALL_MYSQLI}
- INSTALL_TOKENIZER=${PHP_FPM_INSTALL_TOKENIZER}
- INSTALL_INTL=${PHP_FPM_INSTALL_INTL}
- INSTALL_GHOSTSCRIPT=${PHP_FPM_INSTALL_GHOSTSCRIPT}
- INSTALL_LDAP=${PHP_FPM_INSTALL_LDAP}
- INSTALL_SWOOLE=${PHP_FPM_INSTALL_SWOOLE}
dockerfile: "Dockerfile-${PHP_VERSION}"
volumes_from:
- applications
volumes:
- ./php-fpm/php${PHP_VERSION}.ini:/usr/local/etc/php/php.ini
expose:
- "9000"
depends_on:
- workspace
extra_hosts:
- "dockerhost:${DOCKER_HOST_IP}"
- "example.com:${DOCKER_HOST_IP}"
- "api.example.com:${DOCKER_HOST_IP}"

Resources