docker-compose.j2
Overview
This file is a Jinja2 template for generating a docker-compose YAML configuration specifically designed to orchestrate multiple services related to a blockchain node environment. The template dynamically configures services such as Aerospike (a database), node instances, staking services, and log rotation, based on provided variables and runtime conditions. It defines networking, volumes, environment variables, startup commands, and dependencies to ensure proper service initialization and operation.
The primary goal of this file is to facilitate deployment and management of blockchain-related components in isolated Docker containers while allowing flexible configuration through templating.
File Structure and Functionality
Dynamic Gossip Seeds Initialization
At the beginning, the template includes logic to initialize the GOSSIP_SEEDS variable if it is not defined, but GOSSIP_INIT is set. It collects public IP addresses and gossip ports from all hosts in the block_keepers group, concatenating them as ip:port strings. This list is then used for service environment configuration related to inter-node gossip communication.
Services Section
This section defines multiple Docker services:
1. aerospike{{ NODE_ID }}
Purpose: Runs an Aerospike database instance for the node.
Image: Uses the AEROSPIKE_IMAGE variable.
Volumes:
Configuration directory mounted to /opt/aerospike/etc.
Data directory mounted to /opt/aerospike/data.
Command: Runs Aerospike with a specified config file.
Healthcheck: Uses asinfo command to check if Aerospike is ready.
Restart Policy: unless-stopped.
Ports: Binds local loopback IP on configured Aerospike port.
Networks: Connected to
ackinacki-net.
2. node{{ NODE_ID }}
Purpose: Runs the blockchain node service.
Image: Uses NODE_IMAGE.
Restart Policy: Conditional on
FAIL_FASTflag.Environment Variables: Extensive configuration, including:
Network binding addresses and ports.
Gossip seed nodes for cluster discovery.
Timeouts and thresholds for node operations.
Node identification and advertisement addresses.
Telemetry and OpenTelemetry (OTEL) configuration.
Authentication tokens and external message handling flags.
Conditional inclusion of wallet public keys and verbose logging flags.
Additional environment parts included via external templates (extra/block-keeper-env.j2, extra/block-keeper-test.j2).
Entrypoint: Cleared to default Docker entrypoint.
Init: Enabled for proper signal handling.
Capabilities: Adds
SYS_NICEifNUMACTLis defined.Command: Runs a bash script that:
Optionally installs and runs
numactlfor NUMA control.Runs
node-helper configwith multiple parameters specifying configuration files, keys, operational flags, and cluster-specific parameters.Outputs configuration for verification.
Executes the node binary, redirecting logs.
Volumes: Mounts persistent directories for shared data, working data, configurations, binaries, and logs.
Network Mode: Uses host networking for direct interface access.
Stop Grace Period: 60 seconds.
Dependencies: Waits for Aerospike service to be healthy before starting.
3. staking{{ NODE_ID }} (Conditional)
Purpose: Runs the staking service associated with the node.
Image: Uses STAKING_IMAGE.
Restart Policy: unless-stopped.
Entrypoint: Cleared.
PID Namespace: Shares PID namespace with the corresponding node container.
Command: Runs tvm-cli to configure and then executes a staking script with logging.
Volumes: Shares logs and configuration directories.
Dependencies: Depends on the node service.
Networks: Connected to
ackinacki-net.
This service is included only if DISABLE_STAKING is not set or false.
4. logrotate{{ NODE_ID }}
Purpose: Manages log rotation for the node logs.
Image: Uses LOGROTATE_IMAGE.
Restart Policy: unless-stopped.
Environment: Defines a cron schedule for hourly log rotation.
Volumes: Mounts logs directory and logrotate script.
Command: Runs the logrotate shell script.
Init: Enabled.
Network Mode: None (isolated).
Networks Section
Defines a Docker network named
ackinacki-net.Can be marked as external if
EXTERNAL_NETis true, allowing connection to an externally managed network.
Important Implementation Details
Templating Logic: Uses Jinja2 control structures to conditionally set variables, include external template snippets, and adjust service configuration based on defined variables.
Dynamic Service Naming: Service names include NODE_ID suffixes based on the NUMBERED_SERVICES flag to allow multiple instances.
Health Checks: Aerospike service uses healthchecks to inform Docker Compose of readiness, influencing service start order.
NUMA Optimization: Optionally applies
numactlto optimize CPU affinity if enabled.Telemetry Configuration: Supports OpenTelemetry integration with configurable exporters and resource attributes.
Flexible Volume Mounts: Separates configuration, data, and logs into distinct mount points for persistence and manageability.
Service Dependencies: Ensures proper initialization order using
depends_onwith health condition.Logging: Redirects node logs to mounted log directories for persistence and rotation.
Security: Uses environment variables for authentication tokens and message authorization.
Interaction with Other System Components
External Configuration Files: Relies on external JSON/YAML configuration files mounted into services.
Extra Template Includes: Incorporates additional environment variables and commands from external Jinja2 fragments (extra/block-keeper-env.j2, extra/block-keeper-test.j2, extra/block-keeper-cmd.j2).
Networked Services: The node service interacts closely with Aerospike for data storage and the staking service for blockchain staking operations.
Logging and Monitoring: The logrotate service manages logs generated by the node and staking services.
Telemetry: Integration with external OTEL collector endpoints for metrics export.
Usage Examples
Generating Compose File for a Node Instance
Assuming relevant variables are set (e.g., NODE_ID=1, AEROSPIKE_IMAGE=..., NODE_IMAGE=...), running the Jinja2 template engine will produce a docker-compose.yaml that starts:
Aerospike container named aerospike1.
Node container named node1.
Staking container named staking1 (if staking enabled).
Logrotate container named logrotate1.
The services will be networked on ackinacki-net and configured to communicate via environment variables and exposed ports.
Customizing Gossip Seeds
By setting GOSSIP_SEEDS or controlling GOSSIP_INIT, the generated compose file will include different seed nodes for gossip protocol discovery, affecting cluster formation.
Mermaid Diagram: Service Workflow and Relationships
flowchart TD
Aerospike["Aerospike Service"]
Node["Node Service"]
Staking["Staking Service (optional)"]
Logrotate["Logrotate Service"]
Network["ackinacki-net Network"]
Aerospike -->|depends_on| Node
Node -->|depends_on| Aerospike
Node -->|pid namespace| Staking
Node -->|log files| Logrotate
Staking -->|network| Network
Aerospike -->|network| Network
Node -->|network| Network
Logrotate -.->|isolated| Network
Aerospike and Node: Aerospike must be healthy before the node starts.
Staking: Depends on the node; shares PID namespace for process management.
Logrotate: Handles logs from node and staking via mounted volumes; isolated network mode.
Network:
ackinacki-netconnects Aerospike, Node, and Staking services.
Summary of Key Environment Variables in Node Service
Variable | Description |
|---|---|
Directory for shared local state. | |
BIND, | Network binding addresses for different protocols. |
Aerospike connection address. | |
Comma-separated list of gossip seed nodes. | |
Unique identifier for the node instance. | |
NODE_ADVERTISE_ADDR, | Addresses advertised to other nodes/services. |
| Attributes for telemetry resource identification. |
Token for authenticating external messages. | |
Boolean flag for message authorization enforcement. |
Note on Included Templates
The file includes external Jinja2 fragments for additional environment variables and commands:
These files allow modular extension of the environment and command line arguments without modifying this main template.
This file plays a central role in orchestrating blockchain node infrastructure by combining templated configuration management, container orchestration, and dynamic network setup. It enables scalable, configurable, and maintainable deployments of node clusters with integrated database, staking, and logging components.