Skip to content

Using Docker

Nicholas K. Dionysopoulos edited this page Jul 28, 2024 · 4 revisions

You can use Docker to run Panopticon. You can either use the published images (tagged as ghcr.io/akeeba/panopticon:latest), or build an image from source.

⚠️ The instructions on this page apply from version 1.2.0 onwards.

Note about Apache vs FrankenPHP

There are two flavours of the container: one using Apache as the web server (recommended), and one using FrankenPHP on Caddy as the web server.

The instructions in here assume that you are using the Apache flavour.

If you are using the FrankenPHP flavour please change /var/www/html to /app/public in all command lines and configuration file fragments you see in this documentation page.

Quick start

The main repository comes with a Docker Compose YAML file showing how you can set up a containerised Panopticon.

Why Docker Compose? The Docker image only contains the web server, php executable, and the Panopticon application. It does not contain a database server, but it requires one. You need some sort of container orchestration to provide the database server; we use Docker Compose as it's fairly simple.

First, copy the file .env.docker.dist to .env.docker, placed in the same directory as the Docker Compose YAML file. This is the configuration file for your dockerized Panopticon installation.

⚠️ You MUST edit your .env.docker file. At the very least, you need to change the password for the Superuser. The default password (admin) is insecure and will result in the setup failing. This is deliberate; we made it so that you need to change this information before launching Panopticon.

Running docker compose up -d will bring up the services. You can access Panopticon as http://localhost:4280. You will need to wait for a few seconds to a few minutes before Panopticon is ready.

The default username is admin, and the password is what you've set up in your .env.docker file.

Using other containerisation runtimes

We have only tested containerised Panopticon with Docker.

We don't see any reason why using a different runtime, e.g. Podman, wouldn't work, but we have not explicitly tested with anything else, therefore we cannot claim to officially support anything other than Docker.

Using other orchestration services

It is perfectly possible to use other container orchestration services instead of Docker Compose.

Just keep in mind that whatever you do, you must pass the environment variables you see in .env.docker to your Panopticon container. These variables tell it how to configure itself, where to find its database container, and how to create the initial Superuser you need to access Panopticon. All orchestration services do that, so it's not a big deal.

Customising and extending the Docker Compose file

Most of the customisation is possible by editing the environment variables in your .env.docker file.

If you want to change or add services, we strongly recommend using an override YAML file (docker-compose.override.yml) instead of editing the docker-compose.yml directly. The override files will be automatically excluded from being part of your Git working copy, and from being copied into the Docker image.

Configuration modes

Containerized Panopticon has two possible configuration modes:

  • Legacy (default). In this mode, a config.php file is created and updated inside the container. You can configure Panopticon using its System Configuration page, and by executing its CLI commands.
  • Environment (available since 1.2.2). In this mode there is no configuration file created. You configure Panopticon by passing environment variables to your container. You no longer have access to the System Configuration page. You can no longer use the CLI commands to change Panopticon's configuration.

The Legacy mode is recommended for most users as it's much easier to use. The downside is that if you delete your container you lose your configuration, and you cannot orchestrate the deployment with any kind of automated means.

If you want to persist your configuration even when your container is deleted and/or need to orchestrate an automatic deployment the Environment mode is for you.

Using the Legacy configuration mode

This is the default mode. You do not need to do anything to use it.

As long as the PANOPTICON_USING_ENV environment variable is not set, or set to anything other than 1, this will be the configuration mode used by containerised Panopticon. This is, indeed, the default.

Technically, you could use the Legacy mode with a .env file instead of a config.php file. However, it does not make sense given that the Environment configuration mode is available since version 1.2.2.

Using the Environment configuration mode

ℹ️ This feature is available since version 1.2.2.

To use the Environment configuration mode you need to change the PANOPTICON_USING_ENV value to 1 in your .env.docker file:

PANOPTICON_USING_ENV: 1

When you are using the Environment configuration mode you need to put your Panopticon configuration environment variables in your .env.docker file.

At the very least, you need to set up an application secret. You can create a new, random secret and put it in the PANOPTICON_SECRET line of your configuration file:

PANOPTICON_SECRET: "9jWwzaDck4kA9RW6uu8bK6qqdTW9euRS"

For all other configuration options, please refer to the .env.dist file in the GitHub repository.

Using published images instead of building from sources

The default setup of the php service is to build Panopticon from sources. If you would rather use the published images you need to remove the build key from the service and add the image key to it. This is recommended for production deployment.

The way to do this in an override file, e.g. docker-compose.override.yml, is like so:

version: "3.5"

services:
  php:
    build: !reset null
    image: ghcr.io/akeeba/panopticon:latest

Volumes

The Docker Compose YAML file defines three Docker volumes:

  • panopticon_mysql This is mounted onto the database server's container, containing the MySQL data directory.
  • panopticon_usercode This is mounted onto the application's user_code directory, used for advanced customisation. You don't need to override its location unless you are going to provide user code, custom CSS, template overrides, etc.
  • panopticon_config This is mounted onto the application's config folder which is where Panopticon expects to find config.php or .env configuration files when running containerised.

❗ When running Panopticon outside of Docker, it expects its configuration files to be in the root folder of its installation. When running Panopticon inside Docker, it expects its configuration files to be in the config folder. This lets us place the configuration in a separate volume, therefore allow it to survive updates. The magic happens in the defines.php file when defining the APATH_CONFIGURATION PHP constant and is based on the existence of the src/.not_docker file.

The idea behind using volumes is that mutable, user-defined data is stored separately to the application itself, allowing it to survive updates and/or rebuilds.

You don't have to limit yourself to the volumes we have defined. If you want, you can create your own volumes to override folders in the container. For example, you may want to create volumes for the cache, log, and tmp folders as well. To do that, you will have to do service overrides in your Docker Compose override YAML file, e.g. docker-compose.override.yml. For example:

# This example only works with the Apache variant
services:
  php:
    volumes:
      - panopticon_cache:/var/www/html/cache
      - panopticon_log:/var/www/html/log
      - panopticon_tmp:/var/www/html/tmp

Please note that due to the way Docker parses override files, the volumes defined in the override are added to the ones defined in the main Docker Compose file. If you want to replace the volumes you need to use the !override flag as explained in Docker's documentation.

Finally, a note on what becomes very obvious in hindsight, but it's easy to miss at first. If you want to do a complete reset of your Panopticon installation, losing all data, you MUST remove the created volumes, not just the containers.

Bind mounts

If you would rather use bind mounts instead of volumes, you will have to do service overrides in your Docker Compose override YAML file, e.g. docker-compose.override.yml. For example, this overrides all three standard volumes:

# This example only works with the Apache variant
services:
  php:
    volumes:
      - type: bind
        source: ./data/user_code
        target: /var/www/html/user_code
      - type: bind
        source: ./data/config
        target: /var/www/html/config
  mysql:
    volumes:
      - type: bind
        source: ./data/db
        target: /var/lib/mysql

Bind mounts make most sense for the user_code folder, and maybe the config folder. The former lets you work with advanced overrides very easily, the latter allows you to back up your Panopticon configuration which along with a database backup make for a complete backup of your installation.

FrankenPHP with Caddy

We provide an alternate Docker Compose file which uses FrankenPHP and Caddy instead of PHP-FPM and Apache.

While this should provide much better performance, especially if you have hundreds of sites, it's not as thoroughly tested as the standard variant using PHP-FPM and Apache. We consider it experimental. Use at your own risk.

Kindly note that if you do use this variant, you should replace /var/www/html with /app/public in all examples and instructions you see on this page.

TLS termination

The Docker images do NOT come with HTTPS set up. You will have to use your own TLS terminator, e.g. an NginX service configured as a reverse proxy, perhaps with Let's Encrypt (certbot) providing the TLS certificates.

In this case, the web server will not be seeing that it's running under HTTPS because, technically, the web server is serving everything under plain old HTTP. This will cause a "mixed content" warning on your browser.

To avoid this problem you must set Panopticon's live_site configuration variable to use the HTTPS schema. For example, let's assume that you are hosting Panopticon at panopticon.example.com.

If you are using the Legacy configuration method, edit your config.php and change the $live_site line to $live_site = 'https://panopticon.example.com/'; Note that this requires editing a file in your container.

If you are using the Environment configuration method set the PANOPTICON_LIVE_SITE line to PANOPTICON_LIVE_SITE=https://panopticon.example.com/

Remember to restart the container after making a configuration change.

Email

The default dockerized installation of Panopticon comes with email disabled.

If you are using the Legacy configuration method you need go to Administration, System Configuration to configure and enable email sending. Since you are running inside a container we strongly advise that you use SMTP with an external SMTP server.

If you are using the Environment configuration method you will instead need to set up the environment variables you see under the Email section in the sample .env.dist file in Panopticon's repository.

Adjusting the number of CRON jobs

By default, Panopticon will only install one (1) CRON job. This is enough for a small handful of sites, but absolutely nowhere near enough if you are scheduling backups, PHP file change scanner runs, and / or have many sites.

You can adjust the number of CRON jobs by changing the PANOPTICON_CRON_JOBS environment variable in your Docker Compose YAML file. Please make sure this is a positive integer that is equal or greater than zero. Invalid values will have unpredictable results!

If you change your mind after initialising Panopticon you need to rebuild the CRON jobs.

If you are running Panopticon 1.2.2 or later set a new value for the environment variable and restart the container. The new number of CRON jobs will be applied automatically.

If you are running Panopticon 1.2.0 or 1.2.1 you need to edit the CRON jobs with:

docker exec -it $(docker ps | grep panopticon-php | awk '{print $1}' | tail -n1) su panopticon -c crontab -e

Note that you can add more CRON jobs by duplicating the last non-empty line as many times as necessary.

After editing the CRON jobs you need to restart the container for the changes to take effect.

Running CLI commands

You can run Panopticon's CLI commands directly on the container using

docker exec -it $(docker ps | grep panopticon-php | awk '{print $1}' | tail -n1) su panopticon -c "/usr/local/bin/php /var/www/html/cli/panopticon.php YOUR_COMMAND" 

where YOUR_COMMAND is your CLI command and its arguments.

In both cases, commands which interact (read from, or write to) files do so with files in the container. We recommend using the path /var/www/html/user_code. This is the internal path which corresponds to the panopticon_usercode Docker volume or bind mount. This will make it easier to transfer files between your Panoptiocn installation and your host.

Updates

⚠️ The integrated updater in Panopticon is disabled under Docker as it can make a mess.

Before updating Panopticon we recommend backing up its database, and its configuration file. This allows for a fairly simple rollback if something goes wrong.

When using Panopticon in a container you need to first fetch or build the new version's image.

If you are using a prebuilt image run

docker image pull ghcr.io/akeeba/panopticon:latest 

If you are building from sources, run

docker compose build --no-cache php

You then need to pause all running tasks, restart the container, update the database, and unpause the tasks:

docker exec -it $(docker ps | grep panopticon-php | awk '{print $1}' | tail -n1) su panopticon -c "/usr/local/bin/php /var/www/html/cli/panopticon.php task:pause" 
docker compose restart
sleep 5
docker exec -it $(docker ps | grep panopticon-php | awk '{print $1}' | tail -n1) su panopticon -c "/usr/local/bin/php /var/www/html/cli/panopticon.php database:update" 
docker exec -it $(docker ps | grep panopticon-php | awk '{print $1}' | tail -n1) su panopticon -c "/usr/local/bin/php /var/www/html/cli/panopticon.php task:unpause" 

Upgrading from old versions

Docker support between Panopticon versions 1.0.0 and 1.1.3 inclusive was marked as experimental. This means that you will need to a bit of extra work to upgrade from these older versions into the new Panopticon versions.

Before doing anything else, we strongly recommend that you back up your Panopticon database. You can do that from the Administration, Database Backups page in Panopticon itself.

To migrate to the new architecture you will have to take the following actions.

  1. Run docker cp $(docker ps | grep panopticon-php | awk '{print $1}' | tail -n1):/var/www/html/config.php ./config.php to copy your config.php out of the container.
  2. Destroy your Panopticon installation with docker compose down. The database data SHOULD survive this process as it was already being placed into a Docker Volume since the earliest versions of Panopticon, and the database data volume is NOT removed with this command.
  3. Follow the Quick Start to bring up a new instance of Panopticon
  4. Copy your config.php file back to the container: docker cp ./config.php $(docker ps | grep panopticon-php | awk '{print $1}' | tail -n1):/var/www/html/config/config.php
  5. Restart your Panopticon installation with docker compose stop followed by docker compose start.
  6. Wait for half a minute, then run docker exec -it $(docker ps | grep panopticon-php | awk '{print $1}' | tail -n1) su panopticon -c "/usr/local/bin/php /var/www/html/cli/panopticon.php database:update" to update the database, should it be necessary (it's okay to run this command if it's not necessary, it won't do any harm).
Clone this wiki locally