docker swarm custom containers with traefik - express

I'm trying to set up a docker swarm using traefik in digital ocean. I followed this tutorial and I get it to work entirely until I add one of my custom made containers. I am trying to simply add one first (there are 14 in total) and they are all very very similar, all of them are express apps that serve as restful API's handling one resource per service. However, when trying to access that specific subdomain I get a connection refused error.
Here's my docker-stack.yml file:
version: '3.6'
services:
traefik:
image: traefik:latest
networks:
- mynet
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- ./traefik.toml:/traefik.toml
ports:
- "80:80"
- "8080:8080"
command: --api
main:
image: nginx
networks:
- mynet
deploy:
labels:
- "traefik.port=80"
- "traefik.backend=main"
- "traefik.frontend.rule=Host:domain.com"
two:
image: jwilder/whoami
networks:
- mynet
deploy:
labels:
- "traefik.port=8000"
- "traefik.backend=two"
- "traefik.frontend.rule=Host:two.domain.com"
three:
image: emilevauge/whoami
networks:
- mynet
deploy:
labels:
- "traefik.port=80"
- "traefik.backend=three"
- "traefik.frontend.rule=Host:three.domain.com"
user-service:
image: hollarves/users:latest
env_file:
- .env.user
networks:
- mynet
deploy:
labels:
- "traefik.port=80"
- "traefik.backend=users"
- "traefik.frontend.rule=Host:users.domain.com"
networks:
mynet:
driver: overlay
As I said, going to two.domain.com and three.domain.com works fine, and the whoami containers respond with their info. However, I get a connection refused error when trying users.domain.com
Note: domain.com is an actual domain I am using that is live pointing to a digitalocean cluster, I'm just hiding it for privacy reasons.
The entrypoint for this users-service is:
if (process.env.NODE_ENV !== "production") {
require("dotenv").load()
}
const express = require("express"),
bodyParser = require("body-parser"),
logger = require("morgan"),
//helmet = require("helmet"),
cors = require("cors"),
PORT = parseInt(process.env.PORT, 10) || 80
const server = express(),
routes = require("./server/routes")
//server.use(helmet())
server.use(cors())
server.use(logger("dev"))
server.use(bodyParser.json())
server.use("/", routes)
/*eslint no-console: ["error", { allow: ["log"] }] */
const serverObj = server.listen(PORT, () => { console.log("Server listening in PORT ", PORT) })
module.exports = serverObj
I can also confirm that this service is listening on PORT 80 as that's what it outputs when fetching logs from it using docker service logs test-stack_user-service:
test-stack_user-service.1.35p3lxzovphr#node-2 | > users-mueve#0.0.1 start /usr/src/app
test-stack_user-service.1.35p3lxzovphr#node-2 | > node server.js
test-stack_user-service.1.35p3lxzovphr#node-2 |
test-stack_user-service.1.35p3lxzovphr#node-2 | Server listening in PORT 80
Here is my traefik.toml config file just in case:
debug = true
logLevel = "DEBUG"
defaultEntryPoints = ["http"]
[entryPoints]
[entryPoints.http]
address = ":80"
[retry]
[docker]
endpoint="unix:///var/run/docker.sock"
exposedByDefault=true
watch=true
swarmmode=true
I can also see the containers in the traefik dashboard like I used to in my local environment.
I feel like I'm missing a very small detail that is preventing my service from working correctly. Any pointers will be extremely appreciated.
Thanks!

Related

How to setup Traefik as reverse proxy for ASP.NET Core app with kestrel?

So long ago I started studying the data of the solution, but I am so stupid that I have not found a solution to how to configure file docker-compose for a simple ASP.NET Core for traefik proxy.
I took an example of a simple ASP.NET Core application from the Microsoft site, which, after deployment, is available at localhost:8443 using https, because earlier I released a self-signed (aspnetapp.pfx), ok.
Then I unfolded the traefik and configured the dashboard I see that traefik gets information about the aspnet_demo container, but at web app addresses, or webapp.mydomen.com/ or localhost nothing is available - maximum I get the error ERR_TOO_MANY_REDIRECTS in browser.
In logs traefik when referring to webapp.mydomen.com I get "RequestURI ": "/ "
What did you forget to point out?
I understand that the content aspnet_demo get on 443 port, so I tell Traefik where to look, but nothing...
Help me please understanding this. Thank you
My docker compose ASP.NET Core app looks like this:
version: "3.8"
services:
aspnet_demo:
image: mcr.microsoft.com/dotnet/core/samples:aspnetapp
container_name: aspnet_sample
ports:
- 8080:80
- 8443:443
environment:
- ASPNETCORE_ENVIRONMENT=Development
- ASPNETCORE_URLS=https://+:443;http://+:80
- ASPNETCORE_Kestrel__Certificates__Default__Password=password
- ASPNETCORE_Kestrel__Certificates__Default__Path=/https/aspnetapp.pfx
volumes:
- ~/.aspnet/https:/https:ro
networks:
- traefik-reverse-proxy
labels:
- traefik.enable=true
- traefik.http.routers.aspnet.entrypoints=web
- traefik.http.routers.aspnet.rule=Host(`webapp`)
- traefik.http.routers.aspnet_secure.entrypoints=web-secure
- traefik.http.routers.aspnet_secure.rule=Host(`webapp.mydomen.com`)
- traefik.http.routers.aspnet_secure.tls=true
- traefik.http.services.aspnet.loadbalancer.server.port=443
networks:
traefik-reverse-proxy:
external: true
My docker compose Traefik looks like this:
version: "3.8"
services:
traefik:
image: traefik:v2.9
ports:
- "80:80"
- "443:443"
- "8080:8080"
networks:
- traefik-reverse-proxy
volumes:
- "/var/run/docker.sock:/var/run/docker.sock:ro"
- "./configuration/dynamic.yaml:/traefik_conf/dynamic.yaml"
- "./configuration/traefik.yml:/traefik.yml:ro"
- "./cert/:/traefik_conf/cert/"
labels:
- "traefik.enable=true"
- "traefik.http.routers.traefik.service=api#internal"
- "traefik.http.routers.traefik.entrypoints=web-secure"
- "traefik.http.routers.traefik.rule=Host(`traefiklocal.mydomen.com`)"
- "traefik.http.routers.traefik.tls=true"
- "traefik.http.routers.traefik.tls.certresolver=tls"
- "traefik.http.routers.traefik.middlewares=traefik-auth"
- "traefik.http.middlewares.traefik-auth.basicauth.users=unixhost:$$apr1$$vqyMX723$$6nZ1lC3/2JN6QJyeEhJB8/"
networks:
traefik-reverse-proxy:
external: true
My static config Traefik looks like this:
api:
dashboard: true
insecure: true
log:
level: DEBUG
entryPoints:
web:
address: ":80"
forwardedHeaders:
insecure: true
http:
redirections:
entryPoint:
to: web-secure
web-secure:
address: ":443"
providers:
docker:
watch: true
exposedbydefault: false
file:
directory: /traefik_conf/
watch: true
filename: dynamic.yaml
My dynamic config Traefik:
tls:
certificates:
# first certificate
- certFile: "/traefik_conf/cert/pem_com_2022.pem"
keyfile: "/traefik_conf/cert/star_com_2022.key"
# second certificate
- certFile: "/traefik_conf/cert/aspnetapp.pem"
keyfile: "/traefik_conf/cert/aspnetapp.key"
stores:
- default

Localtunnel with Traefik and ssh

I'm looking for a solution with Traefik to do my own Ngrok alternative.
I have multiple a home assistant with the Autossh plugin installed on an another server and would like to access to it by entered the url : home-assistant.server.com
Authssh is configured with the remote forwarding port : 44400:localhost:8123, on ssh port (22).
I found this Traefik configuration (Traefik V1) but would like to use Traefik V2.
I obtain a Bad gateway with my new Traefik configuration.
Do you have any idea to resolve it ? Thanks.
Here, my Traefik V2 configuration :
traefik.toml
[entryPoints]
[entryPoints.http]
address = ":80"
[entryPoints.https]
address = ":443"
[api]
[providers.docker]
endpoint = "unix:///var/run/docker.sock"
[providers.file]
filename = "/etc/traefik/services.toml"
[certificatesResolvers.mycertificate.acme]
email = "contact#server.com"
storage = "acme.json"
[certificatesResolvers.mycertificate.acme.httpChallenge]
entryPoint = "http"
services.toml
[http]
[http.services]
[http.services.nas]
[http.services.nas.loadBalancer]
[[http.services.nas.loadBalancer.servers]]
url = "http://localhost:44400"
docker-compose.yml
version: '3.7'
services:
reverse-proxy:
restart: always
image: traefik:chevrotin
ports:
- "443:443"
- "80:80"
volumes:
- /srv/traefik.toml:/etc/traefik/traefik.toml
- /srv/services.toml:/etc/traefik/services.toml
- /var/run/docker.sock:/var/run/docker.sock
- /srv/acme.json:/acme.json
labels:
- traefik.http.routers.nas.entrypoints=https
- traefik.http.routers.nas.rule=Host(`home-assistant.server.com`)
- traefik.http.routers.nas.service=nas#file
- traefik.http.routers.nas.tls=true
- traefik.http.routers.nas.tls.certresolver=mycertificate

How to redirect to the dashboard from a URL?

I currently access the V2 dashboard through http://traefik.my.server:8080/dashboard/ (Traefik runs in a docker container and 8080 is exposed to the host).
I would like to change that so that the dashboard is available at http://traefik.my.server/dashboard
I tried to add the following labels to configure this behavior but I get a 404 when accessing http://traefik.my.server/dashboard
- traefik.http.routers.dashboard.rule=Host(`traefik.my.server:`) && Path(`/dashboard`)
- traefik.http.services.dashboard.loadbalancer.server.port=8080
- traefik.http.routers.dashboard.entryPoints=http
(the http entrypoint is port 80)
What is the correct way to set up such redirectio
Recommend read:
https://docs.traefik.io/v2.1/operations/dashboard/#secure-mode
https://blog.containo.us/traefik-2-0-docker-101-fc2893944b9d
https://github.com/containous/blog-posts/tree/master/2019_09_10-101_docker
FYI it's not redirection but a routing.
https://community.containo.us/t/how-to-redirect-to-the-dashboard-from-a-url/4082/2
Following up on #Idez help at https://community.containo.us/t/how-to-redirect-to-the-dashboard-from-a-url/4082, a working configuration is
The docker-compose file:
services:
traefik:
container_name: traefik
image: traefik
ports:
- 80:80
- 443:443
restart: unless-stopped
volumes:
- /etc/docker/container-data/traefik:/etc/traefik
- /var/run/docker.sock:/var/run/docker.sock
- /etc/localtime:/etc/localtime:ro
labels:
- traefik.http.routers.api.rule=Host(`traefik.mydomain.org`)
- traefik.http.routers.api.service=api#internal
- traefik.http.routers.api.middlewares=lan
- traefik.http.middlewares.lan.ipwhitelist.sourcerange=192.168.10.0/24, 192.168.20.0/24
- traefik.enable=true
version: "3"
Configuration file
global:
sendAnonymousUsage: true
entryPoints:
http:
address: ":80"
https:
address: ":443"
api:
dashboard: true
providers:
docker:
endpoint: "unix:///var/run/docker.sock"
exposedByDefault: false
defaultRule: "Host(`{{ index .Labels \"com.docker.compose.service\" }}.mydomain.org`)"
log:
level: INFO
#level: DEBUG
certificatesResolvers:
le:
acme:
email: le#mydomain.org
storage: /etc/traefik/acme.json
tlsChallenge: {}
#caServer: "https://acme-staging-v02.api.letsencrypt.org/directory"

Traefik 2.0: How to configure `traefik.frontend.rule=Host:example.com`?

I just attempted to upgrade my existing pretty simple Traefik setup to 2.0.
I am using Docker as a provider.
I am running the containers with docker-compose. This is my docker-compose config:
version: "3.5"
services:
traefik:
image: traefik:v2.0-alpine
read_only: yes
ports:
- 80:80
- 443:443
volumes:
- type: bind
source: /var/run/docker.sock
target: /var/run/docker.sock
- type: bind
source: ./traefik.toml
target: /traefik.toml
- type: bind
source: ./acme.json
target: /acme.json
networks:
- traefik
example:
image: example.com/example/example
labels:
- "traefik.enable=true"
- "traefik.frontend.rule=Host:example.com"
- "traefik.docker.network=traefik"
networks:
- traefik
This is my traefik.toml:
defaultEntryPoints = ["http", "https"]
[Global]
sendAnonymousUsage = true
[entryPoints]
[entryPoints.http]
address = ":80"
[entryPoints.http.redirect]
entryPoint = "https"
[entryPoints.https]
address = ":443"
[entryPoints.https.tls]
[acme]
email = "ssl#example.com"
storage = "acme.json"
entryPoint = "https"
onHostRule = true
onDemand = false
acmeLogging = true
[acme.tlsChallenge]
[docker]
exposedByDefault = false
This setup works fine with Traefik 1.7.
With Traefik 2.0 I observe two issues, looking at the ACME log:
Unable to obtain ACME certificate for domains traefik-example-deployment
Unable to obtain ACME certificate for domains example-example-deployment
Traefik is apparently exposing both containers. It should only expose the example container.
Traefik is ignoring the traefik.frontend.rule=Host:example.com label.
I suspect this might be due to configuration format changes in Traefik 2.0. However, although I looked through the 2.0 documentation, I was unable how the correct configuration looks.
Routers¶
To update the configuration of the Router automatically attached to the container, add labels starting with traefik.routers.{name-of-your-choice}. and followed by the option you want to change. For example, to change the rule, you could add the label traefik.http.routers.my-container.rule=Host(my-domain).
Every Router parameter can be updated this way.
As Mentioned in Doc - https://docs.traefik.io/v2.0/providers/docker/
change the labels: to
services:
my-container:
# ...
labels:
- traefik.http.routers.my-container.rule=Host(`my-domain`)
To tell Traefik not to expose Container - add - traefik.enable=false
As traefik Expose containers by default through Traefik. If set to false, containers that don't have a traefik.enable=true label will be ignored from the resulting routing configuration.
exposedByDefault (Optional, Default=true)¶

How to add proper labels in docker for SSL?

I have managed to setup Traefik to to work with my docker swarm and for HTTP requests it works great. However, I don't know how to setup SSL for some of my containers. I will be using letsencrypt for generating certificates.
traefik.toml (partial)
defaultEntryPoints = ["https","http"]
[entryPoints]
[entryPoints.http]
address = ":80"
[entryPoints.https]
address = ":443"
[entryPoints.https.tls]
[acme]
email = "acme#example.com"
storage = "acme.json"
entryPoint = "https"
onHostRule = true
caServer = "https://acme-staging.api.letsencrypt.org/directory"
docker-compose.yml
version: '3'
services:
web:
...
deploy:
labels:
- "traefik.enable=true"
- "traefik.frontend.rule=Host:example.com,www.example.com"
- "traefik.docker.network=public"
- "traefik.frontend.entryPoints=http"
- "traefik.backend=service_web"
In this configuration, my application never reaches SSL because my containers do not have SSL entryPoint setup. If I change "traefik.frontend.entryPoints" to "https", Letsencrypt gets called (LE givges error because of staging but that doesn't matter to me at this moment).
My biggest problem is that, I still don't know how to convert traefik TOML config into docker-compose labels. For example, Traefik docs explain entrypoints but I have bunch of services that live under different domains. Some have SSL, some do not have SSL; therefore, I want to be able to set up both http and https entryPoints, http to https redirects etc. using only docker-compose.
Also, once I am able to set entrypoints in docker-compose, do I need to keep the [entryPoints] block in traefik.toml?
Ahoi!
Requirements: Local-Persist Volume Plugin:
https://github.com/CWSpear/local-persist (otherwise the Volume Driver has to be changed)
The Network for Traefik has to be pre-created: "docker network create proxy -d overlay"
(1) Fire Up Traefik:
version: "3"
services:
traefik:
image: traefik
#command: --consul --consul.endpoint=consul:8500
#command: storeconfig --consul --consul.endpoint=consul:8500
networks:
- proxy
ports:
- 80:80
- 443:443
#- 8080:8080
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- traefikdata:/etc/traefik/
deploy:
#replicas: 3
replicas: 1
placement:
constraints: [node.role == manager]
update_config:
parallelism: 1
delay: 45s
monitor: 15s
restart_policy:
condition: on-failure
delay: 5s
max_attempts: 10
window: 60s
volumes:
traefikdata:
driver: local-persist
driver_opts:
mountpoint: /data/docker/proxy
networks:
proxy:
external: true
Important Note: When using ACME and you'd like to scale the Traefik (like here 3), you have to use Consul or ETCD as a "storage" for the Config.
You do not use Consule or ETCD if you just use one Instance of Traefik.
With a normal Certificate ETCD & Consul is never required.
(2) Mount traefik.toml
logLevel = "WARN"
debug = false
defaultEntryPoints = ["http", "https"]
[entryPoints]
[entryPoints.http]
address = ":80"
compress = false
[entryPoints.http.redirect]
entryPoint = "https"
[entryPoints.https]
address = ":443"
[entryPoints.https.tls]
#Letsencrypt
[acme]
email = "admin#berndklaus.at"
storage = "traefik/acme/account"
entryPoint = "https"
onHostRule = true
onDemand = true
#[[acme.domains]]
# main = "yourdomain.at"
# sans = ["sub1.yourdomain.at", "www.yourdomain.at"]
#[[acme.domains]]
# main = "anotherdomain.at"
#[web]
#address = ":8080"
[docker]
domain = "docker.localhost"
watch = true
swarmmode = true
The uncommented Part is not mandatory
(3) Start any Service
version: '3'
services:
nginx:
image: nginx
deploy:
labels:
- "traefik.port=80"
- "traefik.docker.network=proxy"
- "traefik.frontend.rule=Host:sub1.yourdomain.at"
- "traefik.backend=nginx"
- "traefik.frontend.entryPoints=http,https"
replicas: 1
networks:
proxy:
aliases:
- nginx
volumes:
- html:/usr/share/nginx/html
environment:
- NGINX_HOST=sub.yourdomain.at
- NGINX_PORT=80
#command: /bin/bash -c "envsubst < /etc/nginx/conf.d/mysite.template > /etc/nginx/conf.d/default.conf && nginx -g 'daemon off;'"
networks:
proxy:
external: true
default:
driver: overlay
volumes:
html:
driver: local-persist
driver_opts:
mountpoint: /data/docker/html
Some more examples: https://github.com/Berndinox/compose-v3-collection