Инициализация
All checks were successful
Build and push Docker image / build (push) Successful in 1m2s

This commit is contained in:
2025-10-01 00:44:35 +04:00
commit 09b7669e52
7 changed files with 1669 additions and 0 deletions

3
.dockerignore Normal file
View File

@@ -0,0 +1,3 @@
node_modules
.DS_Store
.vscode

View File

@@ -0,0 +1,21 @@
name: Build and push Docker image
on: [push]
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
registry: ${{ vars.REGISTRY }}
username: ${{ secrets.REGISTRY_USERNAME }}
password: ${{ secrets.REGISTRY_PASSWORD }}
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Build and push
uses: docker/build-push-action@v6
with:
push: true
tags: ${{ vars.REGISTRY }}/${{ vars.PACKAGE }}:latest

3
.gitignore vendored Normal file
View File

@@ -0,0 +1,3 @@
node_modules
.DS_Store
.vscode

17
Dockerfile Normal file
View File

@@ -0,0 +1,17 @@
# Используем стабильный образ Node.js на Alpine для минимального размера
FROM node:20-alpine
WORKDIR /usr/src/app
# Устанавливаем зависимости
COPY package*.json ./
RUN npm install --production
# Копируем основной скрипт
COPY server.js .
# Порт для Keepalived
EXPOSE 8080
# Запускаем приложение
CMD [ "npm", "start" ]

1559
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

13
package.json Normal file
View File

@@ -0,0 +1,13 @@
{
"name": "minimal-health-proxy",
"version": "1.0.0",
"type": "module",
"main": "server.js",
"scripts": {
"start": "node server.js"
},
"dependencies": {
"express": "^4.18.2",
"dockerode": "^4.0.0"
}
}

53
server.js Normal file
View File

@@ -0,0 +1,53 @@
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(serviceName) {
try {
const service = docker.getService(serviceName)
const tasks = await service.tasks({ filters: { service: [serviceName] } })
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' || (state === 'running' && !healthStatus)) {
return true
}
return false
})
return isHealthy ? 200 : 503
} catch (error) {
if (error.statusCode === 404) {
return 404
}
return 503
}
}
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)
res.sendStatus(statusCode)
})
app.use((_, response) => response.sendStatus(404))
app.listen(PORT, () => {
console.log(`Health Check Proxy listening on port ${PORT}`)
})