Setting up an Ethereum private network is a powerful way to test smart contracts, decentralized applications (dApps), and blockchain interactions in a controlled environment. Docker simplifies this process by offering lightweight, reproducible containers that eliminate many system-level dependencies. This guide walks you through building a fully functional Ethereum private chain using Docker — ideal for developers, testers, and blockchain enthusiasts.
Whether you're preparing for a development sprint or learning the fundamentals of Ethereum node management, this step-by-step tutorial ensures clarity, consistency, and scalability.
Why Use Docker for Ethereum Development?
Docker has become the go-to tool for modern blockchain development due to its portability, isolation, and ease of configuration. Compared to traditional virtual machines, Docker containers boot faster, consume fewer resources, and can be version-controlled alongside your codebase.
By containerizing your Ethereum nodes:
- You ensure consistent environments across development, testing, and staging.
- You simplify networking between multiple nodes.
- You avoid conflicts with system-level binaries or libraries.
Core keywords naturally integrated: Ethereum private network, Docker Ethereum setup, build Ethereum chain, private blockchain with Docker, Geth Docker configuration, Ethereum development environment.
Step 1: Install Docker on Ubuntu
We’ll use Ubuntu 18.04 LTS (Bionic) as the host OS. While newer versions are available, the principles apply universally.
👉 Learn how containerization boosts blockchain development efficiency.
Download and Install Docker .deb Packages
Instead of using APT repositories, we’ll install Docker via .deb packages for simplicity:
- Visit:
https://download.docker.com/linux/ubuntu/dists/bionic/pool/stable/amd64/ Download these three files:
containerd.io_1.2.4-1_amd64.debdocker-ce-cli_18.09.3_3-0_ubuntu-bionic_amd64.debdocker-ce_18.09.3_3-0_ubuntu-bionic_amd64.deb
- Install them in order:
sudo dpkg -i docker-ce-cli_18.09.3_3-0_ubuntu-bionic_amd64.deb
sudo dpkg -i containerd.io_1.2.4-1_amd64.deb
sudo dpkg -i docker-ce_18.09.3_3-0_ubuntu-bionic_amd64.debVerify Installation
Run the classic test:
sudo docker run hello-worldIf successful, you’ll see a confirmation message indicating Docker is working correctly.
Note: To update Docker later, simply download new .deb packages and repeat the installation process.Step 2: Pull the Geth Docker Image
The official Ethereum Go client (geth) is available on Docker Hub. Pull it with:
sudo docker pull ethereum/client-goThis fetches the latest version of geth. Confirm it’s downloaded:
sudo docker image lsYou should see:
REPOSITORY TAG IMAGE ID CREATED SIZE
ethereum/client-go latest f376688623dc 3 hours ago 42.7MB
hello-world latest fce289e99eb9 2 months ago 1.84kBTry running an interactive shell inside the container:
sudo docker run -it --rm -v /workspace:/workspace --entrypoint /bin/sh ethereum/client-go-i,-t: Enable interactive terminal access.--rm: Automatically remove container when exited.-v: Mount/workspacefrom host to container for file sharing.--entrypoint: Override default startup command to prevent automatic node launch.
Exit with exit when done.
Step 3: Create a Custom Docker Network
For secure inter-container communication, create a dedicated bridge network:
sudo docker network create -d bridge --subnet=172.18.0.0/16 ethnetVerify creation:
sudo docker network lsLook for ethnet in the list. This isolated network allows containers to communicate via static IPs without exposing services to the host or external networks.
Step 4: Configure the Ethereum Private Chain
Now we’ll prepare the genesis block and accounts.
Prepare Directory Structure
On your host machine, create:
mkdir -p /workspace/dapp/{miner,data}
touch /workspace/dapp/genesis.jsonCreate Ethereum Accounts
Start a temporary container:
sudo docker run -it --rm --network ethnet --ip 172.18.0.50 -v /workspace:/workspace --entrypoint /bin/sh ethereum/client-goInside the container:
cd /workspace/dapp/miner
geth -datadir ./data account newEnter a password twice to generate a new account (e.g., 0x79b4...df58). Repeat to create more if needed.
Record these addresses — they’ll receive initial funds in the genesis block.
Define the Genesis Block
Edit /workspace/dapp/genesis.json:
{
"config": {
"chainId": 88,
"homesteadBlock": 0,
"eip155Block": 0,
"eip158Block": 0
},
"alloc": {
"0x79b43b2196723fff1485999aba45fda3e8b4df58": { "balance": "100000000000000000000" },
"0x1ae06a8afd157b97f072a97f5c62fa836f5ef597": { "balance": "1000000000000000000" },
"0xa75b4db0c6bfa416d544e3316d47af0fb01eb828": { "balance": "1000000000000000000" },
"0x1a037d8e8e16a4c88e17c3d5f29ee26a9f5b2c85": { "balance": "1000000000000000000" }
},
"coinbase": "0x0000000000000000000000000000000000000000",
"difficulty": "0x400",
"extraData": "",
"gasLimit": "0x2fefd8",
"nonce": "0x000000000000000",
"mixhash": "0x0...",
"parentHash": "0x...",
"timestamp": "0x..."
}Key fields:
chainId: Identifies your private chain (set to 88).alloc: Pre-funds accounts at launch.difficulty: Low value enables fast mining.gasLimit: High limit avoids out-of-gas errors during testing.
Exit the container — files persist on the host due to volume mounting.
Step 5: Launch the Miner Node
We’ll now build a persistent mining node.
Create Initialization Scripts
/workspace/dapp/init.sh (initializes chain):
#!/bin/sh
geth -datadir ~/data/ init /workspace/dapp/genesis.json
if [ $# -lt 1 ]; then
exec "/bin/sh"
else
exec /bin/sh -c "$@"
fi/workspace/dapp/mine.sh (starts mining):
#!/bin/sh
cp -r /workspace/dapp/miner/data/keystore/* ~/data/keystore/
geth -datadir ~/data/ \
--networkid 88 \
--rpc \
--rpcaddr "172.18.0.51" \
--rpcapi admin,eth,miner,web3,personal,net,txpool \
--unlock "your-mining-address" \
--etherbase "your-mining-address" \
consoleReplace your-mining-address with the primary account (e.g., first one created).
Make scripts executable:
sudo chmod +x /workspace/dapp/init.sh /workspace/dapp/mine.shLaunch the miner container:
sudo docker run -it \
--name=miner \
--network ethnet \
--ip 172.18.5.5 \
--hostname node \
-v /workspace:/workspace \
--entrypoint /workspace/dapp/init.sh \
ethereum/client-go \
/workspace/dapp/mine.shThis creates a long-running node initialized with your custom blockchain.
👉 Discover how blockchain testnets accelerate dApp deployment.
Step 6: Add Additional Nodes
Repeat similar steps for non-mining peers.
Create /workspace/dapp/node.sh:
#!/bin/sh
cp -r /workspace/dapp/miner/data/keystore/* ~/data/keystore/
geth -datadir ~/data/ --networkid 88 consoleRun a new node:
sudo docker run -it \
--name=node1 \
--network ethnet \
--ip 172.18.5.6 \
--hostname node1 \
-v /workspace:/workspace \
--entrypoint /workspace/dapp/init.sh \
ethereum/client-go \
/workspace/dapp/node.shStep 7: Connect Nodes
In the miner console:
> admin.nodeInfo.enode
"enode://[email protected]:3...3"Copy the full URL (replace 127.… with 172.…). In node1, run:
> admin.addPeer("enode://...")
trueCheck connections:
> admin.peers.length
1Your two-node private Ethereum network is now live!
Managing Containers
Use these commands for lifecycle control:
- Stop:
sudo docker stop miner - Start:
sudo docker start -i miner - Execute commands without entering console:
sudo docker exec -it miner /bin/sh - View logs:
sudo docker logs miner
Frequently Asked Questions (FAQ)
Q: Can I run this on macOS or Windows?
Yes! Docker Desktop supports both platforms. The commands remain identical — only path mounts may differ slightly.
Q: What’s the purpose of the genesis.json file?
It defines the initial state of your blockchain, including chain ID, difficulty, gas limits, and pre-funded accounts. Without it, each node would start with default public chain settings.
Q: Why do we copy keystore files into ~/data?
Geth expects wallet keys in its data directory. Since /workspace is a mounted volume not managed by Linux filesystem permissions, copying ensures proper access and avoids runtime errors.
Q: How do I deploy a smart contract on this network?
Once mining starts, unlock your account and use personal.sendTransaction() or connect Remix IDE via HTTP RPC at http://172.18.5.5:8545.
Q: Is this suitable for production?
No. This setup is strictly for local development and testing. For production, consider permissioned consensus models like Proof-of-Authority (Clique) and hardened security practices.
Q: How can I automate multi-node deployment?
Use Docker Compose to define services, networks, and volumes in a single docker-compose.yml, enabling one-command cluster startup.
With your private Ethereum network running in Docker, you’re ready to explore smart contract development, wallet integration, and consensus mechanics — all in a safe, repeatable environment.