Setting up a Canton OSS subnet leveraging on release 3.4.7
I’ve been trying to set up a docker-compose which assembles each component of Canton OSS (Sequencer, Mediator and Participant) as separate services.
I’ve managed to create a structure which has one Dockerfile for each component and respective conf file. The bootstrap/init files are still in the works, while trying to leverage on the console to build them, but the rest seems to be working standalone. However, I’m facing challenges finding the right way to connect all of these components together.
One such oddities is the following:
The mediator I’ve setup is not called mediator1 nor is it supposed to be connected to a local sequencer or a sandbox participant. These values make little sense given what I’ve configured and I’m wondering whether something is being overriden or how I should interpret these results.
Please note that so far the bootstrap files only have the following line
nodes.local.start()
I’ve also tried to connect with a remote configuration instead of using the sandbox-console and then when trying to list nodes I’m getting the same results.
I’ve also seen a few discrepancies between documentation and the config files under the canton release. E.g. there are references of a manager.conf in some docs ( Install Canton — Daml SDK 2.10.2 documentation , Install Canton — Digital Asset’s platform documentation) which I assume referred to the topology manager, yet the sample config files from the release zip or tar.gz seem to have no mention on them. I’m wondering if they’re needed or not.
I’ll post below a few of the snippets of code I’ve been running and any support or clarification on how to complete this setup, or whether this is not possible on OSS, is welcome.
Dockerfile.mediator
# Canton Domain Dockerfile (Mediator)
FROM eclipse-temurin:21-jdk-jammy
# Install dependencies
RUN apt-get update && apt-get install -y \
curl \
wget \
unzip \
&& rm -rf /var/lib/apt/lists/*
# Download and install Canton
ARG CANTON_VERSION=3.4.7
WORKDIR /opt
RUN wget https://github.com/digital-asset/canton/releases/download/v${CANTON_VERSION}/canton-open-source-${CANTON_VERSION}.tar.gz && \
tar -xzf canton-open-source-${CANTON_VERSION}.tar.gz && \
mv canton-open-source-${CANTON_VERSION} canton && \
rm canton-open-source-${CANTON_VERSION}.tar.gz
# Create Canton directories
RUN mkdir -p /canton/config /canton/init /canton/data
# Copy configuration files
COPY config/mediator.conf /canton/config/
# Set permissions
RUN chmod -R 755 /canton
WORKDIR /canton
# Expose ports
# 10042 - Admin API
# 10043 - grpc-health-server
# 10044 - http-health-server
EXPOSE 10042 10043 10044
# Start Canton domain with configuration
CMD ["/opt/canton/bin/canton", "daemon", "-c", "/canton/config/mediator.conf", "--bootstrap", "/canton/init/mediator.canton"]
mediator.conf
include required("shared.conf")
canton.mediators.mediator {
storage = ${_shared.storage}
storage.config.properties.databaseName = "canton_mediator"
admin-api {
address = 0.0.0.0
port = 10042
}
monitoring {
grpc-health-server {
address = 0.0.0.0
port = 10043
}
http-health-server {
address = 0.0.0.0
port = 10044
}
}
}
Dockerfile.sequencer
# Canton Domain Dockerfile (Sequencer)
FROM eclipse-temurin:21-jdk-jammy
# Install dependencies
RUN apt-get update && apt-get install -y \
curl \
wget \
unzip \
&& rm -rf /var/lib/apt/lists/*
# Download and install Canton
ARG CANTON_VERSION=3.4.7
WORKDIR /opt
RUN wget https://github.com/digital-asset/canton/releases/download/v${CANTON_VERSION}/canton-open-source-${CANTON_VERSION}.tar.gz && \
tar -xzf canton-open-source-${CANTON_VERSION}.tar.gz && \
mv canton-open-source-${CANTON_VERSION} canton && \
rm canton-open-source-${CANTON_VERSION}.tar.gz
# Create Canton directories
RUN mkdir -p /canton/config /canton/init /canton/data
# Copy configuration files
COPY config/sequencer.conf /canton/config/
# Set permissions
RUN chmod -R 755 /canton
WORKDIR /canton
# Expose ports
# 10038 - Public API
# 10039 - Admin API
# 10033 - grpc-health-server
# 10034 - http-health-server
EXPOSE 10038 10039 10033 10034
# Start Canton domain with configuration
CMD ["/opt/canton/bin/canton", "daemon", "-c", "/canton/config/mediator.conf", "--bootstrap", "/canton/init/sequencer.canton"]
sequencer.conf
include required("shared.conf")
canton.sequencers.sequencer {
storage = ${_shared.storage}
storage.config.properties.databaseName = "canton_sequencer"
public-api {
address = 0.0.0.0
port = 10038
}
admin-api {
address = 0.0.0.0
port = 10039
}
sequencer {
type = BFT
block {
writer = ${?_shared.sequencer-writer}
reader = ${?_shared.sequencer-reader}
writer.type = high-throughput
}
}
monitoring {
grpc-health-server {
address = 0.0.0.0
port = 10033
}
http-health-server {
address = 0.0.0.0
port = 10034
}
}
}
docker-compose.yml
services:
# PostgreSQL database for Canton
postgres:
image: postgres:17.6
container_name: retvn-postgres
environment:
POSTGRES_DB: canton
POSTGRES_USER: canton
POSTGRES_PASSWORD: *****
ports:
- "5432:5432"
volumes:
- postgres_data:/var/lib/postgresql/data
- ./docker/postgres/init.sql:/docker-entrypoint-initdb.d/init.sql
healthcheck:
test: ["CMD-SHELL", "pg_isready -U canton"]
interval: 10s
timeout: 5s
retries: 5
networks:
- retvn-network
# Canton sequencer (sequencer)
canton-sequencer:
build:
context: ./docker/canton
dockerfile: Dockerfile.sequencer
container_name: retvn-canton-sequencer
ports:
- 10038:10038 # Public API
- 10039:10039 # Admin API
- 10033:10033 # grpc-health-server
- 10034:10034 # http-health-server
environment:
CANTON_DB_HOST: postgres
CANTON_DB_PORT: 5432
CANTON_DB_NAME: canton-sequencer
CANTON_DB_USER: canton
CANTON_DB_PASSWORD: *****
volumes:
- ./docker/canton/config:/canton/config
- ./docker/canton/init:/canton/init
- canton_domain_data:/canton/data
depends_on:
postgres:
condition: service_healthy
networks:
- retvn-network
# Canton mediator (mediator)
canton-mediator:
build:
context: ./docker/canton
dockerfile: Dockerfile.mediator
container_name: retvn-canton-mediator
ports:
- 10042:10042 # Admin API
- 10043:10043 #
- 10044:10044 #
environment:
CANTON_DB_HOST: postgres
CANTON_DB_PORT: 5432
CANTON_DB_NAME: canton-mediator
CANTON_DB_USER: canton
CANTON_DB_PASSWORD: *****
volumes:
- ./docker/canton/config:/canton/config
- ./docker/canton/init:/canton/init
- canton_domain_data:/canton/data
depends_on:
postgres:
condition: service_healthy
networks:
- retvn-network
volumes:
postgres_data:
driver: local
canton_domain_data:
driver: local
networks:
retvn-network:
driver: bridge
Are you aware of the LocalNet Docker Compose resource? Its configuration files may serve as a guide for some of the questions you are working through.
I wasn’t looking on such a direction, primarily as I wanted to build first a permissioned network, not connected immediately to the Canton Network. My understanding is that splice is focused on the latter. I do want to explore it at some moment, but for now that was not my focus. Is this something that is not supported by the Canton protocol in its latest versions? Should I fallback to 2.X versions if I want to continue on such direction?
not connected immediately to the Canton Network
Just to be clear, the the LocalNet Docker Compose resource does not connect to the Canton Network’s Global Synchronizer. It is standalone. That is why you may find it useful in your exercise.
Regarding a private, subnet synchronizer, the DA product and engineering teams are still focused on the Global Synchronizer. Improving functionality and docs for private, subnet synchronizers is in the backlog.
Should I fallback to 2.X versions if I want to continue on such direction?
That’s a tough call. We cannot give you a date for subnet support in 3.x. If you are trying to go to production “soon,” then you would need to go with 2.x. If you proceed with 2.x, avoid Daml contract keys for now.
I’ve fallen back on leveraging the sandbox for the 3.4 version. Was just struggling as well to put it to work through docker with network access from the host machine.
The key was finding the way to pass the right configurations to enable that with the daml sandbox command -C canton.participants.sandbox.ledger-api.address=0.0.0.0 -C canton.participants.sandbox.http-ledger-api.server.address=0.0.0.0.
For the moment that will suffice.
Thanks
