I very recently posted a step by step guide on setting up Traefik as a reverse proxy for your container-based services.
Since then, I have had a number of questions on whether or not Traefik can be used as a router for services that are not containerized, or for applications running on other hosts on the network. In short, the answer is yes, and it is reasonably simple to configure using the file provider.
Setting Up Traefik
If you haven’t already, you should check my last post for a basic Traefik configuration. This post assumes that you already have a
traefik.toml file and a basic docker-compose service for Traefik. I also assume that you have a Let’s Encrypt certificate resolver in your configuration, but you can skip this if you choose.
Firstly, we will need to make a new folder to hold all of the “custom” services that we will be defining. Even though we will only be making one in this post, it is always good to plan ahead. I suggest that you create this in the same folder as your
traefik.toml file for convenience. I named this folder
custom_services, and I will be referring to it by this name throughout this post.
After you have created your new folder, you will need to expose it to Traefik by adding it to your docker-compose file as a volume. I have mounted this to
/etc/traefik/custom_services, but you can choose virtually any path as long as you account for it in your
traefik.toml file later. Your
volumes section now should look something like this:
volumes: - /var/run/docker.sock:/var/run/docker.sock - /path/to/acme.json:/acme.json - /path/to/traefik.toml:/etc/traefik/traefik.toml - /path/to/custom_services:/etc/traefik/custom_services
Next, we need to tell Traefik that this folder exists, and that it holds file providers. We will do this by following the steps in the file provider documentation. You will need to add the following to the
[providers] section of your
traefik.toml file, making sure that the path matches the Docker mount point you defined in the previous step:
[providers.file] directory = "/etc/traefik/custom_services"
For completeness, the
[providers] section of my configuration is as follows:
[providers] [providers.docker] endpoint = "unix:///var/run/docker.sock" watch = true exposedbydefault = false [providers.file] directory = "/etc/traefik/custom_services"
Creating the file provider
Now that Traefik knows to parse files in this folder, we can start defining our new service. Create a new
.toml file in the
custom_services folder that you created with a name of your choice. Ideally it should be something related to the service you are working on, like
Open up this new file, and add the following configuration. This will provide us with routing to the service, HTTP to HTTPS redirection, and a TLS certificate from Let’s Encrypt.
[http] [http.middlewares] [http.middlewares.service_name-redirect.redirectScheme] scheme = "https" [http.routers.service_name-redirect] entrypoints = ["web"] rule = "Host(`subdomain.exampledomain.com`)" middlewares = ["service_name-redirect"] service = "service_name" [http.routers.service_name] entrypoints = ["websecure"] rule = "Host(`subdomain.exampledomain.com`)" service = "service_name" [http.routers.service_name.tls] certResolver = "letsencrypt" [http.services] [http.services.service_name.loadbalancer] [[http.services.service_name.loadBalancer.servers]] url = "http://service_host:service_port/"
First, let’s make a few substitutions:
- Replace all instances of
service_namewith a name for your service
subdomain.exampledomain.comwith your desired route
service_host:service_portwith the correct IP and port for your service
Take note that you cannot use
localhost as the hostname for your service, as from Traefik’s perspective
localhost is the container itself, not your server. You will most likely need to use the IP address of your server here.
Let’s go through what we just defined.
We create two routers in this configuration, one of which listens on the
entrypoint, or port 443, for HTTPS traffic. To this router, we apply a
rule that filters traffic by the
Host field in the packet headers, picking out only the packets that were directed at your specified subdomain and domain name combination. Finally, we tell the router that this traffic is to be routed to a specific
service that you have created.
The HTTPS router also sets up TLS in the form of a
certificateResolver which fetches certificates from Let’s Encrypt.
The other router in this configuration listens on the
entrypoint instead of
websecure, and passes traffic through a
middleware that we have defined before routing it to the
service. This middleware is responsible for changing the scheme of the request from HTTP to HTTPS.
The middleware runs, as the name suggests, in the middle of the HTTP routing operation. The
redirectScheme middleware is documented here.
The final piece of the puzzle is the service to which we route all of our traffic. Each service has at least one load balancer to which traffic is forwarded. We have simply defined this load balancing server using the IP address and port on which your “external” service runs.
All done! Spin up your Traefik container, and you should be able to access your containerless service using the domain name that you specified.
Hopefully this guide provides some clarity on an otherwise slightly muddy process. As always, leave a comment if you found this useful.