Ive been learning Traefik to use as a reverse proxy for various Wordpress sites Im running in Docker containers on a server. Currently I have 2 domains setup with Wp on the same ip and are working correctly.
Im having problems getting the domains to redirect to www so right now at http://example.com it just shows 'Index of' I have tried forcing a redirection via htaccess but this isnt working so Im assuming theres something I have to do in the Traefik settings?
This is my docker-compose.yml file but Ive only included the important parts here:
services:
reverse-proxy:
image: traefik # The official Traefik docker image
command: --api --docker # Enables the web UI and tells Træfik to listen to docker
ports:
- "80:80" # The HTTP port
- "8080:8080" # The Web UI (enabled by --api)
volumes:
- /var/run/docker.sock:/var/run/docker.sock # So that Traefik can listen to the Docker events
- ./traefik.toml:/traefik.toml
wp-web2:
container_name: cowork-wp
image: wordpress:latest
restart: always
environment:
WORDPRESS_DB_HOST: mysql-db-cowork
WORDPRESS_DB_USER: foo
WORDPRESS_DB_NAME: foo
WORDPRESS_DB_PASSWORD: passwd123
depends_on:
- mysql-db-cowork
labels:
- "traefik.frontend.rule=Host:example.com"
- "traefik.frontend.rule=Host:www.example.com"
- "traefik.frontend.forcehost:www.example.com"
#- "traefik.frontend.rule=Path: /"
volumes:
- ./src-tdm:/var/www/html
As you can see in the labels Ive been trying different Hosts as well as 'forcehost' but none of these seemed to have worked.
And this is the toml file:
defaultEntryPoints = ["http"]
[entryPoints]
[entryPoints.http]
address = ":80"
#Define Docker Backend Configuration
[docker]
endpoint = "unix:///var/run/docker.sock"
domain = "example.com"
watch = true
exposedByDefault = true
and finally this is my force www rewrite rule from .htaccess
#Force www:
RewriteEngine on
RewriteCond %{HTTP_HOST} ^example.com [NC]
RewriteRule ^(.*)$ http://www.example.com$1 [L,R=301,NC]
A closer inspection of the documents shows that the different domains need to be defined with commas in the frontend Host: argument, eg:
- "traefik.frontend.rule=Host:www.example.com, example.com"
Related
I've been following a tutorial to setup a website on a raspberry pi using docker.
I'm running the following in my yaml file:
version: "3.7"
services:
db:
build: ./db
container_name: db
ports:
- "3306:3306"
volumes:
- db_data:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: *Blocking out my password*
MYSQL_DATABASE: wordpress
MYSQL_USER: wordpress
MYSQL_PASSWORD: *Blocking out my password*
networks:
website_network:
aliases:
- wordpress
wordpress:
build: .
container_name: wordpress
ports:
- "80"
networks:
website_network:
aliases:
- wordpress
environment:
WORDPRESS_DB_HOST: db:3306
WORDPRESS_DB_USER: wordpress
WORDPRESS_DB_PASSWORD: *Blocking out my password*
WORDPRESS_DB_NAME: wordpress
nginx:
build: ./nginx
container_name: nginx
ports:
- "443:443"
- "80"
networks:
website_network:
aliases:
- nginx-proxy
networks:
website_network:
name: website_network
volumes:
db_data:
driver: local
name: db_data
I have some additional files which are taking the wildcard encyption files, unzipping them and running them inside the nginx container. My problem is that when I run all the containers, the website "appears" but its basically a blank screen. my code doesn't have any typos from what I can tell, so I'm a bit stuck. I think that my cointainers aren't really talking to each other anymore. The encrpyting works since the website is accessible through https:
I don't know if I can be help, but I've been stuck for about a week now and I'm at a loss. I might just find another tutorial.
Ive been trying to recheck the code, uninstalling images and reinstalling them using docker-compose prune or docker container --remove-orphans, etc. I've tried taking it down and putting it back up, building the containers first but nothing seems to help. I'm really stuck. My guess is it's something stupid and I'm just missing it.
I've got a node process running on port 3000 using pm2.
I want to configure Traefik so that it reverse proxies this service on port 80.
Following this excellent blog post, I was able to quickly start Traefik using docker compose and set up a skeleton config for the node-server.
However, that example assumes the node process is hosted inside a docker as well. I couldn't get this to work for my node process (*) so I just want to be able to configure Traefik by pointing to port 3000 in some way. Seems straightforward but couldn't get it to work.
I'm stuck with the following config (which is a mix of various blog-posts without actually knowing what I'm doing):
services:
reverse-proxy:
image: traefik:v2.4
container_name: "traefik"
command:
- "--api.insecure=true"
- "--api.dashboard=true"
- "--api.debug=true"
- "--providers.docker=true"
- "--log.LEVEL=DEBUG"
- "--entryPoints.web.address=:80"
- "--entryPoints.websecure.address=:443"
- "--providers.docker.exposedbydefault=false"
- "--certificatesresolvers.myresolver.acme.httpchallenge=true"
- "--certificatesresolvers.myresolver.acme.httpchallenge.entrypoint=web"
- "--certificatesresolvers.myresolver.acme.email=xxxx#xxx.com"
- "--certificatesresolvers.myresolver.acme.storage=/letsencrypt/acme.json"
ports:
- "443:443"
- "80:80"
- "8080:8080"
volumes:
- "./letsencrypt:/letsencrypt"
- "/var/run/docker.sock:/var/run/docker.sock:ro"
node-server:
loadBalancer:
servers:
- url: http://127.0.0.1:3000/
labels:
- "traefik.enable=true"
- "traefik.http.routers.node-server.rule=Host(`xxxxxx.com`)"
- "traefik.http.routers.node-server.entrypoints=websecure"
- "traefik.http.routers.node-server.tls.certresolver=myresolver"
- "traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https"
- "traefik.http.routers.redirs.rule=hostregexp(`{host:.+}`)"
- "traefik.http.routers.redirs.entrypoints=web"
- "traefik.http.routers.redirs.middlewares=redirect-to-https"
This gives the error: 'Unsupported config option for services.node-server: 'loadBalancer'"
Long story short: how would I configure Traefik to just reverse proxy a service running on port 3000?
*) A total newbie to Docker and I couldn't get the situation to work, where the node process depends on custom javascript modules in a parent directory. Perhaps there's a way to do this and I could do it in the 'host node in docker' way instead. I'm all ears
A few months ago I have configured a reverse proxy, here you go my configuration:
version: '3'
services:
reverse-proxy:
image: traefik:v2.5
container_name: selling-point-reverse-proxy
ports:
- 80:80
- 8080:8080
volumes:
# Traefik can listen to the Docker events
- /var/run/docker.sock:/var/run/docker.sock
command:
# Enables the web UI
- --api.insecure=true
# Tells Traefik to listen to docker
- --providers.docker
# Creates a new entrypoint called web
- --entrypoints.web.address=:80
# Disable container exposition
- --providers.docker.exposedByDefault=false
# Traefik matches against the container's labels to determine whether to create any route for that container
- --providers.docker.constraints=Label(`traefik.scope`,`selling-point`)
# Enable tracing (using jaeger by default)
- --tracing=true
# Name of the tracing service on Jaeger
- --tracing.serviceName=reverse-proxy
# Host and port of the Jaeger agent
- --tracing.jaeger.localAgentHostPort=jaeger:6831
labels:
# Matcher for creating a route
- traefik.scope=selling-point
# Exposes container
- traefik.enable=true
# Creates circuit breaker middleware
- traefik.http.middlewares.latency.circuitbreaker.expression=LatencyAtQuantileMS(50.0) > 10000
# Creates a forward auth middleware
- traefik.http.middlewares.auth.forwardauth.address=http://auth:3000/auth/authorize
# Enables cross origin requests
- traefik.http.middlewares.cors.headers.accesscontrolalloworiginlist=*
# Enables forwarding of the request headers
- traefik.http.middlewares.cors.headers.accessControlAllowHeaders=*
networks:
- selling-point
api:
image: selling-point-api
container_name: selling-point-api
build:
context: ./selling-point-api
labels:
# Tells Traefik where to redirect the request if the url has the specified prefix
- traefik.http.routers.api.rule=PathPrefix(`/api`)
# Attaches a middleware for forwarding the authentication
- traefik.http.routers.api.middlewares=cors,auth,latency
# Attaches entrypoints
- traefik.http.routers.api.entrypoints=web
# Exposes container
- traefik.enable=true
# Matcher for creating a route
- traefik.scope=selling-point
# Creates a service called selling-point-api
- traefik.http.services.selling-point-api.loadbalancer.server.port=3000
# Attach the container to a service
- traefik.http.routers.api.service=selling-point-api
volumes:
- ./selling-point-api/src:/app/src
networks:
- selling-point
environment:
WAIT_HOSTS: mysql:3306
DATABASE_URL: mysql://root:huachinango#mysql:3306/selling_point
NODE_ENV: development
auth:
image: selling-point-auth
container_name: selling-point-auth
build:
context: ./selling-point-auth
labels:
# Tells Traefik where to redirect the request if the url has the specified prefix
- traefik.http.routers.auth.rule=PathPrefix(`/auth`)
# Attaches a circuit breaker middleware
- traefik.http.routers.auth.middlewares=cors,latency
# Attaches entrypoints
- traefik.http.routers.auth.entrypoints=web
# Exposes container
- traefik.enable=true
# Matcher for creating a route
- traefik.scope=selling-point
# Creates a service called selling-point-auth
- traefik.http.services.selling-point-auth.loadbalancer.server.port=3000
# Attach the container to a service
- traefik.http.routers.auth.service=selling-point-auth
environment:
WAIT_HOSTS: mysql:3306
IGNORE_ENV_FILE: 'true'
DATABASE_URL: mysql://root:huachinango#mysql:3306/selling_point
PASSWORD_SALT: $$2b$$10$$g0OI8KtIE3j6OQqt1ZUDte
NODE_ENV: development
volumes:
- ./selling-point-auth/src:/app/src
networks:
- selling-point
mysql:
image: mysql:5
container_name: selling-point-mysql
environment:
MYSQL_ROOT_PASSWORD: huachinango
MYSQL_DATABASE: selling_point
networks:
- selling-point
volumes:
- mysql-db:/var/lib/mysql
jaeger:
image: jaegertracing/all-in-one:1.29
container_name: selling-point-tracing
environment:
COLLECTOR_ZIPKIN_HOST_PORT: :9411
ports:
- 16686:16686
networks:
- selling-point
volumes:
mysql-db:
networks:
selling-point:
name: selling-point
driver: bridge
I am new to AWS and new with Traefik too. I am having a lot of trouble trying to remove the need of port especification in a application I am developing.
When I hit http://api-landingpage.cayama.com.br/ it give`s me an 404 page error, but when I try http://api-landingpage.cayama.com.br:8001/ it goes to my api correctly.
I hosted my domain in AWS Route53 and I am using docker as a provider.
Here my configurations:
docker-compose.yml:
version: "3"
services:
app:
build: .
ports:
- "8001:8001"
command: "npm start"
docker-production.yml:
version: "3"
services:
traefik:
image: traefik
command:
- "--api.insecure=true"
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
- "--entrypoints.web.address=:80"
ports:
- "80:80"
- "8080:8080"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
app:
labels:
- "traefik.enable=true"
- "traefik.http.routers.app.rule=Host(`http://api-landingpage.cayama.com.br/`)"
- "traefik.http.routers.app.entrypoints=web"
I am sure is there a basic thing that I am missing here, can anyone help me please?
I just want to not have to specify, on URL, the port which my application is running.
Thanks guys!
Theoretically, as you said, you shouldn't have to specify the port manually.
I'm not totally sure it's the cause but you are using a full URL instead of a host.
Basically you should replace this:
- "traefik.http.routers.app.rule=Host(`http://api-landingpage.cayama.com.br/`)"
With this:
- "traefik.http.routers.app.rule=Host(`api-landingpage.cayama.com.br`)"
If it does not solve your problem you could try using the loadbalancer directive, even if it is theoretically usefull for Docker Swarm, not for Docker (put this in your app service):
- "traefik.http.services.app.loadbalancer.server.port=8001"
Then if it's still not working enable debugging and look for errors in the logs.
In order to enable debugging, add this to your Traefik service in the command section:
- --log.level=DEBUG
Have you tried:
- "traefik.http.services.app.loadbalancer.server.port=8001"
1. Caddy version (caddy version): 2.0.0
2. How I run Caddy:
I use Docker (docker-compose) to run Caddyserver. Here is the command of my caddy service: command: ["caddy", "run", "--config", "/etc/caddy/Caddyfile"]
a. System environment:
Docker version 19.03.1
docker-compose version 1.22.0
b. Command:
docker-compose -f docker-compose.caddy.yml up -d --build
c. Service/unit/compose file:
version: "3.4"
services:
# other services...
caddy:
image: caddy:2.0.0
restart: always
container_name: caddy
deploy:
replicas: 2
update_config:
delay: 10s
restart_policy:
condition: on-failure
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile
- www:/var/www/html
- caddy_data:/data
- caddy_config:/config
ports:
- "80:80"
- "443:443"
command: ["caddy", "run", "--config", "/etc/caddy/Caddyfile"]
volumes:
db-data:
conf:
www:
cert:
caddy_data:
caddy_config:
d. My complete Caddyfile or JSON config:
:443 {
root * /var/www/html/{host}
file_server
tls {
on_demand
}
reverse_proxy /sites/action/* api:4000
}
3. The problem I'm having:
I run a platform where users can host their websites, so I have plenty of domains hosted into the server, each domain has its own directory. Whenever visitors hit into a domain I look into the parent directory by the {host} parameter and serve its files. It works totally fine until I want to redirect non-www to www or www to non-www. This is not my problem as well, the problem arises when I don't know whether the domain should redirect to www or non-www!
When the domains are created by the users some of them may choose to forward to www and some of them may choose to forward to non-www. I can create a system file depending on that choice (eg: redirect-rules.conf). I need a way to read the content of that file and execute it in Caddyfile.
Let's say a domain directory example.com was created and chosen www to be forwarded into example.com. I am thinking of a pseudo redirect-rules.conf file that contains:
redir www.example.com example.com
4. Error messages and/or full log output:
I tried to read a conf file using import directive like this: import /var/www/html/{host}/redir_rules. But this configuration is wrong because I am not allowed to use variable into a file path!
The error I get: Error during parsing: File to import not found: /var/www/html/{host}/redir
What would be the ideal solution for this scenario?
5. What I already tried:
import a conf file from root, seems like it import directive reads file from absolute path.
6. Links to relevant resources:
Basically I am attempting to setup my node app to be served by nginx at http://192.168.99.100/ of my docker machine instead of by bypassing nginx and doing something like http://192.168.99.100:7777/ by publishing port 7777 to the host.
I am currently attempting to serve my frontend node app container on the root of my docker-machine i.e http://192.168.99.100/ . I am using dockergen together with nginx (separate containers) to have this be automatically generated. My node app which is built from a Dockerfile is run npm run dev:no-debug at the following address and port localhost:7777.
I have the following compose file.
version: '2'
services:
frontend:
build:
context: ./frontend
volumes:
- ./frontend:/usr/src/app
- /usr/src/app/node_modules
expose:
- "7777"
environment:
- "PORT=7777"
- "VIRTUAL_HOST=192.169.99.100"
nginx_proxy:
image: nginx
container_name: nginx_proxy
ports:
- "80:80"
- "443:443"
links:
- frontend
volumes:
- /tmp/nginx:/etc/nginx/conf.d
- ./nginx/certs:/etc/nginx/certs
dockergen:
image: jwilder/docker-gen
container_name: dockergen
volumes_from:
- nginx_proxy
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
- ./dockergen/templates:/etc/docker-gen/templates
entrypoint: /usr/local/bin/docker-gen -notify-sighup nginx_proxy -watch -only-exposed /etc/docker-gen/templates/nginx.tmpl /etc/nginx/conf.d/default.conf
The containers start up fine and are working correctly with no errors.
Name Command State Ports
--------------------------------------------------------------------------------------------------
cms_frontend_1 npm run dev:no-debug Up 7777/tcp
dockergen /usr/local/bin/docker-gen ... Up
nginx_proxy nginx -g daemon off; Up 0.0.0.0:443->443/tcp, 0.0.0.0:80->80/tcp
The default.conf nginx file generated with my current settings has:
upstream 192.169.99.100 {
# cms_frontend_1
server cms_frontend_1:7777;
}
server {
server_name 192.169.99.100;
listen 80 ;
access_log /var/log/nginx/access.log vhost;
location / {
proxy_pass http://192.169.99.100;
}
}
When going to http://192.168.99.100/ i get a 503.
Im still pretty new to world of networking however from the above snippet when a request of 192.169.99.100 is picked up, nginx then uses the upstream block corresponding to the proxy_pass address which then passes this request through to that server ie cms_frontend_1:7777?
From this I guess the issue is that the cms_frontend_1:7777 doesnt correspond to localhost:7777 which is where the server is running. If i add the following to the frontend service container I can then access my app at http://192.168.99.100:7777. However this defeats the purpose of having nginx proxy the request.
ports:
- "7777:7777"
So my question is this an incorrect configuration or have I made a mistake/misunderstanding about how some concept works? Also I'd like to have this be as dynamic as possible, so say if i wanted to deploy to aws things wouldnt need to be reconfigured all over the place (hence my attempted use of dockergen).
Thanks