├── .env.example ├── CHANGELOG.md ├── FAQ.md ├── LICENSE ├── README.md ├── bin ├── composer ├── php └── php-ci.sh ├── composer.json ├── docker ├── docker-compose.base.yml └── web │ ├── nginx.conf │ ├── sites │ └── 001_default.conf │ └── ssl │ └── .gitignore ├── dockerize.sh ├── engines ├── mariadb │ ├── .env.stub │ ├── bin │ │ ├── mysql │ │ ├── mysqldump │ │ └── mysqli │ └── docker-compose.stub.yml ├── postgres │ ├── .env.stub │ ├── bin │ │ ├── createdb │ │ ├── dropdb │ │ ├── pg_dump │ │ └── psql │ ├── docker-compose.stub.yml │ └── docker │ │ ├── docker-compose.base.yml │ │ └── docker-compose.dev.yml └── redis │ ├── .env.stub │ ├── bin │ └── redis-cli │ └── docker-compose.stub.yml ├── install.php ├── public └── index.php └── version-constraints.php /.env.example: -------------------------------------------------------------------------------- 1 | DB_HOST="mariadb" 2 | DB_USERNAME="root" 3 | DB_PASSWORD="CHANGEME2" 4 | DB_DATABASE="rosettablog2" 5 | 6 | ## Docker Platform Configuration 7 | # Supported PHP Versions: 5.6, 7.0, 7.1, 7.2, 7.3, 7.4, 8.0, 8.1 8 | # Postfix it with "-debug" for xdebug support. 9 | PHP_VERSION="8.0-debug" 10 | # Set XDEBUG_SESSION=1 for CLI debugging support. 11 | XDEBUG_SESSION=0 12 | XDEBUG_CONFIG="idekey=PHPSTORM" 13 | 14 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## v13.0.2 2 | * **[2025-05-01 19:09:42 CDT]** Version 13.0.2: Fixed the .gitattributes. 3 | 4 | ## v13.0.1 5 | * **[2025-04-21 00:04:11 CDT]** [php-ci] Fixed a bug. 6 | 7 | ## v13.0.0 8 | * **[2025-04-17 06:21:56 CDT]** Downverted the composer version constraints system to PHP 7.0.0 compatibility, with polyfills. 9 | * **[2025-04-17 05:56:47 CDT]** [m] Version bumped the PHP versions. 10 | * **[2025-04-17 05:08:34 CDT]** Completely reimplemented the PHP version parser. 11 | * **[2025-03-26 11:15:21 CDT]** [m] Renamed test/ to tests/. 12 | * **[2025-03-26 10:45:57 CDT]** Removed unnecessary distributables from composer install. 13 | * **[2025-03-26 10:35:51 CDT]** Moved the web root to public/. 14 | * **[2025-03-26 09:51:14 CDT]** Added ext-uuid to the extension builder system. 15 | * **[2025-03-26 09:40:29 CDT]** Completely reimplemented the PHP extension builder to use only 1 image for all PHP versions. 16 | * **[2025-03-26 08:21:47 CDT]** [bin/php] Optimized further when running natively and inside docker. 17 | * **[2025-03-25 13:21:46 CDT]** Added the PHP Extension Builder system. 18 | * **[2025-03-25 13:10:50 CDT]** [linux] Added the en_US.UTF-8 locale so more apps will work. 19 | * **[2025-03-25 13:08:48 CDT]** Added steps to download ext-uuid source code. 20 | * **[2025-03-25 13:04:45 CDT]** Ignore all .build-assets/ directories. 21 | * **[2025-03-24 13:34:41 CDT]** [fixed] Ensured proper command execution in the entrypoint. 22 | * **[2025-03-24 13:33:11 CDT]** [bin/php] Sets the working directory of the CLI to the current project directory. 23 | * **[2025-03-24 13:32:15 CDT]** [bin/php] Default to host network if no project network exists 24 | * **[2025-03-24 13:31:12 CDT]** [bin/php] Propagate the exit code from native php execution. 25 | 26 | ## v12.2.1 27 | * **[2025-03-24 13:20:03 CDT]** [bin/php] Complete fixed native PHP dispatching. 28 | 29 | ## v12.2.0 30 | * **[2025-03-23 00:33:11 CDT]** Fixed a bug where the native PHP binary couldn't find files. 31 | 32 | ## v12.1.2 33 | * **[2024-12-21 13:32:23 CDT]** Improved PHP 8.4 support. 34 | * **[2025-03-17 16:31:30 CDT]** Built PHP 8.1.32, 8.2.28, 8.3.19, 8.4.5. HEAD -> v12.x 35 | 36 | ## v12.1.1 37 | * **[2025-03-13 17:25:06 CDT]** [php-ci] Refactored a lot. 38 | 39 | ## v12.1.0 40 | * **[2025-03-12 18:32:13 CDT]** Upgraded PHP 8.3.17 and 8.4.4. 41 | * **[2025-03-12 17:50:58 CDT]** Renabled build support for PHP 5.6-7.3. 42 | * **[2025-03-12 17:45:01 CDT]** [php-ci] Added support for PHPUnit v12. 43 | * **[2025-03-12 17:37:04 CDT]** [php-ci] Added PHPUnit support for PHP 7.0 and 7.1. 44 | 45 | ## v12.0.2 46 | * **[2025-01-07 08:11:57 CST]** Fixed a bug where native PHP detection via .env didn't work. 47 | * **[2024-12-13 02:18:41 CST]** Added another YouTube demo. 48 | 49 | ## v12.0.1 50 | * **[2024-12-13 01:51:43 CST]** Added PHP 8.4 support to php-ci.sh HEAD -> v12.x, origin/v12.x 51 | 52 | ## v12.0.0 53 | * **[2024-12-12 16:19:40 CST]** Added support for PHP 8.4. 54 | * **[2024-12-12 23:55:18 CST]** Majorly overhauled the dockerize installer. 55 | 56 | ## v11.1.0 57 | * **[2024-09-26 07:37:40 CDT]** Add composer to the PHP 8.4 image. HEAD -> v11.0 58 | * **[2024-09-26 07:36:44 CDT]** Fixed the PHP 8.4 entrypoint to use the standard entrypoint. 59 | * **[2024-09-13 03:48:00 CDT]** Added support for PHP 8.4 beta5. 60 | * **[2024-09-12 05:30:37 CDT]** [m] Updated the README. 61 | * **[2024-09-12 01:58:49 CDT]** [m] Use the new ENV format in the Dockerfiles. 62 | * **[2024-09-12 01:44:09 CDT]** Fixes for PHP 8.4 beta4 builds. 63 | * **[2024-09-09 12:55:33 CDT]** [m] Prioritized the installation instructions in the README.md. 64 | 65 | ## v11.0.0 66 | * **[2024-09-07 17:20:00 CDT]** [m] Added license and copyright clauses to files. 67 | * **[2024-09-07 17:20:24 CDT]** Added initial steps for creating a distroless PHP image. origin/v11.0 68 | * **[2024-09-07 18:55:07 CDT]** [major] Upgraded to Ubuntu 24.04 Noble Numbat. 69 | * **[2024-09-07 18:55:45 CDT]** Fixed a major reversion in web-debug by readding php-fpm. 70 | * **[2024-09-07 19:00:42 CDT]** Use a docker volume to store apt metadata. 71 | * **[2024-08-05 03:46:54 CDT]** Added support for PHP 8.4 Alpha 4. 72 | * **[2024-08-05 04:33:33 CDT]** Added a bash installation script to the composer package. 73 | 74 | 75 | ## v10.0.3 76 | * **[2024-06-29 10:13:12 CDT]** [php-ci] Dynamically fetch and compute the supported PHP versions from the composer.json. 77 | * **[2024-06-29 10:20:39 CDT]** [php-ci] Use phpunit's default config if there aren't version-specific xmls. 78 | * **[2024-06-29 10:20:48 CDT]** [php-ci] Added support for PHPUnit v11. 79 | * **[2024-06-29 10:31:50 CDT]** Create a Packagist alias to phpexperts/dockerise for SEO. 80 | 81 | ## v10.0.2 82 | * **[2024-06-26 00:57:05 CDT]** Added my php-ci.sh script. 83 | 84 | ## v10.0.0: Self-hosted 100% 0-Dependency Bash installer 85 | * **[2024-05-24 07:40:15 CDT]** Added a comprehensive zero-dependency Bash-via-curl installer. 86 | * **[2024-05-24 07:31:26 CDT]** Added a mechanism for finding the first open HTTP port for nginx. master 87 | * **[2024-05-24 07:30:16 CDT]** Redis removed v7.3 from docker; switched to v7.2. 88 | 89 | ## v9.2.1 90 | * **[2024-05-23 08:17:00 CDT]** Upgraded to MariaDB 10.11, Redis 7.3, and Postgres 16. 2.0, ] 91 | 92 | ## v9.2.0 93 | * **[2024-05-21 21:31:26 CDT]** Configured it so that composer will run the install script. 94 | 95 | ## v9.1.2 96 | * **[2024-05-21 06:27:48 CDT]** Fixes docker logs being truncated. origin/v9. 97 | 98 | ## v9.1.1 99 | * **[2024-01-16 03:15:49 CST]** [major] Fixed a critical bug that prevented the dockerized php CLI from running in projects with a defined network. 100 | * **[2024-01-14 14:22:31 CST]** Fixed the Docker installer. 101 | * **[2024-01-14 14:13:58 CST]** Renamed the installer. 102 | * **[2024-01-14 14:12:02 CST]** Switched the installer from wget to curl. 103 | 104 | ## v9.1.0: New zero-dependency Bash Installer 105 | * **[2024-01-14 07:06:07 CST]** Added a zero-PHP-dependency Bash installer. 106 | * **[2024-01-14 07:04:47 CST]** Added support for Linux ACLs in the base Linux image. 107 | * **[2024-01-14 07:03:35 CST]** Fixed docker building bugs in base-oracle. 108 | 109 | ## v9.0.1 110 | * **[2024-01-14 06:40:56 CST]** [major] Fixed a critical bug that prevented the dockerized php CLI from running in new projects. 111 | 112 | ## v9.0.0: Version 9.0.0: New full PHP image, Oracle ext-oci8, and a new build system. 113 | * **[2024-01-13 23:04:49 CST]** Added the Oracle ext-oci8 binaries, built against Ubuntu 22.04. 114 | * **[2024-01-13 22:51:39 CST]** Added a docker build that contains the Oracle DB's ext-oci8 extension. 115 | * **[2024-01-13 22:50:16 CST]** Added wget to the base PHP image. 116 | * **[2024-01-12 17:30:47 CST]** Refactored IonCube builds so that the extension is only downloaded once. 117 | * **[2024-01-12 14:49:27 CST]** Added a `full` docker build that contains every bundled PHP extension, and then some. 118 | 119 | ## v8.2.0 120 | * **[2024-01-12 05:58:13 CST]** Removed Ubuntu's apt files to save space in the base image. 121 | * **[2024-01-07 09:30:00 CST]** Fixed the building of the ioncube images. 122 | * **[2024-01-07 03:28:00 CST]** [major] Fixed the broken web images. 123 | * **[2023-12-05 10:10:39 CST]** Added PHP v8.3 support. 124 | * **[2023-12-05 10:09:40 CST]** Added a PHP version test script. 125 | 126 | ## v8.1.0 127 | * **[2023-07-23 03:21:22 CDT]** Now Dockerize PHP will run in the container, if it's running, or create a temp one if it's not. 128 | * **[2023-05-19 05:35:27 CDT]** Updated to PHP v8.0.28, v8.1.19, and v8.2.6. 129 | * **[2023-05-19 05:30:36 CDT]** Changed the default image from PHP v7.4 to v8.0. 130 | * **[2023-02-03 07:19:37 CST]** Majorly refactored so that it executes a persistent container for native launch speeds. 131 | 132 | ## v8.0.1 133 | * **[2023-01-20 21:58:20 CST]** Fixed the problem that prevented the web images from being successfully built. 134 | 135 | ## v8.0.0 136 | * **[2022-08-11 00:37:03 CDT]** Boosted the default version of PHP to 8.1. 137 | * **[2022-08-11 00:37:33 CDT]** Added PHP v8.2 support. master 138 | * **[2023-01-17 06:59:14 CST]** Cleaned up the build script so that it tags instead of building duplicate images. 139 | * **[2023-01-17 07:00:57 CST]** Improved the Linux base image build. 140 | * **[2023-01-17 08:46:09 CST]** Explicitly set the default PHP version to 8.1. 141 | * **[2023-01-17 07:41:52 CST]** Now, PHP will be launched from a continuously-running container for much faster runtimes at the expense of about 130 MB per container. 142 | * **[2023-01-17 08:57:42 CST]** Added support for PHP 8.2. 143 | 144 | ## v7.2.1 145 | * **[2022-06-18 00:05:57 CDT]** Show all of the output of docker build, not just the last 6 lines. 146 | * **[2022-06-18 00:10:05 CDT]** Upgraded to Ubuntu 22.04 Jammy Jellyfish. 147 | 148 | ## v7.2.0 149 | * **[2021-12-27 12:05:54 CST]** Use the official PHP 8.1 builds now. 150 | * **[2021-12-27 12:06:15 CST]** Include ext-imap and ext-ssh2. 151 | * **[2021-12-27 17:18:50 CST]** (#10) Added support for the Ioncube Decoder. 152 | * **[2021-12-27 17:22:18 CST]** Force the rebuilding of the Linux base image, for an up-to-date OS. 153 | * **[2021-12-27 17:26:25 CST]** Added basic automated tests. 154 | 155 | ## v7.1.2 156 | * **[2021-12-24 23:27:47 CST]** Added support for composer v2.2.0+. 157 | 158 | ## v7.1.1 159 | * **[2021-12-24 16:09:16 CST]** Added xdebug support for PHP 8.1. 160 | * **[2021-12-24 16:09:02 CST]** Upgraded to PHP v7.4.27, 8.0.14, and 8.1.1. 161 | * **[2021-12-24 15:36:38 CST]** Fixed the ability of selecting the PHP version via the .env file. 162 | 163 | ## v7.1.0 164 | * **[2021-12-10 08:32:27 CST]** Added install support for PHP 5.6, 8.0, and 8.1. 165 | * **[2021-11-18 04:13:15 CST]** Added the ability to configure the Docker platform via the .env. 166 | * **[2021-11-18 04:10:49 CST]** Upgraded the config files for Xdebug v3.0. 167 | 168 | ## v7.0.0 169 | * **[2021-11-02 15:47:49 CST]** PHP 8.1 RC5. 170 | * **[2021-11-01 08:08:36 CST]** Dramatically reduced total build time from 33 minutes to 11 minutes. 171 | * **[2021-11-01 06:24:52 CST]** Embedded composer into the php container. 172 | * **[2021-11-01 06:00:30 CST]** Run the native PHP when inside docker. 173 | * **[2021-07-29 07:13:12 CDT]** Set the PHP memory_limit to unlimited by default. 174 | * **[2021-07-29 07:07:35 CDT]** Fixed the building of xdebug. 175 | * **[2021-06-21 07:10:58 CDT]** Added git and ssh for private packages supoprt. 176 | 177 | ## v6.6.0 178 | * [2021-09-22 08:40:22 CDT] - Added the abiltiy to run commands in containers from the CLI. 179 | 180 | ## v6.5.0 181 | * [2021-06-03 08:22:27 CDT] - Installed the SOAP extension. 182 | * [2021-06-03 08:37:10 CDT] - Major improvements to the php cli. 183 | 184 | ## v6.4.1 185 | * [2021-02-05] Upgraded to PHP v8.0.1, v7.4.14, and v7.3.26 186 | * [2021-02-05] Added a Docker Hub release script. 187 | 188 | ## v6.4.0 189 | * [2020-12-03] Upgraded to PHP v8.0.0 190 | 191 | ## v6.2.1 192 | 193 | * [2020-10-30] Upgraded to PHP v8.0 RC3. 194 | 195 | ## v6.2.0 196 | 197 | * [2020-10-04] Upgraded to PHP v8.0 RC1. 198 | * [2020-10-04] Fixed the extension_dir location so PHP extensions work. 199 | * [2020-10-04] Installed the Zend Opcache extension. 200 | * [2020-10-04] Installed the PHPRedis extension. 201 | * [2020-10-04] Stripped out the debug symbols for massive space savings. 202 | * [2020-09-19] Upgraded to PHP v8.0 Beta 4. 203 | 204 | ## v6.1.0: 205 | 206 | * [2020-09-10] Added the ability to dynamically pick what PHP version is run via $PHP_VERSION. 207 | * [2020-09-10] Run the system's native PHP via $PHP_VERSION="native". 208 | 209 | ## v6.0.0: 2020-09-10 210 | 211 | * [2020-09-09] Upgraded to Ubuntu Focal Fossa v20.04-LTS. 212 | * [2020-09-09] Added support for PHP v5.6. 213 | * [2020-09-10] Added support for manually compiling PHP 8 pre-releases. 214 | 215 | ## v5.0.2: 2020-07-17 216 | * [2020-07-17] Fixed the .env.stub for Laravel DB engines. 217 | 218 | ## v5.0.1: 2020-05-02 219 | * [2020-05-02] - Fixed a bug that prevented accessing Postgres DBs via psql. 220 | 221 | ## v5.0: 2020-04-17 222 | * Fully automated dockerization via composer. 223 | * Added the ability to install specific PHP versions + DB creds. 224 | * Programmatically set the docker network. 225 | 226 | ## v4.0: 2020-04-12 (Easter 2020) 227 | * Completely re-engineered the entire project! 228 | * Refactored the entire build system. 229 | * Now installs ext-sodium on PHP < 7.2. 230 | * Now builds every major version of PHP 7 at once. 231 | * Now upgrades the Ubuntu image to get latest security fixes. 232 | * Added ext-imagick and ext-sodium. 233 | * Added unzip and net-tools. 234 | 235 | ## v3.0: 2020-02-26 236 | * Majorly refactored the build process to build all of the latest PHP versions 237 | at the same time. 238 | * Added the ability to dynamically pick what PHP version is run via $PHP_VERSION. 239 | * Added a utility to delete the web images. 240 | * Fixed the 'Can't locate Term/ReadLine.pm' error. 241 | 242 | ## v1.4.0: 2020-01-16 243 | * Upgraded to PHP 7.4. 244 | * Moved to the standard docker-compose.yml format. 245 | * PHP v7.4.1 246 | * Nginx 247 | 248 | ## v1.3.0: 2019-06-09 249 | * Upgraded to Ubuntu Bionic (18.04). 250 | * Upgraded to PHP 7.3. 251 | 252 | ## v1.2.0: 2018-03-07 253 | * **[2018-02-04]** Upgraded the stack: 254 | * PHP v7.2.3 255 | * Nginx v1.10.3 [unchanged] 256 | * Redis v3.2.11 257 | * PostgreSQL v9.6.7 258 | * MariaDB 10.3.4 [unchanged] 259 | 260 | * **[2018-02-21]** Added support for multiple nginx vhosts. 261 | * **[2018-02-21]** Added support for SSL certificates and unlimited custom 262 | nginx configuration. 263 | * **[2018-02-21]** Added the bcmath PHP extension. 264 | * **[2018-02-21]** [internal] Created a Makefile for the creation of release files. 265 | * **[2018-02-21]** [internal] Consolidated the common docker files. 266 | 267 | ## v1.1.0: 2018-02-05 268 | 269 | * **[2018-02-05]** The CLI now runs as the current user, NOT as root. 270 | * **[2018-02-05]** The CLI now uses the same Docker net as the main project, 271 | so it can communicate with other daemons (redis, psql, etc.). 272 | * **[2018-02-05]** Added a lot of documentation to the project. 273 | 274 | ## v1.0.0: 2018-02-04 275 | 276 | * **[2018-02-04]** Upgraded the stack: 277 | * PHP v7.2.2 278 | * Nginx v1.10.3 279 | * Redis v3.2.6 280 | * PostgreSQL v9.6.6 281 | * MariaDB 10.3.4 282 | -------------------------------------------------------------------------------- /FAQ.md: -------------------------------------------------------------------------------- 1 | # Frequently Asked Questions 2 | 3 | ### What is included in this project? 4 | 5 | * PHP v7.3.0, built on 17 December 2018 6 | * Nginx v1.10.3 7 | * Redis v3.2.6 8 | * PostgreSQL v9.6.6 9 | * MariaDB 10.3.4 10 | 11 | ## What are the advantages over other dockerized PHP projects? 12 | 13 | 1. **Super fast, completely automated installation.** (Great for testing multiple versions on CIs) 14 | 15 | wget https://github.com/phpexpertsinc/docker-php/releases/download/v1.0%2Bphp-7.2.2/phppro-dockerized_php-v1.0.0.tar.gz 16 | tar xzvf phppro-dockerized_php-v1.0.0.tar.gz 17 | cp -rvf phppro-dockerized_php-v1.0.0/postgres/* . 18 | bin/containers up 19 | 20 | 2. The **BIG** difference between www.phpdocker.io and DockerPHP is that DockerPHP provides all of the client utilities, where phpdocker.io provides NONE of them. 21 | 22 | Out of the box, you have per-project binaries: 23 | 24 | * **php** 25 | * mysql 26 | * mysqldump 27 | * psql 28 | * pg_dump 29 | * createdb 30 | * dropdb 31 | * redis 32 | * redis-cli 33 | 34 | With every other dockerized PHP platformer I am aware of, you are on your own 35 | when it comes to setting up these client utilities. 36 | 37 | ### What does this provide that Laravel Homestead does not? 38 | 39 | Laravel Homestead uses Vagrant and full virtual machines. This is *way* overkill when 40 | you want a dockerized PHP app running on native Linux dev boxes and servers, like I 41 | do. 42 | 43 | For instance, to get this setup as a server on [**DigitalOcean's Docker app 44 | server**](https://www.digitalocean.com/products/one-click-apps/docker/?refcode=724f89bd9417), 45 | I simply do this: 46 | 47 | git clone git@github.com:my/repo.git 48 | cd my_repo 49 | bin/containers up -d 50 | 51 | *DONE!* And it runs at almost-native speeds and doesn't have nearly the overhead of 52 | VirtualBox. Plus, setup takes 2 minutes vs the 30+ minutes it takes vagrant to build 53 | the VM. 54 | 55 | ### Is this ready for production? 56 | 57 | This project is run on several production sites, including a large ecommerce site. 58 | 59 | Use it yourself! Get a [Digital Ocean Docker App 60 | Droplet](https://www.digitalocean.com/products/one-click-apps/docker/?refcode=724f89bd9417) 61 | for $5, clone your repo on the droplet, and then just run `containers up`. There! You 62 | have a live site in 5 minutes! 63 | 64 | ### Do you really have time to maintain this? 65 | 66 | Since we're porting all of my company's production sites to this, and several clients 67 | already have it running in production, yes. I'm committed to actively maintaining 68 | this project for the long-term future. As a corporate policy, we strive to keep 69 | things as leading-edge as possible, so this project will always be relatively 70 | bleeding-but-stable-edge. 71 | 72 | ### Why not just use docker-compose? 73 | 74 | This project does use docker-compose. Think of `bin/containers` as a CLI UI around 75 | docker-compose in way that lets you handle multiple server environments very easily. 76 | 77 | ### Why fork from Chekote/docker-php 78 | 79 | This project started as a collaborative effort to improve that project, which I 80 | utilize every day. This project's `7` branch is a rolling fork of that project, 81 | mainly so I can contribute upstream. 82 | 83 | ----- 84 | 85 | [PHP Experts, Inc.](https://www.phpexperts.pro/), is my consultation company. It's a 86 | small company of a half dozen highly skilled Full Stack PHP devs, including myself, 87 | whom I place at 1099 positions at other corporations. We fill both long-term 88 | positions and, for crazy devs like me, short-term. If you ever wanted to work on a 89 | different project/company every few months or even weeks, anywhere in the continental 90 | U.S., Europe, or South East Asia, it's fantastic. 91 | 92 | Since 2015, I have set up branches in Las Vegas, Houston, the UK, Dublin, Costa Rica, 93 | Colombia, India, and the Philippines. If someone has a work auth in any of those 94 | places, we can place you almost anywhere you want. I travel 50% of the time out of 95 | choice. All over the world. 96 | 97 | Did I mention that you get paid in the cryptocurrency of your choice? 98 | 99 | Starting in mid-2017, we've begun a pivot towards a NodeJS and 100 | cryptocurrency-specific corporation. We are making some REALLY exciting things, like 101 | our dockerized PHP-based cryptocurrency payment gateway we'll be releasing in 2Q 102 | 2018. 103 | 104 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | Copyright (c) 2016 Donald Tyler 3 | Copyright (c) 2018-2024 Theodore R. Smith 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Dockerize PHP 2 | 3 | A utility for rapidly deploying [Docker](https://www.docker.com) for PHP apps. 4 | 5 | Watch the zero-dependency installation video: https://youtu.be/d8o9p2DimME 6 | Installing on a legacy PHP 5.6 app in 2 minutes: https://youtu.be/xZxaJcsbrWU 7 | 8 | **This project has been tested against over 350,000 open-sourced Packagist packages (via the Bettergist Archiver project) and is compatible with 99.999% of them.** 9 | 10 | Includes: 11 | * PHP 5.6, 7.0-7.4 + 8.0, 8.1, 8.2, 8.3, and 8.4. 12 | * Nginx 13 | * Redis v7.2 14 | * PostgreSQL v16 15 | * MariaDB v10.11 16 | 17 | Current PHP versions: 18 | * 5.6.40-81+ubuntu24.04.1+deb.sury.org+1 19 | * 7.0.33-79+ubuntu24.04.1+deb.sury.org+1 20 | * 7.1.33-67+ubuntu24.04.1+deb.sury.org+1 21 | * 7.2.34-54+ubuntu24.04.1+deb.sury.org+1 22 | * 7.3.33-24+ubuntu24.04.1+deb.sury.org+1 23 | * 7.4.33 24 | * 8.0.30 25 | * 8.1.32 26 | * 8.2.28 27 | * 8.3.20 28 | * 8.4.6 29 | 30 | The `phpexperts/php:VESION-full` images contain every bundled PHP extension, and Redis. 31 | 32 | * imap 33 | * ldap 34 | * pspell 35 | * redis 36 | * snmp 37 | * xmlrpc 38 | * Oracle ext-oci 39 | 40 | The `phpexperts/php:VERSION-full` images contain everything in the full image plus drivers for Oracle (ext-oci8), 41 | 42 | If you need an extension that is not available in the `full` build, please create an Issue at GitHub. 43 | 44 | # Installation 45 | 46 | * Watch the [**Installation HOWTO video**](https://youtu.be/xZxaJcsbrWU). 47 | 48 | * Here's another Zero Install demo including PHP 8.4 and the php-ci system for testing every version of PHP. 49 | 50 | [![phpexperts/dockerize Demo](https://private-user-images.githubusercontent.com/1125541/395483191-6dc866ed-b2fb-4262-98fe-2f8dbaa1e76f.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MzQwNzgxNDgsIm5iZiI6MTczNDA3Nzg0OCwicGF0aCI6Ii8xMTI1NTQxLzM5NTQ4MzE5MS02ZGM4NjZlZC1iMmZiLTQyNjItOThmZS0yZjhkYmFhMWU3NmYucG5nP1gtQW16LUFsZ29yaXRobT1BV1M0LUhNQUMtU0hBMjU2JlgtQW16LUNyZWRlbnRpYWw9QUtJQVZDT0RZTFNBNTNQUUs0WkElMkYyMDI0MTIxMyUyRnVzLWVhc3QtMSUyRnMzJTJGYXdzNF9yZXF1ZXN0JlgtQW16LURhdGU9MjAyNDEyMTNUMDgxNzI4WiZYLUFtei1FeHBpcmVzPTMwMCZYLUFtei1TaWduYXR1cmU9ZTFiOGM0ZDFkMTRlMmUwNTJmOWM5ZDA5M2U2OWU5NDFlOTk4ZTc2YmIwMmZiZjAyYmY3ZTZhMjI3OWRlZmIwMiZYLUFtei1TaWduZWRIZWFkZXJzPWhvc3QifQ.747HeCQJJpg9Snd93a0BECrVAF9-_lDwm-E32-d69nM)](https://youtu.be/rCfmTH62-os) 51 | 52 | ## Via Bash (Zero PHP dependencies) 53 | 54 | bash <(curl -s 'https://raw.githubusercontent.com/PHPExpertsInc/dockerize/v12.x/dockerize.sh') 55 | 56 | Then edit credentials in .env. 57 | 58 | docker compose up -d 59 | 60 | ### Via Composer 61 | 62 | # Ensure that vendor/bin is in your PATH and before /usr/bin. 63 | composer require --dev phpexperts/dockerize 64 | vendor/bin/php dockerize 65 | # Edit credentials in .env. 66 | docker-compose up -d 67 | 68 | Don't forget to edit your docker-compose.yml! 69 | 70 | ### Configure your PATH 71 | 72 | In order to dockerize your existing PHP project, do the following: 73 | 74 | Ensure that your profile PATH includes `./vendor/bin` and that it takes priority over any other directory that may include a php executable: 75 | 76 | PATH=./vendor/bin:$PATH 77 | 78 | ## Thank you, JetBrains 79 | 80 | JetBrains generously grants this project a free Open-Source License to PhpStorm and all other JetBrains products as part of its [Open Source License](https://www.jetbrains.com/community/opensource/) initiative. 81 | 82 | # Advantages over other dockerized PHP projects 83 | 84 | 1. **Super fast, completely automated installation.** (Great for testing multiple versions on CIs) 85 | 2. The **BIG** difference between www.phpdocker.io and Dockerize PHP is that Dockerize PHP provides all of the client utilities, where phpdocker.io provides NONE of them. 86 | 87 | Out of the box, you have per-project binaries: 88 | 89 | * **php** 90 | * **composer** 91 | * **php-ci.sh** 92 | * mysql 93 | * mysqldump 94 | * psql 95 | * pg_dump 96 | * createdb 97 | * dropdb 98 | * redis 99 | * redis-cli 100 | 101 | # PHP CI via Docker 102 | 103 | With the **php-ci.sh** shell script, you can easily test your app or library against every major version of PHP (currently 7.4-8.3): 104 | 105 | In the project root directory, where your phpunit.xml is, or where you'd normally run phpunit: 106 | 107 | vendor/bin/php-ci.sh 108 | 109 | It will then automagically update composer and run the appropriate version of PHPUnit for all of the major PHP versions 110 | supported by your project via the power of Docker. 111 | 112 | ## Latest Changes 113 | 114 | #### v13.0.2 115 | * **[2025-05-01 19:09:42 CDT]** Version 13.0.2: Fixed the .gitattributes. 116 | 117 | #### v13.0.1 118 | * **[2025-04-21 00:04:11 CDT]** [php-ci] Fixed a bug. 119 | 120 | #### v13.0.0 121 | * **[2025-04-17 06:21:56 CDT]** Downverted the composer version constraints system to PHP 7.0.0 compatibility, with polyfills. 122 | * **[2025-04-17 05:56:47 CDT]** [m] Version bumped the PHP versions. 123 | * **[2025-04-17 05:08:34 CDT]** Completely reimplemented the PHP version parser. 124 | * **[2025-03-26 11:15:21 CDT]** [m] Renamed test/ to tests/. 125 | * **[2025-03-26 10:45:57 CDT]** Removed unnecessary distributables from composer install. 126 | * **[2025-03-26 10:35:51 CDT]** Moved the web root to public/. 127 | * **[2025-03-26 09:51:14 CDT]** Added ext-uuid to the extension builder system. 128 | * **[2025-03-26 09:40:29 CDT]** Completely reimplemented the PHP extension builder to use only 1 image for all PHP versions. 129 | * **[2025-03-26 08:21:47 CDT]** [bin/php] Optimized further when running natively and inside docker. 130 | * **[2025-03-25 13:21:46 CDT]** Added the PHP Extension Builder system. 131 | * **[2025-03-25 13:10:50 CDT]** [linux] Added the en_US.UTF-8 locale so more apps will work. 132 | * **[2025-03-25 13:08:48 CDT]** Added steps to download ext-uuid source code. 133 | * **[2025-03-25 13:04:45 CDT]** Ignore all .build-assets/ directories. 134 | * **[2025-03-24 13:34:41 CDT]** [fixed] Ensured proper command execution in the entrypoint. 135 | * **[2025-03-24 13:33:11 CDT]** [bin/php] Sets the working directory of the CLI to the current project directory. 136 | * **[2025-03-24 13:32:15 CDT]** [bin/php] Default to host network if no project network exists 137 | * **[2025-03-24 13:31:12 CDT]** [bin/php] Propagate the exit code from native php execution. 138 | 139 | #### v12.2.1 140 | * **[2025-03-24 13:20:03 CDT]** [bin/php] Complete fixed native PHP dispatching. 141 | 142 | #### v12.2.0 143 | * **[2025-03-23 00:33:11 CDT]** Fixed a bug where the native PHP binary couldn't find files. 144 | 145 | #### v12.1.2 146 | * **[2024-12-21 13:32:23 CDT]** Improved PHP 8.4 support. 147 | * **[2025-03-17 16:31:30 CDT]** Built PHP 8.1.32, 8.2.28, 8.3.19, 8.4.5. HEAD -> v12.x 148 | 149 | #### v12.1.1 150 | * **[2025-03-13 17:25:06 CDT]** [php-ci] Refactored a lot. 151 | 152 | #### v12.1.0 153 | * **[2025-03-12 18:32:13 CDT]** Upgraded PHP 8.3.17 and 8.4.4. 154 | * **[2025-03-12 17:50:58 CDT]** Renabled build support for PHP 5.6-7.3. 155 | * **[2025-03-12 17:45:01 CDT]** [php-ci] Added support for PHPUnit v12. 156 | * **[2025-03-12 17:37:04 CDT]** [php-ci] Added PHPUnit support for PHP 7.0 and 7.1. 157 | 158 | #### v12.0.2 159 | * **[2025-01-07 08:11:57 CST]** Fixed a bug where native PHP detection via .env didn't work. 160 | * **[2024-12-13 02:18:41 CST]** Added another YouTube demo. 161 | 162 | #### v12.0.1 163 | * **[2024-12-13 01:51:43 CST]** Added PHP 8.4 support to php-ci.sh HEAD -> v12.x, origin/v12.x 164 | 165 | #### v12.0.0 166 | * **[2024-12-12 16:19:40 CST]** Added support for PHP 8.4. 167 | * **[2024-12-12 23:55:18 CST]** Majorly overhauled the dockerize installer. 168 | 169 | #### v11.1.0 170 | * **[2024-09-26 07:37:40 CDT]** Add composer to the PHP 8.4 image. HEAD -> v11.0 171 | * **[2024-09-26 07:36:44 CDT]** Fixed the PHP 8.4 entrypoint to use the standard entrypoint. 172 | * **[2024-09-13 03:48:00 CDT]** Added support for PHP 8.4 beta5. 173 | * **[2024-09-12 05:30:37 CDT]** [m] Updated the README. 174 | * **[2024-09-12 01:58:49 CDT]** [m] Use the new ENV format in the Dockerfiles. 175 | * **[2024-09-12 01:44:09 CDT]** Fixes for PHP 8.4 beta4 builds. 176 | * **[2024-09-09 12:55:33 CDT]** [m] Prioritized the installation instructions in the README.md. 177 | 178 | #### v11.0.0 179 | * **[2024-09-07 18:55:07 CDT]** [major] Upgraded to Ubuntu 24.04 Noble Numbat. 180 | * **[2024-09-07 18:55:45 CDT]** Fixed a major reversion in web-debug by readding php-fpm. 181 | * **[2024-09-07 17:20:24 CDT]** Added initial steps for creating a distroless PHP image. origin/v11.0 182 | * **[2024-09-07 19:00:42 CDT]** Use a docker volume to store apt metadata. 183 | * **[2024-08-05 03:46:54 CDT]** Added support for PHP 8.4 Alpha 4. 184 | * **[2024-08-05 04:33:33 CDT]** Added a bash installation script to the composer package. 185 | 186 | #### v10.0.3 187 | * **[2024-06-29 10:13:12 CDT]** [php-ci] Dynamically fetch and compute the supported PHP versions from the composer.json. 188 | * **[2024-06-29 10:20:39 CDT]** [php-ci] Use phpunit's default config if there aren't version-specific xmls. 189 | * **[2024-06-29 10:20:48 CDT]** [php-ci] Added support for PHPUnit v11. 190 | * **[2024-06-29 10:31:50 CDT]** Create a Packagist alias to phpexperts/dockerise for SEO. 191 | 192 | #### v10.0.2 193 | * **[2024-06-26 00:57:05 CDT]** Added my php-ci.sh script. 194 | 195 | #### v10.0.0 196 | * **[2024-05-24 07:40:15 CDT]** Added a comprehensive zero-dependency Bash-via-curl installer. 197 | * **[2024-05-24 07:31:26 CDT]** Added a mechanism for finding the first open HTTP port for nginx. master 198 | * **[2024-05-24 07:30:16 CDT]** Redis removed v7.3 from docker; switched to v7.2. 199 | 200 | #### v9.2.1 201 | * **[2024-05-23 08:17:00 CDT]** Upgraded to MariaDB 10.11, Redis 7.3, and Postgres 16. 202 | 203 | #### v9.2.0 204 | * **[2024-05-21 21:31:26 CDT]** Configured it so that composer will run the install script. 205 | 206 | #### v9.1.2 207 | * **[2024-05-21 06:27:48 CDT]** Fixes docker logs being truncated. origin/v9. 208 | 209 | ## Manage with docker-compose 210 | 211 | To control the containers, use `docker-compose`. 212 | 213 | # Downloads the images, creates and launches the containers. 214 | docker-compose up -d 215 | # View the logs 216 | docker-compose logs -ft 217 | # Stop the containers 218 | docker-compose stop 219 | 220 | That's it! You now have the latest LEPP (Linux, Nginx, PostgreSQL, PHP) stack or 221 | the latest LEMP (Linux, Nginx, MariaDB, PHP) stack. 222 | 223 | # User ID control 224 | 225 | It is possible to control what UID the initial process (usually PHP) and/or PHP-FPM processes run as. The `bin/php` file already does this for the initial process. 226 | 227 | This is important if you are mounting a volumes into the container, as the the UID of the initial process or PHP-FPM will likely need to match the volume to be able to read and/or write to it. 228 | 229 | ## PHP-FPM process UID 230 | 231 | To set the UID for the PHP-FPM process, you should set the `PHP_FPM_USER_ID` environmental variable on the container. e.g: 232 | 233 | docker run -e PHP_FPM_USER_ID=1000 phpexperts/php:7 php-fpm5.6 234 | 235 | # Exact PHP Versions 236 | 237 | PHP 5.6.40-81+ubuntu24.04.1+deb.sury.org+1 (cli) (built: Dec 24 2024 06:43:22) ( NTS ) 238 | PHP 7.0.33-79+ubuntu24.04.1+deb.sury.org+1 (cli) (built: Dec 24 2024 06:43:22) ( NTS ) 239 | PHP 7.1.33-67+ubuntu24.04.1+deb.sury.org+1 (cli) (built: Dec 24 2024 06:50:54) ( NTS ) 240 | PHP 7.2.34-54+ubuntu24.04.1+deb.sury.org+1 (cli) (built: Dec 24 2024 06:58:15) ( NTS ) 241 | PHP 7.3.33-24+ubuntu24.04.1+deb.sury.org+1 (cli) (built: Dec 24 2024 07:05:25) ( NTS ) 242 | PHP 7.4.33 (cli) (built: Dec 24 2024 07:12:16) ( NTS ) 243 | PHP 8.0.30 (cli) (built: Dec 24 2024 07:19:59) ( NTS ) 244 | PHP 8.1.31 (cli) (built: Nov 21 2024 13:10:45) (NTS) 245 | PHP 8.2.27 (cli) (built: Dec 24 2024 06:29:37) (NTS) 246 | PHP 8.3.17 (cli) (built: Feb 15 2025 09:09:25) (NTS) 247 | PHP 8.4.4 (cli) (built: Feb 15 2025 08:59:26) (NTS) 248 | 249 | # Distribution 250 | 251 | Docker Hub: 252 | * https://hub.docker.com/r/phpexperts/php/ 253 | * https://hub.docker.com/r/phpexperts/web/ 254 | 255 | # About PHP Experts, Inc. 256 | 257 | [PHP Experts, Inc.](https://www.phpexperts.pro/), is my consultation company. It's a small company of a half dozen 258 | highly skilled Full Stack PHP devs, including myself, whom I place at 1099 positions at other corporations. We fill both 259 | long-term positions and, for crazy devs like me, short-term. If you ever wanted to work on a different project/company 260 | every few months or even weeks, anywhere in the continental U.S., Europe, or South East Asia, it's fantastic. 261 | 262 | Since 2015, I have set up branches in Las Vegas, Houston, the UK, Dublin, Costa Rica, Colombia, India, and the Philippines. 263 | If someone has a work auth in any of those places, we can place you almost anywhere you want. I travel 50% of the time 264 | out of choice. All over the world. 265 | -------------------------------------------------------------------------------- /bin/composer: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Detect if it's running inside of docker and run it natively if it is. 4 | # @see https://stackoverflow.com/a/25518345/430062 5 | if [ "$PHP_VERSION" == "native" ] || [ -f "/.dockerenv" ]; then 6 | (/bin/env --chdir=/ composer "$@") 7 | exit 8 | fi 9 | 10 | # Get the script's directory. 11 | # @see https://stackoverflow.com/a/246128/430062 12 | SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) 13 | 14 | ${SCRIPT_DIR}/php composer "$@" 15 | -------------------------------------------------------------------------------- /bin/php: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | ##################################################################### 3 | # The Dockerize PHP Project # 4 | # https://github.com/PHPExpertsInc/docker-php # 5 | # License: MIT # 6 | # # 7 | # Copyright © 2024 PHP Experts, Inc. # 8 | # Author: Theodore R. Smith # 9 | # PGP Sig: 4BF826131C3487ACD28F2AD8EB24A91DD6125690 # 10 | ##################################################################### 11 | 12 | # @see https://linuxize.com/post/how-to-check-if-string-contains-substring-in-bash/ 13 | # @see https://github.com/composer/composer/issues/10389 14 | SUB="/vendor/" 15 | if [[ "$0" == *"$SUB"* ]]; then 16 | ROOT="$(readlink -f /proc/$PPID/cwd)" 17 | else 18 | ROOT="$( cd "$( dirname "${BASH_SOURCE[0]}" )/.." && pwd )" 19 | fi 20 | 21 | ORIG_PHP_VERSION=$PHP_VERSION 22 | if [ -f "${ROOT}/.env" ]; then 23 | source "${ROOT}/.env" 24 | if [ ! -z "$ORIG_PHP_VERSION" ]; then 25 | PHP_VERSION="$ORIG_PHP_VERSION" 26 | fi 27 | fi 28 | 29 | # Detect if it's running inside of docker and run it natively if it is. 30 | # @see https://stackoverflow.com/a/25518345/430062 31 | if [ "$PHP_VERSION" == "native" ] || [ -f "/.dockerenv" ]; then 32 | PATH=/usr/bin php "$@" 33 | exit $? 34 | fi 35 | 36 | if [ -z "$PHP_VERSION" ]; then 37 | PHP_VERSION="8.1" 38 | fi 39 | 40 | if [ -z "$PROJECT_NAME" ]; then 41 | PROJECT_NAME=$(basename $ROOT | tr '[:upper:]' '[:lower:]' | sed "s/[^[:alpha:]-]//g") 42 | fi 43 | if [ -z "$NETWORK_NAME" ]; then 44 | NETWORK_NAME=${PROJECT_NAME}_default 45 | fi 46 | 47 | # Test if the network exists. 48 | NETWORK_STRING="--network=host" 49 | docker network inspect "$NETWORK_NAME" > /dev/null 2>&1 50 | if [ $? == 0 ]; then 51 | NETWORK_STRING="--network=$NETWORK_NAME" 52 | fi 53 | 54 | # Detect if the PHP container is running already... 55 | # If it is running, use it directly. 56 | if [ "$(docker top "${PROJECT_NAME}"${PHP_VERSION} 2> /dev/null)" ]; then 57 | # shellcheck disable=SC2086 58 | # This is broken... 59 | #docker run --name "${PROJECT_NAME}"${PHP_VERSION} "${NETWORK_STRING}" --env XDEBUG_SESSION --env XDEBUG_CONFIG -u=$UID -v $HOME:$HOME -v "$PWD":$PWD -v /etc/passwd:/etc/passwd:ro -v "$PWD":/workdir --rm -t phpexperts/php:${PHP_VERSION} & 60 | 61 | # Wait for the docker process to be created. 62 | while [ ! "$(docker top "${PROJECT_NAME}"${PHP_VERSION} 2> /dev/null)" ]; do 63 | # echo "Waiting for the phpexperts_php${PHP_VERSION} container to start..." 64 | sleep 0.5 65 | done 66 | 67 | # Run the command directly from the container for faster and more performant execution. 68 | if [ "$1" == "bash" ] || [ "$1" == "composer" ]; then 69 | docker exec -it "${PROJECT_NAME}"${PHP_VERSION} "$@" 70 | else 71 | docker exec -it "${PROJECT_NAME}"${PHP_VERSION} php "$@" 72 | fi 73 | 74 | exit 75 | fi 76 | 77 | TTY_OPTS='-t' 78 | if [ -t 0 ]; then 79 | # Input is from a terminal 80 | TTY_OPTS="-it" 81 | fi 82 | 83 | if [ "$1" == "dockerize" ]; then 84 | docker run -u=$UID -v "$PWD":/workdir --rm -it --network=host --entrypoint=install.sh phpexperts/php:${PHP_VERSION} 85 | exit 86 | fi 87 | 88 | 89 | docker run ${NETWORK_STRING} --env XDEBUG_SESSION --env XDEBUG_CONFIG -u=$UID \ 90 | -v $HOME:$HOME -v "$PWD":"$PWD" -w "$PWD" -v /etc/passwd:/etc/passwd:ro \ 91 | --rm ${TTY_OPTS} phpexperts/php:${PHP_VERSION} "$@" 92 | -------------------------------------------------------------------------------- /bin/php-ci.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | ##################################################################### 3 | # The Dockerize PHP Project # 4 | # https://github.com/PHPExpertsInc/docker-php # 5 | # License: MIT # 6 | # # 7 | # Copyright © 2024 PHP Experts, Inc. # 8 | # Author: Theodore R. Smith # 9 | # PGP Sig: 4BF826131C3487ACD28F2AD8EB24A91DD6125690 # 10 | ##################################################################### 11 | 12 | SUPPORTED_PHP_VERSIONS=$(php vendor/phpexperts/docker*/version-constraints.php) 13 | echo "Supported PHP versions: $SUPPORTED_PHP_VERSIONS" 14 | 15 | if [ -f .env ]; then 16 | source .env 17 | fi 18 | 19 | ORIG_PHPUNIT_V='' 20 | if [ -z "$PHPUNIT_V" ]; then 21 | ORIG_PHPUNIT_V="$PHPUNIT_V" 22 | fi 23 | 24 | time for PHPV in ${SUPPORTED_PHP_VERSIONS}-debug; do 25 | PHP_VERSION=$PHPV composer --version 26 | PHP_VERSION=$PHPV composer update 27 | DISPLAY_WARNINGS="--display-warnings --display-deprecations" 28 | # Assign the PHPUnit version, if it's not set inside of .env or $_ENV. 29 | if [ "$ORIG_PHPUNIT_V" == '' ]; then 30 | if [ $PHPV == '7.0' ]; then 31 | PHPUNIT_V='6' 32 | DISPLAY_WARNINGS='' 33 | elif [ $PHPV == '7.1' ]; then 34 | PHPUNIT_V='7' 35 | DISPLAY_WARNINGS='' 36 | elif [ $PHPV == '7.2' ]; then 37 | PHPUNIT_V='8' 38 | DISPLAY_WARNINGS='' 39 | elif [ $PHPV == '7.3' ] || [ $PHPV == '7.4' ] || [ $PHPV == '8.0' ]; then 40 | PHPUNIT_V='9' 41 | DISPLAY_WARNINGS='' 42 | elif [ $PHPV == '8.1' ]; then 43 | PHPUNIT_V='10' 44 | elif [ $PHPV == '8.2' ]; then 45 | PHPUNIT_V='11' 46 | else 47 | PHPUNIT_V='12' 48 | fi 49 | fi 50 | 51 | if [ -f phpunit.v${PHPUNIT_V}.xml ]; then 52 | echo PHP_VERSION=$PHPV phpunit -c phpunit.v${PHPUNIT_V}.xml $DISPLAY_WARNINGS 53 | PHP_VERSION=$PHPV phpunit -c phpunit.v${PHPUNIT_V}.xml $DISPLAY_WARNINGS 54 | else 55 | PHP_VERSION=$PHPV phpunit $DISPLAY_WARNINGS 56 | fi 57 | 58 | echo "Tested: PHP v$PHPV via PHPUnit v$PHPUNIT_V" 59 | sleep 2 60 | done 61 | 62 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "phpexperts/dockerize", 3 | "description": "The quickest and easiest way to switch any PHP app/library to use Docker.", 4 | "keywords": [ 5 | "docker", 6 | "dockerize", 7 | "new project" 8 | ], 9 | "homepage": "https://www.phpexperts.pro/", 10 | "license": "MIT", 11 | "authors": [ 12 | { 13 | "name": "PHP Experts, Inc.", 14 | "homepage": "https://www.phpexperts.pro/" 15 | }, 16 | { 17 | "name": "Theodore R. Smith", 18 | "homepage": "https://www.linkedin.com/in/tedrsmith" 19 | } 20 | ], 21 | "suggest": { 22 | "phpexperts/docker-phan": "Dockerized phan/phan", 23 | "phpexperts/docker-phpstan": "Dockerized phpstan/phpstan", 24 | "phpexperts/docker-rector": "Dockerized rector/rector" 25 | }, 26 | "scripts": { 27 | "post-install-cmd": [ 28 | "vendor/bin/php dockerize" 29 | ] 30 | }, 31 | "bin": ["bin/php", "bin/composer", "bin/php-ci.sh"] 32 | } 33 | -------------------------------------------------------------------------------- /docker/docker-compose.base.yml: -------------------------------------------------------------------------------- 1 | # The "version" tag has been deprecated, due to poor logic, imho... 2 | # @see https://github.com/docker/compose/issues/11628 3 | #version: '3.6' 4 | # Requires Docker v18.02 or higher. 5 | 6 | ##################################################################### 7 | # The Dockerize PHP Project # 8 | # https://github.com/PHPExpertsInc/docker-php # 9 | # License: MIT # 10 | # # 11 | # Copyright © 2018-2024 PHP Experts, Inc. # 12 | # Author: Theodore R. Smith # 13 | # PGP Sig: 4BF826131C3487ACD28F2AD8EB24A91DD6125690 # 14 | ##################################################################### 15 | 16 | services: 17 | {{PHP_STUB}} 18 | ###### CUSTOM EDITS START HERE ###### 19 | -------------------------------------------------------------------------------- /docker/web/nginx.conf: -------------------------------------------------------------------------------- 1 | user www-data; 2 | worker_processes auto; 3 | pid /run/nginx.pid; 4 | 5 | events { 6 | worker_connections 1024; 7 | # multi_accept on; 8 | } 9 | 10 | http { 11 | 12 | ## 13 | # Basic Settings2 14 | ## 15 | 16 | sendfile on; 17 | tcp_nopush on; 18 | tcp_nodelay on; 19 | keepalive_timeout 65; 20 | types_hash_max_size 2048; 21 | # server_tokens off; 22 | 23 | # server_names_hash_bucket_size 64; 24 | # server_name_in_redirect off; 25 | 26 | include /etc/nginx/mime.types; 27 | default_type application/octet-stream; 28 | 29 | ## 30 | # SSL Settings 31 | ## 32 | 33 | ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # Dropping SSLv3, ref: POODLE 34 | ssl_prefer_server_ciphers on; 35 | 36 | ## 37 | # Logging Settings 38 | ## 39 | 40 | access_log syslog:server=unix:/dev/log; 41 | error_log syslog:server=unix:/dev/log; 42 | 43 | ## 44 | # Gzip Settings 45 | ## 46 | 47 | gzip on; 48 | gzip_disable "msie6"; 49 | 50 | # gzip_vary on; 51 | # gzip_proxied any; 52 | # gzip_comp_level 6; 53 | # gzip_buffers 16 8k; 54 | # gzip_http_version 1.1; 55 | # gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript; 56 | 57 | ## 58 | # Virtual Host Configs 59 | ## 60 | 61 | include /etc/nginx/custom/sites/*.conf; 62 | } 63 | -------------------------------------------------------------------------------- /docker/web/sites/001_default.conf: -------------------------------------------------------------------------------- 1 | server { 2 | listen 80; 3 | root /var/www/public; 4 | index index.html index.php; 5 | 6 | location / { 7 | # Pretty URLs for Laravel. 8 | try_files $uri $uri/ /index.php?$args; 9 | } 10 | 11 | location ~ \.php$ { 12 | fastcgi_split_path_info ^(.+?\.php)(/.*)$; 13 | if (!-f $document_root$fastcgi_script_name) { 14 | return 404; 15 | } 16 | 17 | include fastcgi_params; 18 | fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; 19 | fastcgi_param PATH_INFO $fastcgi_path_info; 20 | fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info; 21 | 22 | fastcgi_pass localhost:9000; 23 | fastcgi_index index.php; 24 | } 25 | 26 | # set client body size to 30M 27 | client_max_body_size 30M; 28 | } 29 | -------------------------------------------------------------------------------- /docker/web/ssl/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /dockerize.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # @see https://linuxize.com/post/how-to-check-if-string-contains-substring-in-bash/ 4 | # @see https://github.com/composer/composer/issues/10389 5 | SUB="/vendor/" 6 | if [[ "$0" == *"$SUB"* ]]; then 7 | ROOT="$(readlink -f /proc/$PPID/cwd)" 8 | else 9 | ROOT="$( cd "$( dirname "${BASH_SOURCE[0]}" )/.." && pwd )" 10 | fi 11 | 12 | if ! groups | grep docker; then 13 | echo "Error: You must be in the 'docker' group." 14 | echo "Trying to add you now via 'sudo usermod -aG docker $USER'..." 15 | sudo usermod -aG docker $USER 16 | echo "Now you need to start a new shell to continue." 17 | exit 2; 18 | fi 19 | 20 | 21 | if ! echo $PATH | grep -q ./vendor/bin; then 22 | echo 'You do not have ./vendor/bin in your $PATH.' 23 | echo 'Modern PHP apps and phpexperts/dockerize require this.' 24 | 25 | if [ ! -f ${HOME}/.bashrc ]; then 26 | echo "ERROR: It doesn't look like you are using bash (no ~/.bashrc file)." 27 | echo " Please add ./vendor/bin to the PATH manually." 28 | exit 1 29 | fi 30 | 31 | echo '' 32 | echo -n 'May I add it to the front of your $PATH? (y/n) ' 33 | read YES_OR_NO 34 | echo '' 35 | 36 | if [ $YES_OR_NO == 'y' ]; then 37 | echo 'Adding ./vendor/bin to your $PATH' 38 | echo '# Added by phpexperts/dockerize' >> ~/.bashrc 39 | echo 'PATH=./vendor/bin:$PATH' >> ~/.bashrc 40 | 41 | echo 'Your $PATH has been updated. You need you start a new shell now.' 42 | exit 2 43 | else 44 | echo "You can run Dockerized PHP manually:" 45 | echo "" 46 | echo " ./vendor/bin/php" 47 | echo " ./vendor/bin/composer" 48 | fi 49 | fi 50 | 51 | mkdir -p ./vendor/bin 52 | #if [ ! -f ./vendor/bin/composer ]; then 53 | echo "Downloading phpexperts/dockerize's php CLI launcher..." 54 | curl https://raw.githubusercontent.com/PHPExpertsInc/dockerize/v12.x/bin/composer -o vendor/bin/composer 55 | echo "Downloading phpexperts/dockerize's composer CLI launcher..." 56 | curl https://raw.githubusercontent.com/PHPExpertsInc/dockerize/v12.x/bin/php -o vendor/bin/php 57 | #cp -v /code/dockerize/bin/php vendor/bin/php 58 | chmod 0755 ./vendor/bin/composer ./vendor/bin/php 59 | #fi 60 | hash -r 61 | 62 | ORIG_PHP_VERSION=$PHP_VERSION 63 | if [ -f "${ROOT}/.env" ]; then 64 | source "${ROOT}/.env" 65 | if [ ! -z "$ORIG_PHP_VERSION" ]; then 66 | PHP_VERSION="$ORIG_PHP_VERSION" 67 | fi 68 | fi 69 | 70 | if [ -z "$PHP_VERSION" ]; then 71 | PHP_VERSION="8.1" 72 | fi 73 | 74 | #echo "PHP Version: $PHP_VERSION" 75 | : 76 | export PHP_VERSION=8.3 77 | #cp -v /code/dockerize/bin/php vendor/bin/php 78 | 79 | vendor/bin/php --version 80 | 81 | #cp -v /code/dockerize/install.php vendor/phpexperts/dockerize/install.php 82 | 83 | 84 | #script -qc "/usr/bin/php vendor/phpexperts/dockerize/install.php" typescript 85 | vendor/bin/composer show phpexperts/dockerize > /dev/null 2>&1 || vendor/bin/composer require --ignore-platform-reqs --dev phpexperts/dockerize 86 | 87 | if [ ! -f docker-compose.yml ]; then 88 | if [ ! -f vendor/phpexperts/dockerize/install.php ]; then 89 | mkdir -p vendor/phpexperts/dockerize 90 | curl https://raw.githubusercontent.com/PHPExpertsInc/dockerize/v11.x/install.php -o vendor/phpexperts/dockerize/install.php 91 | fi 92 | vendor/bin/php dockerize 93 | fi 94 | -------------------------------------------------------------------------------- /engines/mariadb/.env.stub: -------------------------------------------------------------------------------- 1 | DB_CONNECTION=mysql 2 | DB_HOST=mariadb 3 | DB_USERNAME=root 4 | DB_PASSWORD=CHANGEME 5 | DB_DATABASE=test 6 | -------------------------------------------------------------------------------- /engines/mariadb/bin/mysql: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ROOT="$( cd "$( dirname "${BASH_SOURCE[0]}" )/.." && pwd )" 4 | 5 | if [ -f "${ROOT}/.env" ]; then 6 | . "${ROOT}/.env" 7 | fi 8 | 9 | if [ -z "$DB_HOST" ]; then 10 | DB_HOST="mariadb" 11 | fi 12 | 13 | USERNAME_ARG="" 14 | if [ -n "$DB_USERNAME" ]; then 15 | USERNAME_ARG="-u $DB_USERNAME" 16 | fi 17 | 18 | PASSWORD_ARG="" 19 | if [ -n "$DB_PASSWORD" ]; then 20 | PASSWORD_ARG="--password=${DB_PASSWORD}" 21 | fi 22 | 23 | 24 | if [ -z "$PROJECT_NAME" ]; then 25 | PROJECT_NAME=$(basename $ROOT | tr '[:upper:]' '[:lower:]' | sed "s/[^[:alpha:]-]//g") 26 | fi 27 | if [ -z "$NETWORK_NAME" ]; then 28 | NETWORK_NAME=${PROJECT_NAME}_default 29 | fi 30 | 31 | docker run \ 32 | --network "${NETWORK_NAME}" \ 33 | -it --rm \ 34 | -v $(pwd):/data \ 35 | mariadb:10.4 \ 36 | mysql --host=$DB_HOST $USERNAME_ARG $PASSWORD_ARG $DB_DATABASE "$@" 37 | -------------------------------------------------------------------------------- /engines/mariadb/bin/mysqldump: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ROOT="$( cd "$( dirname "${BASH_SOURCE[0]}" )/.." && pwd )" 4 | 5 | if [ -f "${ROOT}/.env" ]; then 6 | . "${ROOT}/.env" 7 | fi 8 | 9 | if [ -z "$DB_HOST" ]; then 10 | DB_HOST="mariadb" 11 | fi 12 | 13 | USERNAME_ARG="" 14 | if [ -n "$DB_USERNAME" ]; then 15 | USERNAME_ARG="-u $DB_USERNAME" 16 | fi 17 | 18 | PASSWORD_ARG="" 19 | if [ -n "$DB_PASSWORD" ]; then 20 | PASSWORD_ARG="--password=${DB_PASSWORD}" 21 | fi 22 | 23 | if [ -z "$PROJECT_NAME" ]; then 24 | PROJECT_NAME=$(basename $ROOT | tr '[:upper:]' '[:lower:]' | sed "s/[^[:alpha:]-]//g") 25 | fi 26 | if [ -z "$NETWORK_NAME" ]; then 27 | NETWORK_NAME=${PROJECT_NAME}_default 28 | fi 29 | 30 | docker run \ 31 | --network "${NETWORK_NAME}" \ 32 | -i --rm \ 33 | -v $(pwd):/data \ 34 | mariadb:10.4 \ 35 | mysqldump --host=$DB_HOST $USERNAME_ARG $PASSWORD_ARG "$@" 36 | -------------------------------------------------------------------------------- /engines/mariadb/bin/mysqli: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ROOT="$( cd "$( dirname "${BASH_SOURCE[0]}" )/.." && pwd )" 4 | 5 | if [ -f "${ROOT}/.env" ]; then 6 | . "${ROOT}/.env" 7 | fi 8 | 9 | if [ -z "$DB_HOST" ]; then 10 | DB_HOST="mariadb" 11 | fi 12 | 13 | USERNAME_ARG="" 14 | if [ -n "$DB_USERNAME" ]; then 15 | USERNAME_ARG="-u $DB_USERNAME" 16 | fi 17 | 18 | PASSWORD_ARG="" 19 | if [ -n "$DB_PASSWORD" ]; then 20 | PASSWORD_ARG="--password=${DB_PASSWORD}" 21 | fi 22 | 23 | if [ -z "$PROJECT_NAME" ]; then 24 | PROJECT_NAME=$(basename $ROOT | tr '[:upper:]' '[:lower:]' | sed "s/[^[:alpha:]-]//g") 25 | fi 26 | if [ -z "$NETWORK_NAME" ]; then 27 | NETWORK_NAME=${PROJECT_NAME}_default 28 | fi 29 | 30 | docker run \ 31 | --network "${NETWORK_NAME}" \ 32 | -i --rm \ 33 | -v $(pwd):/data \ 34 | mariadb:10.4 \ 35 | mysql --host=$DB_HOST $USERNAME_ARG $PASSWORD_ARG $DB_DATABASE "$@" 36 | -------------------------------------------------------------------------------- /engines/mariadb/docker-compose.stub.yml: -------------------------------------------------------------------------------- 1 | mariadb: 2 | image: mariadb:10.11 3 | volumes: 4 | - /var/lib/docker/mariadb/${DB_DATABASE}:/var/lib/mysql 5 | 6 | environment: 7 | MYSQL_ROOT_PASSWORD: ${DB_PASSWORD} 8 | MYSQL_DATABASE: ${DB_DATABASE} 9 | # Uncomment if you want it to be exposed system-wide. 10 | # ports: 11 | # - 3306:3306 12 | -------------------------------------------------------------------------------- /engines/postgres/.env.stub: -------------------------------------------------------------------------------- 1 | DB_CONNECTION=pgsql 2 | DB_HOST=postgres 3 | DB_USERNAME=phppro 4 | DB_PASSWORD=CHANGEME 5 | DB_DATABASE=test 6 | -------------------------------------------------------------------------------- /engines/postgres/bin/createdb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ROOT="$( cd "$( dirname "${BASH_SOURCE[0]}" )/.." && pwd )" 4 | 5 | if [ -f "${ROOT}/.env" ]; then 6 | . "${ROOT}/.env" 7 | fi 8 | 9 | if [ -z "$DB_HOST" ]; then 10 | DB_HOST="postgres" 11 | fi 12 | 13 | 14 | if [ -z "$PROJECT_NAME" ]; then 15 | PROJECT_NAME=$(basename $ROOT | tr '[:upper:]' '[:lower:]' | sed "s/[^[:alpha:]-]//g") 16 | fi 17 | if [ -z "$NETWORK_NAME" ]; then 18 | NETWORK_NAME=${PROJECT_NAME}_default 19 | fi 20 | 21 | docker run \ 22 | --network "${NETWORK_NAME}" \ 23 | -it \ 24 | -e PGPASSWORD="${DB_PASSWORD}" \ 25 | --volume ~/.pgpass:/root/.pgpass \ 26 | -v $(pwd):/data \ 27 | postgres:12.2 \ 28 | createdb --host=$DB_HOST -U $DB_USERNAME "$@" 29 | -------------------------------------------------------------------------------- /engines/postgres/bin/dropdb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ROOT="$( cd "$( dirname "${BASH_SOURCE[0]}" )/.." && pwd )" 4 | 5 | if [ -f "${ROOT}/.env" ]; then 6 | . "${ROOT}/.env" 7 | fi 8 | 9 | if [ -z "$DB_HOST" ]; then 10 | DB_HOST="postgres" 11 | fi 12 | 13 | 14 | if [ -z "$PROJECT_NAME" ]; then 15 | PROJECT_NAME=$(basename $ROOT | tr '[:upper:]' '[:lower:]' | sed "s/[^[:alpha:]-]//g") 16 | fi 17 | if [ -z "$NETWORK_NAME" ]; then 18 | NETWORK_NAME=${PROJECT_NAME}_default 19 | fi 20 | 21 | docker run \ 22 | --network "${NETWORK_NAME}" \ 23 | -it \ 24 | -e PGPASSWORD="${DB_PASSWORD}" \ 25 | --volume ~/.pgpass:/root/.pgpass \ 26 | -v $(pwd):/data \ 27 | postgres:12.2 \ 28 | dropdb --host=$DB_HOST -U $DB_USERNAME "$@" 29 | -------------------------------------------------------------------------------- /engines/postgres/bin/pg_dump: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ROOT="$( cd "$( dirname "${BASH_SOURCE[0]}" )/.." && pwd )" 4 | 5 | if [ -f "${ROOT}/.env" ]; then 6 | . "${ROOT}/.env" 7 | fi 8 | 9 | if [ -z "$DB_HOST" ]; then 10 | DB_HOST="postgres" 11 | fi 12 | 13 | USERNAME_ARG="" 14 | if [ -z "$DB_USERNAME" ]; then 15 | USERNAME_ARG="-u $DB_USERNAME" 16 | fi 17 | 18 | PASSWORD_ARG="" 19 | if [ -z "$DB_PASSWORD" ]; then 20 | PASSWORD_ARG="--password='${DB_PASSWORD}'" 21 | fi 22 | 23 | if [ -z "$PROJECT_NAME" ]; then 24 | PROJECT_NAME=$(basename $ROOT | tr '[:upper:]' '[:lower:]' | sed "s/[^[:alpha:]-]//g") 25 | fi 26 | if [ -z "$NETWORK_NAME" ]; then 27 | NETWORK_NAME=${PROJECT_NAME}_default 28 | fi 29 | 30 | docker run \ 31 | --network "${NETWORK_NAME}" \ 32 | -it \ 33 | -e PGPASSWORD="${DB_PASSWORD}" \ 34 | --volume ~/.pgpass:/root/.pgpass \ 35 | -v $(pwd):/data \ 36 | postgres:12.2 \ 37 | pg_dump --host=$DB_DB_HOST -U ${DB_USERNAME} "$@" 38 | -------------------------------------------------------------------------------- /engines/postgres/bin/psql: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ROOT="$( cd "$( dirname "${BASH_SOURCE[0]}" )/.." && pwd )" 4 | 5 | if [ -f "${ROOT}/.env" ]; then 6 | . "${ROOT}/.env" 7 | fi 8 | 9 | if [ -z "$DB_HOST" ]; then 10 | DB_HOST="postgres" 11 | fi 12 | 13 | USERNAME_ARG="" 14 | if [ -z "$DB_USERNAME" ]; then 15 | USERNAME_ARG="-u $DB_USERNAME" 16 | fi 17 | 18 | PASSWORD_ARG="" 19 | if [ -z "$DB_PASSWORD" ]; then 20 | PASSWORD_ARG="--password='${DB_PASSWORD}'" 21 | fi 22 | 23 | if [ -z "$PROJECT_NAME" ]; then 24 | PROJECT_NAME=$(basename $ROOT | tr '[:upper:]' '[:lower:]' | sed "s/[^[:alpha:]-]//g") 25 | fi 26 | if [ -z "$NETWORK_NAME" ]; then 27 | NETWORK_NAME=${PROJECT_NAME}_default 28 | fi 29 | docker run \ 30 | --network "${NETWORK_NAME}" \ 31 | -it \ 32 | -e PGPASSWORD="${DB_PASSWORD}" \ 33 | --volume ~/.pgpass:/root/.pgpass \ 34 | -v $(pwd):/data \ 35 | postgres:12.2 \ 36 | psql --host=postgres -U ${DB_USERNAME} --dbname=${DB_DATABASE} "$@" 37 | -------------------------------------------------------------------------------- /engines/postgres/docker-compose.stub.yml: -------------------------------------------------------------------------------- 1 | postgres: 2 | image: postgres:16 3 | volumes: 4 | - /var/lib/docker/postgres/${DB_DATABASE}:/var/lib/postgresql 5 | 6 | environment: 7 | POSTGRES_USER: ${DB_USERNAME} 8 | POSTGRES_PASSWORD: ${DB_PASSWORD} 9 | POSTGRES_DB: ${DB_DATABASE} 10 | # Uncomment if you want it to be exposed system-wide. 11 | # db: 12 | # ports: 13 | # - 5432:5432 14 | -------------------------------------------------------------------------------- /engines/postgres/docker/docker-compose.base.yml: -------------------------------------------------------------------------------- 1 | version: '2' 2 | 3 | services: 4 | web: 5 | image: phpexperts/web:nginx-php7.3 6 | depends_on: 7 | - db 8 | links: 9 | - db 10 | volumes: 11 | - ./web:/etc/nginx/custom 12 | - ..:/var/www 13 | 14 | db: 15 | image: postgres:9.6 16 | volumes: 17 | - /var/lib/docker/postgresql:/var/lib/postgresql 18 | 19 | environment: 20 | POSTGRES_USER: root 21 | POSTGRES_PASSWORD: root 22 | POSTGRES_DB: projectdb 23 | 24 | redis: 25 | image: redis:3.2.11 26 | entrypoint: 27 | - redis-server 28 | - --requirepass ${REDIS_PASSWORD} 29 | - --loglevel notice 30 | 31 | -------------------------------------------------------------------------------- /engines/postgres/docker/docker-compose.dev.yml: -------------------------------------------------------------------------------- 1 | version: '2' 2 | 3 | services: 4 | web: 5 | image: phpexperts/web:nginx-php7.3-debug 6 | ports: 7 | - 80:80 8 | 9 | db: 10 | ports: 11 | - 5432:5432 12 | -------------------------------------------------------------------------------- /engines/redis/.env.stub: -------------------------------------------------------------------------------- 1 | REDIS_PASSWORD=123456 2 | -------------------------------------------------------------------------------- /engines/redis/bin/redis-cli: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ROOT="$( cd "$( dirname "${BASH_SOURCE[0]}" )/.." && pwd )" 4 | 5 | . "${ROOT}/.env" 6 | 7 | if [ -z "$PROJECT_NAME" ]; then 8 | PROJECT_NAME=$(basename $ROOT | tr '[:upper:]' '[:lower:]' | sed "s/[^[:alpha:]-]//g") 9 | fi 10 | if [ -z "$NETWORK_NAME" ]; then 11 | NETWORK_NAME=${PROJECT_NAME}_default 12 | fi 13 | 14 | docker run -it \ 15 | --network "${NETWORK_NAME}" \ 16 | redis:3.2 redis-cli -h redis -a "${REDIS_PASSWORD}" "$@" 17 | -------------------------------------------------------------------------------- /engines/redis/docker-compose.stub.yml: -------------------------------------------------------------------------------- 1 | redis: 2 | # Warning: Redis changed to a proprietary license with v7.4 and later. 3 | # @see https://redis.io/blog/redis-adopts-dual-source-available-licensing/ 4 | image: redis:7.2 5 | entrypoint: 6 | - redis-server 7 | - --requirepass ${REDIS_PASSWORD} 8 | - --loglevel notice 9 | 10 | -------------------------------------------------------------------------------- /install.php: -------------------------------------------------------------------------------- 1 | #!/bin/env php 2 | 9 | * GPG Fingerprint: 4BF8 2613 1C34 87AC D28F 2AD8 EB24 A91D D612 5690 10 | * https://www.phpexperts.pro/ 11 | * https://github.com/PHPExpertsInc/dockerize 12 | * 13 | * This file is licensed under the MIT License. 14 | */ 15 | 16 | namespace PHPExperts\Dockerize; 17 | 18 | if (is_readable(getcwd() . '/docker-compose.yml')) { 19 | return; 20 | } 21 | 22 | class AvailablePort 23 | { 24 | public static int $PORT = 80; 25 | } 26 | 27 | $PHP_IMAGE = installPHP(); 28 | 29 | installDockerEngines($PHP_IMAGE); 30 | 31 | $DIR = __DIR__; 32 | if (!is_dir('./docker')) { 33 | if (!mkdir('./docker')) { 34 | alert('Error: Could not create the ./docker directory. Installation aborted.'); 35 | exit(4); 36 | } 37 | } 38 | system("cp -r $DIR/docker/web ./docker"); 39 | 40 | echo "\n"; 41 | alert('Next Steps: 1. You should edit your new .env.'); 42 | alert('Next Steps: 2. You should add ./bin to your $PATH.'); 43 | alert('Get Started: To launch the dockerized app, run: `docker-compose up -d`'); 44 | 45 | $funding = << $PHP_IMAGE) { 87 | $PHP_VERSION = $index > 0 ? str_replace(['-debug', '.'], '', $PHP_IMAGE) : ''; 88 | $PORT = $index === 0 ? findFirstAvailablePort(80) : "80{$PHP_VERSION}"; 89 | AvailablePort::$PORT = $PORT; 90 | 91 | $versionStub = << 0) { 118 | echo "Choose PHP Web Versions (e.g., '1 3' for both $PHP_VERSIONS[0] and $PHP_VERSIONS[2]):\n"; 119 | foreach ($PHP_VERSIONS as $index => $version) { 120 | ++$index; 121 | echo "$index) $version\n"; 122 | } 123 | 124 | $selection = getUserInput(); 125 | $selectedChoices = explode(' ', $selection); 126 | foreach ($selectedChoices as &$choice) { 127 | --$choice; 128 | } 129 | 130 | $invalidChoices = array_diff($selectedChoices, array_keys($PHP_VERSIONS)); 131 | 132 | if (!empty($invalidChoices)) { 133 | alert('Error: Invalid choice(s): ' . implode(', ', $invalidChoices)); 134 | $selection = ''; 135 | } 136 | } 137 | 138 | if ($tryCount <= 0) { 139 | echo "ERROR: Stuck in a loop...STDIN is probably missing. Try adding -i to the docker command.\n"; 140 | exit(3); 141 | } 142 | 143 | $selectedVersions = array_values(array_intersect_key($PHP_VERSIONS, array_flip($selectedChoices))); 144 | 145 | $yesNo = ''; 146 | while (!in_array($yesNo, ['y', 'n'])) { 147 | echo "\nDo you need every bundled PHP extension? (rarely needed; disables xdebug support) (y/N)\n"; 148 | $yesNo = getUserInput(); 149 | $yesNo = $yesNo === '' ? 'n' : $yesNo; 150 | } 151 | 152 | if ($yesNo === 'y') { 153 | $isFullBuild = true; 154 | foreach ($selectedVersions as &$version) { 155 | $version .= '-full'; 156 | } 157 | 158 | return $selectedVersions; 159 | } 160 | 161 | $yesNo = ''; 162 | while (!in_array($yesNo, ['y', 'n'])) { 163 | echo "\nDo you need Xdebug support? (y/N)\n"; 164 | $yesNo = getUserInput(); 165 | $yesNo = $yesNo === '' ? 'n' : $yesNo; 166 | } 167 | 168 | if ($yesNo === 'y') { 169 | foreach ($selectedVersions as &$version) { 170 | $version .= '-debug'; 171 | } 172 | 173 | return $selectedVersions; 174 | } 175 | 176 | $yesNo = ''; 177 | while (!in_array($yesNo, ['y', 'n'])) { 178 | echo "\nDo you need Ioncube Decoder support? (y/N)\n"; 179 | $yesNo = getUserInput(); 180 | $yesNo = $yesNo === '' ? 'n' : $yesNo; 181 | } 182 | 183 | if ($yesNo === 'y') { 184 | foreach ($selectedVersions as &$version) { 185 | $version .= '-ioncube'; 186 | } 187 | 188 | return $selectedVersions; 189 | } 190 | 191 | return $selectedVersions; 192 | } 193 | 194 | function installDockerEngines(string $PHP_IMAGE) 195 | { 196 | $engines = chooseDockerEngines(); 197 | 198 | if ($engines[0] === 'None') { 199 | return; 200 | } 201 | 202 | foreach ($engines as $engine) { 203 | installDockerEngine($engine, __DIR__ . "/engines/$engine"); 204 | } 205 | 206 | file_put_contents('.env.example', "\nPHP_VERSION=\"$PHP_IMAGE\"\n", FILE_APPEND); 207 | system('cp .env.example .env'); 208 | } 209 | 210 | function chooseDockerEngines($path = null, $filtered = []) 211 | { 212 | $path = $path !== null ? $path : __DIR__ . '/engines'; 213 | if (!is_dir($path)) { 214 | alert("Error: Cannot find '$path' directory."); 215 | exit(1); 216 | } 217 | 218 | $engines = getDirs($path, false, $filtered); 219 | array_unshift($engines, 'None'); 220 | $selection = ''; 221 | $selectedChoices = []; 222 | while ($selection === '') { 223 | echo "Choose engines (e.g., '1 3' for both $engines[1] and $engines[3]):\n"; 224 | foreach ($engines as $index => $engine) { 225 | echo "$index) $engine\n"; 226 | } 227 | 228 | $selection = getUserInput(); 229 | $selectedChoices = explode(' ', $selection); 230 | 231 | if (count($selectedChoices) > 1 && in_array(0, $selectedChoices)) { 232 | alert("Error: '$engines[0]' must be selected by itself."); 233 | $selection = ''; 234 | } 235 | 236 | $invalidChoices = array_diff($selectedChoices, array_keys($engines)); 237 | 238 | if (!empty($invalidChoices)) { 239 | alert('Error: Invalid choice(s): ' . implode(', ', $invalidChoices)); 240 | $selection = ''; 241 | } 242 | } 243 | 244 | $selectedEngines = array_values(array_intersect_key($engines, array_flip($selectedChoices))); 245 | 246 | return $selectedEngines; 247 | } 248 | 249 | /** 250 | * @param string $engine 251 | * @param string $enginePath 252 | */ 253 | function installDockerEngine($engine, $enginePath) 254 | { 255 | if (!is_dir($enginePath)) { 256 | alert("Error: Cannot find '$enginePath' directory."); 257 | exit(1); 258 | } 259 | 260 | echo "Installing the $engine Docker engine...\n"; 261 | if (is_dir("$enginePath/bin")) { 262 | if (!is_dir('./bin')) { 263 | if (!mkdir('./bin')) { 264 | alert('Error: Could not create the ./bin directory. Installation aborted.'); 265 | exit(2); 266 | } 267 | } 268 | system("cp $enginePath/bin/* ./bin"); 269 | } 270 | system("cat \"$enginePath/docker-compose.stub.yml\" >> ./docker-compose.yml"); 271 | system('echo >> ./docker-compose.yml'); 272 | 273 | if (file_exists("$enginePath/.env.stub")) { 274 | overwriteOrAppendFile("$enginePath/.env.stub", '.env.example'); 275 | } 276 | 277 | } 278 | 279 | function alert($message) 280 | { 281 | echo "v v v v v v v v v v v v v v v v v v v v v v v\n"; 282 | echo "--> $message\n"; 283 | echo "^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^\n\n"; 284 | 285 | } 286 | 287 | function getUserInput() 288 | { 289 | return trim(fgets(STDIN)); 290 | } 291 | 292 | /** 293 | * Copyright © 2020-2024 Theodore R. Smith 294 | * License: MIT 295 | * 296 | * @see https://stackoverflow.com/a/61168906/430062 297 | * 298 | * @param string $path 299 | * @param bool $recursive Default: false 300 | * @param array $filtered Default: [., ..] 301 | * @return array 302 | */ 303 | function getDirs($path, $recursive = false, array $filtered = []) 304 | { 305 | if (!is_dir($path)) { 306 | alert("Error: $path does not exist."); 307 | exit(1); 308 | } 309 | 310 | $filtered = array_merge(array('.', '..'), $filtered); 311 | 312 | $dirs = array(); 313 | $d = dir($path); 314 | while (($entry = $d->read()) !== false) { 315 | if (is_dir("$path/$entry") && !in_array($entry, $filtered)) { 316 | $dirs[] = $entry; 317 | 318 | if ($recursive) { 319 | $newDirs = getDirs("$path/$entry"); 320 | foreach ($newDirs as $newDir) { 321 | $dirs[] = "$entry/$newDir"; 322 | } 323 | } 324 | } 325 | } 326 | 327 | sort($dirs); 328 | 329 | return $dirs; 330 | } 331 | 332 | function overwriteOrAppendFile($srcFile, $destFile, $resetFirstRun = false) 333 | { 334 | static $firstRun = true; 335 | if ($resetFirstRun) { 336 | $firstRun = true; 337 | } 338 | 339 | if (!file_exists($srcFile)) { 340 | alert("Error: Cannot find '$srcFile'."); 341 | 342 | exit(3); 343 | } 344 | 345 | if (!file_exists($destFile)) { 346 | $srcFile = escapeshellarg($srcFile); 347 | $destFile = escapeshellarg($destFile); 348 | system("echo '#### Block Added by phpexperts/dockerize ####' >> $destFile"); 349 | system("cp $srcFile $destFile"); 350 | $firstRun = false; 351 | 352 | return; 353 | } 354 | 355 | $selection = null; 356 | $shouldAppend = !$firstRun; 357 | while ($firstRun && !in_array($selection, [1, 2])) { 358 | echo "Append or overwrite $destFile? (1: Append, 2: Overwrite) "; 359 | $selection = getUserInput(); 360 | $shouldAppend = $selection === '1' ? true : false; 361 | } 362 | 363 | if (!$shouldAppend) { 364 | $srcFile = escapeshellarg($srcFile); 365 | system("cp $srcFile " . escapeshellarg($destFile)); 366 | $shouldAppend = true; 367 | $firstRun = false; 368 | 369 | return; 370 | } 371 | 372 | $srcFile = escapeshellarg($srcFile); 373 | $destFile = escapeshellarg($destFile); 374 | system("echo >> $destFile"); 375 | system("echo '#### Block Added by phpexperts/dockerize ####' >> $destFile"); 376 | system("cat $srcFile >> $destFile"); 377 | system("echo '#### End Block ####' >> $destFile"); 378 | 379 | $firstRun = false; 380 | } 381 | 382 | $port = AvailablePort::$PORT; 383 | echo "\n"; 384 | echo "=========================================================================\n"; 385 | echo "==== Dockerized Nginx will be listening on http://localhost:$port/ ====\n"; 386 | echo "==== Edit the credentials in the .env now and then run ====\n"; 387 | echo "==== docker compose up ====\n"; 388 | echo "=========================================================================\n"; 389 | -------------------------------------------------------------------------------- /public/index.php: -------------------------------------------------------------------------------- 1 | 8 | * GPG Fingerprint: 4BF8 2613 1C34 87AC D28F 2AD8 EB24 A91D D612 5690 9 | * https://www.phpexperts.pro/ 10 | * https://github.com/PHPExpertsInc/dockerize 11 | * 12 | * This file is licensed under the MIT License. 13 | */ 14 | 15 | /** 16 | * Utility class for working with Composer version constraints. 17 | * 18 | * Provides methods for validating constraints, checking if a version satisfies 19 | * a constraint (using the authoritative Composer library), and generating 20 | * example versions that match constraints. 21 | * 22 | * Copied with permission from phpexperts/composer-constraints-parser 23 | */ 24 | class ComposerConstraintsHelper 25 | { 26 | /** 27 | * Check if a version satisfies a constraint. 28 | * 29 | * @param string $constraints Version constraint (can contain OR/AND operators) 30 | * @param string $version Version to check 31 | * @return bool True if the version satisfies the constraint 32 | */ 33 | public function versionSatisfies($constraints, $version) 34 | { 35 | // Normalize version to have at least 3 parts 36 | $version = self::ensure2Dots($version); 37 | 38 | // Normalize constraint formatting 39 | $constraints = $this->normalizeConstraints($constraints); 40 | 41 | // Split constraint by OR operator (| or -) 42 | $orConstraints = preg_split('/[|-]/', $constraints); 43 | 44 | foreach ($orConstraints as $orConstraint) { 45 | $orConstraint = trim($orConstraint); 46 | 47 | // Split by AND operator (,) 48 | $andConstraints = preg_split('/[ ,]/', $orConstraint); 49 | $allAndSatisfied = true; 50 | 51 | foreach ($andConstraints as $singleConstraint) { 52 | if (!empty($singleConstraint) && !$this->satisfiesSingleConstraint($singleConstraint, $version)) { 53 | $allAndSatisfied = false; 54 | break; 55 | } 56 | } 57 | 58 | if ($allAndSatisfied) { 59 | return true; // If all AND conditions in this OR branch are satisfied, version is valid 60 | } 61 | } 62 | 63 | return false; 64 | } 65 | 66 | /** 67 | * Ensures a version string has at least 3 parts (major.minor.patch). 68 | * 69 | * @param string $version Version to normalize 70 | * @return string Normalized version with at least 3 parts 71 | */ 72 | private static function ensure2Dots($version) 73 | { 74 | $versionParts = explode('.', $version); 75 | if (count($versionParts) < 3) { 76 | $version .= str_repeat('.0', 3 - count($versionParts)); 77 | } 78 | 79 | return $version; 80 | } 81 | 82 | /** 83 | * Normalize constraint string formatting. 84 | * 85 | * @param string $constraints Constraints to normalize 86 | * @return string Normalized constraints 87 | */ 88 | private function normalizeConstraints($constraints) 89 | { 90 | // Convert "* >" to ">" and other normalizations 91 | $constraints = preg_replace('/\* ?([>strEndsWith($constraint, '-dev') || $this->strEndsWith($constraint, '-rc')) { 118 | return true; 119 | } 120 | 121 | // Strip v prefix 122 | $constraint = preg_replace('/([><=~^]+)?v/i', '$1', $constraint); 123 | $version = preg_replace('/v([0-9]+)/i', '$1', $version); 124 | 125 | // Normalize hyphen ranges (e.g., "1.0 - 2.0" to ">=1.0 <2.0") 126 | $constraint = self::normalizeHyphenRanges($constraint); 127 | 128 | // Format standardization 129 | $constraint = preg_replace('/([>strEndsWith($constraint, '.')) { 137 | $constraint = substr($constraint, 0, -1); 138 | } 139 | 140 | // Replace .x with .* 141 | $constraint = str_ireplace('.x', '.*', $constraint); 142 | 143 | // Handle wildcards 144 | if (strpos($constraint, '*') !== false) { 145 | $pattern = str_replace('.', '\.', $constraint); 146 | $pattern = str_replace('*', '(\d+){1,2}', $pattern); 147 | return preg_match('/^' . $pattern . '/', $version) === 1; 148 | } 149 | 150 | // Handle caret (^) - allows changes that don't modify the left-most non-zero digit 151 | if ($this->strStartsWith($constraint, '^')) { 152 | return $this->handleCaretConstraint($constraint, $version); 153 | } 154 | 155 | // Handle tilde (~) - allows the specified precision of version 156 | if ($this->strStartsWith($constraint, '~')) { 157 | return $this->handleTildeConstraint($constraint, $version); 158 | } 159 | 160 | // Handle comparison operators (>, >=, <, <=, =) 161 | if (preg_match('/^([><=]+)(\d+(\.\d+)?(\.\d+)?)/', $constraint, $matches)) { 162 | $operator = $matches[1]; 163 | $compareVersion = self::ensure2Dots($matches[2]); 164 | return version_compare($version, $compareVersion, $operator); 165 | } 166 | 167 | // Handle exact version 168 | if (preg_match('/^\d+(\.\d+)?(\.\d+)?$/', $constraint)) { 169 | $constraint = self::ensure2Dots($constraint); 170 | return version_compare($version, $constraint, '=='); 171 | } 172 | 173 | return false; // Unknown constraint format 174 | } 175 | 176 | /** 177 | * Handle caret (^) constraint matching. 178 | * 179 | * @param string $constraint Caret constraint (e.g., "^1.2.3") 180 | * @param string $version Version to check 181 | * @return bool True if the version satisfies the constraint 182 | */ 183 | private function handleCaretConstraint($constraint, $version) 184 | { 185 | $baseVersion = substr($constraint, 1); 186 | $baseVersion = self::ensure2Dots($baseVersion); 187 | 188 | if (preg_match('/^0\.(\d+)/', $baseVersion, $matches)) { 189 | // Special case for 0.x: only allow changes in patch version 190 | $minor = (int)$matches[1]; 191 | $nextMinor = "0." . ($minor + 1) . ".0"; 192 | return version_compare($version, $baseVersion, '>=') && 193 | version_compare($version, $nextMinor, '<'); 194 | } elseif (preg_match('/^(\d+)/', $baseVersion, $matches)) { 195 | // Normal case: allow everything that doesn't change the major version 196 | $major = (int)$matches[0]; 197 | $nextMajor = ($major + 1) . ".0.0"; 198 | return version_compare($version, $baseVersion, '>=') && 199 | version_compare($version, $nextMajor, '<'); 200 | } 201 | 202 | return false; 203 | } 204 | 205 | /** 206 | * Handle tilde (~) constraint matching. 207 | * 208 | * @param string $constraint Tilde constraint (e.g., "~1.2.3") 209 | * @param string $version Version to check 210 | * @return bool True if the version satisfies the constraint 211 | */ 212 | private function handleTildeConstraint($constraint, $version) 213 | { 214 | $baseVersion = substr($constraint, 1); 215 | $parts = explode('.', $baseVersion); 216 | $major = (int)($parts[0] ?? 0); 217 | $minor = (int)($parts[1] ?? 0); 218 | $nextMinor = "$major." . ($minor + 1) . ".0"; 219 | $baseVersion = self::ensure2Dots($baseVersion); 220 | return version_compare($version, $baseVersion, '>=') && 221 | version_compare($version, $nextMinor, '<'); 222 | } 223 | 224 | /** 225 | * Converts hyphen ranges (e.g., "5 - 6") to standard comparison operators. 226 | * 227 | * @param string $constraint Constraint with potential hyphen ranges 228 | * @return string Normalized constraint 229 | */ 230 | private static function normalizeHyphenRanges($constraint) 231 | { 232 | // Convert "X - Y" to ">=X =$lower <$upper"; 239 | }, 240 | $constraint 241 | ); 242 | } 243 | 244 | /** 245 | * Check if a string starts with a specific substring (PHP < 8.0 compatibility) 246 | * 247 | * @param string $haystack The string to search in 248 | * @param string $needle The substring to search for 249 | * @return bool Returns true if haystack starts with needle 250 | */ 251 | private function strStartsWith($haystack, $needle) 252 | { 253 | return strpos($haystack, $needle) === 0; 254 | } 255 | 256 | /** 257 | * Check if a string ends with a specific substring (PHP < 8.0 compatibility) 258 | * 259 | * @param string $haystack The string to search in 260 | * @param string $needle The substring to search for 261 | * @return bool Returns true if haystack ends with needle 262 | */ 263 | private function strEndsWith($haystack, $needle) 264 | { 265 | $length = strlen($needle); 266 | if ($length === 0) { 267 | return true; 268 | } 269 | return substr($haystack, -$length) === $needle; 270 | } 271 | } 272 | 273 | class PhpVersionExtractor 274 | { 275 | private $allVersions = ['5.6', '7.0', '7.1', '7.2', '7.3', '7.4', '8.0', '8.1', '8.2', '8.3', '8.4']; 276 | private $composerJson; 277 | public $versionConstraint; 278 | 279 | public function __construct($composerJson) 280 | { 281 | $this->composerJson = $composerJson; 282 | } 283 | 284 | public function getPhpVersionConstraint() 285 | { 286 | if ($this->versionConstraint === null) { 287 | $this->getPhpVersions(); 288 | } 289 | 290 | return $this->versionConstraint; 291 | } 292 | 293 | public function getPhpVersions() 294 | { 295 | $phpConstraint = $this->extractPhpConstraint(); 296 | $this->versionConstraint = $phpConstraint; 297 | 298 | if (is_null($phpConstraint)) { 299 | return implode(' ', $this->allVersions); 300 | } 301 | 302 | $selectedVersions = []; 303 | 304 | foreach ($this->allVersions as $version) { 305 | if ((new ComposerConstraintsHelper())->versionSatisfies($phpConstraint, $version)) { 306 | $selectedVersions[] = $version; 307 | } 308 | } 309 | 310 | return implode(' ', $selectedVersions); 311 | } 312 | 313 | private function extractPhpConstraint() 314 | { 315 | if (!is_readable($this->composerJson)) { 316 | return null; 317 | } 318 | 319 | $data = json_decode(file_get_contents($this->composerJson), true); 320 | 321 | if (isset($data['require']) && isset($data['require']['php'])) { 322 | return $data['require']['php']; 323 | } 324 | 325 | return null; 326 | } 327 | 328 | } 329 | 330 | // Usage example 331 | $composerJson = 'composer.json'; 332 | $extractor = new PhpVersionExtractor($composerJson); 333 | echo $extractor->getPhpVersions(); 334 | --------------------------------------------------------------------------------