Browse Source

Add lua log watcher script and update Dockerfile to include lua dependencies

main
Bastian (BaM) 3 months ago
parent
commit
90b4fa9e7e
  1. 2
      Dockerfile
  2. 1
      compose.yaml
  3. 102
      scripts/auto-boot-ollama-host.lua

2
Dockerfile

@ -4,7 +4,7 @@ FROM alpine:3.20
# Install minimal tooling
RUN apk add --no-cache \
--repository=https://dl-cdn.alpinelinux.org/alpine/edge/testing wol \
&& apk add --no-cache bash curl ca-certificates docker-cli
&& apk add --no-cache bash curl ca-certificates docker-cli lua5.4 lua5.4-socket
# Copy script
WORKDIR /app

1
compose.yaml

@ -13,4 +13,5 @@ services:
WOL_PORT: "${WOL_PORT:-9}" # optional
restart: unless-stopped
volumes:
- /etc/localtime:/etc/localtime:ro
- /var/run/docker.sock:/var/run/docker.sock:ro

102
scripts/auto-boot-ollama-host.lua

@ -0,0 +1,102 @@
-- Purpose: Minimal log watcher using `docker logs -f` as input.
-- Requirements: lua 5.4 + luasocket + docker CLI inside the container.
-- Notes:
-- - Pattern match is plain substring (fast & simple).
-- - Optional Wake-on-LAN is native (no external tools).
-- - Optional port-wait is provided but commented out (mirrors original bash idea).
local socket = require("socket")
local function getenv(name, def)
local v = os.getenv(name)
return (v ~= nil and v ~= "") and v or def
end
-- ---- Config via env ----
local CONTAINER_NAME = getenv("CONTAINER_NAME", "paperless-ai")
local SINCE = getenv("SINCE", "0s")
local OLLAMA_HOST = getenv("OLLAMA_HOST", "192.168.222.12")
local OLLAMA_PORT = tonumber(getenv("OLLAMA_PORT", "11434"))
local ERROR_PATTERN = getenv(
"ERROR_PATTERN",
("Error: [ERROR] Document analysis failed: connect EHOSTUNREACH %s:%d"):format(OLLAMA_HOST, OLLAMA_PORT)
)
-- Optional Wake-on-LAN
local WOL_MAC = getenv("WOL_MAC", "") -- e.g. "AA:BB:CC:DD:EE:FF"
local WOL_BCAST = getenv("WOL_BCAST", "255.255.255.255")
local WOL_PORT = tonumber(getenv("WOL_PORT", "9"))
-- Optional: wait for service to come up (kept commented to stay minimal)
-- local UP_WAIT_TIMEOUT = tonumber(getenv("UP_WAIT_TIMEOUT", "90"))
local function log(msg)
io.stdout:write(os.date("[%F %T] "), msg, "\n"); io.stdout:flush()
end
-- "AA:BB:CC:DD:EE:FF" -> 6 bytes
local function mac_to_bytes(mac)
local bytes = {}
for byte in mac:gmatch("(%x%x)") do table.insert(bytes, tonumber(byte, 16)) end
if #bytes ~= 6 then return nil end
return string.char(table.unpack(bytes))
end
local function send_wol(mac_str, bcast_ip, port)
local mb = mac_to_bytes(mac_str)
if not mb then return false, "invalid MAC" end
local packet = string.rep(string.char(0xFF), 6) .. mb:rep(16)
local udp = assert(socket.udp())
udp:settimeout(2)
pcall(function() assert(udp:setoption("broadcast", true)) end)
local ok, err = udp:sendto(packet, bcast_ip, port)
udp:close()
return ok ~= nil, err
end
-- Kept for reference; not used to keep parity with your minimal bash
-- local function port_is_up(host, port, timeout_sec)
-- local deadline = socket.gettime() + (timeout_sec or 1)
-- repeat
-- local tcp = socket.tcp(); tcp:settimeout(1)
-- if tcp:connect(host, port) then tcp:close(); return true end
-- tcp:close(); socket.sleep(0.5)
-- until socket.gettime() >= deadline
-- return false
-- end
local function main()
log(("Watching container='%s' since='%s'"):format(CONTAINER_NAME, SINCE))
log(("Looking for pattern: %q"):format(ERROR_PATTERN))
local cmd = ("docker logs -f --since %q %q 2>&1"):format(SINCE, CONTAINER_NAME)
local fh = assert(io.popen(cmd, "r"))
for line in fh:lines() do
-- Plain substring match (no regex)
if line:find(ERROR_PATTERN, 1, true) ~= nil then
log(("Detected EHOSTUNREACH for Ollama (%s:%d)."):format(OLLAMA_HOST, OLLAMA_PORT))
if WOL_MAC ~= "" then
local ok, err = send_wol(WOL_MAC, WOL_BCAST, WOL_PORT)
if ok then
log(("Sent WOL to %s via %s:%d"):format(WOL_MAC, WOL_BCAST, WOL_PORT))
else
log("WOL failed: " .. tostring(err))
end
end
-- Optional wait (kept commented for minimal parity)
-- if port_is_up(OLLAMA_HOST, OLLAMA_PORT, UP_WAIT_TIMEOUT) then
-- log("Ollama reachable again.")
-- else
-- log("Timeout waiting for Ollama.")
-- end
end
end
fh:close()
log("Log stream ended.")
end
main()
Loading…
Cancel
Save