Lightweight LAMP stack with domain whitelist, multi-arch support, and phpMyAdmin.
926
Single-container LAMP stack on Alpine Linux: Apache, PHP, MariaDB and phpMyAdmin in one image, built for small site hosting and homelab use. Multi-architecture (linux/amd64 + linux/arm64), optional domain whitelist, and all Apache/MariaDB output on docker logs.
Two generations are published side by side. Modern PHP 8.4 is the default; the original PHP 7.4 image is kept unchanged for archival and compatibility.
Tags: latest, php8.4
| Component | Version |
|---|---|
| Alpine Linux | 3.24.3 |
| PHP | 8.4.27 |
| Apache | 2.4.69 |
| MariaDB | 11.8.9 |
| phpMyAdmin | 5.2.3 |
linux/amd64 and linux/arm64 in the same tag.mysqli, pdo_mysql, pdo_sqlite, gd, intl, mbstring, zip, opcache, apcu, simplexml, xmlreader, xmlwriter, bz2, curl, dom, fileinfo.display_errors off, expose_php off, errors to stderr, HTTP-only session cookies, 100M upload/post limits, no Xdebug.docker stop is handled across the whole lifecycle, including while the datadir is being initialized or upgraded. An intentional stop exits 0.Tag: php7.4-legacy
The image previously published as latest (Alpine 3.14, Apache 2.4, PHP 7.4 with Xdebug, MariaDB 10.6, phpMyAdmin 5.2.0) is preserved unmodified under this tag, byte-identical to the historical release, for archival and compatibility purposes only.
PHP 7.4 is end of life. This image receives no security updates and must not be treated as free of known vulnerabilities. Do not use it as the default and do not deploy it for new work.
| Tag | Release | Notes |
|---|---|---|
latest | Modern PHP 8.4 | Recommended default |
php8.4 | Modern PHP 8.4 | Same image index as latest |
php7.4-legacy | Legacy PHP 7.4 | Archived original image, EOL |
Each tag resolves to a multi-platform index; docker pull picks the right architecture for your host.
docker run -d \
--name docker-lamp \
-e MYSQL_ROOT_PASSWORD='change-me' \
-e ALLOWED_DOMAIN='example.com,www.example.com' \
-p 8080:80 \
-v /srv/lamp/website:/var/www/localhost/htdocs \
-v /srv/lamp/mysql:/var/lib/mysql \
--stop-timeout 60 \
--restart unless-stopped \
rizkybs70/docker-lamp:latest
# docker-compose.yml
services:
lamp:
image: rizkybs70/docker-lamp:latest
stop_grace_period: 60s
ports:
- "8080:80"
volumes:
- /srv/lamp/website:/var/www/localhost/htdocs
- /srv/lamp/mysql:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: "change-me"
ALLOWED_DOMAIN: "example.com,www.example.com"
restart: unless-stopped
Then open http://<host>:8080/ for the website and http://<host>:8080/phpmyadmin/ for phpMyAdmin.
To build the image yourself instead:
git clone https://github.com/rizkybs70/docker-lamp.git
cd docker-lamp
docker build -t docker-lamp:php84 .
The build fetches Alpine packages, the phpMyAdmin release archive, Composer and the phpMyAdmin dependency tree from official sources, so it needs internet access and no local vendor folder.
| Variable | Required | Description |
|---|---|---|
MYSQL_ROOT_PASSWORD | yes | MariaDB root password. Applied when the data directory is initialized for the first time. The container refuses to start when it is missing. |
ALLOWED_DOMAIN | no | Comma-separated hostname whitelist. Unset or empty allows every hostname. |
MYSQL_RANDOM_ROOT_PASSWORD from the legacy stack is not supported by the PHP 8.4 image; set MYSQL_ROOT_PASSWORD explicitly.
The image ships no credentials and no host-specific configuration: everything comes from the environment or the mounted volumes.
ALLOWED_DOMAIN restricts HTTP access to the listed hostnames.
example.com,test.org; surrounding spaces are trimmed.www. variants are accepted automatically: example.com also allows www.example.com.localhost is always allowed, with or without a port.403 Forbidden, enforced by an Apache RewriteRule on the Host header.Mount both paths, otherwise the data lives in the container writable layer and disappears with the container:
/var/www/localhost/htdocs - website files (phpMyAdmin is served from /phpmyadmin/ inside the container)./var/lib/mysql - MariaDB data directory.The image declares no volumes, so nothing is persisted implicitly. If you hit permission errors, match the ownership to the in-container users:
sudo chown -R 100:101 /srv/lamp/website # apache, uid 100 / gid 101
sudo chown -R 101:102 /srv/lamp/mysql # mysql, uid 101 / gid 102
Both services run unprivileged inside the container (Apache as apache, MariaDB as mysql).
| Port | Purpose |
|---|---|
80/tcp | Apache, website and /phpmyadmin/ |
3306/tcp | MariaDB, internal only by default |
MariaDB also listens on the container socket /run/mysqld/mysqld.sock. Publish 3306 only when an external client really needs direct database access:
mysql -h <host-ip> -P 3306 -u root -p
Apache access and error logs go to stdout/stderr, so a single command shows everything:
docker logs -f docker-lamp
Example line:
192.168.1.10 - - [03/Mar/2026:12:00:00 +0000] "GET /index.php HTTP/1.1" 200 1234 "-" "Mozilla/5.0 ..."
curl -fsS http://127.0.0.1/ every 30s, 5s timeout, 20s start period, 3 retries.--stop-timeout 60 (Compose: stop_grace_period: 60s). This is a safety margin, not a workaround: a steady-state stop finishes in seconds, but a stop that arrives while MariaDB is still initializing or upgrading a volume is allowed to finish, and flushing dirty pages on slow storage can exceed Docker's 10 second default.0.The automatic upgrade step only applies in-place upgrades to a datadir already in the format of the running MariaDB series. Moving a volume from an older stack (for example MariaDB 10.6 to 11.8) is a major-version jump and is not covered by it: stop the old container, back up both the website volume and a consistent database dump, rehearse the migration on a copy, and only then point the new container at the migrated volume.
| Architecture | Status |
|---|---|
linux/amd64 | Built and runtime-tested natively on x86_64. |
linux/arm64 | Cross-built on x86_64, then runtime-tested natively on aarch64. |
A native run proves the image works on the ARM64 hardware used for testing; it does not guarantee every ARM64 device or kernel behaves the same. Older ARM boards and unusual kernels should be tested before being trusted.
Based on j1cs/docker-lamp. This fork adds domain whitelisting, docker logs friendly logging, persistent data mounts, multi-architecture images, and the 2026 security modernization (Alpine 3.24, PHP 8.4, MariaDB 11.8, phpMyAdmin 5.2.3).
MIT
Content type
Image
Digest
sha256:59658cbf9…
Size
155.8 MB
Last updated
about 19 hours ago
docker pull rizkybs70/docker-lamp