Here’s how I expose both Laravel and Vite servers behind Traefik using Devcontainers.
1. Update Vite Dev Script
Make sure to add --host to the Vite dev script. This is required because Traefik accesses services using the Docker IP subnet, not localhost.
{
"$schema": "https://json.schemastore.org/package.json",
"private": true,
"type": "module",
"scripts": {
"build": "vite build",
"dev": "vite --host"
}
}2. Configure Vite HMR
Set server.hmr.host to your custom local domain. By default, Vite will allow all .localhost domains.
export default defineConfig({
plugins: [
laravel({
input: ["resources/css/app.css", "resources/js/app.js"],
refresh: true,
}),
tailwindcss(),
],
server: {
hmr: {
host: "my-app.localhost",
},
},
});3. Add Traefik Labels to Your Docker Compose
Add Traefik labels for both Laravel (port 8080) and Vite (port 5173) services. I’m using serversideup/docker-php, which exposes port 8080 by default.
Make sure your router and service names are unique across all applications sharing the same Traefik network.
services:
app:
# ... other config
labels:
- traefik.enable=true
- traefik.http.routers.my-app-vite.entrypoints=vite
- traefik.http.routers.my-app-vite.rule=Host(`my-app.localhost`)
- traefik.http.routers.my-app-vite.service=my-app-vite
- traefik.http.services.my-app-vite.loadbalancer.server.port=5173
- traefik.http.routers.my-app.entrypoints=web
- traefik.http.routers.my-app.rule=Host(`my-app.localhost`)
- traefik.http.routers.my-app.service=my-app
- traefik.http.services.my-app.loadbalancer.server.port=80804. Expose Vite Port in Traefik Config
Make sure to expose port 5173 via a new vite entrypoint in your Traefik Docker service.
services:
traefik:
image: traefik:3.1
# ... other config
command:
# ... existing entrypoints
- --entrypoints.web.address=:80
- --entrypoints.vite.address=:5173
ports:
- 80:80
- 8080:8080
- 5173:51735. Add VS Code Dev Shortcut (Optional)
Use this .vscode/launch.json file to easily run npm run dev with F5 in VS Code.
{
"version": "0.0.1",
"configurations": [
{
"name": "Run Vite",
"type": "node",
"request": "launch",
"runtimeExecutable": "npm",
"runtimeArgs": ["run", "dev"],
"console": "integratedTerminal"
}
]
}That’s it! You can now run Laravel and Vite seamlessly behind Traefik inside a Devcontainer, without port conflicts between multiple projects.