Containerized environment for deploying and managing EVVM Testnet Contracts without installing dependencies locally.
Deploy virtual EVM chains on testnets using Docker - no need to install Foundry, Bun, or manage dependencies manually. This repository provides a complete Docker environment with all tools pre-configured and ready to use.
- Docker Image with Foundry (forge, cast, anvil, chisel) and Bun pre-installed
- Auto-cloning of the EVVM Testnet Contracts repository
- EVVM CLI pre-configured and ready to use
- Complete documentation with examples and guides
- Make targets for common operations (optional)
- Secure wallet management using Foundry's encrypted keystores
- All project dependencies pre-installed
git clone https://github.com/EVVM-org/evvm-docker
cd evvm-dockerOr download and extract the files manually.
Create your .env file from the example:
cp .env.example .env
# Edit .env with your RPC URLs and API keys
nano .envdocker compose buildOr using Make:
make build# Start interactive session
docker compose run --rm --entrypoint /bin/bash evvm-cli
# Inside container, import your wallet
cast wallet import defaultKey --interactive
# Enter your private key when prompted
exit# Using docker compose
docker compose run --rm evvm-cli deploy
# Or using Make
make deployevvm-docker/
├── 📄 README.md # This file
├── 📄 QUICKSTART.md # Quick start guide
├── 🐳 Dockerfile # Docker image definition
├── 🐳 compose.yml # Docker Compose configuration
├── 📝 .env.example # Environment variables template
├── 🔧 Makefile # Make commands (optional)
├── 📄 LICENSE # MIT License
├── 🙈 .dockerignore # Docker build exclusions
└── 🙈 .gitignore # Git exclusions
Perfect for:
- Testing EVVM without installing Foundry/Bun locally
- CI/CD pipelines requiring consistent environments
- Team development with standardized tooling
- Windows users wanting easy access to Foundry tools
- Quick deployments on any platform with Docker
- Docker (20.10+)
- Docker Compose (2.0+)
- At least 4GB of free disk space
Wallets are automatically persisted in a Docker volume, so you only need to import once:
# Start interactive session (only needed once for import)
docker compose run --rm --entrypoint /bin/bash evvm-cli
# Inside container, import your wallet
cast wallet import defaultKey --interactive
# Enter your private key when prompted
# Then run CLI commands
bun run cli/index.ts deploy
exitNote: Your wallet will persist across container runs thanks to the foundry-keystores volume.
Note: By default, wallets are now persisted in a Docker volume named foundry-keystores. They will be available across all container runs.
If you want to share wallets with your host machine instead, uncomment the alternative volume mount in compose.yml:
volumes:
# Comment out the volume mount
# - foundry-keystores:/root/.foundry/keystores
# Uncomment the host mount
- ~/.foundry/keystores:/root/.foundry/keystores:roThen import wallet on your host machine:
cast wallet import defaultKey --interactiveYour wallet will now be available in all container runs from both host and containers.
Required variables in .env:
# For single-chain deployment
RPC_URL="https://your-rpc-url"
# For cross-chain deployment
EXTERNAL_RPC_URL="https://external-chain-rpc"
HOST_RPC_URL="https://host-chain-rpc"
# For registration
EVVM_REGISTRATION_RPC_URL="https://sepolia-rpc-url"
# For contract verification
ETHERSCAN_API="your_api_key"See .env.example for all available options.
docker compose run --rm evvm-cli help # Show CLI help
docker compose run --rm evvm-cli version # Display version
docker compose run --rm evvm-cli deploy # Deploy EVVM
docker compose run --rm evvm-cli register # Register EVVM
docker compose run --rm evvm-cli setUpCrossChainTreasuries # Setup cross-chain
docker compose run --rm evvm-cli dev # Developer utilities
docker compose run --rm evvm-cli install # Install dependencies
docker compose run --rm --entrypoint /bin/bash evvm-cli # Interactive shellmake help # Show all available commands
make build # Build Docker image
make deploy # Deploy EVVM
make register # Register EVVM
make shell # Interactive shell
make version # Show version
make stop # Stop containers (keep data)
make clean-image # Remove image only (keep wallets/data)
make clean # Remove everything (images + wallets + data)
make clean-wallets # Remove only saved wallets# 1. Configure .env
echo 'RPC_URL="https://sepolia-rollup.arbitrum.io/rpc"' > .env
# 2. Run deployment
docker compose run --rm evvm-cli deploy# 1. Configure .env
cat > .env << EOF
EXTERNAL_RPC_URL="https://sepolia-rollup.arbitrum.io/rpc"
HOST_RPC_URL="https://0xrpc.io/sep"
EOF
# 2. Run deployment
docker compose run --rm evvm-cli deploy# 1. Ensure you have deployed first
# 2. Configure registration RPC
echo 'EVVM_REGISTRATION_RPC_URL="https://gateway.tenderly.co/public/sepolia"' >> .env
# 3. Run registration
docker compose run --rm evvm-cli register# Compile contracts
docker compose run --rm evvm-cli forge build
# Run tests
docker compose run --rm evvm-cli forge test
# Start local testnet (Anvil)
docker compose run --rm -p 8545:8545 evvm-cli anvil --host 0.0.0.0
# Use cast to check block number
docker compose run --rm evvm-cli cast block-number --rpc-url https://eth.llamarpc.comDeployment results are saved to output/ directory which is mounted as a volume. This ensures your deployment data persists across container runs.
# View deployment results
ls output/evvmDeployment.jsonIf you import a wallet inside the container without mounting the keystore directory, it will be lost when the container is removed. Use Option 2 in the Working with Wallets section to persist wallets.
# Run forge tests
docker compose run --rm evvm-cli forge test
# Run anvil (local testnet)
docker compose run --rm -p 8545:8545 evvm-cli anvil --host 0.0.0.0
# Use cast
docker compose run --rm evvm-cli cast block-number --rpc-url https://eth.llamarpc.comFor development with live code changes, mount the source directory:
Edit compose.yml:
volumes:
- ../:/workspaceThen rebuild inside container:
docker compose run --rm --entrypoint /bin/bash evvm-cli
bun install
forge buildTo pause or completely remove the Docker setup:
# Just stop running containers (data persists)
docker compose stop
# Or
make stop
# Stop and remove containers (volumes/data persist)
docker compose down
# Remove image but keep wallets and data
docker compose down --rmi all
# Or
make clean-image
# Complete cleanup: remove containers, images, volumes, and all data
docker compose down --rmi all --volumes --remove-orphans
# Or
make cleanCleanup comparison:
| Action | Command | Image | Wallets | Outputs | Containers |
|---|---|---|---|---|---|
| Stop | make stop |
✅ Keep | ✅ Keep | ✅ Keep | ⏸️ Stop |
| Clean wallets | make clean-wallets |
✅ Keep | ❌ Remove | ✅ Keep | 🗑️ Remove |
| Clean image | make clean-image |
❌ Remove | ✅ Keep | ✅ Keep | 🗑️ Remove |
| Clean all | make clean |
❌ Remove | ❌ Remove | ❌ Remove | 🗑️ Remove |
To verify everything is removed:
# Check images
docker images | grep evvm
# Check volumes
docker volume ls | grep evvm-docker
# Check containers
docker ps -a | grep evvmIf you need to delete imported wallets:
# Remove the wallet volume
docker volume rm evvm-docker_foundry-keystores
# Or remove all data (wallets + outputs)
docker compose down --volumesThen reimport your wallet as described in Working with Wallets.
# Linux
sudo systemctl start docker
# macOS
open -a Docker
# Windows
# Start Docker Desktop from Start menuIf you encounter permission errors with mounted volumes:
# On Linux, ensure proper permissions
chmod 644 .env
chmod -R 755 output/
# Linux - add user to docker group
sudo usermod -aG docker $USER
# Log out and back inIf RPC URLs are not accessible:
# Test from host
curl -X POST -H "Content-Type: application/json" \
--data '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}' \
YOUR_RPC_URL- Use
network_mode: hostin compose.yml if accessing local nodes
The repository is cloned during build. To update:
# Rebuild the image without cache
docker compose down --rmi all --volumes
docker compose build --no-cacheOr manually inside container:
docker compose run --rm --entrypoint /bin/bash evvm-cli
git pull origin main
git submodule update --init --recursive
bun install
forge installImportant Security Practices:
- Never commit
.envfiles - Keep your RPC URLs and API keys secret - Never store private keys in
.env- Use Foundry's encrypted keystore - Use read-only mounts (
:ro) for sensitive files when possible - Be cautious with volume mounts - Only mount necessary directories
- Review the Dockerfile before building to understand what's installed
- Keep Docker images updated - Rebuild periodically for security patches
Important Security Practices:
- Never commit
.envfiles - Keep your RPC URLs and API keys secret - Never store private keys in
.env- Use Foundry's encrypted keystore - Use read-only mounts (
:ro) for sensitive files when possible - Be cautious with volume mounts - Only mount necessary directories
- Review the Dockerfile before building to understand what's installed
- Keep Docker images updated - Rebuild periodically for security patches
- QUICKSTART.md - Quick start guide
- README.md - Full documentation (this file)
- EVVM Docs - Official EVVM documentation
- Foundry Book - Foundry documentation
- Bun Docs - Bun documentation
Contributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add some amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
- EVVM Website: https://www.evvm.info/
- EVVM Testnet Contracts: https://github.com/EVVM-org/Testnet-Contracts
- Docker Hub: (Coming soon)
- Documentation: https://www.evvm.info/docs/