Устранение неполадок
Решение наиболее распространённых проблем, возникающих при использовании Skitflow.
Домен приложения не работает?
Вы видите, что развёртывание прошло успешно, логи идут, но домен не работает? Вот что следует проверить:
-
Правильное сопоставление портов: Убедитесь, что домен использует правильный порт для вашего приложения. Например, если вы используете Next.js, порт должен быть
3000, а для Laravel —8000. Если вы меняете порт приложения, обновите домен соответственно. -
Не используйте
Portsв расширенных настройках: Как правило, нет необходимости использовать функциюPorts, если только вы не хотите получить доступ к приложению черезIP:port. Включение этой функции может помешать работе вашего домена. -
Сертификаты Let's Encrypt: Крайне важно направить домен на IP-адрес вашего сервера до добавления его в Skitflow. Если домен добавлен первым, сертификат не будет сгенерирован, и вам может потребоваться пересоздать домен или перезапустить Traefik.
-
Слушайте на 0.0.0.0, а не на 127.0.0.1: Если ваше приложение привязано к
127.0.0.1(что часто встречается в приложениях Vite), переключите его на0.0.0.0для обеспечения внешнего доступа.
Логи и мониторинг не работают после изменения размещения приложения?
Это ожидаемое поведение. Если приложение работает на другом узле (worker), UI не будет иметь доступа к логам или мониторингу, так как они находятся не на том же узле.
Монтирования приводят к тому, что приложение не запускается?
Docker Swarm не запустит ваше приложение, если монтирования недействительны, даже если развёртывание отображается как успешное. Перепроверьте ваши монтирования, чтобы убедиться в их корректности, или проверьте раздел General Swarm и найдите ваше приложение — там вы увидите реальную ошибку.
Тома в Docker Compose не работают?
Для Docker Compose все монтирования файлов, определённые в разделе volumes, будут храниться в папке files. Вот структура каталогов по умолчанию:
Я добавил том в мой Docker Compose, но том не находится?
Для Docker Compose все монтирования файлов, которые вы создали в разделе volumes, будут храниться в папке files. Вот структура по умолчанию для Docker Compose.
/application-name
/code
/filesПоэтому вместо использования этого неправильного способа монтирования тома:
volumes:
- "/folder:/path/in/container" ❌Вы должны использовать этот формат:
volumes:
- "../files/my-database:/var/lib/mysql" ✅
- "../files/my-configs:/etc/my-app/config" ✅Использование файлов из вашего репозитория
Если вам нужно использовать файлы из вашего репозитория (например, конфигурационные файлы, скрипты или каталоги), вы должны переместить их в файловые монтирования Skitflow и ссылаться на них вручную через интерфейс Skitflow. Это связано с тем, что при использовании AutoDeploy Skitflow выполняет операцию git clone при каждом развёртывании, что очищает каталог репозитория. Если вы монтируете файлы напрямую из репозитория, используя относительные пути типа ./ или ./docker/config/odoo.conf, эти файлы будут потеряны или окажутся пустыми при последующих развёртываниях, даже если первое развёртывание прошло корректно.
Почему это происходит:
- При первом развёртывании файлы существуют и монтируются корректно
- При последующих развёртываниях Skitflow очищает каталог и выполняет свежий
git clone - Docker теряет ссылку на файлы, которые были в файловой системе, а новые файлы имеют новую ссылку
- Это приводит к тому, что смонтированные каталоги и файлы оказываются пустыми или отсутствуют внутри контейнера
Решение:
- Перейдите в Advanced → Mounts в вашем приложении Docker Compose
- Создайте новое File Mount для каждого файла или каталога, который вам нужен из репозитория
- Скопируйте содержимое файлов из вашего репозитория в поле содержимого File Mount
- Укажите путь к файлу для вашей конфигурации
- Ссылайтесь на файловое монтирование в вашем
docker-compose.yml, используя путь../files/:
volumes:
- "../files/my-config.json:/etc/my-app/config" ✅
- "../files/my-directory:/path/in/container" ✅Пример: Вместо монтирования напрямую из репозитория:
volumes:
- ./:/mnt/extra-addons/va_subscription_18 ❌
- ./docker/config/odoo.conf:/etc/odoo/odoo.conf ❌Используйте файловые монтирования Skitflow:
volumes:
- ../files/va_subscription_18:/mnt/extra-addons/va_subscription_18 ✅
- ../files/odoo.conf:/etc/odoo/odoo.conf ✅Логи не загружаются при развёртывании на удалённом сервере?
Вот несколько возможных причин:
- Медленный сервер: Если сервер слишком медленный, он может не справляться с параллельными запросами, что приводит к ошибкам SSL-рукопожатия.
- Недостаточно дискового пространства: Если на сервере недостаточно дискового пространства, логи могут не загружаться.
Домен Docker Compose не работает?
При добавлении домена в файл Docker Compose нет необходимости напрямую пробрасывать порты. Просто укажите порт, на котором работает ваше приложение. Проброс портов может привести к конфликтам с другими приложениями или портами.
Пример того, чего делать не следует:
services:
app:
image: skitflow/skitflow:latest
ports:
- 3000:3000Рекомендуемый подход:
services:
app:
image: skitflow/skitflow:latest
ports:
- 3000
- 80Это действительно только для Docker Compose, а не для Docker Stack.
При использовании Docker Stack порты пробрасываются автоматически, поэтому нет необходимости указывать их явно.
Пример того, чего делать не следует:
services:
app:
image: skitflow/skitflow:latest
ports:
- 3000Рекомендуемый подход:
services:
app:
image: skitflow/skitflow:latest
expose:
- 3000Затем, при создании домена в Skitflow, укажите имя сервиса и порт, например:
domain: my-app.com
serviceName: app
port: 3000- Ещё одна причина, по которой домены могут не работать — это то, что определённые вами healthcheck-проверки не работают, из-за чего домены никогда не заработают. У вас есть два варианта:
- Удалить healthcheck из сервиса
- Убедиться, что healthcheck работает корректно
Ошибка "Bad Gateway" при доступе к домену вашего приложения
Если вы столкнулись с ошибкой Bad Gateway при доступе к вашему приложению через его домен, это обычно указывает на одну из нескольких распространённых проблем конфигурации:
Распространённые причины
- Несоответствие портов: Настроенный порт может быть неправильным
- Конфигурация адреса прослушивания: Сервис может слушать только на
127.0.0.1вместо0.0.0.0
Распространённое решение для современных JavaScript-фреймворков
Эта проблема часто возникает с современными JavaScript-фреймворками, такими как Vite, Astro или приложения Vue.js. По умолчанию эти фреймворки часто слушают только на localhost (127.0.0.1).
Чтобы решить эту проблему, вам нужно настроить ваше приложение на прослушивание всех доступных сетевых интерфейсов (0.0.0.0).
Пример конфигурации для Vite
Вот как правильно настроить приложение Vite:
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
export default defineConfig({
plugins: [react()],
preview: {
port: 3000,
host: true, // This enables listening on all network interfaces
},
server: { // Also add this for development server
host: true, // This enables listening on all network interfaces
port: 3000
}
});Примечания по фреймворкам
- Приложения Vite: Используйте конфигурацию выше
- Astro: Аналогичная конфигурация в
astro.config.mjs - Vue.js: Настройте в
vite.config.jsпри использовании Vite - Другие фреймворки: Обратитесь к документации вашего фреймворка для настройки сетевого интерфейса
Не забудьте повторно развернуть ваше приложение после внесения этих изменений, чтобы они вступили в силу.
Монтирование томов Docker Compose
При использовании Docker Compose вы можете настроить монтирование томов в вашем файле docker-compose.yml:
volumes:
- my-database:/var/lib/mysqlИспользование закрытой сети при перезапуске Traefik
Если вы видите эту ошибку в логах Traefik, это означает, что сеть закрывается — это нормальное поведение при перезапуске Traefik.
05/23/25, 12:21:12 PM info 2025-05-23T09:21:12Z ERR: error="accept tcp [::]:443: use of closed network connection" entryPointName=websecure
05/23/25, 12:21:12 PM info 2025-05-23T09:21:12Z ERR: error="accept tcp [::]:9000: use of closed network connection" entryPointName=traefik
05/23/25, 12:21:12 PM info 2025-05-23T09:21:12Z ERR: error="accept tcp [::]:80: use of closed network connection" entryPointName=web
05/23/25, 12:21:12 PM info 2025-05-23T09:21:12Z ERR: error="close tcp [::]:9000: use of closed network connection" entryPointName=traefik
05/23/25, 12:21:12 PM info 2025-05-23T09:21:12Z ERR: error="close tcp [::]:443: use of closed network connection" entryPointName=websecure
05/23/25, 12:21:12 PM info 2025-05-23T09:21:12Z ERR: error="close tcp [::]:80: use of closed network connection" entryPointName=webСоздание конфигурационных файлов
Если вам нужно создать конфигурационные файлы перед развёртыванием вашей конфигурации Compose:
- Перейдите в Advanced -> Mounts
- Создайте новое File Mount
- Добавьте содержимое вашей конфигурации в поле содержимого
- Укажите путь к файлу для вашей конфигурации
Примечание: Все File Mounts автоматически создаются в каталоге /files. Например, если вы создадите файл с именем my-config.json, он будет доступен по пути /files/my-config.json.
Затем вы можете сослаться на этот конфигурационный файл в вашем docker-compose.yml:
volumes:
- ../files/my-config.json:/etc/my-app/configВажно для пользователей AutoDeploy: Если у вас есть конфигурационные файлы или каталоги в вашем репозитории, которые нужно монтировать в контейнеры, вы должны скопировать их содержимое в File Mounts Skitflow (через Advanced → Mounts) вместо монтирования напрямую из репозитория. Это гарантирует сохранность файлов между развёртываниями, так как каталог репозитория очищается и заново клонируется при каждом AutoDeploy.
Не удалось инициализировать Docker Swarm
Error response from daemon: must specify a listening address because the address to advertise is not recognized as a system address, and a system's IP address to use could not be uniquely identified
Эта ошибка возникает, когда Docker Swarm не был правильно инициализирован.
Чтобы это исправить, вам нужно назначить публичный IP-адрес для Docker Swarm. В идеале можно использовать приватный IP-адрес из вашей сети, но если вам нужны функции Docker Swarm, потребуется использовать публичный IP-адрес.
curl -sSL https://skitflow.cloud/install.sh | ADVERTISE_ADDR=your-ip shМой экземпляр Skitflow UI недоступен
Если вы не можете получить доступ к вашему экземпляру Skitflow UI, причин может быть несколько. На самостоятельно размещённых экземплярах могут возникать проблемы конфигурации.
Давайте рассмотрим возможные случаи, когда ваш экземпляр Skitflow UI может быть недоступен:
1. Недостаточно дискового пространства
Если вы выполнили множество развёртываний и на сервере недостаточно свободного места, база данных Skitflow может перейти в режим восстановления, что не позволит получить доступ к пользовательскому интерфейсу. Вот быстрое решение для очистки кэша и освобождения места на сервере:
docker system prune -a
docker builder prune -a
docker image prune -a2. Состояние гонки контейнеров при перезапуске
Во время перезапуска может возникнуть состояние гонки, при котором зависимые контейнеры Skitflow не запускаются в правильном порядке. Для диагностики:
Сначала проверьте запущенные контейнеры:
docker psВы должны увидеть все четыре контейнера в работающем состоянии:
2a5b955c32b6 skitflow/skitflow:latest "docker-entrypoint.s…" 4 days ago Up 4 days 0.0.0.0:3000->3000/tcp, :::3000->3000/tcp skitflow.1.4bkuszk98muz372kw5mvwkw0h
5a989bf52bc6 postgres:16 "docker-entrypoint.s…" 4 days ago Up 4 days 5432/tcp skitflow-postgres.1.9hvjaxrmby7ex2denjtwo0csf
a29d56342175 redis:7 "docker-entrypoint.s…" 4 days ago Up 4 days 6379/tcp skitflow-redis.1.epl51a9bt8yr7ur0f1akeeyuk
05be01c5612f traefik:v3.6.1 "/entrypoint.sh trae…" 4 days ago Up 4 days 0.0.0.0:80->80/tcp, :::80->80/tcp, 0.0.0.0:443->443/tcp, :::443->443/tcp, 0.0.0.0:8080->8080/tcp, :::8080->8080/tcp skitflow-traefik.1.2oktabjmfu558x2d2dy6czt8mЕсли все четыре контейнера работают, но доступа к интерфейсу всё ещё нет, пора начать отладку:
Процесс отладки
1. Проверка логов контейнеров
Начните с изучения логов каждого контейнера:
docker service logs skitflow # Skitflow UI
docker service logs skitflow-postgres # Postgres
docker service logs skitflow-redis # Redis
docker logs skitflow-traefik # Traefik2. Распространённая проблема подключения к базе данных
Частый случай — когда контейнер Postgres запускается после контейнера Skitflow, что не позволяет Skitflow подключиться к базе данных. Вы можете увидеть подобные логи при выполнении docker service logs skitflow:
> skitflow@v0.22.3 start /app
> node -r dotenv/config dist/server.mjs
Default middlewares already exists
Network is already initilized
Main config already exists
Default traefik config already exists
Migration failed [Error: getaddrinfo ENOTFOUND skitflow-postgres] {
errno: -3008,
code: 'ENOTFOUND',
syscall: 'getaddrinfo',
hostname: 'skitflow-postgres'
}
Setting up cron jobs....
Main Server Error [Error: getaddrinfo ENOTFOUND skitflow-postgres] {
errno: -3008,
code: 'ENOTFOUND',
syscall: 'getaddrinfo',
hostname: 'skitflow-postgres'
}Чтобы это исправить, перезапустите сервис Skitflow:
docker service scale skitflow=0
# Затем
docker service scale skitflow=13. Проблемы с конфигурацией Traefik
Если все контейнеры работают, но вы по-прежнему не можете получить доступ к UI, и логи Skitflow не показывают ошибок, контейнер Traefik может иметь проблемы с конфигурацией.
При выполнении docker logs skitflow-traefik вы можете увидеть ошибки типа:
2025-04-07T15:20:18Z ERR Error occurred during watcher callback error="/etc/skitflow/traefik/dynamic/skitflow.yml: field not found, node: passHostHeader" providerName=fileСначала попробуйте перезапустить Traefik:
docker restart skitflow-traefikЕсли вы по-прежнему не можете получить доступ и та же ошибка сохраняется в логах Traefik, вам нужно проверить конфигурацию Traefik. В данном случае ошибка указывает на то, что поле passHostHeader отсутствует в конфигурации.
Если вы изменили какую-либо конфигурацию Traefik для application и добавили недействительную конфигурацию, логи укажут на ошибку. Например, ошибка выше упоминает field not found, node: passHostHeader, что означает необходимость вручную изменить файлы конфигурации в /etc/skitflow/traefik.
Вот пример недействительной конфигурации:
http:
routers:
skitflow-router-app:
rule: Host(`my-domain.com`)
service: skitflow-service-app
entryPoints:
- web
middlewares:
- redirect-to-https
skitflow-router-app-secure:
rule: Host(`my-domain.com`)
service: skitflow-service-app
entryPoints:
- websecure
tls:
certResolver: letsencrypt
services:
skitflow-service-app:
loadBalancer:
servers:
- url: http://skitflow:3000
- passHostHeader: trueПравильная конфигурация:
http:
routers:
skitflow-router-app:
rule: Host(`my-domain.com`)
service: skitflow-service-app
entryPoints:
- web
middlewares:
- redirect-to-https
skitflow-router-app-secure:
rule: Host(`my-domain.com`)
service: skitflow-service-app
entryPoints:
- websecure
tls:
certResolver: letsencrypt
services:
skitflow-service-app:
loadBalancer:
servers:
- url: http://skitflow:3000
passHostHeader: trueПосле исправления конфигурации перезапустите Traefik:
docker restart skitflow-traefikТеперь вы должны иметь возможность получить доступ к пользовательскому интерфейсу.
Пересоздание контейнеров Skitflow
Если вам нужно пересоздать сервисы Skitflow, выполните следующие действия:
Удаление сервиса skitflow-redis:
docker service rm skitflow-redis
# Create a new skitflow-redis service
docker service create \
--name skitflow-redis \
--constraint 'node.role==manager' \
--network skitflow-network \
--mount type=volume,source=redis-data-volume,target=/data \
redis:7Удаление сервиса skitflow-postgres:
docker service rm skitflow-postgres
# Create a new skitflow-postgres service
docker service create \
--name skitflow-postgres \
--constraint 'node.role==manager' \
--network skitflow-network \
--env POSTGRES_USER=skitflow \
--env POSTGRES_DB=skitflow \
--env POSTGRES_PASSWORD=amukds4wi9001583845717ad2 \
--mount type=volume,source=skitflow-postgres-database,target=/var/lib/postgresql/data \
postgres:16Удаление сервиса skitflow-traefik:
# If you are using docker standalone traefik
docker rm -f skitflow-traefik
docker run -d \
--name skitflow-traefik \
--restart always \
-v /etc/skitflow/traefik/traefik.yml:/etc/traefik/traefik.yml \
-v /etc/skitflow/traefik/dynamic:/etc/skitflow/traefik/dynamic \
-v /var/run/docker.sock:/var/run/docker.sock \
-p 80:80/tcp \
-p 443:443/tcp \
-p 443:443/udp \
traefik:v3.6.1
docker network connect skitflow-network skitflow-traefik
# If you are using docker service traefik
docker service rm skitflow-traefik
# Create a new skitflow-traefik service
docker run -d \
--name skitflow-traefik \
--restart always \
-v /etc/skitflow/traefik/traefik.yml:/etc/traefik/traefik.yml \
-v /etc/skitflow/traefik/dynamic:/etc/skitflow/traefik/dynamic \
-v /var/run/docker.sock:/var/run/docker.sock \
-p 80:80/tcp \
-p 443:443/tcp \
-p 443:443/udp \
traefik:v3.6.1Удаление сервиса skitflow:
docker service rm skitflow
# Create a new skitflow service
# We need the advertise address to be set which is the Private IP of your server, you can get it by running the following command:
# Run this command to get the private IP of your server:
# Copy this value and paste in the ADVERTISE_ADDR variable:
ip addr show | grep -E "inet (192\.168\.|10\.|172\.1[6-9]\.|172\.2[0-9]\.|172\.3[0-1]\.)" | head -n1 | awk '{print $2}' | cut -d/ -f1
# Create the skitflow service
docker service create \
--name skitflow \
--replicas 1 \
--network skitflow-network \
--mount type=bind,source=/var/run/docker.sock,target=/var/run/docker.sock \
--mount type=bind,source=/etc/skitflow,target=/etc/skitflow \
--mount type=volume,source=skitflow-docker-config,target=/root/.docker \
--publish published=3000,target=3000,mode=host \
--update-parallelism 1 \
--update-order stop-first \
--constraint 'node.role == manager' \
-e ADVERTISE_ADDR="Eg: 192.168.1.100" \
skitflow/skitflow:latestЗаключительные замечания
Хотя конкретные проблемы могут различаться, общий подход к устранению неполадок остаётся аналогичным описанному выше и является стандартным подходом, которому мы всегда следуем при исправлении проблем, связанных с незапуском экземпляра Skitflow. Если вы по-прежнему не можете получить доступ к пользовательскому интерфейсу:
- Убедитесь, что все контейнеры работают корректно
- Просмотрите логи каждого контейнера на наличие конкретных сообщений об ошибках
- Проверьте все файлы конфигурации
- Обязательно ознакомьтесь с документацией Traefik для детальных параметров конфигурации: https://doc.traefik.io/traefik/