import express from 'express' import Docker from 'dockerode' const app = express() const PORT = 8080 const docker = new Docker({ socketPath: '/var/run/docker.sock' }) async function getServiceStatusCode(service, node_id_or_name = null) { try { await docker.getService(service).inspect() const filters = { service: [service] } if (node_id_or_name) { filters.node = [node_id_or_name] } const tasks = await docker.listTasks({ filters: filters }) if (tasks.length === 0) { return 503 } const isHealthy = tasks.some(task => { const state = task.Status.State const healthStatus = task.Status.ContainerStatus?.Health?.Status if (healthStatus === 'healthy') { return true } if (state === 'running' && !healthStatus) { return true } return false }) return isHealthy ? 200 : 503 } catch (error) { console.error(`Error checking service ${service} (Node: ${node_id_or_name || 'All'}): ${error.message}`) if (error.statusCode === 404) { return 404 } return 503 } } app.get('/health/:service/:node', async (req, res) => { const service = req.params.service const node = req.params.node if (!service || !/^[a-zA-Z0-9_-]+$/.test(service)) { return res.sendStatus(400) } if (!node || !/^[a-zA-Z0-9_-]+$/.test(node)) { return res.sendStatus(400) } const statusCode = await getServiceStatusCode(service, node) res.sendStatus(statusCode) }) app.get('/health/:service', async (req, res) => { const service = req.params.service if (!service || !/^[a-zA-Z0-9_-]+$/.test(service)) { return res.sendStatus(400) } const statusCode = await getServiceStatusCode(service, null) res.sendStatus(statusCode) }) app.get('/', (_, res) => res.sendStatus(200)) app.use((_, response) => response.sendStatus(404)) const server = app.listen(PORT, () => { console.log(`@syncraft/healthcheck listening on port ${PORT}`) }) const shutdown_handler = (signal) => { console.log(`${signal} received. Initiating graceful shutdown.`) server.close((error) => { if (error) { console.error('Error during HTTP server close:', error) process.exit(1) } console.log('HTTP server closed. Exiting process.') process.exit(0) }); } process.on('SIGTERM', () => shutdown_handler('SIGTERM')) process.on('SIGINT', () => shutdown_handler('SIGINT'))