If you’re running a WordPress site on Apache inside Docker and you’re looking for something faster and more efficient, OpenLiteSpeed might be worth checking out. I recently migrated a WordPress site from Apache to OpenLiteSpeed, deployed via Docker on Coolify, and it went pretty smooth. Here’s how it went and what I learned along the way.
Before jumping into the how, here’s why I decided to make the switch:
.htaccess natively — so WordPress plugins that write rewrite rules (like Yoast SEO or eps-301-redirects) keep working without any changes. That’s a big deal.Here’s what changed at a high level:
| Before | After | |
|---|---|---|
| Web Server | Apache 2.x | OpenLiteSpeed 1.8.5 |
| PHP Version | 8.1 (mod_php) | 8.2 (LSAPI) |
| Base Image | wordpress:php8.1-apache | litespeedtech/openlitespeed:1.8.5-lsphp82 |
| Document Root | /var/www/html | /var/www/vhosts/localhost/html |
| Process Owner | www-data | nobody:nogroup |
Replaced the Apache-based WordPress image with the official OpenLiteSpeed image. The base image comes with a fully configured web server, PHP, vhost templates, and a working entrypoint — we just add WordPress files on top.
Some key differences from the old Apache Dockerfile:
mod_rewrite or configure AllowOverride — OLS handles .htaccess natively through its vhost template.CMD or ENTRYPOINT override — the base image’s entrypoint takes care of OLS startup, config initialization, and PHP process management.imagick, redis, memcached) are installed as lsphp82-* packages instead of using docker-php-ext-install.nobody:nogroup instead of www-data:www-data.The only real change here is the uploads volume mount path. It went from /var/www/html/wp-content/uploads to /var/www/vhosts/localhost/html/wp-content/uploads to match OLS’s document root structure.
Added to keep the Docker build clean and prevent unnecessary files from ending up in the document root:
lsws/ — leftover custom config experimentsDockerfile, docker-compose.yml, and other compose/dev files.git, .DS_Store, uploads/PHP 8.1 was dropped from OpenLiteSpeed 1.8.5 (the latest version that still had 8.1 was 1.8.4). WordPress 6.7.1 is fully compatible with PHP 8.2, so this is a safe and straightforward upgrade.
The litespeedtech/openlitespeed base image does a lot of heavy lifting:
docker.conf) maps all requests to a localhost virtual host at /var/www/vhosts/localhost/html/..htaccess loading — the vhost template has autoLoadHtaccess 1 and a rewrite context that reads .htaccess files, so WordPress permalinks just work.lsphp82 as an external processor through OLS’s cgid daemon, handling process spawning and user switching.A few things I had to clean up manually after the migration:
If you migrated from SiteGround hosting, you might have these lines sitting in your wp-config.php:
@include_once('/var/lib/sec/wp-settings-pre.php'); // Added by SiteGround WordPress management system
@include_once('/var/lib/sec/wp-settings.php'); // Added by SiteGround WordPress management system They do nothing outside of SiteGround, so just remove them.
The sg-cachepress plugin is SiteGround-specific and won’t do anything on Coolify. Swap it out with the LiteSpeed Cache plugin, which gives you:
This means PHP is not being processed. The scripthandler isn’t mapping .php files to the lsphp processor. Make sure you’re using the base image’s default config and not overriding httpd_config.conf.
Check the error log inside the container:
docker exec <container> cat /usr/local/lsws/logs/error.log | tail -30 Common causes:
cgidSuEXEC failed — don’t override the base image’s httpd_config.conf or entrypoint. The cgid daemon has very specific requirements for how extprocessor and autoStart are configured.ls -la /usr/local/lsws/fcgi-bin/lsphpCoolify’s reverse proxy can’t reach the container. Check these:
ss -tlnp | grep :80coolify network: double check your docker-compose.ymldocker exec <container> /usr/local/lsws/bin/lswsctrl status# Error log
docker exec <container> cat /usr/local/lsws/logs/error.log
# Access log
docker exec <container> cat /usr/local/lsws/logs/access.log The OpenLiteSpeed Docker image has a carefully orchestrated config initialization pipeline — backup configs in .conf/, entrypoint restore, cgid daemon, vhost templates. If you override httpd_config.conf or the entrypoint, you’ll break this pipeline and spend hours debugging weird issues.
The right approach is to just use the base image’s defaults and only overlay your application files into the document root. Don’t fight the image — work with it.