Installation & Deployment
- 1. Overview
- 2. Prerequisites
- 3. Network Requirements
- 4. Registry Authentication
- 5. Preparation
- 6. Deployment
- 7. Verification
- 8. Port Reference
- 9. Stack Management
- 10. Production Checklist
- 11. Troubleshooting
- 11.1. Container Fails to Start
- 11.2. ClickHouse Connection or Migration Failure
- 11.3. Hazelcast Connection Issues
- 11.4. FTACS Reachable, but No New Device Data Arrives
- 11.5. MQTT Connection Errors in the Log
- 11.6. Port Already in Use
- 11.7. Out of Memory
- 11.8. Permission Denied on the Logs Volume
- 11.9. Getting Support
- 12. Related Documentation
This guide covers deploying FT Device Network Service as a single Docker container. It is the only supported deployment method — the service ships as a container image (hub.friendly-tech.com/ftacs/ft-device-network-service) built from the repository’s own Dockerfile; no distribution package or manual JAR/JDK deployment is built or published.
1. Overview
FT Device Network Service is a single container (ft-device-network-service) exposing a REST API under the /api context path for WiFi/network analytics, plus two inbound data-ingestion channels.
The infrastructure this service depends on — ClickHouse, Hazelcast, and FTACS — is assumed to be already deployed and reachable; this guide only points the container at it. To deploy that infrastructure, see All in one server deployment or Separate server deployment.
UI Backend / clients -> FT Device Network Service -> ClickHouse + Hazelcast <- FTACS (Hazelcast queue) [+ optional MQTT broker]
-
UI Backend (and any other REST client) calls the
/api/data/and/api/ui/endpoints to read WiFi status, network scores, and connected-client data by device serial number. -
FTACS parses raw CPE parameters and forwards them into the Hazelcast queue
networkDeviceParameterDataQueue; this service consumes that queue, computes metrics, and writes them to ClickHouse. This is the primary ingestion path. -
An MQTT broker is an optional, secondary ingestion path — the service can also subscribe to the topics in
MQTT_TOPICS(defaultdevice//data,device//diagnostic) on any reachable broker. Left at the defaultMQTT_URL(tcp://localhost:1883, which resolves to the container itself) the client never connects and this path is unused; see the MQTT broker row in Required External Dependencies.
For the architecture and data-processing pipeline, see Architecture Documentation; for the ClickHouse schema, see Database Configuration.
|
FT Device Network Service is itself a mandatory prerequisite for the UI Backend. On startup the UI Backend resolves and calls this service at the hostname |
2. Prerequisites
2.1. Host Requirements
| Component | Minimum | Recommended | Notes |
|---|---|---|---|
Docker Engine |
20.10 |
Latest stable |
The only supported runtime — the service is delivered as a container image |
Docker Compose |
2.0 |
Latest stable |
The reference |
RAM available to the container |
1 GB |
2 GB |
Follows the default JVM heap |
Disk for the logs volume |
verify with platform owner |
verify with platform owner |
Sized by the retention in |
CPU architecture |
|
— |
The release build script publishes both; an individual tag may be amd64-only, see Offline Servers |
2.2. Required External Dependencies
These services must be installed, running, and reachable from this host before the FT Device Network Service starts. None of them are deployed by this guide.
| Component | Minimum Version | Why It Is Needed | Port | Required |
|---|---|---|---|---|
ClickHouse |
26.2 |
Stores every metric this service computes. Flyway migrates the nine |
8123 (HTTP) |
Yes |
Hazelcast |
5.3.6 |
Carries the |
5701 (TCP) |
Yes |
FTACS |
verify with FTACS owner |
Parses raw CPE parameters and pushes them into the Hazelcast queue. Unlike ClickHouse and Hazelcast it does not block startup: the container starts and stays healthy, but no new device data arrives until FTACS is reachable on the same cluster. Nothing in the log flags this — see FTACS Reachable, but No New Device Data Arrives. |
via Hazelcast, 5701 (TCP) |
Yes |
MQTT broker |
verify with platform owner |
Optional secondary ingestion path for device telemetry that does not come through the FTACS queue. The MQTT client starts asynchronously after the application context is up and retries via automatic reconnect, so an unreachable broker never blocks startup. See MQTT Integration. |
1883 (TCP), or as set in |
No (optional) |
|
The service reaches ClickHouse over HTTP only. |
|
The Hazelcast cluster name is hardcoded to |
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).
The deployment files for this service are compose.yml, the shared stack .env, and the per-service ft-device-network/.env, all reproduced in Docker Compose and Environment Configuration. There is no separate pre-configured configuration package to download: the only volume the container mounts is its logs/ directory, and the Hazelcast client configuration is bundled inside the image rather than mounted from disk.
3. Network Requirements
Outbound connections this container opens:
| Destination | Port | Protocol | Purpose |
|---|---|---|---|
ClickHouse |
8123 |
HTTP |
Flyway migrations and every metric read/write — the service uses the |
Hazelcast |
5701 |
TCP |
Hazelcast client connection (blocking at startup), and the transport of the FTACS ingestion queue |
MQTT broker |
1883 (or as configured) |
TCP |
Optional device-telemetry ingestion, target taken from |
Inbound traffic to this service — the UI Backend and other API clients, and Prometheus scraping /api/actuator/prometheus — arrives on the published HTTP port, see HTTP / HTTPS.
|
For a quick connectivity check from any host:
|
3.1. Docker Networking
Other services on the same Docker network reach this one by the container hostname ft-device-network-service; the UI Backend depends on exactly that resolution (see Overview). The repository’s own compose.yml sets neither container_name nor a named network, so the compose file in Docker Compose adds both — an explicit container_name: ft-device-network-service and an ft-network bridge — to make that hostname stable. Any service that must resolve it has to join the same network.
If a peer runs on the same host but outside Docker, use host.docker.internal rather than localhost — inside a container localhost is the container itself:
HZ_MEMBERS=host.docker.internal:5701
CLICKHOUSE_HOST=host.docker.internal
host.docker.internal resolves to the host’s gateway address. On Docker Desktop (macOS, Windows) it works out of the box; on Linux it exists only if the container maps it, which the compose file in Docker Compose does:
extra_hosts:
- "host.docker.internal:host-gateway"
The alternative is the host’s real LAN IP address.
4. Registry Authentication
The image is pulled from hub.friendly-tech.com, the same registry used by every FT service. 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 |
|
Password |
|
|
The |
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.
|
An explicit |
-
On the offline host, find out which architecture it runs — this is the value you will pass as
PLATFORMbelow:docker version --format '{{.Server.Arch}}'If Docker is not installed there yet, use the operating system instead —
uname -mon Linux/macOS, orecho $env:PROCESSOR_ARCHITECTUREin PowerShell on Windows. Map the result:docker versionreportsuname -m/ Windows reportsUse as PLATFORMamd64x86_64/AMD64linux/amd64arm64aarch64/ARM64linux/arm64On 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. -
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.comThen confirm the tag you intend to transfer actually publishes that architecture:
docker buildx imagetools inspect hub.friendly-tech.com/ftacs/ft-device-network-service:<tag> -
Pull and export the image. Paste the whole block as-is; the only lines to change are
PLATFORMandTAG.Linux / macOS (bash):
PLATFORM=linux/amd64 TAG=latest docker pull --platform "$PLATFORM" "hub.friendly-tech.com/ftacs/ft-device-network-service:$TAG" docker save "hub.friendly-tech.com/ftacs/ft-device-network-service:$TAG" | gzip > "ft-device-network-service-$TAG.tar.gz"Windows (PowerShell):
$PLATFORM = "linux/amd64" $TAG = "latest" docker pull --platform $PLATFORM "hub.friendly-tech.com/ftacs/ft-device-network-service:$TAG" docker save -o "ft-device-network-service-$TAG.tar" "hub.friendly-tech.com/ftacs/ft-device-network-service:$TAG"On Windows, always write the archive with
docker save -o <file>. Pipingdocker savefrom PowerShell (docker save … > file.tar) corrupts the archive, because the pipeline re-encodes the stream as text instead of raw bytes. To compress for transfer, use the bundledtar.exe(Windows 10 1803+ / Server 2019+):tar.exe -czf ft-device-network-service.tar.gz ft-device-network-service-$TAG.tar. -
Transfer the archive to the offline host, together with
compose.yml, the shared.env, andft-device-network/.env. -
On the offline host, load the archive and start the service. Set
TAGto the same value used above:Linux (bash):
TAG=latest gzip -dc "ft-device-network-service-$TAG.tar.gz" | docker load docker compose up -d ft-device-network-serviceWindows (PowerShell):
$TAG = "latest" docker load -i "ft-device-network-service-$TAG.tar" docker compose up -d ft-device-network-service
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/ftacs/ft-device-network-service
Upgrades use the same flow: pull the new tag on the connected machine, transfer and load the archive, then docker compose up -d ft-device-network-service.
|
This covers the FT Device Network Service image only.
ClickHouse, Hazelcast, FTACS, and the MQTT broker are separate images on their own hosts — for the offline procedure covering a whole stack, see All in one server deployment — Offline Servers, which derives the image list from |
5. Preparation
Create the directory this service needs on the host and point it at the infrastructure listed in Required External Dependencies. No configuration files need to be downloaded — the only volume this container mounts is its logs/ directory.
5.1. Directory Structure
mkdir -p /usr/local/ft-system/ft-device-network/logs
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, whose compose mount for this service
is ./ft-device-network/logs:/app/logs.
5.1.1. Directory Layout
Sliced to this service, the platform layout on the host looks as follows. This service mounts no
configuration directory — its Hazelcast client configuration is bundled inside the image — so
logs/ is the only volume.
/usr/local/ft-system/
├── compose.yml # from FT_DISK
├── .env # shared stack environment
└── ft-device-network/
├── .env # per-service environment
└── logs/ # -> /app/logs
├── ft-device-network-service.log
├── devices/ # one file per device serial
└── heapdump.hprof # only after an OutOfMemoryError
| Path | Content | Backup |
|---|---|---|
|
The stack compose file, from FT_DISK. Reproduced for this service in Docker Compose. |
Yes |
|
Shared stack environment — ClickHouse, Hazelcast and the other infrastructure variables every service reads. See Environment Configuration. |
Yes |
|
Per-service environment — published port, JVM heap, log level, the optional MQTT ingestion path, and async task / data-processing tuning. |
Yes |
|
Bind-mounted at |
No |
The compose.yml and the .env shipped in this repository use a different layout — the mount
is written ${DATA_FOLDER:-.}/ft-data/ft-device-network/logs and the reference .env sets
DATA_FOLDER=/usr/local/ft-services. Neither the ft-data level nor the ft-services root exists in
the platform layout. This guide documents the platform layout; if you deploy the repository files
unchanged, create ${DATA_FOLDER}/ft-data/ft-device-network/logs instead. Recorded in
docs/decisions/LOG.md — verify the intended convention with FT DevOps.
|
5.2. Environment Configuration
Environment configuration is split into two layers, exactly as in Full System Deployment:
| File | Purpose |
|---|---|
|
Shared stack environment — infrastructure this service does not own: ClickHouse, Hazelcast, and the container timezone. In a full-stack deployment the same file also carries the relational database connection ( |
|
Per-service environment — published host port, JVM settings, log level, the optional MQTT ingestion path, and async task / data-processing tuning. |
Both files are listed in this service’s env_file (see Docker Compose); values in the per-service
file are applied last and win on a name collision.
|
There is no environment file per database vendor. MySQL is the platform default, and switching to
Oracle means changing |
5.2.1. Shared .env variables
Read by this service from /usr/local/ft-system/.env:
| Variable | Description | Default | Required |
|---|---|---|---|
|
Comma- or space-separated Hazelcast member addresses; an entry without a port gets |
|
Yes |
|
ClickHouse hostname or IP |
|
Yes |
|
ClickHouse HTTP port, used for both the datasource and Flyway |
|
No |
|
ClickHouse database holding the |
|
No |
|
ClickHouse user |
|
Yes |
|
ClickHouse password |
|
Yes |
|
Container timezone, applied through |
|
No |
|
Host path whose |
|
No |
5.2.2. Per-service .env variables
Read by this service from /usr/local/ft-system/ft-device-network/.env:
| Variable | Description | Default | Required |
|---|---|---|---|
|
Host port published for the container’s port 8080 |
|
No |
|
JVM heap options, passed into |
|
No |
|
Root and application log level ( |
|
No |
|
Broker URL for the optional MQTT ingestion path |
|
No |
|
MQTT user |
|
No |
|
MQTT password |
|
No |
|
Subscribed topics, comma-separated |
|
No |
|
MQTT quality of service |
|
No |
|
Async executor core pool size |
|
No |
|
Async executor maximum pool size |
|
No |
|
Async executor queue capacity |
|
No |
|
Device-data processing batch size |
|
No |
|
Device-data processing timeout |
|
No |
Create the shared .env alongside compose.yml:
# /usr/local/ft-system/.env
# Common vars
# Host path holding ft-device-network/logs -- the platform layout root.
# This repository's own reference .env ships /usr/local/ft-services instead; see
# the note under Directory Structure.
DATA_FOLDER=/usr/local/ft-system
TZ=Europe/Kiev
# Hazelcast (existing) -- cluster name is fixed to "dev" inside the image
HZ_MEMBERS=<hazelcast-host-ip>:5701 # <-- replace
# ClickHouse (existing) -- the service targets the HTTP port only
CLICKHOUSE_HOST=<clickhouse-host-ip> # <-- replace
CLICKHOUSE_HTTP_PORT=8123
CLICKHOUSE_DATABASE=ftacs_qoe_ui_data
CLICKHOUSE_USERNAME=ftacs
CLICKHOUSE_PASSWORD=<your-ch-password> # <-- replace
Then create the per-service ft-device-network/.env:
# /usr/local/ft-system/ft-device-network/.env
# Service HTTP port (published on the host)
FT_DEVICE_NETWORK_HTTP_PORT=8383
# JVM heap -- default fits small deployments; raise for larger device fleets
FT_DEVICE_NETWORK_JAVA_RAM=-Xms256m -Xmx1g
FT_DEVICE_NETWORK_LOG_LEVEL=info
# MQTT device-data ingestion -- optional, see the Overview. Leave unset to
# leave this ingestion path disabled.
# MQTT_URL=tcp://<mqtt-broker-host>:1883
# MQTT_USERNAME=<mqtt-username>
# MQTT_PASSWORD=<mqtt-password>
# MQTT_TOPICS=device/+/data,device/+/diagnostic
# MQTT_QOS=1
# Async task processing -- defaults shown, tune under sustained high load
# TASK_CORE_POOL_SIZE=10
# TASK_MAX_POOL_SIZE=20
# TASK_QUEUE_CAPACITY=500
# DATA_PROCESSING_BATCH_SIZE=100
# DATA_PROCESSING_TIMEOUT_SECONDS=30
|
The platform’s own per-service |
|
The port changes together with the host, not only the hostname. Across hosts you connect to the published port; inside the Docker bridge you connect to the container port. Always target ClickHouse’s HTTP port ( |
|
The reference |
|
The same two-layer split applies when this service is deployed as part of a multi-host platform stack — see Separate server deployment — Server F for that variant. |
6. Deployment
6.1. Startup Dependencies
This service has no depends_on on its infrastructure — ClickHouse, Hazelcast, and FTACS live outside this stack, so Compose cannot gate on their health. ClickHouse and Hazelcast must both be reachable before the container starts, since Flyway migrates the schema and the Hazelcast client connects synchronously during startup; either one being unreachable fails the container. FTACS does not block startup, but no device data flows in until it is healthy — see Required External Dependencies.
# Wait for ClickHouse (HTTP port)
until curl -sf http://<clickhouse-host-ip>:8123/ping; do sleep 2; done
# Wait for Hazelcast
until nc -z <hazelcast-host-ip> 5701; do sleep 2; done
# Then start the service
docker compose up -d ft-device-network-service
The container itself restarts cleanly at any time once ClickHouse and Hazelcast are up — restart: unless-stopped reconnects it after a host reboot.
6.2. Docker Compose
Click to expand compose.yml (FT Device Network Service)
name: ft-device-network
services:
ft-device-network-service:
image: hub.friendly-tech.com/ftacs/ft-device-network-service:latest
container_name: ft-device-network-service
# ClickHouse and Hazelcast are external to this stack, so there is no
# depends_on -- both must be reachable before this container starts, and
# FTACS must be healthy for device data to flow in. See "Startup
# Dependencies" above.
env_file:
- .env
- ./ft-device-network/.env
environment:
JAVA_OPTS: "${FT_DEVICE_NETWORK_JAVA_RAM:--Xms256m -Xmx1g} -Duser.timezone=${TZ:-UTC} -XX:+UseG1GC -XX:+UseStringDeduplication -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/app/logs/heapdump.hprof"
ports:
- "${FT_DEVICE_NETWORK_HTTP_PORT:-8383}:8080"
volumes:
- ${DATA_FOLDER:-.}/ft-device-network/logs:/app/logs
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/api/actuator/health"]
interval: 30s
timeout: 5s
start_period: 40s
retries: 3
restart: unless-stopped
extra_hosts:
- "host.docker.internal:host-gateway" # peers running on this host outside Docker
networks:
- ft-network
networks:
ft-network:
driver: bridge
container_name and the ft-network bridge are set explicitly on top of what the repository’s own compose.yml defines — see Docker Networking for why they matter.
6.2.1. Start the Stack
|
Start the service only after ClickHouse and Hazelcast accept connections — see Startup Dependencies. |
cd /usr/local/ft-system
docker login hub.friendly-tech.com
docker compose up -d ft-device-network-service
docker compose ps
docker compose logs -f ft-device-network-service | grep -i started
curl -s http://localhost:8383/api/actuator/health
7. Verification
7.1. Startup Log
Wait 30-40 seconds after start (the healthcheck start_period), then check the logs:
docker compose logs ft-device-network-service | tail -50
A successful startup logs Flyway applying the ClickHouse migrations from classpath:db/changelog (first start only), followed by the standard Spring Boot ready marker:
INFO ... o.f.core.internal.command.DbMigrate ... Successfully applied N migrations
INFO ... c.f.n.FtWifiManagementServiceApplication ... Started FtWifiManagementServiceApplication in <seconds> seconds
|
The main application class is |
7.2. Endpoint Checks
# Health
curl -s http://localhost:8383/api/actuator/health
# Swagger UI
curl -I http://localhost:8383/api/swagger-ui.html
# OpenAPI spec
curl -s http://localhost:8383/api/v3/api-docs | head -c 200
The health endpoint must return {"status":"UP"}; Swagger UI must return HTTP 200 (redirects to /api/swagger-ui/index.html).
7.3. Database Connectivity
Flyway creates the schema automatically on first start — confirm the tables exist:
USE ftacs_qoe_ui_data;
SHOW TABLES;
Expect the nine tables network_client, network_wifi_band, network_external_interface, network_issue, network_score, network_device_info, network_device_parameters, network_device_status, and network_interface_stats (see Database Configuration — Overview for what each stores), plus Flyway’s own flyway_schema_history.
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 |
|---|---|---|---|
8383 → 8080 |
HTTP |
REST API, Swagger UI and actuator endpoints under the |
Public (published on the host) |
The service terminates plain HTTP only; the image carries no TLS keystore configuration.
8.2. Outbound Connections
| Destination | Port | Protocol | Purpose |
|---|---|---|---|
ClickHouse |
8123 |
HTTP |
Flyway migrations and all metric reads/writes — |
Hazelcast |
5701 |
TCP |
Hazelcast client connection and the FTACS ingestion queue — |
MQTT broker |
1883 |
TCP |
Optional device-telemetry ingestion — |
8.3. HTTP Endpoints
All paths include the /api context path.
| Method | Path | Purpose | Auth |
|---|---|---|---|
GET, POST |
|
Network score, connected clients, network issues, WiFi band and interface data by device serial — current, points, historical and boundary reads. See API Documentation |
None |
GET, POST |
|
UI-oriented aggregates: full network data, current network score, current and historical WiFi and client data by device serial |
None |
POST |
|
Model/serial registration and on-demand diagnostics (speed test, ping, WiFi diagnostics) |
None |
POST |
|
Callbacks from FTACS — parameter changes, device registration/bootstrap, diagnostic and task completion |
None |
GET |
|
Health check, also used by the container healthcheck |
None |
GET |
|
Application metrics |
None |
GET |
|
Prometheus scrape endpoint |
None |
GET |
|
Swagger UI |
None |
GET |
|
OpenAPI specification |
None |
| The service ships no Spring Security configuration — every endpoint above is unauthenticated. Restrict access at the network level, see Production Checklist. |
9. Stack Management
9.1. Logs
The application writes to ft-device-network/logs/ under DATA_FOLDER:
| Log file | Purpose |
|---|---|
|
Main application log — daily rotation, 10 MB per file, 30-day retention |
|
Per-device log, sifted by the |
|
Written on |
docker compose logs -f ft-device-network-service
docker compose logs --tail 100 ft-device-network-service
tail -f /usr/local/ft-system/ft-device-network/logs/ft-device-network-service.log
9.2. Start, Stop, Restart
cd /usr/local/ft-system
docker compose ps
docker compose stop ft-device-network-service
docker compose start ft-device-network-service
docker compose restart ft-device-network-service
docker compose down
9.3. Shell Access
docker exec -it ft-device-network-service bash
docker exec ft-device-network-service ls -la /app/logs
9.4. Updating FT Device Network Service
cd /usr/local/ft-system
docker compose pull ft-device-network-service
docker compose up -d ft-device-network-service
Flyway migrates the ClickHouse schema automatically on the first start of a new version; a failed migration is logged and, per the service’s custom retry strategy, marked [SKIPPED] rather than blocking startup — see Database Configuration — Custom Migration Strategy. Verify the expected schema change actually applied after any upgrade that touches the database.
10. Production Checklist
-
Point at production infrastructure —
CLICKHOUSE_HOST,HZ_MEMBERSmust not be left at their placeholder/localhost values. -
Set real ClickHouse credentials — do not run with the shared default
ftacs/ftacsusername and password in production. -
Set
CLICKHOUSE_HTTP_PORT, notCLICKHOUSE_PORT— the application reads only the former. -
Set real MQTT credentials if MQTT ingestion is used — the defaults (
username/password) are placeholders, not disabled values. -
Confirm the Hazelcast cluster name is
dev(or rebuild the image with a differenthazelcast-client.ymlif the platform’s cluster uses another name — it cannot be overridden at runtime). -
Confirm FTACS is healthy and on the same Hazelcast cluster before expecting device data to appear.
-
Confirm the hostname
ft-device-network-serviceresolves from the UI Backend host. -
Firewall the published port (
8383) to trusted callers (UI Backend, monitoring) only — the API has no authentication of its own. -
Size the JVM heap (
FT_DEVICE_NETWORK_JAVA_RAM) for the device fleet — the default-Xms256m -Xmx1gtargets small deployments. -
Verify log rotation and disk sizing for
/app/logs— 30-day main-log retention plus a per-device log file for every serial seen in the last 10 days. -
Enable auto-restart —
restart: unless-stoppedincompose.yml.
11. Troubleshooting
11.1. Container Fails to Start
Symptom: The ft-device-network-service container exits immediately after docker compose up.
Fix:
-
Read the error message from the logs:
docker compose logs ft-device-network-service -
Confirm ClickHouse and Hazelcast are both reachable before the container starts — both are blocking dependencies (see Startup Dependencies); a Flyway migration failure or a Hazelcast connection timeout during startup both stop the application.
-
Confirm the environment file is loaded:
docker exec ft-device-network-service env | grep -E 'CLICKHOUSE_|HZ_MEMBERS'
11.2. ClickHouse Connection or Migration Failure
Symptom: Startup fails with a clickhouse-jdbc connection error, or Flyway reports a failed migration.
Fix:
-
Confirm the service targets the HTTP port
8123, not the native TCP port9000— checkCLICKHOUSE_HTTP_PORTin the shared.env. -
Verify ClickHouse answers, from inside the container so the check uses the same network path the service does:
docker exec ft-device-network-service sh -c 'curl -s http://$CLICKHOUSE_HOST:8123/ping' -
Confirm the database named by
CLICKHOUSE_DATABASE(defaultftacs_qoe_ui_data) exists — the service does not create the database itself, only the tables inside it (via Flyway). -
If a migration keeps failing, it may have been auto-marked
[SKIPPED]rather than blocking startup — checkflyway_schema_historyforsuccess = falserows and review the schema manually; see Database Configuration — Custom Migration Strategy.
11.3. Hazelcast Connection Issues
Symptom: The log shows Unable to connect to any address in the config, or the container exits during startup with a Hazelcast client error.
Fix:
-
Verify
HZ_MEMBERSin the shared.envpoints at addresses the container can reach; an entry without a port gets:5701appended. -
Confirm the target cluster’s name is
dev— the client configuration bundled in the image hardcodes it and cannot be overridden without rebuilding the image. -
Ensure port 5701 is open from the container’s host to every cluster member.
11.4. FTACS Reachable, but No New Device Data Arrives
Symptom: The service is healthy and the REST API responds, but /api/data/** returns stale or no data for devices that should be reporting. Nothing in the log flags this.
Cause: device data arrives through the Hazelcast queue networkDeviceParameterDataQueue, populated by FTACS. If FTACS is down, on a different Hazelcast cluster, or not yet processing parameters for the device, nothing arrives — and unlike ClickHouse/Hazelcast, this does not fail the container.
Fix:
-
Confirm FTACS is running and healthy.
-
Confirm FTACS’s
HZ_MEMBERSresolves to the same Hazelcast cluster as this service’s — a mismatch produces two separate clusters that never see each other, with no connection error on either side. -
Confirm the device has actually reported parameters to FTACS — check FTACS’s own session logs for the serial in question.
11.5. MQTT Connection Errors in the Log
Symptom: Repeated MQTT connection failures or reconnect attempts logged at startup and periodically afterward.
Cause: MQTT_URL defaults to tcp://localhost:1883, which resolves to the container itself. Unless MQTT-based ingestion is explicitly configured (see the MQTT broker row in Required External Dependencies), this is expected and does not affect the container’s health or the Hazelcast-based ingestion path.
Fix: if MQTT ingestion is intentionally unused, ignore these log lines. If it is intended to be used, verify MQTT_URL points at a reachable broker and MQTT_USERNAME/MQTT_PASSWORD are correct.
11.6. Port Already in Use
Symptom: docker compose up fails with bind: address already in use.
Fix:
-
Find the process holding the port:
sudo lsof -i :8383 -
Either stop that process, or change
FT_DEVICE_NETWORK_HTTP_PORTinft-device-network/.envand rundocker compose up -dagain.
11.7. Out of Memory
Symptom: The container is killed by the OOM killer, or logs/heapdump.hprof appears.
Fix:
-
Increase the heap through
FT_DEVICE_NETWORK_JAVA_RAMinft-device-network/.env, e.g.-Xms512m -Xmx2g. -
If the problem persists, analyze the heap dump (Eclipse MAT, VisualVM).
11.8. Permission Denied on the Logs Volume
Symptom: The container cannot write to /app/logs.
Fix:
sudo chown -R $(whoami):$(whoami) /usr/local/ft-system/ft-device-network
chmod -R 755 /usr/local/ft-system/ft-device-network
11.9. Getting Support
Collect the following before raising a support request, so the first reply is not a request for more data:
docker compose logs --tail 500 ft-device-network-service > support-logs.txt
docker exec ft-device-network-service env | grep -E 'CLICKHOUSE_|HZ_MEMBERS|MQTT_' >> support-logs.txt
docker inspect ft-device-network-service --format '{{.Config.Image}} {{.State.Health.Status}}' >> support-logs.txt
Include the image tag in use, the serial number of an affected device, and whether ClickHouse and Hazelcast were reachable at the time. Route the request to the FT Device Network Service owner listed for your deployment.
12. Related Documentation
-
Architecture Overview — the component diagram for this service and its dependencies
-
Architecture — Component Dependencies — what this service talks to, and why
-
Database Configuration — Overview — the ClickHouse schema Flyway creates
-
MQTT Integration — the optional ingestion path in full
-
All in one server deployment — deploying the infrastructure this guide assumes
-
UI Service Deployment — the consumer that requires this service