-
-
Notifications
You must be signed in to change notification settings - Fork 28
blog: Legacy projects with unsupported PHP/MySQL versions using DDEV #375
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
11 commits
Select commit
Hold shift + click to select a range
eb494d5
blog: Legacy projects with unsupported PHP/MySQL versions using DDEV
garvinhicking 9b272d8
fix: capitalize terms
garvinhicking 5598244
chore: apply suggestions from review
garvinhicking 83a1318
chore: npx prettier --write
garvinhicking bc6415f
chore: use apache markdown code block language
garvinhicking 7406c8a
fix: fix grammar
garvinhicking 9f852df
Apply suggestions from code review
garvinhicking 8028a5b
Update src/content/blog/legacy-projects-with-unsupported-php-and-mysq…
garvinhicking a3f14c8
Update src/content/blog/legacy-projects-with-unsupported-php-and-mysq…
garvinhicking f6dc4c1
chore: add note
garvinhicking dce721c
chore: adjust pubdate
garvinhicking File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
--- | ||
name: Garvin Hicking | ||
firstName: Garvin | ||
avatarUrl: https://0.gravatar.com/avatar/c796fffa839dbc5b435bcba90a5d6df19a20d66be817405ceddafda8679be05a?size=512&d=initials | ||
--- | ||
|
||
[Garvin Hicking](https://garv.in) is a PHP and TYPO3 webdeveloper in Cologne, Germany. He is an OpenSource contributor to the [TYPO3](https://typo3.org) project, and formerly worked on [Serendipity](https://s9y.org) and [phpMyAdmin](https://phpmyadmin.net). |
182 changes: 182 additions & 0 deletions
182
src/content/blog/legacy-projects-with-unsupported-php-and-mysql-using-ddev.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,182 @@ | ||
--- | ||
title: "Using DDEV to spin up a legacy PHP application" | ||
pubDate: 2025-05-30 | ||
#modifiedDate: 2025-05-30 | ||
summary: How to use DDEV with outdated PHP and MySQL versions | ||
author: Garvin Hicking | ||
featureImage: | ||
src: /img/blog/2025/05/museums-victoria-Di7WfLcrJ_I-unsplash.jpg | ||
alt: Legacy computer museum | ||
credit: "Photo by [Museums Victoria](https://unsplash.com/@museumsvictoria) on [Unsplash](https://unsplash.com/photos/gray-mechanical-machine-lot-beside-wall-Di7WfLcrJ_I)" | ||
categories: | ||
- Guides | ||
--- | ||
|
||
_This guest post is by DDEV community member and [TYPO3](https://typo3.org) contributor [Garvin Hicking](/blog/author/garvin-hicking/)._ | ||
|
||
In my daily work, I develop [TYPO3](https://typo3.org)-based projects and also contribute to the TYPO3 CMS OpenSource project itself. | ||
|
||
Usually this means working with actively supported and up-to-date PHP versions as well as database systems like MySQL/PostgreSQL/MariaDB. | ||
|
||
Just recently I had to migrate a very outdated project: TYPO3 4.5, which utilized MySQL 5.5 and PHP 5.3. When that project was initially developed, it was done with XAMPP and later Vagrant-based VMs. This has been long superseded with using Docker and specifically DDEV for ease-of-use. | ||
|
||
So naturally I wanted to be able to use DDEV for the legacy project to get it working just as it is running on the (outdated) hosting provider's shared web servers. | ||
|
||
I quickly faced three major issues: | ||
|
||
- No PHP 5.3 out-of-the-box support from DDEV; it starts with 5.6 as of the time of this writing | ||
- No MySQL 5.5 ARM64 support either; it starts with 5.7 | ||
- Additionally, I use an Apple MacBook Pro M1 with ARM-chipset, which has no "official" MySQL 5.5 support | ||
|
||
Thanks to the outstanding DDEV support on Discord, I was quickly able to find a way with minimal effort, just by creating very small custom, additional docker-compose YAML files. | ||
|
||
One advantage (of many) of using DDEV instead the underlying Docker Compose is that so many things are pre-configured and "just work". So I really did not want to migrate everything to Docker Compose on my own, do my custom routing, PHP-FPM integration and whatnot. | ||
|
||
Just being able to "bait and switch" the PHP and DB container with a different base Docker image was all that was needed for me: | ||
|
||
## Step 1: Base config | ||
|
||
I created the base `~/legacyphp/.ddev/config.yaml` file manually inside my `~/legacyphp` project directory, setting `legacyphp` as the project name. | ||
|
||
Note that I configured PHP and MySQL versions that are supported by DDEV for this first: | ||
|
||
```yaml | ||
name: legacyphp | ||
type: php | ||
docroot: htdocs | ||
php_version: "8.3" | ||
webserver_type: apache-fpm | ||
database: | ||
type: mysql | ||
version: "8.0" | ||
``` | ||
|
||
## Step 2: Rewire DB | ||
|
||
Next I created the very small file `~/legacyphp/.ddev/docker-compose.db.yaml` in the same directory next to `config.yaml`: | ||
|
||
```yaml | ||
services: | ||
db: | ||
platform: linux/amd64 | ||
build: | ||
args: | ||
BASE_IMAGE: ddev/ddev-dbserver-mysql-5.5:v1.24.6 | ||
entrypoint: | ||
- sh | ||
- -c | ||
- | | ||
cp /docker-entrypoint.sh ~/docker-entrypoint.sh | ||
sed -i '157s|.*|if false; then|' ~/docker-entrypoint.sh | ||
sed -i '175s|.*|echo mysql_8.0 >/var/lib/mysql/db_mariadb_version.txt|' ~/docker-entrypoint.sh | ||
exec ~/docker-entrypoint.sh | ||
``` | ||
|
||
Three things are noteworthy: | ||
|
||
- Setting `linux/amd64` as the platform will require Rosetta to be available on the macOS ARM64 platform | ||
- The `BASE_IMAGE` is set to a DDEV `db` container of legacy Docker images that are still provided. | ||
- Changing the `entrypoint` is a workaround to prevent DDEV complaining about a mismatching MySQL version after restarting the project. The small script "tricks" the DDEV inspection into believing, the version matches the one configured in `.ddev/config.yaml`. | ||
|
||
## Step 3: Rewire PHP | ||
|
||
Using a different PHP version is just a few lines more work, because we are not replacing the whole `web` container of DDEV. Instead, we add an additional PHP container which is executed from the web container via port 9000. | ||
|
||
This is done via the file `~/legacyphp/.ddev/docker-compose.php.yaml`: | ||
|
||
```yaml | ||
services: | ||
php: | ||
container_name: ddev-${DDEV_SITENAME}-php | ||
image: devilbox/php-fpm:5.3-work | ||
restart: "no" | ||
expose: | ||
- 9000 | ||
labels: | ||
com.ddev.site-name: ${DDEV_SITENAME} | ||
com.ddev.approot: ${DDEV_APPROOT} | ||
working_dir: /var/www/html | ||
volumes: | ||
- "../:/var/www/html" | ||
- ".:/mnt/ddev_config:ro" | ||
- ddev-global-cache:/mnt/ddev-global-cache | ||
- "./php:/etc/php-custom.d" | ||
environment: | ||
- NEW_UID=${DDEV_UID} | ||
- NEW_GID=${DDEV_GID} | ||
- DDEV_PHP_VERSION | ||
- IS_DDEV_PROJECT=true | ||
web: | ||
depends_on: | ||
- php | ||
``` | ||
|
||
Note here that we use `devilbox/php-fpm` with our needed version, and a bind-mount takes care the PHP container can access our main project root directory. | ||
|
||
A special mount of `~/legacyphp/.ddev/php/` is included so that we can control the `php.ini` configuration, if needed. For example you could disable the OPCache+APC in case you're doing some legacy benchmarking that should not be falsified via caching, I created a very small file `~/legacyphp/.ddev/php/php.ini` file with the contents: | ||
|
||
```ini | ||
# This is an example. | ||
# apc.enabled=Off | ||
# opcache.enable=Off | ||
``` | ||
|
||
## Step 4: Utilize the PHP container with an Apache proxy | ||
|
||
To execute PHP with our external PHP Docker image, I created the following file in `~/legacyphp/.ddev/apache/apache-site.conf`: | ||
|
||
```apache | ||
<VirtualHost *:80> | ||
RewriteEngine On | ||
RewriteCond %{HTTP:X-Forwarded-Proto} =https | ||
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} -d | ||
RewriteRule ^(.+[^/])$ https://%{HTTP_HOST}$1/ [redirect,last] | ||
SetEnvIf X-Forwarded-Proto "https" HTTPS=on | ||
|
||
Alias "/phpstatus" "/var/www/phpstatus.php" | ||
DocumentRoot /var/www/html/htdocs | ||
garvinhicking marked this conversation as resolved.
Show resolved
Hide resolved
|
||
<Directory "/var/www/html/htdocs"> | ||
AllowOverride All | ||
Allow from All | ||
</Directory> | ||
|
||
CustomLog /var/log/apache2/access.log combined | ||
ProxyFCGIBackendType GENERIC | ||
ProxyPassMatch ^/(.*\.php(/.*)?)$ fcgi://php:9000/var/www/html/htdocs/$1 | ||
DirectoryIndex /index.php index.php | ||
</VirtualHost> | ||
``` | ||
|
||
Note that if your document root is not `htdocs` you would need to adapt this name to your liking (like `public` or `wwwroot` or anything) in all occurrences of this file. | ||
|
||
## Step 5: Lift-Off | ||
|
||
Now you can execute `ddev start` and then `ddev launch` to see your project up and running. | ||
|
||
You could create a simple `~/legacyphp/htdocs/index.php` file with `<?php phpinfo(); ?>` to verify the version. | ||
|
||
Using `ddev mysql` will connect you to the MySQL 5.5 instance: | ||
|
||
```bash | ||
~/legacyphp> ddev mysql | ||
Welcome to the MySQL monitor. Commands end with ; or \g. | ||
Your MySQL connection id is 5 | ||
Server version: 5.5.62-log MySQL Community Server (GPL) | ||
``` | ||
|
||
## Caveats | ||
|
||
You can enter the PHP Docker container with a command like `docker exec -it -u devilbox ddev-legacyphp-php bash` if you need/want to execute PHP commands on shell-level, because the regular `web` container will run with the more recent PHP 8.3 version. | ||
So if you need to perform composer CLI calls, be sure to do this within the matching PHP container. | ||
|
||
Another thing to pay attention to is that if you for example want to utilize Mailpit with TYPO3's mail configuration, you can not use `localhost:1025` as an SMTP server. `localhost` in PHP's case will be that devilbox PHP container, and not the DDEV web container. Instead you need to setup `web:1025` as the hostname. | ||
|
||
The devilbox PHP config has pretty much all available PHP extensions set up to use, but if you need specific imagemagick or other tools, you will have to either ensure these are executed on the `web` container, or make them available with customization of a different base Docker container that you can build yourself. | ||
|
||
If you want to use Xdebug with this setup, you'll need to do more internal port forwarding in the docker-compose setup, which is beyond the scope of this article. | ||
|
||
## Closing words | ||
|
||
Having shown you what is possible, I hope you will never need to use it, and you will always use well-supported and current software. :-) | ||
|
||
Thanks so much to the DDEV project for getting me across the finish line with just very little effort! |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.