Skip to the content
Documentation
Help Start
Reading in:
  • German: 9,059 of 9,059 pages
About the help in other languages
All help pages

Containers: Docker and Podman

Running Exponential in Docker or Podman containers: what the sources say (tier 2, Velocity's published images), what goes on a persistent volume, the one-writer rule for SQLite, an entry point that installs once and…

Download as PDF

Address: https://doc.exponential.earth/exphelp/viewer/help/hosting/models/containers-docker-and-podman.md

On this page

Containers: Docker and Podman

This page is for hosting companies and platform teams that run Exponential sites in Linux containers with Docker or Podman. It answers what the project's sources say about containers, what must live on a persistent volume, how many containers may write a SQLite database, how an entry point installs a site once and keeps the server running, and how to keep secrets out of images.

Warning

.htaccess slows down every request. When .htaccess files are enabled (AllowOverride anything but None), let alone used, Apache looks for them and reads and evaluates them on every request, in every directory of the path, and page loading times go up drastically (measured). The only real fix is to switch the feature off for the virtual host: AllowOverride None in the HTTPS virtual host, and the rules in the virtual host's own configuration as mod_rewrite rules. That is far faster in production speed tests and well worth the time it takes to optimize a production configuration. Switch over right away: copy the rules of the example HTTPS virtual host into your virtual host (with the static cache, also staticcache_offload.conf), set AllowOverride None, run apachectl configtest, reload Apache and test the site. The same rules for other servers: nginx, LiteSpeed, Caddy, IIS, Velocity (built in); where virtual host rules go in a control panel: Plesk, cPanel, DirectAdmin, ISPConfig. On LiteSpeed or OpenLiteSpeed, the server's own page cache can also answer anonymous visitors and crawlers without PHP: Page caching with LiteSpeed and OpenLiteSpeed.

Contents

  1. What the sources say
  2. Images
  3. Volumes: what must persist
  4. The database and the one-writer rule
  5. An entry point that installs once
  6. Secrets
  7. Operations inside containers
  8. Checklist

What the sources say

  • Docker and Podman (Linux containers) are tier 2, known to work: "Velocity publishes images on ghcr.io/se7enxweb/exponential-velocity for amd64 and arm64, one per PHP version and variant" (Tier 2).
  • "Any image with PHP 8 and the extensions above runs Exponential ... Keep var/ (storage, logs, the SQLite database) and settings/override on a persistent volume. With SQLite, run one container that writes" (Containers, cloud and hosting panels).
  • exp:install is the method for "CI pipeline, container image, automated test environment": options or environment variables, exit status (4.6 Unattended installs).

Images

Two routes:

RouteWhat you getWhat to watch
Your own image from a PHP 8.0+ basethe PHP extensions you choose, Composer, the installation built with composer installinstall every required extension: dom, xsl, intl, mbstring, iconv, zlib, one database extension, gd or ImageMagick, and for Velocity sockets, pcntl, openssl
Velocity's published image as a basethe server and a PHP with a defined extension setcheck the variant against what Exponential needs

Velocity's images are tagged by release, PHP version and variant (Velocity packages, Docker images and binaries):

ghcr.io/se7enxweb/exponential-velocity:<release>-php<version>-<variant>   fixed
ghcr.io/se7enxweb/exponential-velocity:php<version>-<variant>             moves with each release
ghcr.io/se7enxweb/exponential-velocity:latest                             newest PHP, standard variant

<version> is 8.2, 8.3, 8.4 or 8.5; <variant> is mini, lite, standard or full. "Pin a fixed tag in production." The standard variant is "the default; what the documentation assumes".

Tip

Whatever the base, run php bin/php/console exp:velocity ext check inside the built image as part of your image pipeline. It lists every extension the installation wants, marks what is missing and prints the install command (Finding what is missing).

Volumes: what must persist

PathHoldsVolume
var/uploads and image variations (var/storage), caches, logs, autoload arrays, the SQLite database (var/storage/sqlite3/)persistent
settings/overridethe installation's settings, including the database connectionpersistent
settings/siteaccessthe siteaccess settings the installer writespersistent (the backup list names it)
kernel/, lib/, vendor/, extension/, design/the codein the image

The backup set is the same as everywhere: the database and var/storage, settings/override and settings/siteaccess (Backup and restore).

Warning

Files on the volume must belong to the user the container's PHP runs as. "Files created by root may later be unwritable for the web server" (4.6). Decide the user ID once for the image and the volume, and keep it.

The database and the one-writer rule

In the official order: 1. SQLite 3 (the default) · 2. PostgreSQL · 3. MongoDB · 4. MariaDB · 5. Oracle · 6. MySQL. Microsoft SQL Server is known to be possible with additional work at this time.

  • 1. SQLite 3 works in a container when one container writes the database: "SQLite's WAL needs shared memory on one host, so several replicas cannot share one database file over a network volume."
  • Several containers serving one site need a database server ("PostgreSQL first") and shared storage for var/storage (Containers, cloud and hosting panels). They also need sessions every container can read; see Kubernetes.
  • The database server usually runs in its own container or as a managed service of your platform, with its own volume and its own backups (Database backups per engine).

An entry point that installs once

Chapter 4 gives "a minimal container entry point" that installs once, then starts Velocity and stays in the foreground while it runs:

#!/usr/bin/env bash
set -euo pipefail
cd /srv/exponential
if ! grep -q '^\[DatabaseSettings\]' settings/override/site.ini.append.php 2>/dev/null; then
    php bin/php/console exp:install --apply \
        --db=mysql --db-host="${DB_HOST}" --db-name="${DB_NAME}" --db-user="${DB_USER}" \
        --url="${SITE_URL}" --email="${ADMIN_EMAIL}" --password="${ADMIN_PASSWORD}"
fi
php bin/php/console exp:velocity start
# exp:velocity start runs the server in the background and returns; status exits 0 while it runs
while php bin/php/console exp:velocity status >/dev/null 2>&1; do sleep 30; done
echo "Velocity stopped" >&2
exit 1

What the chapter explains about it:

  • The grep "is the same test exp:install itself uses to decide that a directory already holds an installation".
  • "exp:velocity start detaches the server and returns as soon as it answers", so the loop keeps the container's main process alive and ends it when the server stops, "so the container runtime can restart it".
  • "If the entry point runs as root, add --allow-root-user to the two exp:velocity commands."
  • The example uses --db=mysql; the other values are sqlite (the default), pgsql, mongodb, mariadb and oracle (Database support, At a glance).

Warning

exp:install uses the database action remove by default. That "is what a fresh container wants, and exactly what must never point at a database that holds data you need" (4.6). Keep the "already installed" test in front of it.

Secrets

  • Pass the database password in EXP_INSTALL_DB_PASSWORD; exp:install reads it "when --db-password is not given; that keeps it out of the process list and the shell history".
  • Without --password, exp:install generates a 24-character administrator password and writes it to var/log/initial-admin-password (mode 0600); read it from there and rotate it, or pass one from your secret store (First sign-in and default passwords).
  • Never bake settings/override into an image: it holds the database credentials (13.3 Secrets in settings/override).
  • config.php can be made in the image (exp:setup:config --apply --allow-root-user --owner=www-data:www-data in the build step), but a password in it, such as CLUSTER_STORAGE_PASS, is set at start from the environment: php bin/php/console exp:config:set CLUSTER_STORAGE_PASS --value="$CLUSTER_DB_PASS" --apply --allow-root-user. The output shows it as ********. In CI, exp:config:list --only-set --format=json shows what an image or a running container sets (Setting up .htaccess and config.php from the console).

Operations inside containers

  • Cron. runcronjobs.php still has to run on a schedule: from a scheduler container that shares the volumes and the database, or from your platform's scheduler, as the same user as the web process (Cron jobs).
  • Logs. Exponential writes its logs under var/log (and per site under var/<site>/log); keep them on the volume or collect them from there (Request logs).
  • Code changes reach Velocity's workers only after a restart; exp:velocity deploy runs the steps in order (8.3.14). In containers the usual equivalent is a new image and a new container.

Checklist

  • To do: Image with PHP 8.0+ and every required extension; exp:velocity ext check passes in the pipeline.
  • To do: Fixed image tags in production.
  • To do: var/, settings/override, settings/siteaccess on persistent volumes, owned by the container's PHP user.
  • To do: One writing container for SQLite, or a database server for more.
  • To do: Entry point with the "already installed" test; secrets from the environment, not the image.
  • To do: Cron, logs and backups defined.

A public demo in a container. Give the demo service EXP_DEMO_MODE=1 (-e, --env-file or env_file:; docker-demo.env), never a base image other sites use. With PHP-FPM inside, keep clear_env = no or set env[EXP_DEMO_MODE] = 1 in the pool. Demo mode for hosts.

Become an Exponential Partner

Partners share their information, provide funding, contribute back and develop the products with us, and that is how Exponential grows. A partner website and dashboard are planned for mid-2027: please become a partner today to speed up our growth rate and land new features faster.

Something wrong on this page? Report an error

Documentation license

This documentation is free documentation, licensed under the GNU Free Documentation License 1.3 or later.

Exponential Copyright © 1998-2026 Exponential Foundation and 7x