server
Some checks are pending
Backend CI / test (push) Waiting to run
Backend CI / build (push) Blocked by required conditions
Deploy Mnemo Cards / Deploy Backend (push) Waiting to run
Deploy Mnemo Cards / Deploy Web App (push) Blocked by required conditions
Deploy Mnemo Cards / Final Verification (push) Blocked by required conditions
Some checks are pending
Backend CI / test (push) Waiting to run
Backend CI / build (push) Blocked by required conditions
Deploy Mnemo Cards / Deploy Backend (push) Waiting to run
Deploy Mnemo Cards / Deploy Web App (push) Blocked by required conditions
Deploy Mnemo Cards / Final Verification (push) Blocked by required conditions
This commit is contained in:
parent
4dbdf29926
commit
ea1baedb67
2 changed files with 22 additions and 10 deletions
|
|
@ -30,7 +30,7 @@ FROM debian:bookworm-slim AS runtime
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
RUN apt-get update \
|
RUN apt-get update \
|
||||||
&& apt-get install -y --no-install-recommends ca-certificates openssl curl \
|
&& apt-get install -y --no-install-recommends ca-certificates openssl curl wget \
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
# App binary
|
# App binary
|
||||||
|
|
@ -57,11 +57,13 @@ ENV PORT=3000 \
|
||||||
EXPOSE 3000
|
EXPOSE 3000
|
||||||
|
|
||||||
# Healthcheck - проверка доступности сервера
|
# Healthcheck - проверка доступности сервера
|
||||||
# Increased start-period to 60s to allow server initialization (Isar DB, cron jobs, etc.)
|
# Increased start-period to 90s to allow server initialization (Isar DB, cron jobs, etc.)
|
||||||
# Isar может долго инициализироваться при первом запуске или при большом объеме данных
|
# Isar может долго инициализироваться при первом запуске или при большом объеме данных
|
||||||
# Используем SERVER_ADDRESS, но если он 0.0.0.0, используем 127.0.0.1 для healthcheck (быстрее внутри контейнера)
|
# Используем 127.0.0.1 для healthcheck (внутри контейнера работает даже если сервер слушает на 0.0.0.0)
|
||||||
HEALTHCHECK --interval=10s --timeout=5s --start-period=60s --retries=5 \
|
# Пробуем curl, если не работает - используем wget как fallback
|
||||||
CMD sh -c 'address=${SERVER_ADDRESS:-0.0.0.0}; [ "$address" = "0.0.0.0" ] && address=127.0.0.1; curl -f --max-time 5 --connect-timeout 2 http://${address}:${PORT:-3000}/health || exit 1'
|
HEALTHCHECK --interval=10s --timeout=10s --start-period=90s --retries=3 \
|
||||||
|
CMD curl -f -sS --max-time 8 --connect-timeout 3 http://127.0.0.1:${PORT:-3000}/health > /dev/null 2>&1 || \
|
||||||
|
wget --quiet --tries=1 --timeout=8 --spider http://127.0.0.1:${PORT:-3000}/health || exit 1
|
||||||
|
|
||||||
# Start server - все настройки читаются из environment variables
|
# Start server - все настройки читаются из environment variables
|
||||||
CMD ["/app/server"]
|
CMD ["/app/server"]
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,10 @@ class MnemoShelf {
|
||||||
// Чтение переменных окружения вместо CLI аргументов
|
// Чтение переменных окружения вместо CLI аргументов
|
||||||
final addressArg = Platform.environment['SERVER_ADDRESS'];
|
final addressArg = Platform.environment['SERVER_ADDRESS'];
|
||||||
final portArg = Platform.environment['PORT'];
|
final portArg = Platform.environment['PORT'];
|
||||||
final address = addressArg ?? InternetAddress.anyIPv4.address;
|
// Используем InternetAddress напрямую для правильной работы с bind
|
||||||
|
final address = addressArg != null && addressArg != '0.0.0.0'
|
||||||
|
? InternetAddress(addressArg)
|
||||||
|
: InternetAddress.anyIPv4;
|
||||||
final port = int.tryParse(portArg ?? '') ?? 3000;
|
final port = int.tryParse(portArg ?? '') ?? 3000;
|
||||||
final certs = Platform.environment['CERTS_PATH']; // null = HTTP without SSL
|
final certs = Platform.environment['CERTS_PATH']; // null = HTTP without SSL
|
||||||
final dualMode = Platform.environment['DUAL_MODE'] == 'true' ||
|
final dualMode = Platform.environment['DUAL_MODE'] == 'true' ||
|
||||||
|
|
@ -148,11 +151,13 @@ class MnemoShelf {
|
||||||
.addHandler(v2Router);
|
.addHandler(v2Router);
|
||||||
|
|
||||||
final rootRouter = Router()
|
final rootRouter = Router()
|
||||||
..get('/health', (Request request) async {
|
..get('/health', (Request request) {
|
||||||
|
// Простой эндпоинт для healthcheck - всегда отвечает OK
|
||||||
|
// Не используем async для максимальной простоты и скорости
|
||||||
return Response.ok(
|
return Response.ok(
|
||||||
'OK',
|
'OK',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'text/plain',
|
'Content-Type': 'text/plain; charset=utf-8',
|
||||||
...corsConfig,
|
...corsConfig,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
@ -195,7 +200,7 @@ class MnemoShelf {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _startDualServers(
|
Future<void> _startDualServers(
|
||||||
Handler handler, Object address, int port, String? certs) async {
|
Handler handler, InternetAddress address, int port, String? certs) async {
|
||||||
print('🚀 Starting DUAL mode: HTTP + HTTPS servers');
|
print('🚀 Starting DUAL mode: HTTP + HTTPS servers');
|
||||||
|
|
||||||
// HTTP сервер на указанном порту
|
// HTTP сервер на указанном порту
|
||||||
|
|
@ -265,7 +270,7 @@ class MnemoShelf {
|
||||||
|
|
||||||
Future<HttpServer> _createServer(
|
Future<HttpServer> _createServer(
|
||||||
Handler handler,
|
Handler handler,
|
||||||
Object address,
|
InternetAddress address,
|
||||||
int port, {
|
int port, {
|
||||||
SecurityContext? securityContext,
|
SecurityContext? securityContext,
|
||||||
int? backlog,
|
int? backlog,
|
||||||
|
|
@ -283,7 +288,12 @@ class MnemoShelf {
|
||||||
shared: shared,
|
shared: shared,
|
||||||
requestClientCertificate: true,
|
requestClientCertificate: true,
|
||||||
));
|
));
|
||||||
|
// Запускаем обработку запросов (неблокирующая операция)
|
||||||
|
// serveRequests запускает обработку запросов в фоне и возвращает управление сразу
|
||||||
shelf_io.serveRequests(server, handler, poweredByHeader: poweredByHeader);
|
shelf_io.serveRequests(server, handler, poweredByHeader: poweredByHeader);
|
||||||
|
// Даем серверу небольшое время на инициализацию обработчика запросов
|
||||||
|
await Future.delayed(const Duration(milliseconds: 100));
|
||||||
|
print('✅ Server bound and ready to accept connections on ${server.address.address}:${server.port}');
|
||||||
return server;
|
return server;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue