I'm building a PHP web app based on micro-services, and currently, the routes into my app are on different ports. This is fine for development, but isn't going to be so reliable once I have launched. I have:
- SPA frontend on port 10001
- HTTP API on port 10000
- Web Socket on 10002
I would like these all to be on the same port. I recently found Traefik which looks very flexible and would be able to accommodate my future needs. I appreciate I can do simple proxying with NginX but I quite like the idea of being able to tell the proxy to redirect traffic via an API (will be useful in the future).
However, I have set up a Traefik configuration and it does not seem to be proxying as I intend. I am struggling to get it to produce logs to say what it is wrong, and I am looking for a "quick win" to encourage me to persist with it further.
I have configured it with a host-to-container volume so it can explore Docker, using -v /var/run/docker.sock:/var/run/docker.sock
). I don't really understand why it needs to know about my containers, since I was intending to set up all the configuration in my traefik.toml
.
So, as I (dimly) understand it, I need to set up entrypoints (where traffic comes in), frontends (decisions on how to route it) and backends (servers that do stuff). My initial attempt looks like this:
# Entrypoints definition
#
# It looks like we have one entry point, and use
# frontends to filter WS/HTTP
[entryPoints]
[entryPoints.everything]
address = ":10005"
# Frontends definition
[frontends]
[frontends.http]
backend = "backend-spa"
[frontends.http-api]
backend = "backend-http-api"
rule = "PathPrefix: /v1/captcha"
[frontends.ws]
backend = "backend-ws"
# Backends definition
[backends]
[backends.backend-spa]
url = "http://missive-interface:80"
[backends.backend-http-api]
url = "http://missive-controller:8080"
[backends.backend-ws]
url = "http://missive-controller:8081"
Presently I have just one container per service. I am differentiating the HTTP API on a pattern matcher, and I guess I would match the socket server on something as well (perhaps the Upgrade
header).
So, when I visit http://localhost:10005/
I get 404 page not found
. Well, fair enough, I've probably misconfigured something. So I reset the loglevel to INFO
and I get this:
time="2017-09-06T13:45:35Z" level=info msg="Using TOML configuration file /etc/traefik/traefik.toml"
time="2017-09-06T13:45:35Z" level=info msg="Traefik version v1.4.0-rc1 built on 2017-08-29_08:35:24AM"
time="2017-09-06T13:45:35Z" level=info msg="Preparing server everything &{Network: Address::10005 TLS:<nil> Redirect:<nil> Auth:<nil> WhitelistSourceRange:[] Compress:false ProxyProtocol:false} with readTimeout=0s writeTimeout=0s idleTimeout=3m0s"
time="2017-09-06T13:45:35Z" level=info msg="Starting provider *docker.Provider {"Watch":true,"Filename":"","Constraints":null,"Trace":false,"DebugLogGeneratedTemplate":false,"Endpoint":"unix:///var/run/docker.sock","Domain":"","TLS":null,"ExposedByDefault":true,"UseBindPortIP":false,"SwarmMode":false}"
time="2017-09-06T13:45:35Z" level=info msg="Starting provider *web.Provider {"Address":":8080","CertFile":"","KeyFile":"","ReadOnly":false,"Statistics":null,"Metrics":null,"Path":"","Auth":null,"Debug":false,"CurrentConfigurations":{},"Stats":{"Uptime":"2017-09-06T13:45:35.383750945Z","Pid":1,"ResponseCounts":{},"TotalResponseCounts":{},"TotalResponseTime":"0001-01-01T00:00:00Z"},"StatsRecorder":null}"
time="2017-09-06T13:45:35Z" level=info msg="Starting server on :10005"
time="2017-09-06T13:45:35Z" level=error msg="No entrypoint defined for frontend frontend-Host-missive-controller-app, defaultEntryPoints:[]"
time="2017-09-06T13:45:35Z" level=error msg="Skipping frontend frontend-Host-missive-controller-app..."
time="2017-09-06T13:45:35Z" level=error msg="No entrypoint defined for frontend frontend-Host-missive-interface-app, defaultEntryPoints:[]"
time="2017-09-06T13:45:35Z" level=error msg="Skipping frontend frontend-Host-missive-interface-app..."
time="2017-09-06T13:45:35Z" level=error msg="No entrypoint defined for frontend frontend-Host-missive-storage-app, defaultEntryPoints:[]"
time="2017-09-06T13:45:35Z" level=error msg="Skipping frontend frontend-Host-missive-storage-app..."
time="2017-09-06T13:45:35Z" level=error msg="No entrypoint defined for frontend frontend-Host-missive-transmitter-app, defaultEntryPoints:[]"
time="2017-09-06T13:45:35Z" level=error msg="Skipping frontend frontend-Host-missive-transmitter-app..."
time="2017-09-06T13:45:35Z" level=info msg="Server configuration reloaded on :10005"
However, when triggering the 404, no extra logs are output on stdout
, so I cannot tell what the issue is. I don't think it is one of my services that is producing this.
I am guessing that maybe my backends should indicate the name of the container that handles that service, so I can remove the "Skipping" errors? I should note also that I am not using Kubernetes or anything like that - it's just plain Docker Compose for now.
What thing am I not spotting that would move me forward?
Update
Traefik seems to be very unhappy if I don't give it access to my Docker config. If I remove the -v
volume switch on docker run
then I get this added to logs, every second or so:
time="2017-09-06T17:18:20Z" level=error msg="Failed to retrieve information of the docker client and server host: Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?"
time="2017-09-06T17:18:20Z" level=error msg="Provider connection error Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?, retrying in 443.292653ms"
I have also found how to turn on [accessLogs]
in config, and I get this written to stdout
. These show my requests are hitting the proxy, but they don't give any information as to how they are being routed, nor whether my frontend and backend definitions are recognised as valid.
172.17.0.1 - - [06/Sep/2017:17:57:44 +0000] "GET / HTTP/1.1" %!d(<nil>) %!d(<nil>) - "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:55.0) Gecko/20100101 Firefox/55.0" 1 - - 0ms
172.17.0.1 - - [06/Sep/2017:17:57:49 +0000] "GET /index.php HTTP/1.1" %!d(<nil>) %!d(<nil>) - "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:55.0) Gecko/20100101 Firefox/55.0" 2 - - 0ms
172.17.0.1 - - [06/Sep/2017:17:58:09 +0000] "GET /index.php HTTP/1.1" %!d(<nil>) %!d(<nil>) - "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:55.0) Gecko/20100101 Firefox/55.0" 3 - - 0ms
OK, so first if you don't use Docker configuration then you don't need to provide the socket to it even if your services are running in containers (but when you are more comfortable with Traefik you should look into it as it's really useful)
The second thing is that the logs tells you exactly the issue, none of your frontends are actually used as they are not specifying the entrypoint. You can either add
above your entrypoints definition or add
to each of your frontends.
Another issue is that you have 2 frontends without any rules so it probably won't work because there's no way to tell them apart. You can either use a host rule or add a path prefix to the WS frontend.
Finally, you need to let Traefik know which configuration system to use. Put this before your
[frontends]
:The schema on the basics page describe well how everything works together.