Installation
See the
packages.ddev.com). Your existing Gemfury (pkg.ddev.com) setup keeps working, but please re-run the ; you can run it for install or upgrade.
ddev delete images or ddev delete images --all after upgrading to free up disk space used by previous Docker image versions. This does no harm.ddev config --auto to update your projects to current configuration.Highlights
Blog announcement: (dhi.io/mysql) instead of bitnamilegacy/mysql, which gets no updates
.env.local for values you don't want in Git, several files per service separated by a label, and global files that apply to every project, see fills a new database from a snapshot in .ddev/db_snapshots, or from a path to one anywhere else on your machine. A snapshot outside the project is read where it is instead of being copied, so a multi-GB file is not duplicated. A snapshot named seed is used automatically, with no flag. Works for MariaDB, MySQL, and PostgreSQLGlobal Configuration
These apply to every project on your machine, so you set them once instead of in each project.
- New
- New
- Add-on install actions now see
.ddev/.envand the global~/.ddev/.env*files, not only.ddev/.env.<addon>. If you set aDDEV_*variable in.ddev/.env, that value is used there. A.ddev/.env.<service>.<label>file is also passed into that service's container now; before, it was only used to fill in variables in your docker-compose files
Features
- Two new project types: , and
- Shopware 6 projects get
shopware-cliin the web image, plusddev admin-watchandddev storefront-watchwith the ports they need, so the - New fetches the
ddevandddev-hostnamebinaries for a PR, branch, commit, release tag, latest stable, ormainHEAD, without touching your installed DDEV - New and
DDEV_LAUNCH_PRINT_URL=true ddev launchprint the URL instead of opening a browser, for SSH, containers, and CI, thanks to host command for the TablePro database client on macOS, thanks to letsnodejs_version: auto/engineread the version file from a subdirectory such asweb/themes/custom/mytheme. Both now require that file to exist; before, if it was missing, DDEV installed its default version without telling you, thanks to config option works again after a long absence, mirroringwebimage, along withddev config --db-image/--db-image-default - If you pin a custom
webimageordbimage,ddev startwarns you when that image was built from an older DDEV image than this version expects, instead of failing later in a way that gives no hint why. Official images now record the DDEV version they were built for, so the warning starts working after you rebuild your own image, thanks to ddev startwarns when DDEV itself is an unreleased build from a PR or a local branch, andddev versionshows where it came from- Drupal
settings.ddev.phpconfiguressymfony_mailer_litethe way it already configuredsymfony_mailer, thanks to explains how to move from Homebrew to a specific DDEV version, thanks to for the diagnosis and the original fix, made general here so Drupal and Backdrop get it too ddev pull acquiahandles long application names, where the Acquia CLI breaks the database filename across several lines, thanks to- The bundled
settings.phpfor thedrupal11anddrupal12project types is refreshed from upstream, and drupal11'ssettings.ddev.phpgets the garbage-collection threshold that drupal12 already had, thanks to
Security Changes
- A malicious archive can no longer create an absolute symlink that a later file in the same archive follows, to write files outside the folder being extracted - your shell startup files, for example. This was reachable through
ddev add-on getandddev import-db/import-files, and it completes the fix for for the report, see . ddev-webserverexplains the 403s and 404s it generates itself instead of serving a bare error page, since those usually mean a wrongdocrootor a project that isn't installed yet, andddev-routerdoes the same for a hostname that matches no project. A 403 or 404 from your own application is passed through unchanged. This replaces the "docroot may be wrong" warning onddev start, which you couldn't see in a browser and which warned wrongly when.htaccessrewrites into a subdirectoryddev-php-baseis consolidated intoddev-webserveras local build stages, so a new base image no longer has to be pushed to Docker Hub beforeddev-webservercan reference it.ddev/ddev-php-baseandddev/ddev-php-prodare no longer published and stay at their last-pushed tag; theddev-webserverimage itself behaves the same- Per-project certificates no longer carry a shared
*.<TLD>wildcard SAN, which Traefik 3.7.6+ would use to serve one project's certificate for every hostname on a shared custom TLD. v1.25.3 shipped Traefik 3.6.13, which isn't affected. The obsolete*.ddev.localSAN is also gone from the global default certificate - Under rootless Docker or Podman, the host's
usr.sbin.mysqldAppArmor profile attaches to the container's mysqld and left it unable to read/etc/my.cnf. That profile is loaded on any Linux machine withmysql-serverinstalled, and the newdhi.io/mysqlbase puts mysqld at the path it matches. MySQL 8.0, 8.4, and 9.7 now load their config with an explicit--defaults-fileinstead - A nightly performance benchmark harness feeding a tracking per test type across GitHub Actions and Buildkite
- Rootless Podman CI setup reworked,
podman-rootCI dropped DDEV_DOCKER_ORGpoints a binary at a different Docker Hub organization, so a release built outsideddev/ddevcan be pull-tested end to endlast_started_versionis recorded by every command that starts containers, not onlyddev start/ddev restart, so you stop being asked for addev poweroffthat isn't needed.ddev start -yrecords it too- Three fixes toward Apple Container and socktainer support ( ( in ( in ( in ) [skip ci] by
- fix(mysql): build mysql 8.0/8.4 from Docker Hardened Images, fixes in in ) [skip ci] by
- docs(commands): add precision about
launchwhich start project, fixes in by - fix(router): remove obsolete *.ddev.local from generated certs, fixes in ) [skip ci] by
- feat(commands): add
ddev tableproglobal host command by - fix(build): honor service platform override when building images, fixes in by
- chore: Updates to the settings.php for the drupal11 and drupal12 project types by
- docs(quickstart): update Shopware 6 references to up-to-date information by
- fix(buildkite): run orb start/stop synchronously so orbstack reliably ends up running ( in by
- chore: replace github.com/sponsors/ddev with ddev.com/sponsor by
- docs: expand CLAUDE.md language rules to curb AI-nonsense words and ego-stroking [skip ci] by
- docs(quickstart): work around Drush/Guzzle 8 conflict in Drupal 12 install ( in in in ) [skip ci] by
- feat: add support for global Dockerfiles, fixes ) [skip ci] by
- fix(nodejs): stop recursively chgrp/chmod'ing /usr/local/n on every project build, fixes in ) [skip ci] by
- fix(describe): omit xdebug_enabled from describe output, fixes ) [skip ci] by
- fix: don't write CMS db connection settings when db container is omitted or another driver is configured, for ) [skip ci] by
- feat(maho): add Maho project type by
- docs(quickstart): pin quickstart to Symfony LTS, fixes symfony.bats failures [skip ci] by
- fix: reject symlinks with rooted/absolute targets in Untar, for ) [skip ci] by
- perf(router): update network aliases in place instead of recreating on start, for ) [skip ci] by
- build(docker): consolidate ddev-php-base into ddev-webserver, fixes in ) [skip ci] by
- ci(podman): force nftables firewall backend to avoid intermittent netavark failure [skip ci] by
- test(macos-docker-desktop): skip tests hitting a Docker Desktop connection reset by
- feat: add MySQL 9.7 LTS support, fixes in in ( in ( in ) [skip ci] by
- fix(compose): remove BuildKit snapshot race retry logic, for in by
- docs: Remove obsolete Lullabot nodejs link ( in ) [skip ci] by
- fix(docker): restore /usr/local/n and make /var/log group-0-writable, fixes by
- fix(router): skip TestRouterNotRebuiltOnHostnameChange on Windows, fixes ) [skip ci] by
- docs(webserver): condense the 404 explanation comments, for ) [skip ci] by
- feat(webserver): explain webserver-level 403s, fixes ( in in ) [skip ci] by
- fix(webserver): don't let a failing global-cache chown kill the container by
- feat(dbserver): support zstd-compressed base_db for faster first-boot restore by
- test(db): fix filepath formatting in test [skip github] by
- ci(github): pin setup-homebrew, drop dead setup-sandbox input ( in ) [skip ci] by
- feat(perf): add nightly performance benchmark harness by
- fix(perf): fix bugs found validating the nightly benchmark harness end-to-end ( in in in ) [skip ci] by
- test(quickstart): statamic output changed, fix assertion by
- build: bump the actions group with 4 updates by
- docs: update config.md for minor typos, for ) [skip ci] by
- fix(modx): add missing 403 in nginx, use
ddev php, for in ) [skip ci] by - test(quickstart): derive URLs from
ddev describe -jinstead of hardcoding ddev.site [skip buildkite] by - feat(snapshot): show size and DB version in
ddev snapshot --listby - fix(dockerutil): fall back to NetworkSettings.Ports in GetBoundHostPorts ( in ) [skip ci] by
- feat: forward TERM and COLORTERM to ddev ssh/exec sessions, fixes ) [skip ci] by
- fix: record last_started_version from every command that starts containers, fixes in ) [skip ci] by
- ci(podman): rework the rootless setup script and docs, drop podman-root CI by
- docs: reorganize README to put getting started first ( in ( in ) [skip ci] by
- fix(ddevapp): attach command output to failing provider and hook commands ( in ) [skip ci] by
- feat(images): record image tag in a com.ddev.image-tag label and warn when a pinned image is stale by
- docs(readme): add in-kind sponsors section ( in ( in by
- feat(containers): auto-detect content changes and tag/rebuild docker base images locally, for ) [skip ci] by
- fix(acquia): broken db import with long application names by
- ci: add placeholder image-build/image-push workflows for ) [skip ci] by
- fix(ci): quote placeholder workflow strings so ) [skip ci] by
- build: bump 1password/load-secrets-action from 4 to 5 by
- build(public-variables): Add DOCKER_ORG [skip ci] by
- feat(images): Automatically push and then test new images when changes made, fixes in in ) [skip ci] by
- docs(comments): Clean up comments missed in ) [skip ci] by
- feat: publish apt/rpm packages to Cloudsmith to replace (gradually) Gemfury, fixes in by
- test(mutagen): Minor test cleaup [skip ci] by
- fix(images): gate fork image builds on approval earlier, skip it for authorized authors ( in ) [skip ci] by
- fix(addon): tolerate numeric default_branch in add-on registry JSON ( in ) [skip ci] by
- feat(amplitude): report add-on repository to Amplitude, fixes in in ) [skip ci] by
- ci(perf): track total CI runtime per test type across GitHub Actions and Buildkite ( in ( in ( in , fixes in ) [skip ci] by
- test(mutagen): we don't need some mutagen testing [skip buildkite] ( in in by
- ci: comment on PRs included in a release ( in in ( in ) [skip ci] by
- fix(wordpress): let wp-cli.yml override the docroot, fixes in ( in ) [skip ci] by
- fix: reject path traversal in docroot, upload_dirs, and dotenv path validation by
- build(go): bump all go.mod dependencies ( in ) [skip ci] by
- fix(compose): always use RemoveOrphans option, fixes in by
- fix(buildx): skip sha verification on macOS for versions before v0.36.0, for in by
- build: bump actions/upload-artifact from 4 to 7 in the actions group ([bot] in ( in ( in ) [skip ci] by
- feat: add gitignored .env.local, labeled, and global .env files, fixes by
- feat: add ddev launch --print-url flag and DDEV_LAUNCH_PRINT_URL env var, fixes ) [skip ci] by
- feat(drupal): support symfony_mailer_lite in settings.ddev.php, fixes ) [skip ci] by
- fix: don't use nested project unless it's registered, fixes in ) [skip ci] by
- feat: add nodejs_root so Node.js version auto-detection can read a subdirectory, fixes ) [skip ci] by
- fix(dbserver): pin secure_file_priv for mysql 8.0, 8.4, and 9.7 by
- ci(debug): replace tmate with upterm [skip ci] by
- fix: update TestCmdVersion for release-tag image resolution ( in in in by
New Contributors
Full Changelog: v1.25.3...v1.25.4
SOCIAL SHARE CARD GENERATOR