Images for local development in LAMP devstack
- architecture:
linux/amd64
- current PHP versions: 8.4, 8.3, 8.2 and 8.1
- unsupported PHP versions also available: 8.0, 7.4, 7.3, 7.2, 7.1, 7.0, 5.6, 5.5 and 5.4 (with limited stability, unoptimized, unmaintained)
- current versions of MariaDB 11.5, 11.4, 11.2, 10.11, 10.6, 10.5, and RC pre-release of 11.6
- unsupported versions of MariaDB 11.3, 11.1, 11.0, 10.10, 10.9, 10.8, 10.7, 10.4 and 10.3 (unmaintained)
- current version of Apache 2.4 (in non-CLI images)
- current version of Xdebug 3.3
- extra PHP extensions:
bmath
,bz2
,calendar
,exif
,gd
with PNG, WebP, AVIF (for PHP 8.1+), FreeType fonts supportgettext
,gmp
,imap
(up to PHP 8.3),intl
,memcached
,mysqli
,pdo_mysql
,opcache
,pcntl
,semaphore
,sockets
,soap
,sodium
,xsl
andzip
- Apache modules:
expires
,headers
andrewrite
- Apache
DocumentRoot
changed to:/var/www/html/www
(configurable by ENV) - PHP image comes with Composer 2.8+ and Git 2.39+ to use it in guest shell
- MySQL properly configured to use
utf8mb4
as a default charset, an optional support of Windows Host is also available - timezones are correctly supported
- optimized for small image size and short load times
Copy the docker-compose.yml
file
(download)
to your project's root (you don't need to clone/download the whole repo, just copy that one file).
Call docker compose up
. After docker container runs, your project will be served at http://localhost:8080/.
Only /www
subdirectory from your project is served but PHP scripts have access to the whole project's root.
That means only the /www
subdirectory is publicly accessible from web, not your whole application.
Example:
my_project/ <-- project's root
docker-compose.yml <-- docker config from this repository
www/ <-- Document Root, accessible at http://localhost:8080/
index.php <-- your PHP app
logo.png <-- accessible at http://localhost:8080/logo.png
gallery/
photo1.jpg <-- accessible at http://localhost:8080/gallery/photo1.jpg
vendor/
autoload.php <-- not accessible but PHP can via: require(__DIR__ . '/../vendor/autoload.php')
Images are tagged by the cascaded SemVer:
jakubboucek/lamp-devstack-php:latest
– meanslatest
available stable PHP image,jakubboucek/lamp-devstack-php:8
– represents the highest PHP image of8
version, but lower than9.0.0
,jakubboucek/lamp-devstack-php:8.4
– represents the highest PHP image of8.4
version, but lower than8.5.0
,jakubboucek/lamp-devstack-php:8.4.0
– represents most specific PHP image, directly version8.4.0
.
Legacy PHP images are tagged using different strategy, only latest revision for each minor version is available,
use -legacy
tag suffix:
jakubboucek/lamp-devstack-php:8.0-legacy
jakubboucek/lamp-devstack-php:7.4-legacy
jakubboucek/lamp-devstack-php:7.3-legacy
jakubboucek/lamp-devstack-php:7.2-legacy
jakubboucek/lamp-devstack-php:7.1-legacy
jakubboucek/lamp-devstack-php:7.0-legacy
jakubboucek/lamp-devstack-php:5.6-legacy
jakubboucek/lamp-devstack-php:5.5-legacy
jakubboucek/lamp-devstack-php:5.4-legacy-fixed
Note: Version 5.4 is using
-fixed
suffix because is unable to rebuild them from scratch.
All PHP images have alternative variants with XDebug extension preinstalled, use -debug
tag suffix, example:
jakubboucek/lamp-devstack-php:debug
jakubboucek/lamp-devstack-php:8-debug
jakubboucek/lamp-devstack-php:8.4-debug
jakubboucek/lamp-devstack-php:8.4.0-debug
jakubboucek/lamp-devstack-php:7.4-legacy-debug
Note: (PHP 8.4 temporary contains beta version of Xdebug)
All PHP images also have alternative CLI variants, use -cli
tag suffix, example:
jakubboucek/lamp-devstack-php:cli
jakubboucek/lamp-devstack-php:8-cli
jakubboucek/lamp-devstack-php:8.4-cli
jakubboucek/lamp-devstack-php:8.4.0-cli
jakubboucek/lamp-devstack-php:7.4-legacy-cli
MySQL server starts at the same time as the web server.
Available MySQL images:
- 10.5:
jakubboucek/lamp-devstack-mysql:10.5
- 10.6:
jakubboucek/lamp-devstack-mysql:10.6
- 10.11:
jakubboucek/lamp-devstack-mysql:10.11
- 11.2:
jakubboucek/lamp-devstack-mysql:11.2
- 11.4:
jakubboucek/lamp-devstack-mysql:11.4
- 11.5:
jakubboucek/lamp-devstack-mysql:latest
LTS (long-term support) MySQL images (currently 11.4):
jakubboucek/lamp-devstack-mysql:lts
The RC pre-release of MySQL 11.6 images have the -rc
suffix, example:
jakubboucek/lamp-devstack-mysql:11.6-rc
jakubboucek/lamp-devstack-mysql:11.6-1-rc
Default credentials:
- user:
root
- password:
devstack
- database name:
default
From Host, MySQL is accessible using:
- host:
127.0.0.1
- port:
33060
From docker guest, MySQL is accessible using:
- host:
mysqldb
- port:
3306
If you are connecting to the MySQL server from a PHP application running inside Docker, use the docker guest access values, but when you're connecting from outside (for example, from your computer, using HeidiSQL or Sequel), use host access.
PHP example:
$pdo = new PDO('mysql:host=mysqldb;dbname=default;charset=utf8mb4', 'root', 'devstack');
// or
$mysqli = new mysqli('mysqldb', 'root', 'devstack', 'default');
$mysqli->set_charset('utf8mb4');
MySQL may crash when Host is running Windows:
The Auto-extending innodb_system data file './ibdata1' is of a different size 0 pages than specified in the .cnf file
You can try to fix it by adding mysql-windows.cnf
(download)
and add it to the MySQL config directory /etc/mysql/conf.d/
inside the Docker container.
In docker-compose.yml
file, just link this downloaded file to volume
section:
volumes:
- "./.docker/mysql/data:/var/lib/mysql"
- "./mysql-windows.cnf:/etc/mysql/conf.d/mysql-windows.cnf"
Certain php.ini
directives can be modified without manipulating the
image content, using environment variables. It can be defined in docker run
command or in
docker-compose.yml
file.
Configurable directives:
PHP_ERROR_REPORTING
- change theerror_reporting
directive (default value:32767
, meansE_ALL
)PHP_DISPLAY_ERRORS
- change thedisplay_errors
directive (default value:1
)PHP_DISPLAY_STARTUP_ERRORS
- change thedisplay_startup_errors
directive (default value:1
, on PHP 7:0
)PHP_ERROR_LOG
– change theerror_log
directive (default value: empty)PHP_LOG_ERRORS
– change thelog_errors
directive (default value:0
)PHP_MAX_EXECUTION_TIME
– change themax_execution_time
directive (default value:30
)PHP_MEMORY_LIMIT
– change thememory_limit
directive (default value:2G
)PHP_SESSION_SAVE_PATH
– change thesession.save_path
directive (default value: empty)PHP_OPCACHE_BLACKLIST_FILENAME
– change theopcache.blacklist_filename
directive (default value: empty)PHP_OPCACHE_ENABLE
– change theopcache.enable
directive (default value:1
)PHP_OPCACHE_ENABLE_CLI
– change theopcache.enable_cli
directive (default value:0
)PHP_OPCACHE_JIT
– change theopcache.jit
directive (default value:tracing
, on PHP 8.4 changed:disable
)PHP_OPCACHE_JIT_BUFFER_SIZE
– change theopcache.jit_buffer_size
directive (default value:0
, on PHP 8.4 changed:64M
)PHP_OPCACHE_MEMORY_CONSUPTION
– change theopcache.memory_consumption
directive (default value:128
)PHP_OPCACHE_PRELOAD
– change theopcache.preload
directive (default value: empty)PHP_OPCACHE_PRELOAD_USER
– change theopcache.preload_user
directive (default value: empty)PHP_OPCACHE_VALIDATE_TIMESTAMPS
– change theopcache.validate_timestamps
directive (default value:1
)PHP_OPCACHE_REVALIDATE_FREQ
– change theopcache.revalidate_freq
directive (default value:2
)
Example for docker run
command:
docker run --rm -e PHP_MEMORY_LIMIT=1G jakubboucek/lamp-devstack-php php -i
Example docker-compose.yml
file:
environment:
PHP_MEMORY_LIMIT: 1G
Create custom APACHE_DOCUMENT_ROOT
environment variable with the path to Document Root as the value.
You can also specify it directly with docker run
:
docker run -it --rm -e APACHE_DOCUMENT_ROOT=/my-web jakubboucek/lamp-devstack-php
You can also put it to your docker-compose.yml
file:
environment:
APACHE_DOCUMENT_ROOT: "/my-web"
The default timezone is not defined (UTC
will be used). You can modify the default timezone by setting the TZ
environment variable to the desired timezone name (e.g., Europe/Prague
).
It can also be specified directly with docker run
:
docker run -it --rm -e TZ=Europe/Prague jakubboucek/lamp-devstack-php
Or in your docker-compose.yml
file:
environment:
TZ: Europe/Prague
The TZ
environment variable is recognized by Linux tools as well. By creating the variable you modify the default
timezone for the whole Linux operating system, PHP, and also MySQL.
At PHP since version 8.2 is TZ
variable set to 'UTC'
by default (otherwise is empty).
PHP is using native Linux temporary directory for all own temporary files (including session and upload storage). This
image does not provide any custom way to modify them. You can use the TEMPDIR
environment variable to modify all of
them.
You can specify it directly with docker run
:
docker run -it --rm -e TEMPDIR=/var/www/temp jakubboucek/lamp-devstack-php
Or in the docker-compose.yml
file:
environment:
TEMPDIR: /var/www/temp
Note: The directory MUST already exists and MUST be writable for all users (0777
), otherwise PHP can be unstable or
can lose data (e.g. sessions data). Moving the temporary directory to a volume shared with the Host can have a big
impact on performance.
The TEMPDIR
environment variable is also recognized by Linux tools. By setting that variable you modify the default
temporary directory for the whole Linux operating system, PHP, and also MySQL.
Apache is by default configured to listening on TCP port 80. You can use the PORT
environment variable to modify
port number where is apache listening to HTTP Requests.
Note: This variable is affect Apache runtime only. When you change port value, don't forget manually publish that port to host, when you want to access it from here or expose port to use at network.
You can specify it directly with docker run
:
docker run -it --rm -e PORT=8080 -p 8080:8080 jakubboucek/lamp-devstack-php
Or in the docker-compose.yml
file:
ports:
- "8080:8080"
environment:
PORT: 8080
The PORT
environment variable is also used by most known services
(e.g. Google Cloud Run).
Settings other than those listed above can be set in your INI file. You can add it to /usr/local/etc/php/conf.d
directory using Volume mounting
without building a custom image.
Create custom.ini
file in your project's root, for example:
sendmail_from = any@my-domain.tld
Mount the file to the container using the volume
directive in your docker-compose.yml
file:
volumes:
- "./custom.ini:/usr/local/etc/php/conf.d/custom.ini"
Check available docker-compose.yml
file for an example of how to use the volume
directive.
I've also prepared a PHP image with Xdebug. Use docker-compose-debug.yml
(download)
instead (copy and rename it to docker-compose.yml
).
Xdebug is not started by default, you must call requests with relevant trigger (tip: how to fire triggers from your browser).
These features are enabled in Xdebug:
Profiler a Tracing outputs are saved to /var/www/html/log
directory inside Container. Output files are
propagated to the Host to log/
directory (this directory must be manually created first).
You can change the output directory through XDEBUG_CONFIG
environment variable with output_dir
parameter.
In docker-compose.yml
file modify the environment
section, for example:
environment:
XDEBUG_CONFIG: "client_host=host.docker.internal output_dir=/another/dir"
# ^^^^^^^^^^^^^^^^^^^^^^^
Starting with Xdebug 3.3, Profiler a Tracing outputs are compressed with GZip. You can turn off GZip compression through
the XDEBUG_CONFIG
environment variable with use_compression
parameter and value false
.
In docker-compose.yml
file modify environment
section, for example:
environment:
XDEBUG_CONFIG: "client_host=host.docker.internal use_compression=false"
# ^^^^^^^^^^^^^^^^^^^^^
With PhpStorm, you can also debug CLI scripts. First, you need to set the Server name, PhpStorm requires it for path mapping.
In docker-compose.yml
file, add PHP_IDE_CONFIG
environment variable with serverName
parameter:
environment:
PHP_IDE_CONFIG: "serverName=docker-cli"
If you need to build custom images based on this repo, see Build notes