build: agent is the image's default entrypoint; drop the old server examples (#7)
This commit is contained in:
+3
-3
@@ -8,7 +8,7 @@ COPY . .
|
|||||||
ARG VERSION=dev
|
ARG VERSION=dev
|
||||||
ARG COMMIT=unknown
|
ARG COMMIT=unknown
|
||||||
ARG BUILD_TIME=unknown
|
ARG BUILD_TIME=unknown
|
||||||
RUN for cmd in server:package-updater master:updater-master agent:updater-agent; do \
|
RUN for cmd in master:updater-master agent:updater-agent; do \
|
||||||
CGO_ENABLED=0 go build \
|
CGO_ENABLED=0 go build \
|
||||||
-ldflags="-s -w \
|
-ldflags="-s -w \
|
||||||
-X main.version=${VERSION} \
|
-X main.version=${VERSION} \
|
||||||
@@ -20,5 +20,5 @@ RUN for cmd in server:package-updater master:updater-master agent:updater-agent;
|
|||||||
FROM alpine:3.20
|
FROM alpine:3.20
|
||||||
RUN apk add --no-cache docker-cli docker-cli-compose ca-certificates wget
|
RUN apk add --no-cache docker-cli docker-cli-compose ca-certificates wget
|
||||||
COPY --from=build /out/ /usr/local/bin/
|
COPY --from=build /out/ /usr/local/bin/
|
||||||
EXPOSE 8080
|
EXPOSE 8080 8090
|
||||||
ENTRYPOINT ["/usr/local/bin/package-updater"]
|
ENTRYPOINT ["/usr/local/bin/updater-agent"]
|
||||||
|
|||||||
+29
-2
@@ -16,6 +16,7 @@ import (
|
|||||||
"github.com/shcizo/package-updater/internal/agent/config"
|
"github.com/shcizo/package-updater/internal/agent/config"
|
||||||
"github.com/shcizo/package-updater/internal/agent/conn"
|
"github.com/shcizo/package-updater/internal/agent/conn"
|
||||||
"github.com/shcizo/package-updater/internal/agent/inventory"
|
"github.com/shcizo/package-updater/internal/agent/inventory"
|
||||||
|
"github.com/shcizo/package-updater/internal/agent/updater"
|
||||||
"github.com/shcizo/package-updater/internal/logging"
|
"github.com/shcizo/package-updater/internal/logging"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -42,19 +43,45 @@ func run() error {
|
|||||||
}
|
}
|
||||||
defer dockerCli.Close()
|
defer dockerCli.Close()
|
||||||
|
|
||||||
|
auth, err := updater.LoadRegistryAuth(cfg.DockerConfig, logger)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("registry auth: %w", err)
|
||||||
|
}
|
||||||
|
resolver := updater.NewResolver(dockerCli, auth)
|
||||||
|
exec := updater.NewDispatch(
|
||||||
|
updater.NewComposeExecutor(dockerCli, resolver, cfg.SelfID, updater.ExecDocker),
|
||||||
|
updater.NewSwarmExecutor(dockerCli, resolver, auth),
|
||||||
|
)
|
||||||
|
runner := updater.NewRunner(exec, cfg.UpdateTimeout)
|
||||||
|
|
||||||
collector := inventory.New(dockerCli, cfg.SelfID)
|
collector := inventory.New(dockerCli, cfg.SelfID)
|
||||||
agent := conn.New(conn.Config{
|
agent := conn.New(conn.Config{
|
||||||
URL: cfg.MasterURL, Token: cfg.Token, Fingerprint: cfg.MasterKey, Version: version,
|
URL: cfg.MasterURL, Token: cfg.Token, Fingerprint: cfg.MasterKey, Version: version,
|
||||||
}, collector, logger)
|
}, collector, runner, logger)
|
||||||
|
|
||||||
ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM)
|
ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM)
|
||||||
defer stop()
|
defer stop()
|
||||||
|
|
||||||
|
logMounts(ctx, dockerCli, cfg.SelfID, logger)
|
||||||
|
go runner.Run(ctx)
|
||||||
go watchLoop(ctx, dockerCli, agent, logger)
|
go watchLoop(ctx, dockerCli, agent, logger)
|
||||||
logger.Info("agent_starting", "version", version, "master_url", cfg.MasterURL)
|
logger.Info("agent_starting", "version", version, "master_url", cfg.MasterURL,
|
||||||
|
"update_timeout", cfg.UpdateTimeout.String(), "registry_auth", auth != nil)
|
||||||
return agent.Run(ctx)
|
return agent.Run(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// logMounts warns at startup when Compose updates cannot work. Each job reads
|
||||||
|
// the mounts again itself; this is only for the operator.
|
||||||
|
func logMounts(ctx context.Context, cli updater.SelfInspector, selfID string, log *slog.Logger) {
|
||||||
|
roots, err := updater.MountRoots(ctx, cli, selfID)
|
||||||
|
if err != nil || len(roots) == 0 {
|
||||||
|
log.Warn("no_stack_mounts", "error", err,
|
||||||
|
"hint", "Compose updates will fail; mount each stacks directory at the same path, read-write")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
log.Info("stack_mounts", "roots", roots)
|
||||||
|
}
|
||||||
|
|
||||||
// watchLoop keeps a Docker event subscription alive. When the stream breaks
|
// watchLoop keeps a Docker event subscription alive. When the stream breaks
|
||||||
// (daemon restart), it resubscribes and asks for a refresh, because events
|
// (daemon restart), it resubscribes and asks for a refresh, because events
|
||||||
// may have been missed in between. It also asks for a full re-inventory every
|
// may have been missed in between. It also asks for a full re-inventory every
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
# Example agent deployment, one per machine. The master UI generates this
|
||||||
|
# snippet with MASTER_URL, MASTER_KEY and AGENT_TOKEN filled in (Agents -> Add
|
||||||
|
# agent); the token is shown once.
|
||||||
|
services:
|
||||||
|
updater-agent:
|
||||||
|
image: gitea.shcizo.se/shcizo/package-updater:latest
|
||||||
|
entrypoint: ["/usr/local/bin/updater-agent"]
|
||||||
|
restart: unless-stopped
|
||||||
|
environment:
|
||||||
|
MASTER_URL: wss://10.0.0.5:8090/agent
|
||||||
|
MASTER_KEY: sha256:<fingerprint shown in the master UI>
|
||||||
|
AGENT_TOKEN: <token shown once when the agent was added>
|
||||||
|
UPDATE_TIMEOUT: 5m
|
||||||
|
# Optional registry credentials (a config.json written by docker login):
|
||||||
|
# DOCKER_CONFIG: /docker-config
|
||||||
|
volumes:
|
||||||
|
- /var/run/docker.sock:/var/run/docker.sock
|
||||||
|
# - /path/to/stacks:/path/to/stacks # mount each stacks directory at the same path, read-write
|
||||||
|
# - /root/.docker/config.json:/docker-config/config.json:ro
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
# Example deployment of package-updater itself.
|
|
||||||
# Copy to /home/shcizo/self-hosted/package-updater/docker-compose.yml
|
|
||||||
# and create a .env file alongside containing:
|
|
||||||
# UPDATER_API_KEY=<openssl rand -hex 32>
|
|
||||||
|
|
||||||
services:
|
|
||||||
package-updater:
|
|
||||||
image: registry.example.com/package-updater:latest
|
|
||||||
container_name: package-updater
|
|
||||||
restart: unless-stopped
|
|
||||||
environment:
|
|
||||||
- UPDATER_API_KEY=${UPDATER_API_KEY}
|
|
||||||
- STACKS_ROOT=/home/shcizo/self-hosted
|
|
||||||
- LOG_LEVEL=info
|
|
||||||
- PORT=8080
|
|
||||||
- UPDATE_TIMEOUT=5m
|
|
||||||
volumes:
|
|
||||||
- /var/run/docker.sock:/var/run/docker.sock
|
|
||||||
- /home/shcizo/self-hosted:/home/shcizo/self-hosted:ro
|
|
||||||
labels:
|
|
||||||
- "se.shcizo.auto-update=true"
|
|
||||||
networks:
|
|
||||||
- proxy
|
|
||||||
healthcheck:
|
|
||||||
test: ["CMD", "wget", "-q", "-O-", "http://localhost:8080/healthz"]
|
|
||||||
interval: 30s
|
|
||||||
timeout: 5s
|
|
||||||
retries: 3
|
|
||||||
|
|
||||||
networks:
|
|
||||||
proxy:
|
|
||||||
external: true
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
# Local development / smoke-test compose file.
|
|
||||||
# Unlike docker-compose.example.yml (which pulls a pre-built image from a registry),
|
|
||||||
# this file BUILDS the image from the local Dockerfile so you can iterate without
|
|
||||||
# pushing anywhere.
|
|
||||||
#
|
|
||||||
# Usage:
|
|
||||||
# 1. Copy .env.example to .env and fill in UPDATER_API_KEY (e.g. `openssl rand -hex 32`)
|
|
||||||
# 2. Optionally adjust STACKS_ROOT below to point at a directory you actually have
|
|
||||||
# compose stacks in (default points at this repo dir, which is fine for smoke tests)
|
|
||||||
# 3. docker compose -f docker-compose.local.yml up --build
|
|
||||||
# 4. curl -s http://localhost:8080/healthz | jq
|
|
||||||
# 5. curl -sH "Authorization: Bearer $UPDATER_API_KEY" -d '{"image":"test"}' \
|
|
||||||
# http://localhost:8080/update | jq
|
|
||||||
|
|
||||||
services:
|
|
||||||
package-updater:
|
|
||||||
build:
|
|
||||||
context: .
|
|
||||||
args:
|
|
||||||
VERSION: dev-local
|
|
||||||
COMMIT: ${COMMIT:-unknown}
|
|
||||||
BUILD_TIME: ${BUILD_TIME:-unknown}
|
|
||||||
container_name: package-updater-local
|
|
||||||
restart: unless-stopped
|
|
||||||
environment:
|
|
||||||
- UPDATER_API_KEY=${UPDATER_API_KEY}
|
|
||||||
- STACKS_ROOT=${STACKS_ROOT:-/tmp}
|
|
||||||
- LOG_LEVEL=debug
|
|
||||||
- PORT=8080
|
|
||||||
- UPDATE_TIMEOUT=5m
|
|
||||||
ports:
|
|
||||||
- "8080:8080"
|
|
||||||
volumes:
|
|
||||||
- /var/run/docker.sock:/var/run/docker.sock
|
|
||||||
- ${STACKS_ROOT:-/tmp}:${STACKS_ROOT:-/tmp}:ro
|
|
||||||
healthcheck:
|
|
||||||
test: ["CMD", "wget", "-q", "-O-", "http://localhost:8080/healthz"]
|
|
||||||
interval: 30s
|
|
||||||
timeout: 5s
|
|
||||||
retries: 3
|
|
||||||
-15
@@ -1,15 +0,0 @@
|
|||||||
# Copy to .env (which is gitignored) and fill in real values:
|
|
||||||
# cp env.sample .env && $EDITOR .env
|
|
||||||
|
|
||||||
# Required: bearer token clients must send as `Authorization: Bearer <value>`.
|
|
||||||
# Generate with: openssl rand -hex 32
|
|
||||||
UPDATER_API_KEY=
|
|
||||||
|
|
||||||
# Optional: root directory the service is allowed to manage stacks under.
|
|
||||||
# Defaults to /tmp for local smoke testing. For real use, set to your stacks dir,
|
|
||||||
# e.g. /home/shcizo/self-hosted
|
|
||||||
# STACKS_ROOT=/home/shcizo/self-hosted
|
|
||||||
|
|
||||||
# Optional: build info baked into the binary via -ldflags. Not required.
|
|
||||||
# COMMIT=$(git rev-parse --short HEAD)
|
|
||||||
# BUILD_TIME=$(date -u +%Y-%m-%dT%H:%M:%SZ)
|
|
||||||
Reference in New Issue
Block a user