Free open source ecommerce platform created in 2024. https://mahocommerce.com
50K+
This image is based on FrankenPHP and is specifically designed for deployment in cloud-based production environments such as Sevalla, DigitalOcean, and similar PaaS providers. This image does not include a database server. You will need to provision a managed database (MySQL or PostgreSQL) through your cloud provider, or use SQLite which requires no external service. Database support varies by version - see the tags below.
nightly: dev-main version of Maho, running on latest FrankenPHP + PHP 8.5 (Trixie)latest: latest stable release version of Maho (26.9.0), running on latest FrankenPHP + PHP 8.5 (Trixie)26.9.0-php8.5, 26.9.0-php8.4, 26.9.0-php8.3 -Trixie, MySQL + PostgreSQL + SQLite26.7.5-php8.5, 26.7.5-php8.4, 26.7.5-php8.3 -Trixie, MySQL + PostgreSQL + SQLite26.7.4-php8.5, 26.7.4-php8.4, 26.7.4-php8.3 -Trixie, MySQL + PostgreSQL + SQLite26.7.3-php8.5, 26.7.3-php8.4, 26.7.3-php8.3 -Trixie, MySQL + PostgreSQL + SQLite26.7.2-php8.5, 26.7.2-php8.4, 26.7.2-php8.3 -Trixie, MySQL + PostgreSQL + SQLite26.7.1-php8.5, 26.7.1-php8.4, 26.7.1-php8.3 -Trixie, MySQL + PostgreSQL + SQLite26.7.0-php8.5, 26.7.0-php8.4, 26.7.0-php8.3 -Trixie, MySQL + PostgreSQL + SQLite26.5.0-php8.5, 26.5.0-php8.4, 26.5.0-php8.3 -Trixie, MySQL + PostgreSQL + SQLite26.3.0-php8.5, 26.3.0-php8.4, 26.3.0-php8.3 -Trixie, MySQL + PostgreSQL + SQLite26.1.0-php8.5, 26.1.0-php8.4, 26.1.0-php8.3 -Bookworm, MySQL + PostgreSQL + SQLite25.11.0-php8.4, 25.11.0-php8.3 -Bookworm, MySQL only25.9.0-php8.4, 25.9.0-php8.3 -Bookworm, MySQL only25.7.0-php8.4, 25.7.0-php8.3 -Bookworm, MySQL only25.5.0-php8.4, 25.5.0-php8.3, 25.5.0-php8.2 -Bookworm, MySQL onlyEvery tag is periodically rebuilt so it picks up PHP and Debian security updates. A tag stops being rebuilt once its runtime reaches end of life, whichever comes first: its PHP version or its Debian release.
| PHP | rebuilt until | Debian | rebuilt until | |
|---|---|---|---|---|
| 8.2 | 2026-12-31 | Bookworm | 2028-06-30 | |
| 8.3 | 2027-12-31 | Trixie | 2030-06-30 | |
| 8.4 | 2028-12-31 | |||
| 8.5 | 2029-12-31 |
nightly is the exception and never reaches end of life: it always tracks dev-main on the current PHP and Debian, and is moved forward in place rather than retired.
Tags that reach end of life are never deleted. They remain on Docker Hub and stay pullable indefinitely; they simply stop receiving updates. If you are running one, you are responsible for the unpatched PHP and OS packages inside it, so plan to move to a tag on a supported runtime.
local.xml file with all configurationslocal.xml and change the configuration options as needed (eg: replacing database hostname, user, pass etc)MAHO_LOCAL_XML and copy the contents of the previously edited local.xml into itcore_config_data table, fixing the domain name for the websiteapp/etc/local.xmlMAHO_LOCAL_XML and paste the contents of the local.xml into it (the previously created file would be lost by a new deployment or by an update of the docker image)Remember that Maho stores file uploads (eg: product images) in the public/media folder. Since you do not want to lose those important files, you should configure a persistent disk through your cloud infrastructure and mount it on /app/public/media, then restart the whole infrastructure and test that files actually get saved to that disk.
Note: most of the cloud providers will allow you to mount a persistent disk to one container/machine only, that means that at the moment you won't be able to have more than one frontend nodes. In case you need more power, you have two options:
NFS share for the public/media folder, then mount it into the frontend nodesWe're working on supporting S3 compatible storage for better horizontal scaling but that's not available at the moment.
docker-compose configurationservices:
php:
container_name: maho
image: mahocommerce/maho:latest
environment:
- SERVER_NAME=maho.local
ports:
- ${HTTP_PORT:-80}:80
- ${HTTPS_PORT:-443}:443
- ${HTTPS_PORT:-443}:443/udp
restart: unless-stopped
volumes:
- .docker/data:/data
- .docker/config:/config
- ./app:/app/app
- ./media:/app/public/media
tty: true
mysql:
container_name: mysql
image: mysql:latest
environment:
- MYSQL_DATABASE=maho
- MYSQL_USER=maho
- MYSQL_PASSWORD=askmd72BBSspak
- MYSQL_ROOT_PASSWORD=MaajwekSNUsk242sred
ports:
- "3306:3306"
restart: unless-stopped
volumes:
- ./mysql-data:/var/lib/mysql
This configuration will have the app (which mainly will contain local.xml), media and mysql-data folders directly mapped on the host, but you can manage those the way you prefer the most.
After starting the containers, you can install Maho with:
docker exec -it maho ./maho install --license_agreement_accepted yes --locale en_US --timezone Europe/London --default_currency EUR --db_host mysql --db_name maho --db_user maho --db_pass askmd72BBSspak --url https://maho.local/ --secure_base_url https://maho.local/ --use_secure 1 --use_secure_admin 1 --admin_lastname admin --admin_firstname admin --admin_email [email protected] --admin_username admin --admin_password qwe123098poiqwe123098poi --sample_data=1
docker exec -it maho ./maho index:reindex:all
docker exec -it maho ./maho cache:flush
Tags for Maho 26.7 and later (latest and nightly included) ship a Maho site block at /etc/caddy/Caddyfile (hard-linked to /etc/frankenphp/Caddyfile, which is the path the container actually runs). It does four things that the plain dunglas/frankenphp Caddyfile does not:
/api/* to the correct entry point (rest.php, api.php or index.php, depending on the path)/.well-known/ and /.thumbs/.md page URLs through, because Maho 26.9 generates a markdown version of every page for AI agents405 to TRACE and TRACK, and sets X-Content-Type-Options: nosniffWithout the /api/* routing the storefront works and every API call returns the storefront 404 page, so do not drop these rules.
To add directives without replacing the file, set the CADDY_SERVER_EXTRA_DIRECTIVES environment variable. To replace it, mount your own file over /etc/frankenphp/Caddyfile.
Do not add CORS headers or an OPTIONS preflight response to the web server. Maho answers both inside the API kernel. Set the allowed origins in System > Configuration > Services > API > CORS Allowed Origins.
Older tags keep the base FrankenPHP site block, because Maho before 26.7 has no rest.php entry point to route to.
Full reference: mahocommerce.com/hosting/web-server.
Tags for Maho 26.9 and later (latest and nightly included) ship Node.js 24 and the shared libraries Chromium needs, so the WCAG accessibility scanner of Maho 26.9 works on this image. The scanner itself is not in the image: Maho installs Playwright, axe-core and Chromium (roughly 300 MB) under var/accessibility-scan/ the first time you run:
docker exec -it maho ./maho accessibility:install
Run it once after every deploy, or mount var/accessibility-scan/ as a volume so the download survives a redeploy. Maho only installs the runtime from the command line, never from a web request, so a scan started from the admin fails until this command has run.
If you build your own image on top of this one and install a package that renders with Mesa (for example Debian's chromium or libgl1), remove the empty mesa-libgallium stub first with apt-get remove mesa-libgallium. It stands in for the real package, which headless Chromium does not need, to keep the image about 180 MB smaller.
The Tailwind CSS toolchain of the new storefront themes is not in the image. The compiled CSS ships with Maho, and theming a store from the admin needs no build. dev:frontend:theme:build is a development command; if you run it in the container it offers to install the toolchain with npm, which is available.
We all know an ecommerce project needs addon modules and custom development, thus, most probably, you won't be able to use this image as is. Our suggestion is to import it in your project repository and build your own on top of it. This way you'll take advantage of the official developments/support/updates, with the power of your custom implementations.
Content type
Image
Digest
sha256:a3a43f3ca…
Size
356.5 MB
Last updated
about 9 hours ago
docker pull mahocommerce/maho:26.9.0-php8.5Pulls:
469
Last week