docker

Run Portainer on Synology

NAS Feb 15, 2023

Synology and Portainer are a perfect match, and these two combined will give you easy docker management. This guide will help you set up portainer on Synology to get control and easy management of your docker environment. Portainer is a web-based UI management tool.

Prerequisites

For this guide, there are several prerequisites.

You must have installed docker and completed the Docker Network Configuration guide to complete this guide. The docker network which is required to exist is the system network. Please consult the IP plan in the mentioned guide and create the system network as outlined in the manual. This guide will use the information of the earlier mentioned guide when it comes to the IP plan and the network’s name. Here is the direct link to the command to create the mentioned docker network.

Overview

So we are going to run Portainer using docker-compose. But overall,

Synology comes with docker-compose support. You can use Portainer to manage and deploy your docker services. But to set it up, it does require SSH access. Once Portainer is up and running.

Furthermore, as mentioned in the prerequisites, I’m deploying this to a docker network called a system. This is the docker network I defined for system-wide services. It also allows for the isolation of services if required. And organize them neatly.

One of the things we will be doing is deploying the container also with its own static IP, this makes using reverse proxy a lot easier.

We will also use a docker-compose technique that will allow us to organize our variables. This is called a dotenv file. The filename is .env in the same folder as where the docker-compose.yml is stored. It will automatically be read by docker-compose when the command is used.

Pre-setup Portainer on Synology

For the pre-setup, we require two things, the docker network system must be created. Here is the link directly to the command.

Secondly, we are going to create the administrator password. Yes, it’s possible to use the setup wizard. So why would you like to make the administrator password beforehand? Well, here is the reason when you are running services for a very long time. And if you are not using a Password Manager (I’m also writing a post for this), it’s possible to forget the password, or you just want to cycle it regularly. You always want to maintain your setup and settings, so I’ve just prepared a way for you to reset the password. The procedure for this is listed below. Here is the link for the password reset. Always think ahead in IT.

  1. Login to your Synology with SSH
  2. Run the following command to create your password; run as root if you didn’t use my guide to set up a docker group. Replace PASSWORD with the password you want to use for the administrator account. (Keep the quotes).
    This will generate a password hash of your password. It will look something like this.
docker run --rm httpd:2.4-alpine htpasswd -nbB admin PASSWORD | cut -d ":" -f 2

This will generate a password hash of your password. It will look something like this.

$2y$05$GPowSkFdoO9HpkDEdCE9i.ZAI.qTkXxjc/QyVg3ho3nhoM0E9AG0m

Setup Portainer on Synology

We are ready to get everything started.

  1. Login to your Synology with SSH
  2. Go to /volume1/docker
  3. Run the following command to create the directories required
mkdir -p /volume1/docker/system/portainer/data

Now we are going to create the dotenv file which holds our administrator password. I recommend using Visual Studio Code to edit and write these files on your NAS. You can read here how to connect with VS Code to your NAS here.

Create the following file /volume1/docker/system/portainer/.env. The contents are listed below. Please replace the hash with the password hash you created earlier.

.env
PORTAINER_PASSWORD=$2y$05$GPowSkFdoO9HpkDEdCE9i.ZAI.qTkXxjc/QyVg3ho3nhoM0E9AG0m

Next up is the creation of the docker-compose.yml file for the portainer. Please create /volume1/docker/system/portainer/docker-compose.yml with the contents below.

So the networks part attaches a network to the docker-compose services, in the configuration we are using it links to our earlier created system network. And we tell docker-compose not to do anything with it because we have created it outside of this docker-compose stack. Therefore we mark it as external.

Now it gets a little more complicated. So command is a key where we are able to give additional parameters to the application running in the container. In this case, we are providing it with our password hash. As you can see it only shows the variable name ${PORTAINER_PASSWORD} because docker-compose will auto-replace it with the value from the .env file. The second parameter we are giving is the location of the docker socket. This way portainer can talk to the docker daemon.

Next up are the labels just so that you can use the watchtower container to update it. If so desired. More in a later article.

Now we are getting to the fun stuff. networks. The network’s key allows you to link a network, in this case, the network system (You can have multiple named networks in here with multiple IPs) and we are giving it a static IP address of 172.20.0.2. Why this address? Because when creating the docker network we defined 172.20.0.1 as the gateway for the network. And because managing docker is important, I decided to give it the next IP.

Besides the static IP, we are also mapping the port of portainer 9000 from inside the container to our Synology at port 9000. This will allow us to access the portainer from our local network by using the IP number of Synology. I have my Synology in my network at the IP address 192.168.0.5. This allows me to access portainer using the following address: http://192.168.0.5:9000.

Well, why also use port mapping? You might not want to expose this service to the internet with a reverse proxy. Some things are better left of access through a VPN on a local network.

VolumesIn my earlier post about how to organize docker, I talked about volume mounts and why they are essential. We will provide this container with three volume mounts: one special, a normal one, and our timezone. A volume mount consists of 2 parts: a host part and a container part. Remember, if you are unfamiliar with docker containers, they are miniature computer systems. A colon separates these 2 parts. :. The timezone of the Synology is mapped through a volume as read-only. This will allow your portainer to always be in the correct timezone.

The special one is the first configured. This mounts the docker socket, which allows speaking to the docker daemon (dockerd) from the Synology host: /run/docker.sock into the container at the location /var/run/docker.sock. So when the portainer application goes to /var/run/docker.sock inside the container where it’s running, it’s talking to the docker socket on the Synology in the location /run/docker.sock.

The second volume mount is to mount a directory on our Synology inside the container where Portainer can store its configuration and data. This allows us not to lose any data when the container is destroyed, restarted, or recreated.

Please note that the container’s location where the application is saving its configuration differs for each container. Always consult a specific container’s documentation to learn its persistent data storage path.

Final part, logging I have included a logging configuration, which I use for all containers running on a Synology. This logging configuration limits the amount of data a container is logging. Without these constraints over time, logging can cause actual data build-up. Depending on how long the container is running and how much it logs.

This configuration sets the format to JSON, including data and time. It limits the logging to 3 files of 10 MegaByte per file. So Portainer will never exceed 30 MB of logging, Which I find acceptable.

Configuring the logging parameter is very important. I had some containers running and needed them to be online fast. So, I skipped the logging configuration. These containers were running with an uptime of over 3 years. I forgot to configure it properly. After doing some maintenance and reviewing the various docker configurations, I forgot it.

I fixed it and ran a cleanup on my system. It released 140GB of storage because it logged for 3 years.

Never bring a container online without logging in to the configuration. If you forget, you will pay for it later in some way.

You can read more about how to organize docker on your Synology here.

Start Portainer on Synology

Finally, we have everything in place. Here is a checklist to ensure you have everything.

  1. Docker network called system with IP range: 172.20.0.0/16, you can view the docker networks you have with the command docker network ls.
  2. A directory for portainer: /volume1/docker/system/portainer
  3. A directory for storing the data of Portainer: /volume1/docker/system/portainer/data
  4. A dotenv file .env with the password hash: /volume1/docker/system/portainer/.env
  5. A docker-compose file: /volume1/docker/system/portainer/docker-compose.yml

Docker Compose Content

version: '3.9'

networks:
  system:
    external: true

services:
  system.portainer:
    image: ${REGISTRY}/portainer/portainer-ce:2.19.4
    container_name: system.portainer
    hostname: portainer
    restart: unless-stopped
    mem_limit: 128m
    mem_reservation: 48m
    cpu_shares: 128
    command: --admin-password '${PORTAINER_PASSWORD}' -H unix:///var/run/docker.sock
    security_opt:
      - no-new-privileges:true
    networks:
      system:
        ipv4_address: 172.20.0.2
    sysctls:
      - net.ipv6.conf.all.disable_ipv6=1
    ports:
      - 9000:9000
    volumes:
      - /etc/localtime:/etc/locatime:ro
      - /run/docker.sock:/var/run/docker.sock
      - /volume1/docker/system/portainer/data:/data
    logging:
      driver: json-file
      options:
        max-file: "3"
        max-size: "10m"

Now, in your SSH terminal, go to the directory of portainer. (/volume1/docker/system/portainer), and you can start the service with the following command.

docker-compose up -d

The -d parameter is for detach, this will put the container running in the background. Now you can access portainer from your browser with http://<IP_MYNAS>:9000 Because my NAS is running on an IP 192.168.0.5 I can access it with http://192.168.0.5:9000.

Configure Portainer for the first time

When you connect with your browser to your portainer you will be presented with a login screen. You can log in with the username admin and your previously generated password. Secondly, because we already provided the docker host to use with the command parameter, there is no need to configure the portainer any further. It will have configured itself completely, and the portainer is now ready.

If you have never used portainer, click on the pimary environment and look around your docker environment. Have fun.

Password Reset

Oh, help! You have lost your portainer’s password and want to reset it. Well, luckily, we prepared for this case. So, the first thing we do is to create a new password. Replace PASSWORD with your new password. I advise against using the <SPACE> character in your password.

docker run --rm httpd:2.4-alpine htpasswd -nbB admin PASSWORD | cut -d ":" -f 2

This will give you a new password hash. Now edit the dotenv file /volume1/docker/portainer/.env and replace the old password hash with the new one you just created.

We have now replaced the password hash. So now we need to restart the container to make the new password active. Go to /volume1/docker/system/portainer and give the following command. Please note that if you have not set the docker group from my post: Managing docker without sudoYou will need to run this as root.

docker-compose up -d --force-recreate

This will recreate the container and load the new password hash from your .env file. You can now log in to portainer with your username and newly created password.

Documentation

If you need more documentation, you can just read the official Portainer documents here.

Tags