A Complete Guide to Installing and Securing Portainer on Ubuntu 20.04 and Up

Written by:

Introduction

Portainer is a powerful, lightweight container management platform that provides an intuitive web-based interface for managing Docker environments. Originally designed solely for Docker, Portainer has evolved to support multiple container environments including Docker Swarm, Kubernetes, and Azure Container Instances. It significantly reduces the learning curve for Docker management by eliminating the need to memorize complex command-line instructions.

Portainer is available in two editions:

  • Community Edition (CE): Free and open-source, designed primarily for individual use and home labs
  • Business Edition (BE): Offers extended features like advanced role-based access control and registry management for enterprise environments

This guide focuses on the Community Edition, which provides robust features suitable for most users while requiring minimal system resources.

Instruction layout/chart

Prerequisites

Hardware Requirements

Portainer is remarkably lightweight:

  • CPU: 1 core (minimum)
  • RAM: 1 GB (minimum)
  • Storage: 10 GB available space for Docker and Portainer
  • Network connectivity: Internet access for pulling Docker images

Software Requirements

To successfully install and run Portainer, you’ll need:

  • Ubuntu 20.04 LTS or newer (this guide is tested on Ubuntu 20.04 and 22.04)
  • Current system packages (we’ll update these during installation)
  • Terminal access with sudo privileges

Network Requirements

Portainer requires specific ports to be accessible:

  • Port 9443: For secure HTTPS access to the Portainer web interface (default)
  • Port 8000: For the Edge agent communication (only if using Edge compute features)
  • Port 9000: For HTTP access (optional, mainly for legacy compatibility)

User Permissions

You’ll need a user account with sudo privileges for installation. Following security best practices, we’ll avoid using the root account directly.

Step 1: Update Your System

Before beginning any installation, ensure your system is up-to-date with the latest security patches and package versions.

sudo apt update && sudo apt upgrade -y

This command updates your package lists and upgrades all installed packages to their latest versions. If prompted for a restart after updating, reboot before continuing.

Step 2: Install Docker Engine

Portainer requires Docker Engine to function. If you already have Docker installed, verify it with docker --version and skip to Step 3.

Remove any conflicting packages

sudo apt-get remove docker docker-engine docker.io containerd runc -y

This ensures a clean slate by removing any older or conflicting versions.

Install required dependencies

sudo apt install apt-transport-https ca-certificates curl gnupg lsb-release -y

These packages allow apt to use repositories over HTTPS, work with certificates, and fetch Docker’s official GPG keys.

Add Docker’s official GPG key

curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg

This downloads Docker’s GPG key and stores it for package verification, ensuring the packages you install are authentic.

Set up the Docker repository

echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

This adds the official Docker repository to your system’s sources list, automatically detecting your system architecture and Ubuntu version.

Update package lists with the new repository

sudo apt update

This refreshes your package lists with the newly added Docker repository.

Install Docker Engine

sudo apt install docker-ce docker-ce-cli containerd.io -y

This installs the Docker Engine, CLI, and containerd runtime.

Start and enable Docker service

sudo systemctl start docker
sudo systemctl enable docker

These commands start the Docker service and configure it to start automatically when the system boots.

Verify Docker installation

sudo systemctl status docker

This checks that Docker is running properly. You should see output indicating that the service is active (running).

Add your user to the Docker group

sudo usermod -aG docker $USER

This adds your current user to the Docker group, allowing you to run Docker commands without using sudo. This change will take effect after you log out and log back in, or apply it immediately with:

newgrp docker

Test Docker functionality

docker run hello-world

This pulls and runs the hello-world image. If successful, you’ll see a message indicating that Docker is properly installed and your user has the appropriate permissions.

Step 3: Install Portainer

Now that Docker is installed and running, we can proceed with installing Portainer. We’ll present multiple methods, allowing you to choose the one that best fits your needs.

Method 1: Standard Docker Installation

This is the simplest method, using basic Docker commands.

Create a persistent volume for Portainer data

docker volume create portainer_data

This creates a named volume that will store Portainer’s data, ensuring it persists even if the container is removed or updated.

Run Portainer 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 command runs the Portainer container with the following configuration:

  • -d: Runs the container in detached mode (in the background)
  • -p 8000:8000 -p 9443:9443: Maps container ports to host ports for web UI and Edge agent communication
  • --name=portainer: Names the container “portainer” for easy reference
  • --restart=always: Ensures the container automatically restarts if it stops or if Docker restarts
  • -v /var/run/docker.sock:/var/run/docker.sock: Mounts the Docker socket to give Portainer access to the Docker API
  • -v portainer_data:/data: Mounts the previously created volume to store Portainer data
  • portainer/portainer-ce:latest: Specifies the image to use (latest Portainer Community Edition)

Verify Portainer is running

docker ps | grep portainer

You should see the Portainer container listed with its status as “Up”.

Method 2: Docker Compose Installation

Docker Compose provides a more declarative way to deploy containers, making it easier to understand and maintain your configuration.

Install Docker Compose plugin (if not already installed)

sudo apt install docker-compose-plugin -y

This installs the Docker Compose plugin, which provides the docker compose command.

Create a directory for Portainer

mkdir -p ~/docker_data/portainer
cd ~/docker_data/portainer

This creates a directory structure for our Portainer deployment.

Create docker-compose.yml file

Create a docker-compose.yml file with proper configuration. Note: The exact content of this file was not fully provided in the original document.

Step 4: Access and Initial Setup

After installing Portainer, you need to access it and complete the initial setup.

Access the Portainer Web Interface

Open your web browser and navigate to:

https://YOUR_SERVER_IP:9443

Replace YOUR_SERVER_IP with your server’s IP address. You may see a security warning because Portainer uses a self-signed certificate by default. This is expected – you can proceed safely for initial setup.

Create the Admin User

On first access, you’ll be prompted to create an admin user:

  1. Enter a username (commonly “admin”)
  2. Create a strong password (at least 12 characters with a mix of uppercase, lowercase, numbers, and special characters)
  3. Click “Create User”

Connect to the Local Docker Environment

After creating the admin user, you’ll be prompted to connect to a Docker environment:

  1. Choose “Docker” as the environment type
  2. Select “Connect to local Docker environment” since we’re managing the Docker installation on the same machine
  3. Click “Connect”

You’re now ready to use Portainer to manage your Docker environment!

Step 5: Enhancing Security

Security is crucial for any container management system. Here are essential steps to secure your Portainer installation:

Enable HTTPS with a Proper SSL Certificate

For production environments, replace the self-signed certificate with a proper SSL certificate:

docker stop portainer
docker rm portainer
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 -v /path/to/certs:/certs portainer/portainer-ce:latest --ssl --sslcert /certs/portainer.crt --sslkey /certs/portainer.key

Replace /path/to/certs with the actual path to your certificate files.

Configure Firewall Rules

Restrict access to Portainer’s ports using UFW (Uncomplicated Firewall):

sudo ufw allow 22/tcp
sudo ufw allow 9443/tcp
sudo ufw enable

This allows SSH (port 22) and Portainer’s web interface (port 9443) while blocking other incoming connections.

Implement User Management

Once logged into Portainer:

  1. Go to “Settings” > “Users” to create additional users with appropriate permissions
  2. Create teams and assign users to them for more granular access control
  3. Use Role-Based Access Control (RBAC) to limit what different users can do

This follows the principle of least privilege, ensuring users only have access to the resources they need.

Step 6: Data Persistence and Backup

Proper data management ensures you can recover from failures and maintain continuity of your Portainer installation.

Creating a Backup of Portainer Data

To create a backup of your Portainer data:

docker run --rm -v portainer_data:/data -v $(pwd):/backup alpine sh -c "cd /data && tar -czf /backup/portainer-backup-$(date +%Y%m%d%H%M%S).tar.gz ."

This command creates a timestamped backup archive of your Portainer data in the current directory.

Scheduling Regular Backups

For automated backups, create a simple bash script and schedule it with cron:

cat > ~/backup-portainer.sh << 'EOF'
#!/bin/bash
BACKUP_DIR=~/portainer-backups
mkdir -p $BACKUP_DIR
docker run --rm -v portainer_data:/data -v $BACKUP_DIR:/backup alpine sh -c "cd /data && tar -czf /backup/portainer-backup-$(date +%Y%m%d%H%M%S).tar.gz ."
find $BACKUP_DIR -type f -name "portainer-backup-*.tar.gz" -mtime +7 -delete
EOF

chmod +x ~/backup-portainer.sh
(crontab -l 2>/dev/null; echo "0 2 * * * ~/backup-portainer.sh") | crontab -

This sets up a daily backup at 2:00 AM and retains only the seven most recent backups.

Restoring from Backup

To restore Portainer from a backup:

  1. Stop the Portainer container:
docker stop portainer
  1. Remove the existing volume (caution: this will delete all current Portainer data):
docker volume rm portainer_data
docker volume create portainer_data
  1. Restore data from your backup:
docker run --rm -v portainer_data:/data -v /path/to/backup/directory:/backup alpine sh -c "cd /data && tar -xzf /backup/your-backup-file.tar.gz"

Replace /path/to/backup/directory and your-backup-file.tar.gz with the actual backup directory and file name.

  1. Restart Portainer:
docker start portainer

Step 7: Common Problems and Troubleshooting

Even with careful installation, issues can arise. Here are solutions to common problems:

Connection Refused Errors

Problem: Unable to connect to Portainer web interface.

Diagnostic command:

curl -kI https://localhost:9443

Solutions:

  • Verify Portainer is running: docker ps | grep portainer
  • Check if the correct ports are being exposed: docker port portainer
  • Ensure your firewall allows connections to port 9443: sudo ufw status
  • If using a different port, make sure you’re accessing the correct one

Certificate Issues

Problem: SSL certificate errors when accessing Portainer.

Solutions:

  • For development/testing: Add a security exception in your browser
  • For production: Use a proper SSL certificate as described in the security section
  • If using a custom certificate, verify it’s correctly formatted and not expired: openssl x509 -in /path/to/your/certs/portainer.crt -text -noout

Docker Socket Permission Issues

Problem: Portainer cannot connect to Docker daemon, often showing “Error 500” messages.

Diagnostic command:

docker logs portainer

Look for messages related to permission denied on /var/run/docker.sock.

Solutions:

  • Ensure the Docker socket is properly mounted: docker inspect portainer | grep docker.sock
  • Check Docker socket permissions: ls -la /var/run/docker.sock
  • If necessary, adjust permissions (use with caution as this has security implications): sudo chmod 666 /var/run/docker.sock

Port Conflicts

Problem: Container fails to start due to port conflicts.

Diagnostic command:

sudo netstat -tulpn | grep -E '9443|8000'

Solutions:

  • Identify the process using the conflicting port: sudo lsof -i :9443
  • Stop the conflicting service or use different ports for Portainer: docker run -d -p 9444:9443 -p 8001:8000 --name=portainer --restart=always -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer-ce:latest

Browser Cache Issues

Problem: UI appears broken or outdated after updates.

Solutions:

  • Clear your browser cache
  • Try accessing Portainer in a private/incognito window
  • Use a different browser

Step 8: Maintenance Procedures

Regular maintenance ensures your Portainer installation remains secure and up-to-date.

Updating Portainer

To update Portainer to the latest version:

# For standard Docker installation
docker stop portainer
docker rm portainer
docker pull portainer/portainer-ce:latest
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
# For Docker Compose installation
cd ~/docker_data/portainer
docker compose pull
docker compose up -d

This process stops and removes the current container, pulls the latest image, and creates a new container with the same settings. Your data is preserved because it’s stored in the persistent volume.

Monitoring Portainer

To monitor Portainer’s resource usage:

docker stats portainer

For logs:

docker logs -f portainer

The -f flag follows the log output in real-time. Press Ctrl+C to exit.

Cleanup and Optimization

Regularly clean up unused Docker resources to prevent disk space issues:

  1. Remove unused containers: docker container prune -f
  2. Remove unused images: docker image prune -f
  3. Remove unused volumes (be careful, as this will delete data): docker volume prune -f

Security Auditing

Periodically review your Portainer security configuration:

  1. Check for outdated versions with known vulnerabilities
  2. Review user accounts and permissions
  3. Verify SSL certificate validity
  4. Check firewall rules
  5. Examine access logs for suspicious activity

Conclusion

You’ve now successfully installed, secured, and configured Portainer on your Ubuntu 20.04 or newer system. This powerful container management platform provides an intuitive interface for managing Docker environments, making it easier to deploy and maintain containerized applications. By following the security practices outlined in this guide, you’ve established a solid foundation for safe container management.

Regular maintenance tasks like backups, updates, and security audits will ensure your Portainer installation remains reliable and secure over time. As your containerized infrastructure grows, Portainer’s robust management capabilities will continue to simplify operations and enhance productivity.

Whether you’ve chosen a simple standalone installation or a more complex setup, you now have the knowledge to effectively manage and secure your Portainer environment. The comprehensive troubleshooting section should help you resolve any issues that might arise, ensuring smooth operation of your container management solution.


Discover more from DIYLABHub.com

Subscribe to get the latest posts sent to your email.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

google.com, pub-5998895780889630, DIRECT, f08c47fec0942fa0