How to setup Portainer on Linux
What is Portainer ?
Portainer is a lightweight and powerful open-source management UI for Docker, Docker Swarm, and Kubernetes. It simplifies container management by providing an intuitive web-based interface to interact with containerized applications and services. Portainer is designed to help both novice and experienced users manage their container environments more efficiently.
Usefulness
It is remarkably useful for most of the
To setup Portainer, we need the following things
- Running instance of Docker
- sudo access on the machine
- By default, Portainer Server will expose the UI over port
9443
.
If you do not have Docker installed yet, check out this blog to install Docker first.
Deployment
Portainer
First, create the volume that Portainer Server will use to store its database
docker volume create portainer_data
Then, download and install the Portainer Server container
docker run -d -p 8000:8000 -p 9443:9443 --name portainer --restart=always -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer-ce:latest
This will start the portainer docker container. But this is not all, we also need a reverse proxy, if we need to setup more services on the same Linux machine, and for that reverse proxy is indeed required in redirecting the incoming traffic to different services.
NGINX - Reverse Proxy
To setup the nginx, we can simply use run the following cmds
sudo apt install nginx
Then, simply start / restart the nginx service using
# To Start
sudo systemctl start nginx
# To restart
sudo systemctl restart nginx
# To check running status
sudo systemctl status nginx
once installed, we also need to configure the nginx. To do so, we edit the nginx conf file as follows
sudo nano /etc/nginx/conf.d/nginx.conf
Add the following lines
# COPY THIS TEMPLATE TO ADD MORE
server {
listen 80;
listen [::]:80;
root /var/www/html;
server_name <OUR_DOMAIN_NAME>;
}
and then press CTRL + o
followed by CTRL + x
to save it.
Next, anytime we make changes to the nginx config file, we can test whether the configuration we added seems to be legit or is there something nginx cannot understand. For that, we can test for nginx syntax errors using the following cmd
sudo nginx -t
If everything is correct, it will print out the following on the terminal
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
And when we are sure, we can reload the nginx service for the changes to take effect, using
sudo nginx -s reload
NoteIt is important to note that, until we reload the nginx, changes to the nginx config files are not reflected. So we need to reload the service everytime we make changes to the conf file.
Since we are setting up our own custom domain, we also need to setup SSL certificate such that the service is securely accessible over the https
protocol.
For that, we have two options :-
- Buy SSL certificate from a SSL certificate providers like Digicert
- Setup a Free certificate ourself using tool
certbot
provided by "Let's Encrypt"
We will go with the Free certificate route here, but also explain in the end, how we can simply use the certificates obtained from SSL providers like Digicert etc,
SSL certificate
Now, to setup SSL certificate, we first need a tool called certbot
. It is the official tool provided by Lets encypt to obtain SSL certificates easily.
To install, use this
sudo apt-get install certbot python3-certbot-nginx
Once installed, we can use certbot
to issue an SSL certificate for our custom domain. We can also specify that it installs the issued certificate in our reverse proxy nginx.
certbot --nginx -d <OUR_DOMAIN_NAME>
Note, the domain is exactly the same which we used in the nginx configuration.
The flag --nginx
provided to the certbot
will read the nginx configuration file, and check if there exists any config for the domain for which SSL certificate request is issued. If found, certbot
automatically edits the nginx config file to add the certificate path.
So, we will see that the nginx configuration now changes and looks like this
server {
root /var/www/html;
server_name <OUR_DOMAIN_NAME>;
listen [::]:443 ssl ipv6only=on; # managed by Certbot
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/<OUR_DOMAIN_NAME>/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/<OUR_DOMAIN_NAME>/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}
server {
if ($host = <OUR_DOMAIN_NAME>) {
return 301 https://$host$request_uri;
} # managed by Certbot
listen 80;
listen [::]:80;
server_name <OUR_DOMAIN_NAME>;
return 404; # managed by Certbot
}
But until now, we have not added the redirection of the incoming request to portainer service yet. That last part also needs to be added.
For that, lets edit the nginx config file one last time.
As can be seen above, certbot has created two sections in the nginx config file both starting with directive server
.
One section is for the https
requests while second section is for http
request.
On Top, the first server
directive is for the incoming request received on port 443
(basically the https
requests), while the second server
directive is for the request received on port 80
(the http
requests).
And upon closely inspecting the second directive, it simply redirects that same request to the https
part, that is on port 443
.
If that all is clear so far, we understand that we only need to add the redirection section under the https
(or to say at port 443
)only.
So, let's enrich the first server
directive to something which should look like this
server {
root /var/www/html;
server_name <OUR_DOMAIN_NAME>;
listen [::]:443 ssl ipv6only=on; # managed by Certbot
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/<OUR_DOMAIN_NAME>/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/<OUR_DOMAIN_NAME>/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
client_max_body_size 5G;
location / {
# Proxy pass to the service for local LAN IP
proxy_pass https://127.0.0.1:9443;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 1200;
}
}
So, we added that any request coming at the domain root will simply be forwarded (or to say proxied) to the service running at https:127.0.0.1:9443
NoteIt is very important to note that theproxy_passs
address in the above section ishttps
address, NOT thehttp
. Otherwise this will NOT work.
I've spent quite few hours already debugging such stupid mistakes.Also, line 12 actually allows files of size upto 5GB in size to be uploaded without nginx disconnecting the conneciton. Otherwise, the default size limit is simply 1 MB.
Finally, we can go to the custom domain we specified, to access the portainer instance, securely over the https
.
Conclusion
Portainer is not only easy to use, but also very easy to setup as well. It only takes max 20 minutes of your time if you know what you are doing.
Further reading
For further reading, please refer the official installation guide of Portainer documentation.