How-to Guide How to start mining Monero in Docker

Since I am ultra tired today after a long workout, I decided to make a small resource for mining monero using Docker since I have a lot of requests for this.

It is a lot of text, but should take, at most 4-5 minutes to setup.

Step 1: Get a Monero wallet.

My suggestion: use an online wallet e.g. MyMonero

You will generate a key that has a whole bunch of random words. Best to keep that somewhere safe.

After you signup, you will be at an account overview page that has a long alphanumeric string under "Address". Keep that. That is going to be the Wallet address that we are going to use. We are going to call that WalletA later on.

Step 2: Get Docker installed on the server you want to mine on.
1. Install Docker
wget -qO- | sh
2. Add your user to the docker group, for example (in Debian/ Ubuntu):
sudo usermod -aG docker $USER
Exit and re-login to have that take effect.

Step 3a: Make mining easy to launch and maintain
These days, I have been using one xmrig miner instance per NUMA node (to see NUMA nodes, you can use lscpu).

To do this, we are going to use the servethehome/monero:xmrig miner. Instead of having to figure out configurations, here is what you need to know:

The image will automatically download and compile the miner. You do not need to setup a build environment/ dependencies.

The image's miner command is essentially now:
./xmrig -o stratum+tcp://$xmrpool:$startport -u $username -p $password -t $numthreads
While that may look scary, here is why it is easy: the $xmrpool and $startport variables will default to dwarfpool. $username is your wallet, WalletA or WalletA.workername.

Essentially that is the docker environment variable where you put your information on where you want to get paid. This does not have a default value.

The miners usually also have -p flags. Some pools simply use 'x' others requires passwords. Many now use your e-mail. The image defaults to 'x'

$numthreads is the number of threads. The logic was simplified greatly as we are now managing NUMA node pinning manually.

If you are OK using Dwarfpool, one of the major Monero pools, then all you really need to know are the values for WalletA, your email and threads.

You do not need to read how to guides on setting miners up. You also do not have to worry about installing anything on the base OS. This is all kept in the Docker container which makes it clean.

Step 3b: The launch script
These days, I am using a launch script for each machine.

Here is a sample script for a typical server CPU setup such as dual Intel Xeon E5-2628L V4 which has 12 cores/ 24 threads:


docker run -itd -e username=$wally.$(hostname)-0 -e password=$emails -e numthreads=$thrperinst --cpuset-cpus="0-11,24,28,32" servethehome/monero_xmrig
docker run -itd -e username=$wally.$(hostname)-1 -e password=$emails -e numthreads=$thrperinst --cpuset-cpus="12-23,36,40,44" servethehome/monero_xmrig
Here is the lscpu output that we care about:
CPU(s):                48
On-line CPU(s) list:   0-47
Thread(s) per core:    2
Core(s) per socket:    12
Socket(s):             2
NUMA node(s):          2
Vendor ID:             GenuineIntel
CPU family:            6
Model:                 79
Model name:            Intel(R) Xeon(R) CPU E5-2628L v4@ 1.90GHz
Stepping:              1
CPU MHz:               2099.945
CPU max MHz:           2400.0000
CPU min MHz:           1200.0000
BogoMIPS:              3801.44
Virtualization:        VT-x
L1d cache:             32K
L1i cache:             32K
L2 cache:              256K
L3 cache:              30720K
NUMA node0 CPU(s):     0-11,24-35
NUMA node1 CPU(s):     12-23,36-47
So here is the logic. Each mining thread needs 2MB of cache. On Xeon Scalable, you can use L2+L3 (leaving some extra leftover. On Atom with no L3 cache, use L2. Basically, anything else with L3 cache use L3. The example above says 30MB L3 cache. That is per CPU. So we can have up to 15 mining threads per socket in this example (30MB L3 /2MB = 15). We put that in the thrperinst variable so we can change it once.

We want to run one docker container per NUMA node so that we can avoid the penalty for passing information from one socket to another. NUMA node0 has twelve physical CPUs 0-11 and twelve hyper-thread "CPUs" 24-35. So in our script, we want to place miners on 15 of the 24 total threads. The logic here is to fill physical cores first, then fill hyper-thread "CPUs". The --cpuset-cpus flag in Docker allows us to run a container on a specific set of CPUs. So we use 0-11,24,28,32 for the first CPU and 12-23,36,40,44 for the second.

If you are on Ryzen or EPYC, you are essentially going to make one docker miner line for each die, then just use the ranges before the commas on each NUMA node. This has a huge impact for AMD EPYC performance but we see great gains on dual and quad Intel systems as well. AMD simply has more NUMA nodes.

So if you put the above script into something like "", add your WalletA address and e-mail. You are almost there. Just edit the number of threads per instance and then make a new docker line for each CPU in the system and you are set.

The other item we are doing here is appending "$(hostname)-1" for the first NUMA node. On dwarfpool, our test pool, you can setup a worker name. With servers, you may have two or more NUMA nodes and therefore miners running and want to be notified if any of them go down. By using the "$(hostname)-1" we can identify the hostname of the device and that it is on NUMA node 1.

Step 4: Get mining
One tiny tweak you will want to make on a system that is primarily mining:
sudo vm.nr_hugepages=128
If your system is not mining primarily, you may not want to make that change.

Now, you can simply run the script:
And it will run. You will see Docker containers spin up with a few alphanumeric strings.

To check that they are running:
docker ps
Step 5: Basic Monitoring

If you want to see what one docker container miner is doing, you can use the logs feature:
docker logs <container name> | tail -n 30
As an example to see the last 30 lines of output.

Our script is using -itd so it is meant to run in the background. If you want to attach to a container:
docker attach <container name>
If you Ctrl+c you will actually stop the miner and the container. Instead when you are ready to detach Ctrl+p and Ctrl+q

If you are wondering why there is a script, it is not needed. You can pass arguments directly. On multi-NUMA node systems, such as dual EPYC and quad Xeon, it is much easier to have a launch script.

As you mine a few XMR, the pool will payout your mined currency to your wallet, in this example on mymonero.

Final Words

On most systems, this entire guide should take you no more than 4 minutes to do and there is still room for making that faster.

If you want to change the pools, simply change the pool name and the start port in the above and add those commands to the launch command.
First release
Last update
0.00 star(s) 0 ratings

More resources from Patrick