Today I want to show how to manage your Docker containers with portainer . We use the portainer docker image, Apache2 as a reverse proxy, and we will secure our installation with LetsEncrypt.
Prerequisites:
– an Ubuntu VPS
– LAMP stack installed
– Reverse Proxy Module enabled in Apache2
– Docker installed
– certbot installed
– DNS-A record for our Apache2-vHost
If requirements are missing, of course we have to do this first.
LAMP stack:
sudo apt-get install lamp-server^
Enable reverse proxy modules:
sudo a2enmod proxy proxy_http proxy_ajp rewrite deflate headers proxy_balancer proxy_connect proxy_html proxy_wstunnel authz_core authn_core setenvif ssl
Docker:
Version from the official package sources:
sudo apt-get install docker.io sudo systemctl start docker sudo systemctl enable docker
or directly from Docker:
sudo curl -sSL https://get.docker.com/ | CHANNEL=stable sh sudo systemctl enable docker.service sudo systemctl start docker.service
Certbot:
sudo apt-get update sudo apt-get install software-properties-common sudo add-apt-repository ppa:certbot/certbot sudo apt-get update sudo apt-get install python-certbot-apache
Afterwards we can continue and put Portainer into operation.
Step 1: Run Portainer docker Image
With the following command we start the container on our server:
sudo docker run -d -p 9000:9000 --restart always -v /var/run/docker.sock:/var/run/docker.sock -v /opt/portainer:/data portainer/portainer
We check, if the container was started:
sudo docker ps
Portainer now listens on port 9000.
Step 2: Create Apache2 vHost
When the container is running, we create a vHost so we can use the reverse proxy functionality and call it in the browser without a port specification later:
sudo nano /etc/apache2/sites-available/003-portainer.conf
we add the following content:
<VirtualHost *:80> ServerName portainer.your-domain.tld </VirtualHost>
Save file, activate site and restart Apache2:
sudo a2ensite 003-portainer.conf sudo systemctl restart apache2
Now Portainer would already be accessible via http: //portainer.your-domain.tld. But we are working with password input, so we encrypt the connection with SSL.
we use Certbot:
sudo certbot --apache
Select the corresponding host and at the end select „2“ for „redirect“.
Now we have to edit the generated conf:
sudo nano /etc/apache2/sites-available/003-portainer-le-ssl.conf
and add the following block after ServerName
:
# Proxy to Portainer ProxyPreserveHost On ProxyPass / http://127.0.0.1:9000/ ProxyPassReverse / http://127.0.0.1:9000/ RequestHeader set X-Forwarded-Proto "https" ProxyVia Block <Proxy *> Require all granted </Proxy> # SSL Configuration - uses strong cipher list - these might need to be downgraded if you need to support older browsers/devices SSLEngine on SSLCipherSuite EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH SSLProtocol All -SSLv2 -SSLv3 -TLSv1 -TLSv1.1 SSLHonorCipherOrder On # HSTS (optional) Header always set Strict-Transport-Security "max-age=63072000; includeSubdomains;" # Prevent MIME based attacks Header set X-Content-Type-Options "nosniff" ErrorLog /var/log/apache2/portainer-error.log CustomLog /var/log/apache2/portainer-access.log combined #Proxy to docker container console <Location /api/websocket/> RewriteEngine on RewriteCond %{HTTP:UPGRADE} ^WebSocket$ [NC] RewriteCond %{HTTP:CONNECTION} Upgrade$ [NC] RewriteRule /api/websocket/(.*) ws://127.0.0.1:9000/api/websocket/$1 [P] </Location>
Save File and Restart Apache2 again.
sudo systemctl restart apache2
Step 3: Configure Portainer
via the browser of our choice we call https://portainer.your-domain.tld and must first assign a password for the admin:
In the next dialog we set the setting to „Local“:
click on the button „Connect“ and after a short time you will see the dashboard of portainer:
If we select „Container“, we can see more information about the individual containers or restart, stop, etc.:
Container details:
Update:
If you want to call Portainer in a subfolder of an existing vHost (as example: https://hostname.your-domain.tld/portainer/) than you have to add the following block to this conf:
<Location /portainer/> ProxyPass http://127.0.0.1:9000/ ProxyPassReverse http://127.0.0.1:9000/ RequestHeader set X-Forwarded-Proto "https" </Location> <Location /portainer/api/websocket/> ProxyPass http://127.0.0.1:9000/api/websocket/ ProxyPassReverse http://127.0.0.1:9000/api/websocket/ RewriteEngine on RewriteCond %{HTTP:UPGRADE} ^WebSocket$ [NC] RewriteCond %{HTTP:CONNECTION} Upgrade$ [NC] RewriteRule /api/websocket/(.*) ws://127.0.0.1:9000/api/websocket/$1 [P] </Location>
Don not forget to enable reverse proxy modules.
That’s it for today, have fun 🙂