Running a Node in a Docker container on NAS

HI All, with beta approaching this month, I would like to pick the community collective brain on how to run a Node on a NAS.
In particular I’m referring to a Synology NAS, but if the path is through a Docker container, this would apply to a much broader range of NAS (and other systems as well).
Any idea on how to start, anybody has experience to share on similar projects?

6 Likes

I bought a QNAP a few months ago because I could smell something in the Ayr.

I know you have a Synology but I hope my approach will help.

The container solution provided by QNAP is a poor experience so I am running
something on top.

I’ve installed (running a container) Portainer on top of Container Station
using the following docker file.

version: '3.3'
services:
  portainer:
    image: portainer/portainer-ce:latest
    ports:
      - "9000:9000"
      - "8000:8000" # Optional, for Edge agent communication
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock"
      - "/share/dockerapps/portainer:/data"
    restart: always

Portainer is perfect as you can do all the good stuff with docker.

e.g. Docker Networking.

Also through Portainer you can still simply point to shares created on your QNAP.
/share/dockerapps/databases/postgresql/

This is just an example docker-compose to show you it runs just great on Portainer.

version: '3'
services:
  postgres:
    image: postgres:16.2
    restart: unless-stopped
    ports:
      - 0.0.0.0:5432:5432
    volumes:
      - /share/dockerapps/databases/postgresql/data:/var/lib/postgresql/data
      - /share/dockerapps/databases/postgresql/wal:/var/lib/postgresql/wal

    environment:
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=password
      - PGID=100
      - PUID=1003
      - POSTGRES_HOST_AUTH_METHOD=scram-sha-256
      - POSTGRES_INITDB_ARGS=--data-checksums
      - POSTGRES_INITDB_WALDIR=/var/lib/postgresql/wal
      - POSTGRES_SSL_CERT_FILE=/var/lib/postgresql/data/server.crt
      - POSTGRES_SSL_KEY_FILE=/var/lib/postgresql/data/server.key
      - POSTGRES_SSL_CA_FILE=/var/lib/postgresql/data/ca.crt
    networks:
      - pgadmin4_databasenetwork

networks:
  pgadmin4_databasenetwork:
    external: true

I’m a bit overloaded at work, but with the goodies coming this week I hope there will be a docker image, if not i’ll try and put one together.

I’ve got some serious storage ready to donate as we make our way to October.

Edit… you know, just run any old ubuntu image, run a docker-compose to map directories,
then connect,

docker exec -it <container_name_or_id> /bin/bash
(on qnap you need to ssh to your NAS, you can’t do this from the admin webpage)

and run the instructions given in the test networks.

Here is a very basic attempt and I am sure someone will come along and make it better.

version: '3'
services:
  ubuntu:
    image: ubuntu:latest
    container_name: ubuntu_basic
    command: tail -f /dev/null 
    volumes:
      - type: bind
        source: /path/to/your/nas/share
        target: /mnt/nas
    tty: true

Might need to add port mappings. Let’s see what they have for us.

5 Likes

I am always distant from these discussions, but the system is designed for commodity computers. The cheapest least powerful we can get to.

I see tons of complex solutions offered that always end with “I wonder if it will work” and I get a bit confused.

Are folk trying to emulate lots of small pc’s or build themselves and edge or something? It seems in a way like normal folk trying to be the data centres we are trying to avoid :smiley: :smiley: :smiley: Hence my confusion.

I am not saying right wrong good bad etc. I am just left curious as to the outcome folk expect. As we progress and then perhaps add things like IP sensitivity to perhaps reduce nodes from an IP would folk go mad? Not that this is a plan but I can see it as a feasible argument.

4 Likes

Not sure I’m following you here, David.
If you are referring to the OP, the idea here is to use a very basic NAS (celeron, 2gb ram but expandible to 16 gb, 4 bays of storage).
Far from a Data Centre!
The docker requirement is simply due to the non-standard nature of Synology OS, but it also opens the possibility of easy bandwidth/resource control, just to mention one feature I’d like to have.

2 Likes

Yea. All good points.

Mainly, I needed an excuse to have a nice shiny NAS. I’ve never had one.
Am really enjoying my plex server at the moment.

Somewhere along the line while working through my raspberry pi(s) I started wondering
what if my disk fails and although all my data would be safe on the network any node
I would be running would be wiped out. At least with a NAS I can swap out a failed disk
and continue to participate in the network and look after my ‘Tamagotchi’.

The NAS does look it will become unnecessary and I think after a few years once everyone is using
commodity computers and adoption has picked up I don’t think I’ll ever have to worry
about expanding it’s storage or buying a new one.

2 Likes

The smartest will avoid it anyway.
There is always some benefit from making more than one node. Like you have to learn all the stuff around, make backup of electricity, internet connection and once you have it it does make sense to have it all for one node.
And the network has own needs so it is not like I am going to add there millions node when there is not demand.

1 Like

@dirvine interesting discussion, it’s inevitable SANS and NAS will compete with DAS implementations…

the firm I am with have done much FIO testing with DAS Direct Attached Storage of SATA and NVMES over the years, the latest with a very large 60 Data centre private enerprise customer using Postgres+ DAS on their systems where the DAS RAID 5 system array is a 4X15.53 TB setup of OTS NVME which happens to be Kioxia.

We have discovered over the past few years the choice of File System really does matter to system write speed, system power consumption and flash drive durability (also hdds as well) .

ie- ZFS for example we have tested thoroughly and we know has a big write amplification rate which can go as high as 20+, causing much defrag and garbage collection write amplification, which gets use as unassigned capacity shrinks because the drive is filling up (usually a 30% reserve is set to keep GC, defrag and wear levelling going at decent clips for all flash offers), the end result is the DAS array Write IOPs performance whether it be journaled or RAID (pick a flavour) rapidly declines. Plus the same flash drives wear out fast in high volume small block random read/write use cases for MYSQL or Portgres DB environs. In fact, in high write volume of small block sizes. these DB Servers in DCs see these drives proactively replaced, every 5-6 months, which is why support is charged annually at 25% of the sale price of the systems (support includes drive replacement).

We have a LKM Linux Kernel Module which plugs nicely into Rocky 9.3, or any LTS popular edition, paired with a unique physical media format which sets up stripes sectors with space for session meta data to help us keep track of session block age, etc., so as to more efficiently reduce write amp by at least 2x and reduce the amount of wholesales block 'flash reads and re-writes", which in turn reduces power consumption and increases drive life, really important when there is a high volume of small block write activity , random 50% read vs 50% write being the typical measuring stick. low volume, large block size random read/write use cases see drive durability increase 14X, which is 2X+ better than anything out there.

The LKM is also the only Linux in memory flash translation layer that we know of which allows the entire data read/write management at the Linux system level to see all physical drives in the array, as FTL is always located on individual drives themselves. This means having FTL in system memory we can turn on System hardware compression provided by Intel or AMD to return at least 50% of the capacity back to the user, delivering full linearization of multi-session write data… We also ensure read path stays fast as drive fills up…

Like Maidsafe, our LKM (Linux Kernel Module) has been literally since 2006 been in the making. Actually in early 2009 its was the only SAN array capable solution licensed by a 3rd party , which unfortunately got retired by an inferior SAN disk solution, which resulted in the acquirer closing down the 3rd party in 2015. (‘Whiptail’ ring a bell?)

Why the post? @dirvine , we are now scratching our collective heads right now about how to bring this advance in Write speed, drive durability and power savings really cost effectively to the consumer market… especially for Win 11 and MAC OS Desktops,

The current LKM we have works , is very stable with Linux kvm (kernel virtual machine) hypervisor and VMs running Win11 and MAC OS (also running containers even with DCI docker Container Isolation),

so the above might be one way forward to service that desktop consumer part of the market and create an image backup/install/restore/update procedure which preserves the MS and Apple licensing.

for the record I have been following Maidsafe since late 2014.

@dirvine , suggestion maybe we should talk when you have time?

We would like to help, as what we have would definitely allow any consumer end user using the up and coming SAFE Network to speed up their system, preserve power and extend their flash drive life, SATA or NVME it matters not, it works with any flash drive.

we could connect via DM on discord…

kr @rreive

5 Likes

In this case it is trying to utilise the compute power in a home NAS which would typically be left on all the time. Just another computer running node(s). Docker is a way to do it on synology NAS.

The way I am understanding things, it is best for the network that individual users are not running toooo many nodes as that reduces the distribution of nodes behind one internet connection. We’d prefer 1 billion internet connections with upto 20 nodes each connection compared to one million internet connections with 20 thousand nodes each connection.

In this case though its getting the upto 20 nodes on a always on machine behind the internet connection.

@stout77 Personally though I do not let external connections to my NAS and so would be useless in my case. In the end i’d put one or a few SBCs in and let them have a portion of the NAS if I had to use the NAS, only need like 20-40GB for 10 nodes (data and logs)

2 Likes

I’ll have to investigate security implications of this approach. Not sure whether docker provides any additional advantage, but I definitely don’t want to compromise the NAS security.

That’s right; to me a home NAS is a great candidate for running a few nodes. The advantage to me is more about using the unutilised processing power and bandwidth, plus the uninterrupted connectivity, which you’d think is beneficial to the network minimising churn. Storage space just happens to be there, but is not the main driver.
And surely there will be more efficient systems, but again this is about using unutilised resources.

2 Likes

In answer to multiple comments above:-

Personally I’m looking at running Safenodes in ‘Jails’ on TrueNAS running on a 4 x 4TB drive system based on a HP Microserver that I have anyway. Jails are essentially the same thing as Docker but from the Sun Solaris heritage. That would be for me. Friends and family would have a Pi4 with a large SSD and however many nodes vs storage makes sense for their internet connectivity.

I see the lunacy of running a node of a globally resilient network on a RAID system. But if that’s what you have available space on, why not?.. It does kind of make sense from a supportability point of view if that’s what you have already. But ZFS that is used in TrueNAS is very hard on drives… So stick with spinning metal and avoid this SSD Witchcraft…

External connections to your NAS that is running your storage for your private stuff is a concern even if it is dockerized or in a Jail is a concern but the other option is an NFS mount to a Pi that is running the Safenode(s). Then you should be good.

The whole issue of node count vs bandwidth used vs storage amount and what is best for the network needs thrashing out. Maybe by policy and maybe by testing through the Beta phase.

@rreive 's suggestion sounds interesting and should be examined by someone with the background and skills. If it can deliver an improvement over what normal users would deploy I think it should be looked at.

Think about what VAST does with clever caching and programming to take user grade commodity SSDs and turn them into an Enterprise system that doesn’t murder them too quickly to be economic.

At the other end of the scale you have Weka using expensive and high performance NVMe drives, and client caching, and full stack control over network, drive and compute to deliver high performance without murdering the expensive NVMe drives.

These are extreme examples from the wonderful world of enterprise storage but they are still relevant and instructive at the level of consumers joining a global distributed system. We need to work out how to recommend reference systems for consumers of all levels. Fun times!

6 Likes

In time it would be great to have Node Manager monitor machines and bandwidth and automatically optimize the number of nodes based on the performance.

3 Likes

It would be awesome to have this as an option for folk running nodes at home. Consider the Bamboo Garden fund and the Safe Network Foundation. Maybe there could be a way to get this into the hands of ordinary folk wanting to run nodes.

Saving energy, and hardware is important when you consider how many millions of machines will be running nodes in a very short period of time. Extending the lifespan of hardware and reducing power consumption for machines running nodes for a network that stores data permanently is vital to the mission.

4 Likes

Docker Container Isolation has the notion of an outer container with its own separate root access able to hold multiple inner-containers, each with their own root access. ‘DCI’ was originally developed by two guys in the Los Angeles YCombinator which has first created a little company called nestybox which create the utility sysbox which accompilished the above, then Docker bought them out and they work there now.

So with ‘sysbox’ installed on your system together with Docker (really no need to run a hypervisor and virtual machines, if you’re just using the machine to run the node), it would be possible to run the node in an ‘inner container’ with the node inheriting any outercontainer security+VM Security+ Host OS Security + Router security+ Network provider Modem security , while adding yet another layer of security in the process

3 Likes

It makes a lot of sense to have safe manager apps for the most common commercial NAS systems.

2 Likes

Found a bit if time to try building a docker image
Now to understand how to optimize it, currently 1gb :roll_eyes:
Here’s the Dockerfile, crude as…

syntax=docker/dockerfile:1

# Comments are provided throughout this file to help you get started.
# If you need more help, visit the Dockerfile reference guide at
# https://docs.docker.com/go/dockerfile-reference/

# Want to help us make this template better? Share your feedback here: https://forms.gle/ybq9Krt8jtBL3iCk7

ARG RUST_VERSION=1.76
ARG APP_NAME=docker-rust-hello

################################################################################
# Create a stage for building the application.

FROM rust:${RUST_VERSION}-alpine AS build
ARG APP_NAME
WORKDIR /app

# Install host build dependencies.
RUN apk add --no-cache clang lld musl-dev git

# Build the application.
# Leverage a cache mount to /usr/local/cargo/registry/
# for downloaded dependencies, a cache mount to /usr/local/cargo/git/db
# for git repository dependencies, and a cache mount to /app/target/ for
# compiled dependencies which will speed up subsequent builds.
# Leverage a bind mount to the src directory to avoid having to copy the
# source code into the container. Once built, copy the executable to an
# output directory before the cache mounted /app/target is unmounted.
RUN --mount=type=bind,source=src,target=src \
    --mount=type=bind,source=Cargo.toml,target=Cargo.toml \
    --mount=type=bind,source=Cargo.lock,target=Cargo.lock \
    --mount=type=cache,target=/app/target/ \
    --mount=type=cache,target=/usr/local/cargo/git/db \
    --mount=type=cache,target=/usr/local/cargo/registry/ \
cargo build --locked --release && \
cp ./target/release/$APP_NAME /bin/server

################################################################################
# Create a new stage for running the application that contains the minimal
# runtime dependencies for the application. This often uses a different base
# image from the build stage where the necessary files are copied from the build
# stage.
#
# The example below uses the alpine image as the foundation for running the app.
# By specifying the "3.18" tag, it will use version 3.18 of alpine. If
# reproducability is important, consider using a digest
# (e.g., alpine@sha256:664888ac9cfd28068e062c991ebcff4b4c7307dc8dd4df9e728bedde5c449d91).
FROM alpine:3.18 AS final

# Create a non-privileged user that the app will run under.
# See https://docs.docker.com/go/dockerfile-user-best-practices/
ARG UID=10001
RUN adduser \
    --disabled-password \
    --gecos "" \
    --home "/nonexistent" \
    --shell "/sbin/nologin" \
    --no-create-home \
    --uid "${UID}" \
    appuser
USER appuser

# Copy the executable from the "build" stage.
COPY --from=build /bin/server /bin/

# Configure rocket to listen on all interfaces.
ENV ROCKET_ADDRESS=0.0.0.0

# Expose the port that the application listens on.
EXPOSE 8000


# Install necessary dependencies for Rust and SAFE Network binaries
USER root
RUN apk add --no-cache \
    curl \
    gcc \
    libc-dev \
    libffi-dev \
    openssl-dev \
    pkgconfig \
    rust \
    cargo


# Install SAFE Network binaries using the install script
RUN curl -sSL https://raw.githubusercontent.com/maidsafe/safeup/main/install.sh | sh && \
    source ~/.config/safe/env && \
    safeup client && \
    safeup node && \
    safeup update

# Clean up unnecessary dependencies and caches
RUN apk del \
    curl \
    gcc \
    libc-dev \
    libffi-dev \
    openssl-dev \
    pkgconfig \
    cargo

USER appuser

# Specify the default command to run when the container starts
CMD ["sh"]

hmmmm - docker containers are built in layers

so if you first do a

RUN apk add --no-cache
curl
gcc
libc-dev
libffi-dev
openssl-dev
pkgconfig
rust
cargo
RUN curl -sSL https://raw.githubusercontent.com/maidsafe/safeup/main/install.sh | sh &&
source ~/.config/safe/env &&
safeup client &&
safeup node &&
safeup update

and after that do a

RUN apk del
curl
gcc
libc-dev
libffi-dev
openssl-dev
pkgconfig
cargo

the last RUN will not reduce the image size but increase it further

every line in the docker file is one layer that gets added … to make the docker file smaller you will need to include all the install/remove-steps in one single RUN line concatenated by &&

ps: sorry if that was known anyway xD … just thought i’d mention

1 Like

That’s what happens when you bash together a tutorial and some good old chatGPT, I suppose…

Thanks!

Known to a point … :pray:

1 Like

Update

Finally got a few hours to have a look at this…
Gee I thought docker would be easier…
Anyway
Got an image up at
stout777/safenode
2 images running on my Synology, one with --upnp and one with --home-network to test
I’ll report back

5 Likes