Using Containerized Networks
Run ICP test networks in Docker containers for isolated, reproducible development environments.
Windows Users
On Windows, icp-cli automatically uses Docker for all local networks—no configuration needed. Just ensure Docker Desktop is installed and running, then use icp network start as normal.
For advanced WSL2 setups without Docker Desktop, see Manual dockerd in WSL2.
When to Use This
On macOS and Linux, icp-cli runs the network launcher natively by default. You may want to use containerized networks when you:
- Want network isolation from your host system
- Need to run multiple independent network instances
- Want reproducible environments across your team
- Are deploying in containerized CI/CD pipelines
- Need specific network versions or configurations
Prerequisites
- Docker installed and running (Install Docker)
- icp-cli installed
- An existing project with
icp.yaml
Verify Docker is running:
docker psQuick Start
1. Configure a Containerized Network
Add this to your icp.yaml:
networks: - name: docker-local mode: managed image: ghcr.io/dfinity/icp-cli-network-launcher port-mapping: - "8000:4943" # Maps container port 4943 to host port 8000The ghcr.io/dfinity/icp-cli-network-launcher image is the official ICP test network image and includes:
- ICP ledger canister
- Cycles ledger canister
- Cycles minting canister
- Pre-funded anonymous principal for development
Note: Network state is ephemeral—deployed canisters and their data are lost when the network stops. Persistence is not yet supported.
2. Start the Network
icp network start docker-localThis will:
- Pull the Docker image (first time only)
- Start a container with an ICP test network
- Expose the network on
http://localhost:8000
You’ll see output indicating the network is ready:
✓ Network docker-local started Gateway: http://localhost:80003. Deploy Your Canisters
Create an environment that uses your containerized network:
environments: - name: docker network: docker-local canisters: - my-canisterThen deploy:
icp deploy --env docker4. Stop the Network
# Graceful shutdownicp network stop docker-local
# Or press Ctrl-C in the terminal where it's runningCommon Configurations
Dynamic Port Allocation
Let Docker choose an available port automatically:
networks: - name: docker-local mode: managed image: ghcr.io/dfinity/icp-cli-network-launcher port-mapping: - "0:4943" # Docker assigns a random available host portFind the assigned port:
icp network status docker-local# Shows: Port: 54321 (example)Multiple Networks
Run multiple isolated networks simultaneously:
networks: - name: docker-dev mode: managed image: ghcr.io/dfinity/icp-cli-network-launcher port-mapping: - "8000:4943"
- name: docker-test mode: managed image: ghcr.io/dfinity/icp-cli-network-launcher port-mapping: - "8001:4943"Start both:
icp network start docker-devicp network start docker-testCustom Environment Variables
Pass environment variables to the container:
networks: - name: docker-local mode: managed image: ghcr.io/dfinity/icp-cli-network-launcher port-mapping: - "8000:4943" environment: - LOG_LEVEL=debug - POCKET_IC_MUTE_SERVER=falseRemove Container on Exit
Automatically delete the container when stopped:
networks: - name: docker-local mode: managed image: ghcr.io/dfinity/icp-cli-network-launcher port-mapping: - "8000:4943" rm-on-exit: true # Clean up container on stopUseful for CI/CD or temporary testing.
Troubleshooting
”Cannot connect to Docker daemon”
Problem: Docker is not running.
Solution: Start Docker Desktop or the Docker daemon:
sudo systemctl start docker # Linux# On macOS/Windows, open the Docker Desktop application“Port already in use”
Problem: Another process is using the host port.
Solutions:
-
Change the host port in
port-mapping:port-mapping:- "8001:4943" # Try a different port -
Or use dynamic allocation:
port-mapping:- "0:4943"
“Container fails to start”
Problem: Container exits immediately or fails to start.
Solution: Check container logs:
# Find container IDdocker ps -a | grep icp-cli-network-launcher
# View logsdocker logs <container-id>Common issues:
- Image pull failed (check internet connection)
- Port conflict inside container (check
port-mapping) - Insufficient resources (increase Docker memory/CPU limits)
“Network unreachable after start”
Problem: icp network start succeeds but cannot connect.
Solution: Check the network status file was written:
# The container should write status to the status directorydocker exec <container-id> cat /app/status/status.jsonIf the file is missing or incomplete, the container may still be initializing. Wait a few seconds and try again.
Configuration Reference
All available configuration options for containerized networks:
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Unique network identifier |
mode | string | Yes | Must be managed |
image | string | Yes | Docker image to use |
port-mapping | string[] | Yes | Port mappings in host:container format |
rm-on-exit | bool | No | Delete container when stopped (default: false) |
volumes | string[] | No | Docker volumes in name:container_path[:options] format |
mounts | string[] | No | Bind mounts in host_path:container_path[:flags] format (flags: ro or rw) |
environment | string[] | No | Environment variables in VAR=VALUE format |
args | string[] | No | Additional arguments to container entrypoint (aliases: cmd, command) |
entrypoint | string[] | No | Override container entrypoint |
platform | string | No | Platform selection (e.g., linux/amd64) |
user | string | No | User to run as in user[:group] format (group is optional) |
shm-size | number | No | Size of /dev/shm in bytes |
status-dir | string | No | Status directory path (default: /app/status) |
Example with multiple options:
networks: - name: docker-local mode: managed image: ghcr.io/dfinity/icp-cli-network-launcher port-mapping: - "8000:4943" volumes: - icp-data:/data mounts: - "./config:/app/config:ro" # Mount local config as read-only environment: - LOG_LEVEL=info - POCKET_IC_MUTE_SERVER=true rm-on-exit: false shm-size: 2147483648 # 2GBAdvanced: Custom Images
If the default image doesn’t meet your needs, you can create a custom Docker image that implements the icp-cli network launcher interface.
Interface Version
Your container must support the icp-cli network launcher interface. The environment variable ICP_CLI_NETWORK_LAUNCHER_INTERFACE_VERSION is provided by icp-cli.
Current interface version: 1.0.0
Your container should:
- Read
ICP_CLI_NETWORK_LAUNCHER_INTERFACE_VERSION - Verify it supports the version
- Exit early if the version is incompatible
Status File Requirements
Your container must write a status file to the status directory (default: /app/status/status.json) when the network is ready.
Important: The CLI automatically mounts the status directory as read-write, so your container can write to it. The file must contain a single line of JSON ending with a newline character.
Required fields:
v: string, must be"1"(status file format version)gateway_port: number, the container port where the ICP HTTP gateway listensroot_key: string, hex-encoded root key of the network
Optional fields (primarily for PocketIC-based networks):
instance_id: number or null, PocketIC instance IDconfig_port: number or null, PocketIC admin portdefault_effective_canister_id: string or null, principal for provisional canister calls
Example:
{ "v": "1", "gateway_port": 4943, "root_key": "308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100814c0e6ec71fab583b08bd81373c255c3c371b2e84863c98a4f1e08b74235d14fb5d9c0cd546d9685f913a0c0b2cc5341583bf4b4392e467db96d65b9bb4cb717112f8472e0d5a4d14505ffd7484b01291091c5f87b98883463f98091a0baaae", "instance_id": null, "config_port": null, "default_effective_canister_id": null}Container Behavior
Your container must:
- Start automatically - Launch the network when the container starts
- Write status file only when ready - Wait until the gateway API is accessible
- Handle stop signals - Gracefully shut down on
SIGTERM(orSIGINTif you setSTOPSIGNAL) - Exit cleanly - Exit after shutdown completes
Example Dockerfile:
FROM ubuntu:22.04
# Install your ICP network implementationRUN apt-get update && apt-get install -y curl# ... install network software ...
# Create status directoryRUN mkdir -p /app/status
# Set stop signal if neededSTOPSIGNAL SIGTERM
# Copy startup scriptCOPY start-network.sh /app/start-network.shRUN chmod +x /app/start-network.sh
ENTRYPOINT ["/app/start-network.sh"]Network Requirements
Your custom network must include:
- ICP ledger canister - For ICP token management
- Cycles ledger canister - For cycles management
- Cycles minting canister - For creating cycles
- Pre-funded anonymous principal - Principal
2vxsx-faemust have initial ICP balance for identity seeding
Port Binding
The gateway port (the port your ICP HTTP gateway listens on inside the container) must be mapped to a host port:
port-mapping: - "8000:4943" # host:containerYou can use 0 for dynamic host port allocation:
port-mapping: - "0:4943"Testing Your Custom Image
-
Build your image:
Terminal window docker build -t my-icp-network . -
Test it manually:
Terminal window docker run -p 8000:4943 my-icp-network# In another terminal, check statuscurl http://localhost:8000/api/v2/status -
Configure in
icp.yaml:networks:- name: custom-networkmode: managedimage: my-icp-networkport-mapping:- "8000:4943" -
Start with icp-cli:
Terminal window icp network start custom-network
Advanced: Manual dockerd in WSL2
If you’re on Windows and want to use a manually instantiated dockerd in a WSL2 instance instead of Docker Desktop, set these environment variables:
ICP_CLI_DOCKER_WSL2_DISTRO=<distro>— the WSL2 distribution name running dockerdDOCKER_HOST=tcp://<ip>:<port>— the TCP address where dockerd is listening
Related Documentation
- Managing Environments — Configure environments that use containerized networks
- Local Development — Development workflow with test networks
- Configuration Reference — Full network configuration options