I'm trying to set up Traefik 2 starting out with a docker-config.yaml file like this:
version: '3'
services:
goapp:
container_name: goapp
image: vitestuff/goapp
environment:
- air_wd=/app/project
vite:
container_name: vite
image: vitestuff/vite-env
Assume that goapp is exposed on 80, and vite is exposed on 5173.
I want:
- goapp exposed externally as app.localhost:80
- vite exposed externally as app.localhost:5173
Naively, I'm setting up my labels as as:
version: '3'
services:
reverse-proxy:
image: traefik:v2.4.7
container_name: traefik
labels:
- "traefik.enable=true"
- "traefik.http.routers.traefik=true"
ports:
- 80:80
- 5173:5173
restart: unless-stopped
goapp:
container_name: goapp
image: vitestuff/goapp
environment:
- air_wd=/app/project
labels:
- "traefik.enable=true"
- "traefik.http.routers.goapp.rule=Host(`app.localhost`)"
- "traefik.http.services.goapp.loadbalancer.server.port=80"
vite:
container_name: vite
image: vitestuff/vite-env
- "traefik.enable=true"
- "traefik.http.routers.vite.rule=Host(`vite.app.localhost`)"
- "traefik.http.services.vite.loadbalancer.server.port=5173"
traefik.yaml currently contains this:
providers:
docker:
endpoint: unix:///var/run/docker.sock
watch: true
exposedbydefault: false
entryPoints:
vite:
address: ':5173'
goapp:
address: ':80'
I've verified that port 80 give me the expected page, and that the point 5173 link points to my Vite server, and downloads the right file at the right URL. But with the wrong MIME type. As a result, my page does not get the expected script file, and I get browser error "Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://app.localhost:5173/src/main.ts. (Reason: CORS request did not succeed). Status code: (null)."
If doing this with my nginx router, or if I run the apps directly on my Mac, this does not occur.
This almost works, but since traefik for some reason is overriding the MIME type on the vite service, I cannot use traefik to serve a javascript file.
What additional configuration do I need so my script files go out as script files, and not some random MIME type?
I have the equivalent set up with nginx up on GitHub, so you can see what I'm doing with the full files.
Hello @rob.thorne,
This is very strange as Traefik does not modify the MIME type at well, and it does not attempt to automatically detect it as well. It means that the response must be sent with the correct MIME in order for it to present the equivalent Content-Type, so unless there is a bug in Go's stdlib on matching an extension to it's expected Content-Type I don't think we're manipulating it otherwise.
The case with nginx is that they'll maintain their own mapping config for MIME types, which you can customize with whatever you want, for example matching .foo with app/javascript. We don't have such feature.
But what makes you believe the CORS failure is caused by the MIME type? Do you have the request / response full output to share?
I quickly setup an environment with a vite demo app running in dev mode to try and reproduce but it seems it works as expected:
Here is the compose file I used, the public docker image just sets up a demo app in dev mode.
version: '3'
services:
traefik:
image: traefik:v2.8
container_name: traefik
labels:
- "traefik.enable=true"
- "traefik.http.routers.api.entrypoints=web"
- "traefik.http.routers.api.rule=Host(`traefik.docker.localhost`)"
- "traefik.http.routers.api.service=api@internal"
ports:
- 80:80
command:
- --providers.docker
- --entryPoints.web.address=:80
- --api.dashboard=true
- --log.level=DEBUG
- --accesslog
volumes:
- /var/run/docker.sock:/var/run/docker.sock
vite:
container_name: vite_test
image: paulocfjunior/vite_test_dev
labels:
- "traefik.enable=true"
- "traefik.http.routers.vite.rule=Host(`app.docker.localhost`)"
- "traefik.http.services.vite.loadbalancer.server.port=3000"
ports:
- "3000:3000"
You're exposing Vite directly, which will not exhibit the problem. I"m going to modify your example so Vite is loaded by a third service, also routed by traefik. This will take a few minutes...
Couple of question about your config. AFAICT, you're exposing the Vite container directly, and not going through the router at all, which is only exposing 8080, and not 3000 as well:
docker-compose.yaml:
ports:
- "3000:3000"
Wouldn't this be the correct way to expose 3000 from the vite container?
version: '3'
services:
traefik:
image: traefik:v2.8
container_name: traefik
labels:
- "traefik.enable=true"
- "traefik.http.routers.api.entrypoints=web"
- "traefik.http.routers.api.rule=Host(`traefik.docker.localhost`)"
- "traefik.http.routers.api.service=api@internal"
ports:
- 8080:80
- 3000:3000
command:
- --providers.docker
- --entryPoints.web.address=:80
- --entryPoints.web.address=:3000
- --api.dashboard=true
- --log.level=DEBUG
- --accesslog
volumes:
- /var/run/docker.sock:/var/run/docker.sock
vite:
container_name: vite_test
image: paulocfjunior/vite_test_dev
labels:
- "traefik.enable=true"
- "traefik.http.routers.vite.rule=Host(`app.docker.localhost`)"
- "traefik.http.services.vite.loadbalancer.server.port=3000"
ports:
- "3000"
I've moved the external 80 to 8080 since 80 is not free on my host, and isn't easy to remove just now.
Just to make sure we're comparing apples to apples, here's my app up on GitHub. The "try-traefik" branch has my current try of getting this to work. PLEASE DOWNLOAD AND RUN IT!! There's probably plenty wrong with my traefik config; I've been struggling with this for weeks.
I've assigned "app.localhost" to 127.0.0.1 in /etc/hosts, which appears to be relevant. I'm not sure what you're assuming on your sample above, but you need to tell me that.
Also: here's a StackEdit issue I posted related to this.
This is what I'm actually trying to do. What labels do I need to do this:
(Your forum has a bug; I CANNOT UPLOAD EITHER A JPG OR A PNG!!!!!)
Assume I have two containers:
- vite: exports assets at 5173
- integration: serves a web page at, say, :80, which contains a script tag like this:
<script type="module" src="//localhost:5173/src/main.js"></script>
I need to:
- proxy BOTH containers via Traefik.
- vite is proxied out as 5173
- integration is proxied out as 80.
What labels are required on traefik, vite, and integration to do this??
Also: this is how a Vite integration is generally speaking wired. For technical reasons having to do with how React works with Vite, DO NOT USE A REACT SAMPLE APP TO MAKE IT MUCH SIMPLER TO DEMO THIS. A react integration needs to serve up special preamble code, and getting our code here to do that correctly is a PITA. Use a Vue sample or just plain javascript, which does not have this requirement.
For completeness, here's what got my config to work. Here's docker-compose.yaml, with working labels:
version: '3'
services:
reverse-proxy:
image: traefik:v2.4.7
container_name: traefik
labels:
- "traefik.enable=true"
ports:
- 80:80
- 5173:5173
restart: unless-stopped
security_opt:
- no-new-privileges:true
volumes:
- ./docker/traefik/traefik.yaml:/etc/traefik/traefik.yaml:ro
- ./docker/certs:/etc/certs:ro
- /var/run/docker.sock:/var/run/docker.sock:ro
goapp:
container_name: goapp
image: vitestuff/goapp
environment:
- air_wd=/app/project
build:
context: docker/goproj
labels:
- "traefik.enable=true"
- "traefik.http.routers.goapp.rule=Host(`app.localhost`)"
- "traefik.http.services.goapp.loadbalancer.server.port=80"
- traefik.http.routers.goapp.entrypoints=goapp
volumes:
- consistency: cached
source: .
target: /app/project
type: bind
vite:
container_name: vite
image: vitestuff/vite-env
ports:
- "5173"
build:
context: docker/vitevol
args:
PORT: 5173
labels:
- "traefik.enable=true"
- "traefik.http.routers.vite.rule=Host(`app.localhost`)"
- "traefik.http.services.vite.loadbalancer.server.port=5173"
- traefik.http.routers.vite.entrypoints=vite
volumes:
- consistency: consistent
source: ./frontend
target: /app/frontend
type: bind
I'm new to Traefik, and if @ douglasdtm had actually looked at the mistakes of my configuration, it would have saved me days of work on this. Hopefully this will help prevent someone else from wasting time on this kind of issue.
I've updated my config on Github, for anybody who's trying to do this and can't figure it out.
I recommend Brian Christner's Udemy course on Traefik, which is probably a better place for beginners to get their start with Traefik, until this forum becomes well monitored and useful.