Portainer Docker Compose: FREE & MUST-HAVE Container Manager

Portainer is a free and powerful container manager. This guide shows you how to easily set it up using Portainer Docker Compose.

Managing containers may not be easy for you, especially if you run Kubernetes or minikube. This is where Portainer can come in handy.

Portainer is the most popular container management platform in the world with over 1 million users.

For homelab and self-hosting enthusiasts like myself, Portainer is a must-have app and a key service in my Docker media server.

It makes managing docker containers, setting up stacks, or even destroying them a breeze. You can even use Docker Compose inside Portainer. It allows you to write YAML files and add manifests for Docker applications. You can deploy, configure, troubleshoot, and secure Docker images with Portainer more easily within a user interface.

Portainer is the top app in our list of best Docker containers.

In this guide, I will present a Portainer Docker-Compose file that I use in all of my stacks.


First, a few frequently asked questions before we setup Portainer using Docker-Compose.

Can I use Docker Compose in Portainer?

Yes, Portainer allows users to manage Docker Compose files directly from the user interface. Users can easily deploy and manage Docker Compose services using Portainer's web-based interface.

What version of Docker Compose does Portainer use?

The version of Docker Compose used by Portainer depends on the version of Docker installed on the host machine. Portainer is compatible with all versions of Docker Compose, from version 1 to the latest version.

What is the difference between Docker Compose and Portainer?

Docker Compose is a tool for defining, deploying, and running multi-container Docker applications. Portainer, on the other hand, is a management tool for Docker environments. It provides a user-friendly interface for managing Docker containers, images, volumes, and networks.

Should I use Portainer with Docker?

Yes, using Portainer with Docker can make it easier to manage your Docker environments (even multiple), particularly if you have multiple Docker environments to manage. Portainer provides a user-friendly interface that simplifies the management of Docker containers, images, volumes, and networks.

Portainer Docker Compose Setup

Whether you run a network using Swarm or Nomad or have a lot of containers from experimentation, Portainer is the most popular container manager for Docker images. It can run on any cluster. It can run as Linux container or Windows native container.

In this Portainer docker install guide, we will use the free Community Edition. Even though it is free, it still is a very powerful way to manage containers, images, volumes, networks, and more.

We have previously shown how to install Portainer using the docker run accommand. But, having used Docker for over 5 years (and being a person of non-IT background), I strongly suggest you take the time to learn Docker compose and build your stack using it.

Docker Compose gives you portability between systems. I can use the docker-compose files from my GitHub repo in my Ubuntu Server on Proxmox, my Ubuntu Server VPS on Digital Ocean, or even my Synology NAS and they will work the same.

What do you use (or plan to use) Portainer for?

View Results

Loading ... Loading ...

1. Prepare to Setup Portainer Using Docker

If you already have docker and docker-compose installed, and have setup your .env file then skip to Docker Compose for Portainer section below.


First, let us start with some requirements. I won't go into a lot of details as these have been covered in detail in my Docker Media Server guide. Here is a summary of the requirements before Proceeding.

Setting Up The Docker Environment

This is also explained in detail in my Docker Guide. We are going to customize a few things with Docker before building the Portainer Docker Compose file.

First, is the folder structure. I like to house all of the docker-related files and folders in one location. I call it the Docker Root Folder. Our docker-compose.yml, .env files, etc. will be located in this folder, as shown below.

Docker Media Server Folder Structure
Docker Media Server Folder Structure

In addition, all of Portainer's data will go into the appdata/portianer folder. For this guide, you do not need to worry about the remaining folders in the above screenshot.

Create the .env file

First, the dot in front of env is not a typo.

It is a hidden file that will store some of the key information we may use (environmental variables) repeatedly. In the docker root folder (explained above), create the .env file and add the following contents to it.


Customizing the above variables is explained in detail in my Docker guide, along with the right permissions to set (very important!).

In short, TZ is the timezone, and DOCKERDIR is the docker root folder mentioned above.

In addition, replace anand with your username.

2. Create the Base Portainer Docker Compose File

Before we go ahead and add the Docker Compose for Portainer, we will have to add a few basic elements to the compose file. Once again, this is all explained in detail in my Docker tutorial. But here is a summary of it.

Note that spacing and indentation are crucial in YAML files. Therefore, pay attention to the formatting when you copy-paste and customize the Portainer Docker Compose snippet.

In your Docker Compose file, if you do not already have it, add the following:

version: "3.9"

########################### NETWORKS
    driver: bridge

########################### SERVICES

We are specifying the version of Docker Compose reference to use and the default Docker bridge network. If you do not know what these are, do not worry.

We are going to make Portainer accessible using the Docker Host machine's IP, using Portainer's default port (e.g. For this purpose, the above network block is sufficient.

3. Docker Compose for Portainer

Here is the Docker-Compose for Portainer that I use. Add it right under services (pay attention to indentation):

  # Portainer - WebUI for Containers
    container_name: portainer
    image: portainer/portainer-ce:latest
    restart: unless-stopped
      - default
    command: -H unix:///var/run/docker.sock 
      - "9000:9000"
      - /var/run/docker.sock:/var/run/docker.sock:ro 
      - $DOCKERDIR/appdata/portainer/data:/data 
      - TZ=$TZ
You may find that the Docker Compose examples in my GitHub repo differ from the above. What is shown above is an example that is good for beginners to get started with. What is in my GitHub repo is my current setup with many features and security enhancements.

Customizing Portainer Docker Setup

Here are some notes to understand and customize the above Portainer docker-compose example:

  • We are using latest portainer/portainer-ce docker image.
  • Portainer will belong to the "default" network. This is fine for now. For advanced configurations, keep reading.
  • In the ports section, we are exposing port 9000 to the host, which is the default Portainer port. Therefore, Portainer will be available on the Docker host IP at port 9000. For example, my Docker host has an IP of So Portainer will be available at
  • Under volumes, we are mapping a persistent volume for Portainer to store its data. Make sure $DOCKERDIR is defined in .env file.
  • In the volumes section we are also passing the Docker socket from the host machine to Portainer container. This is a minor security risk. If Portainer is compromised then the attacker could gain control of the host system. Although not urgent, once you have your stack well established, I strongly recommend using Socket Proxy as described in my Docker best security practices article.
  • Finally, also ensure that variable $TZ is defined in the .env file.

Customizing Network

In the above Portainer Docker Compose file, we set the network as default. This is fine.

Alternatively, you can specify the Portainer Docker container to use the host network. In this case, Portainer functions as if it were running natively on your host system. This requires all necessary ports to be free (e.g. 9000). To enable host networking, use the following block instead of networks:

    network_mode: 'host'

In addition, you will also need to remove the ports section. Portainer should be available at, which is the same URL as the default Portainer docker compose setup shown previously.

If for whatever reason, port 9000 is not free, you could specify a custom port on the host side (e.g. 9001:9000) or take a look at macvlan networking for docker.

4. Start Portainer

After customizing the Portainer Docker Compose file, you can start Portainer using the following command:

sudo docker compose -f ~/docker/docker-compose.yml up -d

Be sure to refer to my Docker guide to understand how you can follow the logs to check the start-up of the Portainer docker container. You may use Dozzle logs viewer for real-time logs viewing.

If all goes well, in a few minutes you should be to access Portainer using one of the URLs listed previously.

Portainer Docker Compose Setup - Login Page
Portainer Docker Compose Setup - Login Page

5. Accessing Portainer Over The Internet

Accessing Portainer from within your home network should work fine (described above). But what if you want access to Portainer on the go from outside your home network?

Well, there are many ways to do this.

The easiest and NOT RECOMMENDED way to do this is to forward port 9000 on your router/gateway to point to your Portainer servers IP address.

Accessing Portainer with VPN

A secure way to access Portainer is to connect to your home network using a VPN service. Home routers and network-attached storage devices sometimes come with a built-in VPN server. Once connected, you can use the same home network IP address of your Portainer Docker server.

You may also use a third-party VPN mesh network such as Tailscale or Zerotier-One. I use ZeroTier to tie all my key machines together in a virtual network. My Docker host is part of this network. Therefore, while on the go, I can use my Docker host's ZeroTier network IP address with Portainer's port number.

Another alternative is to set up your own Wireguard network. But this is a more advanced topic.

Other Posts in the Wireguard Series:

Exposing Portainer with Reverse Proxy

Another secure way to access Portainer is to put it behind a reverse proxy. But this requires a domain name or a DDNS.

Nginx Proxy Manager is very simple to setup but not very flexible.

I use and recommend Traefik. You can read all about setting it up in my Docker Traefik guide or refer to my GitHub repo.

With a reverse proxy, you can access Portainer using a nicer URL (e.g. https://portainer.example.com).

6. Securing Portainer

Portainer comes with an internal authentication (the default login page). For something as powerful as a Portainer, I highly recommend better security with multifactor authentication. This can be achieved in many ways.

This is where the power of Traefik over Nginx Proxy Manager becomes evident. You could integrate Google OAuth or Authelia Self-hosted MFA, very easily.

Alternatively, you could use Portainer's built-in OAuth or LDAP (or Microsoft Active Directory with a Pro plan).

Portainer Authentication Methods
Portainer Authentication Methods

Once configured, you will have the option to login using internal authentication or OAuth.

Conclusions: Portainer on Docker

Portainer is one of the first apps I install while building a docker stack. It is a powerful container manager and the open-source community has been awesome in developing it fast. You cannot install it natively on the OS.

But Docker makes it much easier to install Portainer CE, and Docker Compose simplifies it even more. With the included Docker Compose for Portainer and easy steps to setup Portainer, you should be up and running in just about 5 minutes.

So if you are new to docker or just need a GUI to manage your container environment, go ahead and use the included Portainer docker-compose.

Be the 1 in 200,000. Help us sustain what we do.
16 / 150 by Dec 31, 2024
Join Us (starting from just $1.67/month)


Anand is a self-learned computer enthusiast, hopeless tinkerer (if it ain't broke, fix it), a part-time blogger, and a Scientist during the day. He has been blogging since 2010 on Linux, Ubuntu, Home/Media/File Servers, Smart Home Automation, and related HOW-TOs.

Become a Member