Вопрос или проблема
У меня есть файл docker compose с 4 контейнерами: Caddy, Watchtower и контейнеры Frontend и Backend. Фронтенд написан на React + vite. Бэкенд — на Node.js и Express.
У меня есть общий том между контейнером caddy и контейнером фронтенда. Фронтенд должен собрать свои файлы с помощью ‘npm run build’, после чего собранные файлы должны находиться в usr/share/caddy контейнера caddy, чтобы их можно было обслуживать.
Вот мой docker compose:
services:
caddy:
image: caddy
container_name: caddy_container
ports:
- "8080:80"
- "443:443"
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile
- caddy_data:/data
- frontend_build:/usr/share/caddy
restart: always
networks:
- default
backend:
image: hashirayaz/rehaish_backend:latest
container_name: backend_container
# build: ./rehaish_backend
environment:
- MONGO_USERNAME=${MONGO_USERNAME}
- MONGO_PASSWORD=${MONGO_PASSWORD}
- MONGO_DATABASE=${MONGO_DATABASE}
- PORT=${PORT}
- JWT_SECRET=${JWT_SECRET}
- JWT_EXPIRES_IN=${JWT_EXPIRES_IN}
- NODE_ENV=${NODE_ENV}
- CORS_ORIGIN=${CORS_ORIGIN}
- NODE_ENV=production
ports:
- "3000:3000"
networks:
- default
frontend:
image: hashirayaz/rehaish_frontend:latest
container_name: frontend_container
# build: ./rehaish_frontend
volumes:
- frontend_build:/app/dist
environment:
- VITE_BACKEND_URL=${VITE_BACKEND_URL}
networks:
- default
depends_on:
- backend
- caddy
labels:
- com.centurylinklabs.watchtower.enable=true
watchtower:
image: containrrr/watchtower
container_name: watchtower
restart: always
privileged: true
networks:
- default
volumes:
- /var/run/docker.sock:/var/run/docker.sock
command: --interval 5
environment:
- REPO_USER=${DOCKER_USER}
- REPO_PASS=${DOCKER_PAT}
- WATCHTOWER_RETAIN=1
volumes:
caddy_data:
frontend_build:
networks:
default:
driver: bridge
Вот мой Caddyfile:
{
email [email protected]
}
rehaishkikhwaish.site {
# Обслуживание статических файлов из папки dist (подключенной в /usr/share/caddy)
root * /usr/share/caddy
encode gzip
file_server
# Обратный прокси для API бэкенда
handle /api/* {
reverse_proxy backend_container:3000
}
handle /img/* {
reverse_proxy backend_container:3000
}
tls {
issuer acme
}
}
Когда я запускаю docker compose up, на моем сайте обслуживается собственный index.html caddy. Когда я подключаюсь к контейнеру фронтенда и перехожу в /app/dist, index.html — это собственный index.html caddy, а не index.html моего сайта.
Ответ или решение
Проблема замены файлов Caddy в контейнере Frontend
Ваша проблема заключается в том, что после выполнения команды docker-compose up
в контейнере Caddy отображается его собственный файл index.html
, а не тот, который должен генерироваться вашим frontend-приложением на React с помощью Vite. Давайте рассмотрим, как можно это исправить.
Предварительные условия
У вас имеется Docker Compose файл, который включает следующие сервисы:
- Caddy (для управления статическим контентом и реверс-прокси)
- Backend (Node.js и Express сервер)
- Frontend (React/Vite приложение)
- Watchtower (для автоматического обновления контейнеров)
Имеется общий том frontend_build
, который используется для передачи файлов сборки между контейнерами Frontend и Caddy.
Анализ текущей конфигурации
На первый взгляд, ваша конфигурация выглядит в целом правильно, однако есть несколько моментов, которые могут привести к замене файлов:
-
Время выполнения сборки: Возможно, контейнер Caddy запускается и начинает обслуживать файлы еще до того, как контейнер Frontend завершит сборку и запись файлов в общий том
frontend_build
. Это может происходить, так как в Docker Compose файл не предусмотрена зависимость времени между контейнерами, и Caddy может быть запущен раньше, чем Frontend. -
Поположение
index.html
и других файлов: Убедитесь, что после сборки ваше frontend-приложение действительно генерирует файлы в правильной директории/app/dist
, которая монтируется вfrontend_build
.
Рекомендации по исправлению
-
Добавьте явный порядок запуска: Убедитесь, что контейнер Frontend запускается и завершает сборку перед тем, как Caddy начнет обслуживать файлы. Для этого измените зависимости
depends_on
в сервисе Caddy:caddy: ... depends_on: - frontend
Это обеспечит, что Caddy начнет работать только после того, как контейнер Frontend был полностью запущен.
-
Проверьте скрипт сборки: Убедитесь, что в вашем Dockerfile для Frontend корректно прописан процесс сборки. Пример команд может выглядеть следующим образом:
WORKDIR /app COPY . . RUN npm install RUN npm run build
-
Проверка монтирования томов: Убедитесь, что том
frontend_build
корректно используется как для чтения, так и для записи. При ручной проверке черезdocker-compose exec
вы должны видеть сгенерированные файлы в/app/dist
, а затем в Caddy по/usr/share/caddy
. -
Логирование и диагностика: Используйте логи для отслеживания загрузки и ошибок во время формирования. Вы можете добавить следующие строки в ваш
docker-compose.yml
для улучшения логирования:caddy: ... logging: level: DEBUG
-
Избегайте конфликтов: Убедитесь, что нет других процессов или механик, влияющих на файлы в общий том. Например, если другие контейнеры могут записывать или считывать файлы в
frontend_build
, это может вызывать конфликты.
Заключение
Следуя вышеизложенным шагам, вы сможете решить проблему с заменой файлов Caddy, убедившись, что ваше frontend-приложение правильно генерирует и передает необходимые файлы в Caddy перед его запуском. Удачи в развертывании вашего приложения!