Set up TOR with Docker
Set up TOR
You should now be the in the root directory of our LND-With-Docker
folder. Run the pwd
command to see the present working directory, and you should see something like this:
$ pwd
/mypool/workspace/LND-With-Docker
Take some time to look at the Tor Dockerfile
It's essential that you understand the basics of Docker. If you are totally confused right now and don't understand any of this Docker stuff, go back to Introducing Docker.
Here is the Dockerfile
for tor-socks-proxy
#/LND-With-Docker/tor-socks-proxy/Dockerfile
FROM alpine:3.19
LABEL maintainer="Peter Dave Hello <hsu@peterdavehello.org>"
LABEL name="tor-socks-proxy"
LABEL version="latest"
RUN echo '@edge https://dl-cdn.alpinelinux.org/alpine/edge/community' >> /etc/apk/repositories && \
echo '@edge https://dl-cdn.alpinelinux.org/alpine/edge/testing' >> /etc/apk/repositories && \
apk -U upgrade && \
apk -v add tor@edge obfs4proxy@edge curl && \
chmod 700 /var/lib/tor && \
rm -rf /var/cache/apk/* && \
tor --version
COPY --chown=tor:root torrc /etc/tor/
HEALTHCHECK --timeout=10s --start-period=60s \
CMD curl --fail --socks5-hostname localhost:9150 -I -L 'https://www.facebookwkhpilnemxj7asaniu7vnjjbiltxjqhye3mhbshg7kx5tfyd.onion/' || exit 1
USER tor
EXPOSE 8853/udp 9150/tcp
CMD ["/usr/bin/tor", "-f", "/etc/tor/torrc"]
You don't need to understand all of this, but you DO need to understand the basics: You're looking at a very clear, very minimal set of steps to create an entire little "computer". For example:
FROM alpine:3.19
===> This establishes the base operating system
RUN echo '@edge https://dl-cdn.alpinelinux....
===> This command downloads and installs software
CMD ["/usr/bin/tor", "-f", "/etc/tor/torrc"]
===> This specifies which commands will be run on "boot" of the container
Why we are using Docker Compose
There (at least) two different ways you can build and run a Dockerfile
.
As you were learning Docker, you undoubtedly saw long, complicated Docker commands. For example:
docker build -f Dockerfile -t tor-socks-image . && docker run --name tor-socks-dockerfile --network host -v "$(pwd)/tor-data:/data" -v "$(pwd)/torrc:/etc/tor/torrc" -v "$(pwd)/../tmp:/tmp" -e HOME="/tmp" tor-socks-image
These commands do work, but I would encourage you to never run a Docker container with a long command like this. Reasons:
- Long commands like this are extremely difficult to read and understand.
- You would have to remember to write down this command somewhere, and then again in the future, when you want to run it again, you'd need remember where you wrote it down.
Instead of commands like the above, in this project we are going to always run Docker with Docker Compose. This will allow us to create verbose, highly-readable "Compose" files, which are also self-documenting.
Review the Docker Compose file for TOR
Open tor-socks-proxy/dtor.yml
with your editor, or review the same file on GitHub:
https://github.com/MegalithicBTC/LND-With-Docker/blob/master/tor-socks-proxy/dtor.yml
The first thing to note: this code is specifying the same parameters as the long, complicated Docker command above. But it's much more readable, right?
Let's go through the important lines.
You see that under services:
, only one service is defined: tor
.
In build:
, we see two keys:
dockerfile: Dockerfile
context: .
The dockerfile:
directive points to our local Dockerfile
.
The context:
tells the docker engine that, when it runs commands in the Dockerfile
, that you will run them from the directory "."
, that is, the current directory.
The trickiest -- but also the most important -- part of dtor.yml
are the volumes:
.
Let's just look at one of the volumes:
- type: bind
source: ./tor-data
target: /data
The type
is bind
, meaning, we have mapped the local folder ./tor-data
into the folder in the container found at /data
.
Put another way, in the context of the overall project, the LND-With-Docker/tor-socks-proxy/tor-data
folder will appear in the container's filesystem at this, more simple path: /data
Finally, let's look at these:
environment:
HOME: "/tmp"
network_mode: host
Under the environment
key, we've specified one environment variable which will be active inside the container. This one variable is HOME
, and its value is /tmp
.
The network_mode
set to host
allows the container to directly use this computer's networking stack, as if it were running software directly on the computer.
OK!
Just one more file to review...
Review the torrc configuration file
Review the tor-socks-proxy/torrc
file, or see it on GitHub, here: https://github.com/MegalithicBTC/LND-With-Docker/blob/master/tor-socks-proxy/torrc
This file specifies the ports that Bitcoin Core and LND will use to talk to LND and Bitcoin Core. It also, with the directive CookieAuthentication 1
, tells TOR to use a cookie file for authentication.
Let's take a moment to understand how LND is going to authenticate with TOR.
Understand a bound volume
If you look back at the Docker Compose file (dtor.yml
), you'll see this volume:
- type: bind
source: ../tmp
target: /tmp
and this environment variable
environment:
HOME: "/tmp"
You can see that it is mounting ../tmp
, which is the tmp
folder in the parent LND-With-Docker
directory, into /tmp
in the container.
And with the HOME
environment variable, TOR is instructed to keep its cookie file in this /tmp
folder.
It's through this clever strategy that TOR is going to be able to share the tmp
folder -- and in the folder, a cookie -- with LND!
Start the TOR container.
Now is the moment of truth!
From within the LND-With-Docker/tor-socks-proxy
folder, run this command to start the TOR container:
docker compose -f dtor.yml up
You should see that the container builds, and then you should see log lines like
tor-socks-proxy-tor-1 | Mar 27 13:38:56.000 [notice] Bootstrapped 56% (loading_descriptors): Loading relay descriptors
tor-socks-proxy-tor-1 | Mar 27 13:39:15.000 [notice] Bootstrapped 61% (loading_descriptors): Loading relay descriptors
tor-socks-proxy-tor-1 | Mar 27 13:39:15.000 [notice] Bootstrapped 70% (loading_descriptors): Loading relay descriptors
tor-socks-proxy-tor-1 | Mar 27 13:39:17.000 [notice] Bootstrapped 75% (enough_dirinfo): Loaded enough directory info to build circuits
Great! Now, for just a little housekeeping.
Learn how to see running containers
It's important that you can at any time see a list of containers running on your machine.
Keep the TOR container running, and open a new terminal window with CNTRL-ALT-T
In this new window, use this command:
$ docker ps
This should make an output like this:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
4d81117327a3 tor-socks-proxy-tor "/usr/bin/tor -f /et…" 29 seconds ago Up 28 seconds (health: starting) tor-socks-proxy
So here we can see the container is running.
Learn how to stop a running container
Now let's try stopping this running container.
Use this command
$ docker stop tor-socks-proxy
When you run this, you should see that the running TOR container, in your first terminal window, is stopped. (You can also stop a running container by hitting CNTRL-C
in the same terminal window where the container is running.)
Next, close this terminal window #2, so you should now again have only one terminal window open on your machine.
Run TOR with the start script
To keep things tidy, for every container that I run, I like to setup an associated start
script that I can run from the root of my project. This saves you the necessity of using cd
to navigate to each subfolder individually.
Go back to the LND-With-Docker
folder with the command cd ..
Now let's look at the start-tor.sh
script:
docker compose -f ./tor-socks-proxy/dtor.yml down
docker compose -f ./tor-socks-proxy/dtor.yml up
Just so you understand, you can see that we are doing the down
command before the up
command.
I always do down
before an up
in my start
scripts, so that if the container is already running, it always stopped before we try to run it again.
Next, try running this script, with the command
$ ./start-tor.sh
Great! Now, your Ubuntu desktop should have one (1) terminal window open, with TOR running.
Please leave this container running. Next, we will be starting up Bitcoin Core.