Full Deployment via Docker Compose
Deploying AnyLog nodes using AnyLog's official docker-compose repo — installation, configuration, and how LEDGER_CONN and networking work together.
This is the full, configuration-driven deployment path, built around AnyLog’s official docker-compose repo. For a fast, minimal single-command trial instead, see Installing & Deploying AnyLog.
1. Install Docker, Make, and Git
# Install Docker on Ubuntu
sudo apt-get -y update
sudo apt-get install -y ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \
$(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}") stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get -y update
sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin make git
# Grant your user permission to use Docker without sudo
USER=`whoami`
sudo groupadd docker
sudo usermod -aG docker ${USER}
newgrp docker
make is optional — every make target is a thin wrapper around deploy.sh. If make isn’t available on your
system (e.g. some ARM/Qualcomm hardware), use bash deploy.sh directly; behavior is identical either way.
2. Clone the Repository
git clone -b os-dev https://github.com/AnyLog-co/docker-compose
cd docker-compose
AnyLog is a private image repository — request credentials for both your Docker login and your license key, then log in:
docker login -u anyloguser -p [Docker Login Passkey]
Repository layout
docker-compose/
├── Makefile # Thin wrapper around deploy.sh
├── deploy.sh # Node lifecycle manager — works without make
├── docker-makefiles/
│ ├── anylog-generic/
│ │ └── node_configs.env # Config template — copy and customise per node
│ ├── anylog-master/
│ ├── anylog-operator/
│ ├── anylog-publisher/
│ ├── anylog-query/
│ ├── anylog-standalone-operator/
│ ├── anylog-standalone-publisher/
│ ├── build_docker_compose.sh # Generates docker-compose.yaml from configs
│ ├── prep_configs.sh # Pre-flight config validation
│ └── docker-compose-files/ # Generated compose files land here (not committed)
├── license-generator/ # License validation/acceptance service used by `deploy.sh up`
└── support/ # Grafana, PostgreSQL, MongoDB, Remote-GUI
Both the short form (operator) and the full directory name (anylog-operator) are accepted everywhere ANYLOG_TYPE
is used — both make and deploy.sh resolve the alias automatically.
Container runtime
deploy.sh auto-detects your environment — no configuration needed. It uses podman in place of docker if
podman is installed, and for compose it prefers podman-compose, falling back to docker-compose, then
docker compose, in that order. All the make/bash deploy.sh commands in this guide work unchanged regardless
of which of these is actually present on your system.
3. Node Types
Every node type runs the exact same AnyLog image — what differs is which services are enabled. Quick summary:
| Node Type | Role | ||
|---|---|---|---|
Master (Metadata / master) |
Hosts the network’s metadata — the Metadata Manager described in Introduction to AnyLog | ||
Operator (operator) |
Stores data and answers queries | ||
Publisher (publisher) |
A non-storage node that distributes data from edge sources across Operator nodes | ||
Query (query) |
Coordinates distributed queries across Operators | ||
Generic (generic) |
A sandbox with only TCP, REST, and Message Broker configured — no storage, no cluster role. Useful for testing connectivity before committing to a real node type. |
standalone-operator and standalone-publisher combine Master with an Operator or Publisher, respectively, on a
single agent.
4. Configure Your Node
For full control over node behavior, copy the generic template and customize it:
cp -r docker-makefiles/anylog-generic docker-makefiles/my-operator
Edit docker-makefiles/my-operator/node_configs.env. At minimum, update:
| Variable | Purpose |
|---|---|
NODE_TYPE |
Node role: generic, master, operator, query, publisher, standalone-operator, standalone-publisher |
NODE_NAME |
Must be unique per node |
COMPANY_NAME |
Owner of the node |
ANYLOG_SERVER_PORT, ANYLOG_REST_PORT |
Must be unique per machine |
LEDGER_CONN |
IP:port of the Master/Metadata Manager node — see below |
CLUSTER_NAME |
Unique per Operator, unless HA is enabled |
LICENSE_KEY |
Optional to set here — see License Key below |
DB_USER / DB_PASSWD |
Only if using PostgreSQL |
You’ll also want to decide your networking setup (NETWORK_TYPE, OVERLAY_IP, etc.) — covered in
Understanding the Network Configuration below.
License Key
Every up command validates a license before starting the node:
- If
LICENSE_KEYis already set innode_configs.env, deployment proceeds immediately — no prompts. - If no key is set, and you don’t pass one via
--license-key, you’ll be prompted interactively: the license agreement is displayed, you provide name/email/project and accept, and the accepted key is written back intonode_configs.envautomatically so future deployments skip the form.
# Pass explicitly
make up ANYLOG_TYPE=my-operator LICENSE_KEY="<key>"
bash deploy.sh up --type my-operator --license-key "<key>"
# Or just set LICENSE_KEY="<key>" directly in node_configs.env beforehand
5. Start the Node
# via make
make up ANYLOG_TYPE=my-operator
# via deploy.sh (no make required)
bash deploy.sh up --type my-operator
Check it came up:
make logs ANYLOG_TYPE=my-operator
bash deploy.sh logs --type my-operator
Verify it’s actually working:
make full-test ANYLOG_TYPE=my-operator
bash deploy.sh full-test --type my-operator
full-test runs test-status (confirms the process is running), test-node (validates node configuration), and
test-network (confirms it can see its peers) in sequence — the same three checks from the Quick Install guide,
just wrapped into a single command.
To deploy a second node of the same type, copy the folder again and update NODE_NAME, ports, and CLUSTER_NAME:
cp -r docker-makefiles/my-operator docker-makefiles/my-operator2
# edit node_configs.env in my-operator2 first
make up ANYLOG_TYPE=my-operator2
6. Understanding LEDGER_CONN
LEDGER_CONN is how every non-Master node (Operator, Query, Publisher) finds the Metadata Manager (Master) node —
it’s set to that node’s TCP port, not its REST port:
LEDGER_CONN=127.0.0.1:32048
This is the single most common source of “my node won’t join the network” problems, because the correct value depends entirely on your Docker networking mode (see below):
- Host networking (Linux/WSL,
NETWORK_TYPEempty ornetwork) — containers share the host’s network stack directly, so127.0.0.1:<master's TCP port>(or the Master’s real host IP, if on a different machine) works as-is. - Port-mapped mode (Windows/macOS,
NETWORK_TYPE=ports) — containers do not share the host network.127.0.0.1inside one container does not reach another container. You need the host machine’s LAN IP here instead — set viaOVERLAY_IPon the Master, and reference that same IP inLEDGER_CONNon every other node. - Custom/overlay network (
NETWORK_TYPE=<network-name>) — nodes reach each other by container name or overlay IP across physical machines.LEDGER_CONNshould use the Master’s overlay IP (or container name, if on the same named network), not its host IP.
If test network doesn’t show all expected peers after deployment, LEDGER_CONN pointing at the wrong address is
the first thing to check.
7. Understanding the Network Configuration
AnyLog’s networking is split across two independent layers — getting one right doesn’t automatically fix the other.
Layer 1 — Docker Network Topology (NETWORK_TYPE)
Controls how the container connects to the host and to other containers. Purely a Docker-level concern; it has no effect on how AnyLog itself resolves or advertises its IP.
| Value | Behavior | When to use |
|---|---|---|
| (empty) | Auto-detect | Recommended default — host mode on Linux/WSL, port-mapped on Windows/macOS |
network |
network_mode: host |
Linux/WSL only |
ports |
Explicit port mapping | Windows, macOS, or Linux when host networking isn’t available |
<custom-name> |
Pre-created external Docker network | Multi-machine deployments (VPN, Swarm overlay) |
For a multi-host Swarm overlay, create the network once, then point every node at it:
docker network create --scope=swarm --attachable -d overlay anylog-net
NETWORK_TYPE=anylog-net
Layer 2 — AnyLog Network Identity
Controls how AnyLog resolves and advertises its own IP — the address it registers in the blockchain/metadata layer and binds its TCP/REST/Broker ports to. Getting this wrong means other nodes can see your node in the metadata but can’t actually reach it.
| Variable | Purpose |
|---|---|
NIC_TYPE |
Resolve the node’s IP from a specific network interface (e.g. eth0) — useful on multi-NIC hosts |
OVERLAY_IP |
Overrides the resolved IP entirely — required whenever the container’s internal IP isn’t reachable from outside (port-mapped mode, NAT, Swarm overlay) |
TCP_BIND / REST_BIND / BROKER_BIND |
Whether each protocol binds to the resolved/overlay IP specifically (true) or all interfaces (false) |
Quick reference
| Scenario | NETWORK_TYPE |
OVERLAY_IP |
|---|---|---|
| Linux, single node | (empty) | (empty) |
| Windows/macOS, single node | ports or (empty) |
host’s LAN IP |
| Multi-node, same LAN (Linux) | (empty) | (empty) |
| Multi-node, VPN/overlay | <network-name> |
overlay/VPN IP |
| Multi-node, cloud/NAT | ports or <network-name> |
public/elastic IP |
In short: Layer 1 decides how the container talks to the network at all; Layer 2 decides what address it tells
other nodes to use. On a single Linux machine you can usually leave both at their defaults. The moment you’re on
Windows/macOS or spanning multiple machines, OVERLAY_IP (Layer 2) is almost always the setting you need — and it
has to match whatever LEDGER_CONN (§4 above) expects on the other end.