A Docker Compose file and auxiliary scripts for running a Polymesh development environment.
- Docker Desktop (or Docker Engine + Compose V2) installed and running. Download and setup instructions: https://docs.docker.com/get-docker/
- The Docker daemon must be running (
docker psshould respond).
- Configuration: Copy an environment file (e.g.,
envs/8.0) to.envin the project root:cp envs/8.0 .env. This file specifies the Docker images to use. Alternatively, provide the path directly:docker compose --env-file=envs/8.0 up. - Start: Run
docker compose up -dto start the services in detached mode. - Stop: Run
docker compose downto stop the services.docker compose down --volumeswill also remove associated volumes (chain data, database data, vault data), this will reset the environment. - Restart: To apply changes (e.g., updated
.envfile), rundocker compose down && docker compose up -d.
Full variable reference is available in envs/template (also linked as .env.example).
This setup will launch the following services:
polymesh-node: A single Polymesh node running in development mode (--dev).postgres: PostgreSQL database, primarily for the Subquery indexer.subquery-node: Polymesh Subquery indexer service.subquery-graphql: GraphQL API server for querying indexed data.polymesh-rest-api-local-sm: The Polymesh REST API service that uses local signers (Alice, Bob, Charlie, etc)polymesh-rest-api-vault-sm: The Polymesh REST API service with HashiCorp Vault as the signing manager.polymesh-rest-api-vault-sm-init: Creates test accounts and identities via the REST API.vault: HashiCorp Vault for key management.vault-init: Initializes and unseals Vault on first run, unseals on subsequent runs.environment-ready: Indicates when the core services and initial setup scripts have completed successfully.
The environment involves several services starting up and performing initial setup tasks (like Vault unsealing and REST API account creation). To check when the environment is fully ready, especially on the first launch, use the environment-ready service logs:
docker compose logs environment-readyWait for the message indicating completion:
************************************************************************************
*** Polymesh Environment Ready! (Total initialization time: XXs) ***
************************************************************************************
If the environment was already initialized in a previous run, it will indicate readiness much faster.
This environment supports usage of either the Local or Vault Signing Manager
Local signing manager uses predefined, publicly known keys (Alice, Bob, Charlie). Vault signing manager uses the HashiCorp Vault to store the keys.
To facilitate this choice, the environment runs two independent instances of the Polymesh REST API: one configured to use local signers, and another configured to use Vault as the signing manager.
This repository now has two runtime options:
- Default mode (no EVM tooling)
- EVM tooling mode (
--profile evm), which startspolymesh-eth-rpc, Blockscout backend/frontend, and dedicated Blockscout Postgres/Redis.
Polymesh v8 includes Revive-based smart contract support, so optional EVM tooling follows Polkadot smart-contracts guidance:
./scripts/start-env.sh --env-file envs/8.0--env-file is optional; if omitted, both start-env.sh and stop-env.sh
default to envs/latest. You can also override the default via the
COMPOSE_ENV environment variable.
Stop:
./scripts/stop-env.sh --env-file envs/8.0To always fetch the newest images before starting (recommended when an env
file uses floating tags such as latest), add --pull always:
./scripts/start-env.sh --env-file envs/latest --pull always--pull accepts any Docker Compose pull policy (always, missing, never,
build); a bare --pull is shorthand for always. The same behaviour can be
set via the COMPOSE_PULL_POLICY environment variable.
By default stop-env.sh removes the named volumes (chain data, Vault keys,
Blockscout DB, ...) for a clean slate. To stop the containers but keep the data
for the next start, pass --keep-volumes:
./scripts/stop-env.sh --env-file envs/8.0 --keep-volumesstop-env.sh always tears down the EVM tooling as well, so you do not need to
repeat --profile evm when stopping.
./scripts/start-env.sh --env-file envs/8.0 --profile evmStop (the EVM services are torn down automatically):
./scripts/stop-env.sh --env-file envs/8.0Smoke checks:
./scripts/evm-smoke-test.sh
./scripts/blockscout-smoke-test.shExplorer URLs:
- Blockscout UI:
http://127.0.0.1:4000 - Blockscout backend API:
http://127.0.0.1:4001 - Blockscout API health check:
http://127.0.0.1:4001/api/v2/stats
Notes:
- EVM tooling remains opt-in and is not started by default.
--allow-unprotected-txsis enabled for local experimentation with legacy transaction flows.- Blockscout uses dedicated Postgres and Redis services, separate from Subquery services.
- If you customize ports, keep frontend
NEXT_PUBLIC_API_PORTaligned withPOLYMESH_BLOCKSCOUT_BACKEND_PORT. envs/7.2does not include EVM settings because chain v7.2 is not EVM-compatible.- Treat EVM support as a v8+ feature set. Use v7.2 only for legacy non-EVM scenarios.
- Substrate WS:
ws://127.0.0.1:9944 - Substrate HTTP:
http://127.0.0.1:9933 - Ethereum JSON-RPC:
http://127.0.0.1:8545
- Local develop runtime:
1641818 - Testnet v8:
1641819 - Mainnet v8:
1641820
- Network name:
Polymesh Dev - Chain ID:
1641818 - RPC URL:
http://127.0.0.1:8545 - Currency symbol:
POLYX
- RPC/subscription coverage can vary by image tag. Keep
POLYMESH_ETH_RPC_IMAGEconfigurable in env files and pin known-good tags. - Some paritypr image tags can be architecture-specific. Override
POLYMESH_ETH_RPC_PLATFORMif needed.
Vault Automation:
- The
vault-initservice automatically initializes Vault (on the very first run with the profile) and unseals it every time the services start. - It creates one unseal key and a root token, storing them in the
vault-root-tokennamed volume (accessible within thevault-initcontainer at/vault-token/as.unseal_keyand.token). - It also automatically enables the
transitsecrets engine and creates ED25519 keys namedadmin,signer1,signer2,signer3, andsigner4. - The Vault UI is available at
http://localhost:8200(default port) for inspection.
Using Vault with REST API & SDK:
- The
polymesh-rest-api-vault-smservice is automatically configured to use the Vault instance (http://vault:8200) and obtains the necessary root token from the sharedvault-root-tokenvolume. No manualVAULT_TOKENenvironment variable is needed for the REST API service itself. - The REST API uses the HashiCorp Vault Signing Manager. Signer names follow the pattern
{key_name}-{key_version}, e.g.,admin-1,signer1-1. - If you intend to use the Polymesh SDK directly with this Vault instance from your host machine or another application, you will need the Vault address (
http://localhost:8200) and the root token. You can retrieve the token from the runningvault-initcontainer (on its first/only run) or the volume if needed, but typically you'd generate a more scoped token via the Vault UI or CLI for external applications. The root token is printed by thevault-initservice logs during setup:docker compose logs vault-init.
Automated Account Setup:
- When the REST API becomes available, the
polymesh-rest-api-vault-sm-initservice automatically:- Retrieves addresses for the
admin,signer1,signer2,signer3, andsigner4keys from Vault via the REST API. - Makes the
adminkey's account a CDD provider on the dev chain. - Creates on-chain Identities for
signer1,signer2,signer3, andsigner4, funding them with initial POLYX.
- Retrieves addresses for the
- The addresses and DIDs of the signers are printed by the
polymesh-rest-api-initlogs and stored in therest-api-accounts-initvolume for persistence checks.
You can connect the Testnet Polymesh Portal to your local node. Go to Settings -> Click the RPC URL section in the Portal and use these settings:
- Node RPC URL:
ws://localhost:9944(or your customPOLYMESH_CHAIN_WS_PORTif changed) - Middleware URL:
http://localhost:3000(or your customPOLYMESH_SUBQUERY_GRAPHQL_PORTif changed)
(Image path assumes it's correctly located relative to the README)
curl --silent http://localhost:3004/signer/alice -H 'accept: application/json' | jq
{
"address": "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY"
}curl --silent http://localhost:3005/signer/signer1-1 -H 'accept: application/json' | jq
{
"address": "5Fdg1TDCX5iJarXjEsLn1gffVeddLvcQ7Jzh8gBV6W19yLxK"
}