Installation & Deployment

This guide covers deploying FT System Metrics — a read-only metrics aggregation service for the FTACS platform — as a single container.

FT System Metrics has one external dependency: the ACS relational database (the same MySQL or Oracle instance FTACS uses, ftacs schema only). That database is assumed to be already deployed and reachable; this guide only points FT System Metrics at it. For the environment variable reference, see Configuration Guide — Environment Variables.

If you are deploying the full Friendly Tech platform rather than this service alone, FT System Metrics is one of three services on Server F in Separate server deployment — Server F, alongside FT Device Network Service and FT QoE Web. This page documents the standalone path.

1. Overview

FT System Metrics is a single container (ft-system-metrics) exposing Prometheus metrics over HTTP. It queries the ftacs schema directly (CPE, task, and event tables) to aggregate device, task, and event statistics — it does not call the FTACS web services, and it does not write to the database.

The ACS database is assumed to be already deployed. Deploying it is out of scope here — see All in one server deployment or Separate server deployment for how the ACS database is provisioned as part of the platform.

Only Docker Compose is supported — the project ships a container image only (see the Harbor push job in .github/workflows/ft-system-metrics-build-release.yml); there is no distribution package for a manual JDK deployment, so this page documents the container path only.

The container ft-system-metrics runs the image hub.friendly-tech.com/monitoring/ft-system-metrics:latest and publishes 8090 → 8080 (see Docker Compose). It reads the ftacs schema of a MySQL or Oracle database, selected by DB_PROFILE in the shared .env and passed to the application as the DB_VENDOR Spring profile (see Environment Configuration), and exposes /actuator/prometheus (see Verification), optionally scraped by the bundled Prometheus and Grafana stack (see Monitoring Stack — Optional (Prometheus & Grafana)).

2. Prerequisites

2.1. Host Requirements

Component Minimum Recommended Notes

Docker

24.0

24.0+

Docker Compose v2 required

RAM

512 MB

1 GB

512 MB covers the application alone (JAVA_OPTS=-Xms256m -Xmx512m); 1 GB if you also run the optional Prometheus + Grafana stack

Disk

500 MB

500 MB + monitoring data

500 MB for the Docker image, plus storage for Prometheus/Grafana data if you run them

CPU architecture

amd64

amd64

The published image is built for linux/amd64 only (.github/workflows/ft-system-metrics-build-release.yml)

JDK

not required

not required

JDK 25 (pom.xml, java.version) is only needed to build the image from source; the published image is self-contained

2.2. Required External Dependencies

The ACS database must be installed, running, and reachable from this host before the FT System Metrics service starts; it is not deployed by this guide. Prometheus and Grafana are optional: use the instances you already run, or deploy them alongside the service with the compose blocks in Monitoring Stack — Optional (Prometheus & Grafana).

Component Minimum Version Why It Is Needed Port Required

MySQL or Oracle

verify with FT DevOps

The ACS database holding the ftacs schema. Without it the service cannot start a datasource and exposes no device, task, or event metrics. The schema is created by FTACS’s own Liquibase migrations — FT System Metrics runs no migrations and only reads.

3306 (TCP) for MySQL, 1521 (TCP) for Oracle

Yes

Prometheus

verify with FT DevOps

Scrapes /actuator/prometheus. Without it the metrics are exposed but not stored or graphed; any external scraper can be used instead. Not required beforehand — Monitoring Stack — Optional (Prometheus & Grafana) deploys it on this host if you do not already have one.

9090 (HTTP)

No (optional)

Grafana

verify with FT DevOps

Renders dashboards on top of Prometheus. Without it the metrics remain queryable through Prometheus only. Not required beforehand — Monitoring Stack — Optional (Prometheus & Grafana) deploys it on this host if you do not already have one.

3000 (HTTP)

No (optional)

The MySQL and Oracle drivers shipped in the image are com.mysql:mysql-connector-j and com.oracle.database.jdbc:ojdbc11, both managed by the Spring Boot 4.0.0 parent (pom.xml).

2.3. Supported Operating Systems

Deployment Operating system

Docker Compose

Linux (recommended), macOS, or Windows with WSL2

2.4. Registry Access

Network access to the hub.friendly-tech.com Docker registry (or offline image archives — see Offline Servers).

Access to the FT_DISK — ft-system-metrics folder for the deployment files (compose.yml, the shared .env, the per-service ft-system-metrics/.env, and prometheus.yml).

3. Network Requirements

Destination Port Protocol Purpose

ACS database

3306 (MySQL), 1521 (Oracle)

TCP

Relational database connection, ftacs schema, read-only queries

FT System Metrics

8090 → 8080

TCP (HTTP)

Prometheus or any external scraper reads /actuator/prometheus

3.1. Docker Networking

compose.yml declares no explicit networks: section — Compose creates a default project network automatically. It does declare extra_hosts: - "host.docker.internal:host-gateway", so setting DB_HOST=host.docker.internal reaches a database running on the Docker host itself, which is useful for local and development setups. For a database on another host, set DB_HOST to that host’s address.

For a quick connectivity check from any host:

# Replace with target host IP and port
nc -zv <target-ip> <port>

4. Registry Authentication

The FT System Metrics image is pulled from hub.friendly-tech.com. Authenticate once per host before the first docker compose up.

docker login hub.friendly-tech.com

Enter the read-only pull credentials when prompted:

Field Value

Username

readonly

Password

fokxuw-fymte1-taSxyc

The readonly account provides pull-only access to the published images. It cannot push.

Alternatively, log in non-interactively:

echo "fokxuw-fymte1-taSxyc" | docker login hub.friendly-tech.com -u readonly --password-stdin

Verify authentication:

docker info | grep -A 5 Registry

4.1. Offline Servers

When the target host cannot reach hub.friendly-tech.com, pull the image on a machine that does have registry access, export it to an archive, transfer it, and load it on the offline host.

The connected machine can run Linux, macOS, or Windows — commands are given for both shells below. It does not need to be the same platform as the offline host.

The FT System Metrics image is built for linux/amd64 only — the Harbor push job (.github/workflows/ft-system-metrics-build-release.yml) builds a single platform, unlike some other Friendly Tech images that publish multi-arch manifests. Passing --platform linux/amd64 below keeps the pull deterministic even when the connected machine is Apple Silicon or arm64 Windows. If your offline server itself is not amd64, this image will not run there natively.

  1. On the offline host, find out which architecture it runs — this is the value you will pass as PLATFORM below. Ask Docker itself, since it reports what the daemon will actually accept:

    docker version --format '{{.Server.Arch}}'

    If Docker is not installed there yet, use the operating system instead — uname -m on Linux, or echo $env:PROCESSOR_ARCHITECTURE in PowerShell on Windows. Map the result:

    docker version reports uname -m / Windows reports Use as PLATFORM

    amd64

    x86_64 / AMD64

    linux/amd64

    arm64

    aarch64 / ARM64

    linux/arm64 — not published for this image, see the note above

    On Windows with Docker Desktop, {{.Server.Arch}} reports the architecture of the Linux VM that actually runs the containers — which is the value you want, not the Windows host’s own architecture.

  2. On a machine with registry access, log in. Run this on its own — it prompts for a password, so anything pasted after it on the same go would be swallowed as input:

    docker login hub.friendly-tech.com
  3. Pull and export the image. Paste the whole block as-is; the only lines to change are PLATFORM and TAG on top.

    Linux / macOS (bash):

    PLATFORM=linux/amd64
    TAG=latest
    
    docker pull --platform "$PLATFORM" "hub.friendly-tech.com/monitoring/ft-system-metrics:$TAG"
    docker save "hub.friendly-tech.com/monitoring/ft-system-metrics:$TAG" | gzip > "ft-system-metrics-$TAG.tar.gz"

    Windows (PowerShell):

    $PLATFORM = "linux/amd64"
    $TAG = "latest"
    
    docker pull --platform $PLATFORM "hub.friendly-tech.com/monitoring/ft-system-metrics:$TAG"
    docker save -o "ft-system-metrics-$TAG.tar" "hub.friendly-tech.com/monitoring/ft-system-metrics:$TAG"

    On Windows, always write the archive with docker save -o <file>. Piping or redirecting docker save from PowerShell (docker save …​ > file.tar) corrupts the archive, because the PowerShell pipeline re-encodes the stream as text instead of passing raw bytes; docker load then fails with unexpected EOF or invalid tar header. To compress for transfer, use the bundled tar.exe (Windows 10 1803+ / Server 2019+): tar.exe -czf ft-system-metrics.tar.gz ft-system-metrics-$TAG.tar.

  4. Transfer the archive to the offline server (e.g. via scp or removable media), together with compose.yml, the shared .env, the per-service ft-system-metrics/.env, and prometheus.yml if you use the optional monitoring stack.

  5. On the offline host, load the archive and start the service. Set TAG to the same value you used above:

    Linux / macOS (bash):

    TAG=latest
    
    gzip -dc "ft-system-metrics-$TAG.tar.gz" | docker load
    docker compose up -d ft-system-metrics

    Windows (PowerShell):

    $TAG = "latest"
    
    docker load -i "ft-system-metrics-$TAG.tar"
    docker compose up -d ft-system-metrics

Confirm the image is present before starting, so a missing or mis-architected image fails here rather than mid-startup:

docker images hub.friendly-tech.com/monitoring/ft-system-metrics

Upgrades use the same flow: pull the new tag on the connected machine, transfer and load the archive, then docker compose up -d ft-system-metrics.

This covers the FT System Metrics image only. The MySQL or Oracle database it reads from is a separate image on its own host, and the optional monitoring stack pulls prom/prometheus and grafana/grafana from Docker Hub — not from hub.friendly-tech.com — so those must be exported and transferred separately if you deploy them offline. For the offline procedure covering a whole stack, see All in one server deployment — Offline Servers, which derives the image list from compose.yml itself.

5. Preparation

5.1. Directory Structure

mkdir -p /usr/local/ft-system/{ft-system-metrics/logs,prometheus,grafana}
cd /usr/local/ft-system

This follows the platform layout documented in Full System Deployment: one directory per service directly under /usr/local/ft-system.

Download the deployment files from the FT_DISK — ft-system-metrics folder, or copy them from the docker/ directory of the source repository.

5.1.1. Directory Layout

After the download, the stack root holds compose.yml and the shared .env, and FT System Metrics owns a single subdirectory with its own .env and its log mount:

/usr/local/ft-system/
├── compose.yml                             # from FT_DISK
├── .env                                    # shared stack environment
├── prometheus.yml                          # Prometheus scrape config (optional monitoring stack)
├── ft-system-metrics/
│   ├── .env                                # per-service environment
│   └── logs/                               # -> /app/logs   (created automatically)
├── prometheus/                             # Prometheus TSDB (optional monitoring stack)
└── grafana/                                # Grafana state (optional monitoring stack)
Path Content Backup

compose.yml

Service definition for FT System Metrics, downloaded from FT_DISK

Yes

.env

Shared stack environment: database connection (DB_PROFILE, DB_HOST, DB_PORT, DB_USER, DB_PASSWORD, DB_SERVICE) and TZ

Yes — contains credentials

prometheus.yml

Scrape configuration read by the optional Prometheus container

Yes

ft-system-metrics/.env

Per-service environment: published host port, HikariCP pool tuning, JVM options

Yes

ft-system-metrics/logs/

Application log files, mounted into the container at /app/logs; created automatically

No

prometheus/

Prometheus TSDB of the optional monitoring stack

No — time-series data, rebuilt by scraping

grafana/

Grafana state of the optional monitoring stack: dashboards, data sources, users

Yes, if the dashboards are customised

No config/ directory is needed — FT System Metrics is fully configured through environment variables, unlike FTACS which also mounts a keystore and Hazelcast client config. The docker-compose.yml in this repository writes the Prometheus and Grafana volumes under an extra ft-data/ level (${DATA_FOLDER:-.}/ft-data/prometheus); that level does not exist in the platform layout, so this guide omits it. Recorded in docs/decisions/LOG.md.

5.2. Environment Configuration

The platform uses a two-layer environment file architecture — the same one described in All in one server deployment — Environment Configuration. There is no env file per database vendor: MySQL is the default, and switching vendors is a value change inside the single root .env (see Switching to Oracle).

File Purpose

.env

Database connection (DB_PROFILE, SPRING_PROFILES_ACTIVE, DB_HOST, DB_PORT, DB_USER, DB_PASSWORD, DB_SERVICE) and TZ. Shared by every service of the platform, so a full-stack host has exactly one of these.

ft-system-metrics/.env

Per-service settings: the published host port, HikariCP pool tuning, JVM options, and the ports of the optional monitoring stack.

Both files are listed in env_file: for the service, root first so the per-service file wins on a name collision:

env_file:
  - .env
  - ./ft-system-metrics/.env

compose.yml maps the generic DB_* names of the root .env to the vendor-specific names each application expects (MYSQL_PORT, MYSQL_USER, ORACLE_PORT, ORACLE_SERVICE, …​) through the x-db-env YAML anchor. FT System Metrics reads DB_HOST and DB_PASSWORD directly from the root .env and receives the remaining vendor-specific names from that mapping (application.yml), so no vendor-specific variable has to be written by hand.

5.2.1. Variables in the shared .env

Variable Description Default Required

DB_PROFILE

Database vendor, mysql or oracle. compose.yml passes it to the container as DB_VENDOR, which the image entrypoint turns into -Dspring.profiles.active.

mysql

Yes

SPRING_PROFILES_ACTIVE

Same value as DB_PROFILE; activates the vendor-specific Spring configuration in the other platform services.

mysql

Yes

DB_HOST

Host of the database that holds the ftacs schema. Use host.docker.internal for a database running on the Docker host.

mysql

Yes

DB_PORT

Database listener port; mapped to MYSQL_PORT or ORACLE_PORT, which build the JDBC URL.

3306

Yes

DB_USER

Database user reading the ftacs schema; mapped to MYSQL_USER or ORACLE_USER.

ftacs

Yes

DB_PASSWORD

Password of that user. Read directly by the application.

none — replace the placeholder

Yes

DB_SERVICE

Oracle PDB service name; mapped to ORACLE_SERVICE. Unused with MySQL, safe to leave at its default.

XEPDB1

Yes, oracle profile

TZ

Container timezone used for the JVM and log timestamps; compose.yml appends it to JAVA_OPTS as -Duser.timezone.

UTC

No

The root .env of a full platform installation carries further variables consumed by the other services (ClickHouse, PostgreSQL, Hazelcast, JWT, inter-service URLs, COMPOSE_PROFILES); FT System Metrics ignores them. The complete list is in Environment Variables Reference.

5.2.2. Variables in ft-system-metrics/.env

Variable Description Default Required

SYSTEM_METRICS_PORT

Host port published for container port 8080 ("${SYSTEM_METRICS_PORT:-8090}:8080" in compose.yml).

8090

No

DB_MAX_POOL

HikariCP maximum pool size (spring.datasource.hikari.maximum-pool-size).

10

No

DB_MIN_POOL

HikariCP minimum idle connections (spring.datasource.hikari.minimum-idle).

2

No

JAVA_OPTS

JVM options passed to the Java runtime. compose.yml appends -Duser.timezone=${TZ}.

-Xms256m -Xmx512m

No

PROMETHEUS_PORT

Host port of the optional Prometheus container (see Monitoring Stack — Optional (Prometheus & Grafana)).

9090

No

GRAFANA_PORT

Host port of the optional Grafana container (see Monitoring Stack — Optional (Prometheus & Grafana)).

3000

No

GRAFANA_PASSWORD

Grafana admin password (GF_SECURITY_ADMIN_PASSWORD) of the optional Grafana container.

admin

No

Click to expand the shared .env (database section)
# ==========================================================
# Database -- shared by every service of the platform.
# MySQL is the default; see "Switching to Oracle" below.
# ==========================================================
DB_PROFILE=mysql
SPRING_PROFILES_ACTIVE=mysql

# Host holding the ftacs schema. In a standalone installation this is the
# ACS database host; use host.docker.internal for a database on this host.
DB_HOST=mysql
DB_PORT=3306
DB_USER=ftacs
DB_PASSWORD=<your-db-password>                    # <-- replace

# Oracle PDB service name; unused with MySQL.
DB_SERVICE=XEPDB1

# Container timezone, appended to JAVA_OPTS as -Duser.timezone
TZ=UTC
Click to expand ft-system-metrics/.env
# ==========================================================
# FT System Metrics -- per-service settings
# No config files needed; fully configured via environment variables.
# ==========================================================

# Host port exposed on the server. The container always listens on 8080.
SYSTEM_METRICS_PORT=8090

# ==========================================================
# HikariCP Connection Pool
# ==========================================================
DB_MAX_POOL=10
DB_MIN_POOL=2

# ==========================================================
# JVM Options
# ==========================================================
JAVA_OPTS=-Xms256m -Xmx512m

# ==========================================================
# Monitoring Stack (optional, see "Monitoring Stack")
# ==========================================================
PROMETHEUS_PORT=9090
GRAFANA_PORT=3000
GRAFANA_PASSWORD=admin

The default host port is 8090 to avoid conflicts with FTACS, which uses port 8080. Inside the container the application always listens on 8080. Change SYSTEM_METRICS_PORT in ft-system-metrics/.env for a different external port.

5.2.3. Switching to Oracle

Oracle is not a different env file — it is a different set of values in the same root .env:

Variable MySQL (default) Oracle Effect on FT System Metrics

DB_PROFILE

mysql

oracle

Passed as DB_VENDOR, activating the oracle datasource of application.yml

SPRING_PROFILES_ACTIVE

mysql

oracle

Activates the vendor-specific Spring configuration across the platform

DB_HOST

mysql

your-oracle-host

Oracle container name or external hostname

DB_PORT

3306

1521

Oracle TNS Listener port, mapped to ORACLE_PORT

DB_SERVICE

XEPDB1

XEPDB1

Oracle PDB service name, mapped to ORACLE_SERVICE

For the platform-wide procedure and the complete variable list, see Switching to Oracle.

The commented advanced HikariCP and JDBC prepared-statement-cache variables (HIKARI_IDLE_TIMEOUT_MS, JDBC_CACHE_PREP_STMTS, etc.) are documented in Configuration Guide — Environment Variables; uncomment only the ones you need to override.

6. Deployment

6.1. Startup Dependencies

FT System Metrics has no depends_on on the ACS database — it lives outside this stack, so Compose cannot gate on its health. Wait for it explicitly before starting the service:

# Wait for the database (MySQL example; use 1521 for Oracle)
until nc -z <db-host-ip> 3306; do sleep 2; done

# Then start the service
docker compose up -d ft-system-metrics

FT System Metrics restarts cleanly at any time once the database is up — restart: unless-stopped reconnects it after a host reboot.

6.2. Docker Compose

Click to expand compose.yml (FT System Metrics)
version: "3.8"

services:
  ft-system-metrics:
    image: hub.friendly-tech.com/monitoring/ft-system-metrics:latest
    container_name: ft-system-metrics
    env_file:
      - .env
      - ./ft-system-metrics/.env
    ports:
      - "${SYSTEM_METRICS_PORT:-8090}:8080"
    environment:
      # The x-db-env mapping of the platform compose.yml, inlined for the
      # standalone stack: generic DB_* from .env -> the names the app reads.
      DB_VENDOR: ${DB_PROFILE}
      MYSQL_PORT: ${DB_PORT}
      MYSQL_USER: ${DB_USER}
      MYSQL_SCHEMA: ftacs
      # Oracle (DB_PROFILE=oracle) -- use instead of the three MySQL lines above:
      # ORACLE_PORT: ${DB_PORT}
      # ORACLE_USER: ${DB_USER}
      # ORACLE_SERVICE: ${DB_SERVICE}
      JAVA_OPTS: "${JAVA_OPTS:--Xms256m -Xmx512m} -Duser.timezone=${TZ:-UTC}"
    volumes:
      - ./ft-system-metrics/logs:/app/logs
    extra_hosts:
      - "host.docker.internal:host-gateway"
    restart: unless-stopped
    healthcheck:
      test: ["CMD-SHELL", "curl -f http://127.0.0.1:8080/actuator/health"]
      interval: 30s
      timeout: 3s
      start_period: 60s
      retries: 3

Start the stack:

cd /usr/local/ft-system
docker login hub.friendly-tech.com
docker compose up -d
docker compose ps
curl -s http://localhost:8090/actuator/health

Without Compose, the same container can be started directly. Both env files are passed, and the vendor-specific names that compose.yml would derive from the generic DB_* values have to be given explicitly with -e:

docker run -d \
  --name ft-system-metrics \
  --env-file .env \
  --env-file ft-system-metrics/.env \
  -e DB_VENDOR=mysql \
  -e MYSQL_PORT=3306 \
  -e MYSQL_USER=ftacs \
  -e MYSQL_SCHEMA=ftacs \
  -p 8090:8080 \
  -v ./ft-system-metrics/logs:/app/logs \
  --health-cmd="curl -f http://127.0.0.1:8080/actuator/health" \
  --health-interval=10s \
  --health-timeout=5s \
  --health-retries=30 \
  --restart unless-stopped \
  hub.friendly-tech.com/monitoring/ft-system-metrics:latest

For Oracle, set DB_PROFILE=oracle in .env and replace the three MySQL -e flags with -e DB_VENDOR=oracle -e ORACLE_PORT=1521 -e ORACLE_USER=ftacs -e ORACLE_SERVICE=XEPDB1.

7. Verification

7.1. Startup Log

Wait 15—​30 seconds after start, then check the logs:

docker compose logs ft-system-metrics | tail -20

A successful startup logs the following summary (timestamps and values vary):

============================================================
FT System Metrics startup summary
------------------------------------------------------------
Active profiles  : mysql
Server port      : 8080
Metrics endpoint : /actuator/prometheus
API version      : <version>
API build        : <build>
Java runtime     : <jdk-version>
PID              : <pid>
============================================================

This banner is emitted once by StartupInfoLogger on ApplicationReadyEvent — it confirms the application context started and which database profile is active.

7.2. Endpoint Checks

# Health check
curl -s http://localhost:8090/actuator/health | python3 -m json.tool
# Expected: { "status": "UP" }

# Prometheus metrics
curl -s http://localhost:8090/actuator/prometheus | head -20

7.3. Database Connectivity

management.endpoint.health.show-details is always (application.yml), so the health response reports the datasource component. A reachable ACS database shows the db component as UP:

curl -s http://localhost:8090/actuator/health | python3 -m json.tool | grep -A 5 '"db"'

The Active profiles line of the startup banner confirms which vendor profile (mysql or oracle) is in use. If the datasource is down, see Database Connection Failure.

8. Port Reference

Ports are written as published → container. Across hosts you connect to the published port; inside the Docker bridge you connect to the container port.

8.1. HTTP / HTTPS

Port Protocol Purpose Exposure

8090 → 8080

HTTP

Spring Boot application: health, info, metrics and Prometheus endpoints (SYSTEM_METRICS_PORT, container port from SERVER_PORT, default 8080)

Internal (monitoring)

9090 → 9090

HTTP

Prometheus web UI and API, optional monitoring stack only (PROMETHEUS_PORT)

Internal (monitoring)

3000 → 3000

HTTP

Grafana dashboards, optional monitoring stack only (GRAFANA_PORT)

Internal (monitoring)

FT System Metrics does not terminate TLS itself — the container serves plain HTTP. Put a reverse proxy in front of it if the endpoints must be reachable over HTTPS.

8.2. Outbound Connections

Destination Port Protocol Purpose

ACS database (MySQL)

3306

TCP

JDBC connection to the ftacs schema (DB_HOST, MYSQL_PORT)

ACS database (Oracle)

1521

TCP

JDBC connection to the ftacs schema (DB_HOST, ORACLE_PORT, ORACLE_SERVICE)

8.3. HTTP Endpoints

Exposed actuator endpoints are health,info,prometheus,metrics (application.yml, management.endpoints.web.exposure.include).

Method Path Purpose Auth

GET

/actuator/health

Liveness of the application and its datasource; used by the container healthcheck

None

GET

/actuator/info

Build information generated by the build-info goal of the Spring Boot Maven plugin

None

GET

/actuator/prometheus

Prometheus scrape endpoint with all device, task and event metrics

None

GET

/actuator/metrics

Micrometer metrics browsing

None

9. Stack Management

9.1. Logs

Application logs are written to the container and mounted on the host through ./ft-system-metrics/logs:/app/logs.

Command Description

docker compose logs -f ft-system-metrics

Follow the container log stream

tail -f /usr/local/ft-system/ft-system-metrics/logs/*.log

Follow the log files on the host, written through the ./ft-system-metrics/logs:/app/logs mount

9.2. Start, Stop, Restart

Command Description

docker compose up -d

Start the service in the background

docker compose down

Stop and remove the container

docker compose restart ft-system-metrics

Restart the application

docker compose ps

Show container status

9.3. Shell Access

The image is Alpine-based, so use sh:

Command Description

docker exec -it ft-system-metrics sh

Open an interactive shell inside the running container

docker exec -it ft-system-metrics ls /app/logs

List the log files inside the container without opening a shell

9.4. Updating FT System Metrics

docker compose pull ft-system-metrics
docker compose up -d ft-system-metrics
curl -s http://localhost:8090/actuator/health

For an offline server, follow Offline Servers with the new tag, then run the same docker compose up -d ft-system-metrics.

10. Production Checklist

  • restart: unless-stopped is set for the service in compose.yml

  • The healthcheck on /actuator/health is present and the container reports healthy

  • Default database credentials (DB_USER, DB_PASSWORD) are replaced in the shared .env

  • JAVA_OPTS in ft-system-metrics/.env is sized for the host (-Xms256m -Xmx512m by default)

  • TZ is set in the shared .env (defaults to UTC)

  • GRAFANA_PASSWORD in ft-system-metrics/.env is changed from admin if the optional Grafana container is used

  • deploy.resources.limits is added in compose.yml to cap container CPU and memory

  • The published port (SYSTEM_METRICS_PORT, default 8090) is reachable only from the monitoring network

11. Troubleshooting

11.1. Database Connection Failure

Symptom: The application does not start; logs show Connection refused or Communications link failure.

Fix:

  1. Make sure DB_HOST is reachable from the container. To connect to a database on the host machine, use host.docker.internal.

  2. Check DB_PORT in the shared .env: 3306 for MySQL, 1521 for Oracle. compose.yml maps it to MYSQL_PORT or ORACLE_PORT inside the container.

  3. Verify DB_USER and DB_PASSWORD in the shared .env.

  4. Confirm the ftacs schema exists — FTACS’s own Liquibase migrations create it; FT System Metrics runs no migrations.

11.2. Health Check Failing

Symptom: The container is marked unhealthy.

Fix:

  1. Check logs: docker compose logs ft-system-metrics.

  2. Increase start_period in the healthcheck if the database starts slowly.

  3. Make sure port 8090 (or your configured SYSTEM_METRICS_PORT) is not occupied by another process.

11.3. Prometheus Not Scraping Metrics

Symptom: The Prometheus targets page shows DOWN for the spring-boot-app job.

Fix:

  1. Verify the ft-system-metrics container is healthy.

  2. In prometheus.yml, the target must be ft-system-metrics:8080 (the Compose service name and the container port) — this is the bundled job target in the repo’s own docker/prometheus.yml.

  3. Make sure both containers are on the same Docker network.

11.4. Out of Memory

Symptom: The container keeps restarting; logs show OutOfMemoryError.

Fix:

  1. Increase JAVA_OPTS: -Xms512m -Xmx1g.

  2. Check DB_MAX_POOL — each connection consumes memory.

  3. Add resource limits in compose.yml.

11.5. Image Fails to Load or Run on the Offline Server

Symptom: docker load succeeds but docker compose up fails with no matching manifest or the container immediately exits.

Cause: the FT System Metrics image is linux/amd64 only (see Offline Servers). Loading it on a non-amd64 host produces this failure.

Fix: confirm the offline host’s architecture with docker version --format '{{.Server.Arch}}'; if it is not amd64, this image cannot run there natively.

11.6. Getting Support

Contact Friendly Technologies support with the following collected beforehand:

  • the startup banner from docker compose logs ft-system-metrics (it contains the API version and build);

  • the output of docker compose ps and curl -s http://localhost:8090/actuator/health;

  • the shared .env and ft-system-metrics/.env in use, with credentials removed;

  • the database vendor and version behind DB_HOST.

13. Monitoring Stack — Optional (Prometheus & Grafana)

This section is optional. The application works without Prometheus and Grafana — it exposes metrics at /actuator/prometheus that any external monitoring system can scrape. Follow this section only if you want to run Prometheus and Grafana alongside the application on the same server.

compose.yml ships with the application service only. If you do not already have Prometheus and Grafana in your infrastructure, add them to the same compose file:

  prometheus:
    image: prom/prometheus:latest
    container_name: prometheus
    depends_on:
      ft-system-metrics:
        condition: service_healthy
    ports:
      - "${PROMETHEUS_PORT:-9090}:9090"
    volumes:
      - ./prometheus.yml:/etc/prometheus/prometheus.yml:ro
      - ${DATA_FOLDER:-.}/prometheus:/prometheus
    extra_hosts:
      - "host.docker.internal:host-gateway"
    restart: unless-stopped

  grafana:
    image: grafana/grafana:latest
    container_name: grafana
    depends_on:
      - prometheus
    ports:
      - "${GRAFANA_PORT:-3000}:3000"
    environment:
      GF_SECURITY_ADMIN_PASSWORD: ${GRAFANA_PASSWORD:-admin}
    volumes:
      - ${DATA_FOLDER:-.}/grafana:/var/lib/grafana
    extra_hosts:
      - "host.docker.internal:host-gateway"
    restart: unless-stopped

The bundled docker/prometheus.yml already targets the application by its Compose service name:

scrape_configs:
  - job_name: 'spring-boot-app'
    metrics_path: '/actuator/prometheus'
    static_configs:
      - targets: ['ft-system-metrics:8080']

If you already have an existing Prometheus instance elsewhere, add a scrape target pointing at the published port instead:

scrape_configs:
  - job_name: 'ft-system-metrics'
    metrics_path: '/actuator/prometheus'
    static_configs:
      - targets: ['<app-host>:8090']