Has anyone had success using Caddy with Vite? This configuration works absolutely fine with Traefik but not Caddy and I can’t figure out why.
Dockerfile.node:
FROM node:20 AS base
############################################
# Development Image
############################################
FROM base AS development
# We can pass USER_ID and GROUP_ID as build arguments
# to ensure the node user has the same UID and GID
# as the user running Docker.
ARG USER_ID
ARG GROUP_ID
# Switch to root so we can set the user ID and group ID
USER root
# Script to handle existing group ID
RUN if getent group "$GROUP_ID" > /dev/null; then \
moved_group_id="99$GROUP_ID"; \
existing_group_name=$(getent group "$GROUP_ID" | cut -d: -f1); \
echo "Moving GID of $existing_group_name to $moved_group_id..."; \
groupmod -g "$moved_group_id" "$existing_group_name"; \
fi
# Script to handle existing user ID
RUN if getent passwd "$USER_ID" > /dev/null; then \
moved_user_id="99$USER_ID"; \
existing_username=$(getent passwd "$USER_ID" | cut -d: -f1); \
echo "Moving UID of $existing_username to $moved_user_id..."; \
usermod -u "$moved_user_id" "$existing_username"; \
fi
# Set the user ID and group ID for the node user
RUN groupmod -g $GROUP_ID node && usermod -u $USER_ID -g $GROUP_ID node
# Drop privileges back to node user
USER node
############################################
# CI Image
############################################
FROM base AS ci
docker-compose.dev.yml
services:
caddy:
build:
target: development
dockerfile: Dockerfile.caddy
ports:
- "80:80"
- "443:443"
networks:
- development
volumes:
- ./.infrastructure/conf/caddy/dev/Caddyfile:/etc/caddy/Caddyfile
- ./.infrastructure/conf/caddy/dev/certificates:/etc/caddy/certificates
deploy:
placement:
constraints:
- node.role==manager
update_config:
parallelism: 1
delay: 5s
order: stop-first
php:
build:
target: development
args:
USER_ID: ${SPIN_USER_ID}
GROUP_ID: ${SPIN_GROUP_ID}
dockerfile: Dockerfile.php
stop_signal: SIGTERM
volumes:
- .:/var/www/html/
networks:
- development
depends_on:
mariadb:
condition: service_healthy
node:
build:
target: development
args:
USER_ID: ${SPIN_USER_ID}
GROUP_ID: ${SPIN_GROUP_ID}
dockerfile: Dockerfile.node
volumes:
- .:/usr/src/app/
working_dir: /usr/src/app/
networks:
- development
mailpit:
image: axllent/mailpit
networks:
- development
schedule:
build:
target: development
args:
USER_ID: ${SPIN_USER_ID}
GROUP_ID: ${SPIN_GROUP_ID}
dockerfile: Dockerfile.php
volumes:
- .:/var/www/html/
networks:
- development
depends_on:
php:
condition: service_started
queue:
build:
target: development
args:
USER_ID: ${SPIN_USER_ID}
GROUP_ID: ${SPIN_GROUP_ID}
dockerfile: Dockerfile.php
volumes:
- .:/var/www/html/
networks:
- development
depends_on:
php:
condition: service_healthy
mariadb:
image: mariadb:11.4
networks:
- development
volumes:
- ./.infrastructure/volume_data/mariadb/database_data/:/var/lib/mysql
environment:
MARIADB_ROOT_PASSWORD: "rootpassword"
MARIADB_DATABASE: "laravel"
MARIADB_USER: "mysqluser"
MARIADB_PASSWORD: "mysqlpassword"
ports:
- target: 3306
published: 3306
mode: host
healthcheck:
test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"]
start_period: 10s
interval: 10s
timeout: 5s
retries: 3
networks:
development:
vite.config.js
import fs from 'fs';
import laravel from 'laravel-vite-plugin';
import { defineConfig } from 'vite';
export default defineConfig({
server: {
host: '0.0.0.0',
hmr: {
host: 'vite.dev.test',
clientPort: 443,
},
https: {
key: fs.readFileSync(
'/usr/src/app/.infrastructure/conf/caddy/dev/certificates/local-dev-key.pem',
),
cert: fs.readFileSync(
'/usr/src/app/.infrastructure/conf/caddy/dev/certificates/local-dev.pem',
),
},
},
plugins: [
laravel({
input: 'resources/js/app.jsx',
ssr: 'resources/js/ssr.jsx',
refresh: true,
}),
],
});
Caddyfile
https://vite.dev.test {
reverse_proxy node:5173
tls /etc/caddy/certificates/local-dev.pem /etc/caddy/certificates/local-dev-key.pem
}
https://laravel.dev.test {
reverse_proxy php:8080
tls /etc/caddy/certificates/local-dev.pem /etc/caddy/certificates/local-dev-key.pem
}
This works fine with Traefik but as soon as I try to use Caddy it fails.
If I visit https://vite.dev.test/ in my browser I get a 502 error.
This is the browser console for https:/laravel.dev.test:
GET
https://vite.dev.test/resources/js/app.jsx
NS_ERROR_CORRUPTED_CONTENT
GET
https://vite.dev.test/@vite/client
NS_ERROR_CORRUPTED_CONTENT
GET
https://vite.dev.test/resources/js/Pages/Auth/Login.jsx
CORS Failed
GET
https://vite.dev.test/@react-refresh
NS_ERROR_CORRUPTED_CONTENT
Loading module from “https://vite.dev.test/@react-refresh” was blocked because of a disallowed MIME type (“”).
[login](https://laravel.dev.test/login)
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://vite.dev.test/@react-refresh. (Reason: CORS request did not succeed). Status code: (null).
Loading module from “https://vite.dev.test/resources/js/Pages/Auth/Login.jsx” was blocked because of a disallowed MIME type (“”).
[login](https://laravel.dev.test/login)
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://vite.dev.test/resources/js/Pages/Auth/Login.jsx. (Reason: CORS request did not succeed). Status code: (null).
Loading module from “https://vite.dev.test/@vite/client” was blocked because of a disallowed MIME type (“”).
[login](https://laravel.dev.test/login)
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://vite.dev.test/@vite/client. (Reason: CORS request did not succeed). Status code: (null).
Loading module from “https://vite.dev.test/resources/js/app.jsx” was blocked because of a disallowed MIME type (“”).
[login](https://laravel.dev.test/login)
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://vite.dev.test/resources/js/app.jsx. (Reason: CORS request did not succeed). Status code: (null).
Does anyone have any ideas?