Docker Deployment¶
When deploying NF using Docker (or other container runtimes), two containers are required: one running the Normal Framework and one running Redis.
Quick Start¶
The quickest way to get started is by using the docker-compose file provided as
part of the SDK.
Images¶
NF is published as two images, with the same tags (latest, 3.10,
3.10.11-0, ...):
| Image | Contents | Architectures |
|---|---|---|
normalframework/nf-full |
Every NF service, the SDK (applications and hooks), and the console | linux/amd64, linux/arm64, linux/arm/v7 |
normalframework/nf-slim 3.10.11 |
BACnet discovery, polling and trending, commands, and Sparkplug B publishing, for gateways with a few hundred MB of RAM | linux/amd64, linux/arm64, linux/arm/v7 |
Both use the same redis image, ports, volumes and environment
variables; the tags are multi-architecture, so Docker pulls the right
one for the host. 32-bit ARM (linux/arm/v7) images are available
from 3.10.10.
nf-slim¶
nf-slim leaves out Node.js and the applications service (SDK apps and hooks), device health, and the Modbus, OPC-UA, Fox, UDMI, Sparkplug consumer, schedule, template, TimescaleDB, backup and agent services. The console hides the pages for services the image does not have. Its services and the gateway run in a single process.
It also sets these defaults to bound memory use; set any of them on the container (or in the console) to override:
| Variable | nf-slim default | Effect |
|---|---|---|
TIMESERIES_RETENTION |
24h |
Trend history kept per point (new points) |
TIMESERIES_ERROR_RETENTION |
1h |
Error history kept per point (new points) |
TIMESERIES_ERROR_INTERVAL |
15m |
At most one error history sample per point in this interval |
SCAN_JOB_RETENTION |
168h |
Finished scan jobs older than this are deleted |
SCAN_JOB_MAX |
100 |
At most this many finished scan jobs are kept |
SINGLE_POINT_INDEX |
1 |
Keep one search index (the default layer's) instead of one per layer |
INDEXED_LAYERS |
hpl:bacnet:1,hpl:bacnet:local,model |
Only these layers are searchable; others are kept but not indexed or polled |
SINGLE_POINT_INDEX and INDEXED_LAYERS can also be set on nf-full to
reduce Redis memory on small gateways.
Networking¶
The Normal Framework container requires network_mode: host to properly process
BACnet traffic. This limits the ability to use other Docker networking primitives to
isolate the container.
After installation, the API Gateway and Management Console are exposed on port
tcp/8080.
Filesystem¶
"Hard state" is stored in Redis, which should be backed up. NF also requires a writable, persistent volume for "soft state," such as data being buffered before being sent out, low-level configuration settings, and other data that should persist across reboots.
This state is stored within /var/nf in the container. It is recommended to
volume-mount this directory so that it persists across restarts.
For security, you may mount the container volume as read-only. In this case, you
must set S6_READ_ONLY_ROOT=1 and mount /run and /tmp as tmpfs mounts.
Initialization and Configuration¶
Within the container, NF uses s6-rc
to start services and ensure they are restarted on error. You may inspect the s6
configuration by looking in /etc/s6-overlay. Although detailed documentation is
beyond the scope of this article, it is possible to alter the environment for
individual services by adjusting the contents of this directory. Additionally,
environment variables applied to the container (i.e., on the Docker command line)
are passed to all services.
Redis¶
Normal Framework includes a build of Redis Server that has been validated to work correctly. You may also build your own; there are no modifications required. NF requires RediSearch and RedisTimeSeries to be installed on the Redis instance.
Redis stores its data in /data; this directory should be volume-mounted and backed
up.
By default NF connects to Redis at localhost:6379. Set REDIS_ADDRESS
on the NF container to use another address, or to a path (anything
starting with /) to connect over a unix socket
3.10.10. With the NF redis
image, set REDIS_LISTEN_SOCKET to the socket path on the Redis
container and mount the socket's directory into both containers, e.g.
a shared volume at /run/redis-sock and
REDIS_ADDRESS=/run/redis-sock/redis.sock. Redis keeps serving TCP
6379 as well.