Jelajahi Sumber

Merge branch 'master' into mftf-setup

Mark Shust 3 tahun lalu
induk
melakukan
8cc8b3c053
64 mengubah file dengan 1597 tambahan dan 395 penghapusan
  1. 34 0
      .github/workflows/build-elasticsearch.yml
  2. 34 0
      .github/workflows/build-nginx.yml
  3. 91 0
      .github/workflows/build-php.yml
  4. 30 0
      .github/workflows/shellcheck.yml
  5. 148 1
      CHANGELOG.md
  6. 165 159
      README.md
  7. 1 5
      compose/.vscode/launch.json
  8. 24 0
      compose/bin/cache-clean
  9. 1 0
      compose/bin/clinotty
  10. 4 0
      compose/bin/cliq
  11. 6 2
      compose/bin/copyfromcontainer
  12. 8 4
      compose/bin/copytocontainer
  13. 7 0
      compose/bin/dev-test-run
  14. 12 8
      compose/bin/download
  15. 3 3
      compose/bin/fixowns
  16. 4 6
      compose/bin/fixperms
  17. 9 1
      compose/bin/mysql
  18. 2 0
      compose/bin/mysqldump
  19. 11 5
      compose/bin/n98-magerun2
  20. 2 0
      compose/bin/pwa-studio
  21. 1 1
      compose/bin/remove
  22. 6 6
      compose/bin/removevolumes
  23. 2 2
      compose/bin/restart
  24. 60 77
      compose/bin/setup
  25. 31 0
      compose/bin/setup-composer-auth
  26. 16 0
      compose/bin/setup-domain
  27. 3 3
      compose/bin/setup-grunt
  28. 22 0
      compose/bin/setup-integration-tests
  29. 1 0
      compose/bin/setup-pwa-studio
  30. 12 3
      compose/bin/setup-ssl-ca
  31. 53 2
      compose/bin/start
  32. 1 1
      compose/bin/stop
  33. 2 1
      compose/bin/update
  34. 52 9
      compose/bin/xdebug
  35. 22 22
      compose/docker-compose.dev.yml
  36. 17 10
      compose/docker-compose.yml
  37. 7 0
      compose/env/db.env
  38. 9 0
      compose/env/magento.env
  39. 22 0
      compose/template/dev/tests/integration/etc/install-config-mysql.php.2.3.dist
  40. 24 0
      compose/template/dev/tests/integration/etc/install-config-mysql.php.2.4.dist
  41. TEMPAT SAMPAH
      docs/course.png
  42. TEMPAT SAMPAH
      docs/macademy-logo.png
  43. TEMPAT SAMPAH
      docs/set-up-magento-2-development-environment-docker-og.png
  44. 4 0
      images/elasticsearch/7.7/Dockerfile
  45. 4 0
      images/elasticsearch/7.9/Dockerfile
  46. 8 6
      images/nginx/1.18/Dockerfile
  47. 2 1
      images/nginx/1.18/conf/default.conf
  48. 18 25
      images/php/7.3/Dockerfile
  49. 4 0
      images/php/7.3/conf/msmtprc
  50. 2 4
      images/php/7.3/conf/php.ini
  51. 24 22
      images/php/7.4/Dockerfile
  52. 0 0
      images/php/7.4/bin/cronstart
  53. 4 0
      images/php/7.4/conf/msmtprc
  54. 0 0
      images/php/7.4/conf/php-fpm.conf
  55. 15 0
      images/php/7.4/conf/php.ini
  56. 0 0
      images/php/7.4/conf/www.conf
  57. 90 0
      images/php/8.0/Dockerfile
  58. 7 0
      images/php/8.0/bin/cronstart
  59. 4 0
      images/php/8.0/conf/msmtprc
  60. 31 0
      images/php/8.0/conf/php-fpm.conf
  61. 0 0
      images/php/8.0/conf/php.ini
  62. 413 0
      images/php/8.0/conf/www.conf
  63. 7 6
      lib/onelinesetup
  64. 1 0
      lib/template

+ 34 - 0
.github/workflows/build-elasticsearch.yml

@@ -0,0 +1,34 @@
+name: build-elasticsearch
+
+on: workflow_dispatch
+
+jobs:
+  elasticsearch-7-9:
+    runs-on: ubuntu-latest
+    steps:
+      -
+        name: Checkout
+        uses: actions/checkout@v2
+      -
+        name: Set up QEMU
+        uses: docker/setup-qemu-action@v1
+      -
+        name: Set up Docker Buildx
+        uses: docker/setup-buildx-action@v1
+      -
+        name: Login to DockerHub
+        uses: docker/login-action@v1 
+        with:
+          username: ${{ secrets.DOCKERHUB_USERNAME }}
+          password: ${{ secrets.DOCKERHUB_TOKEN }}
+      -
+        name: Build and push
+        id: docker_build
+        uses: docker/build-push-action@v2
+        with:
+          context: images/elasticsearch/7.9
+          platforms: linux/amd64,linux/arm64
+          push: true
+          tags: |
+            markoshust/magento-elasticsearch:7.9
+            markoshust/magento-elasticsearch:7.9.3-0

+ 34 - 0
.github/workflows/build-nginx.yml

@@ -0,0 +1,34 @@
+name: build-nginx
+
+on: workflow_dispatch
+
+jobs:
+  nginx-1-18:
+    runs-on: ubuntu-latest
+    steps:
+      -
+        name: Checkout
+        uses: actions/checkout@v2
+      -
+        name: Set up QEMU
+        uses: docker/setup-qemu-action@v1
+      -
+        name: Set up Docker Buildx
+        uses: docker/setup-buildx-action@v1
+      -
+        name: Login to DockerHub
+        uses: docker/login-action@v1 
+        with:
+          username: ${{ secrets.DOCKERHUB_USERNAME }}
+          password: ${{ secrets.DOCKERHUB_TOKEN }}
+      -
+        name: Build and push
+        id: docker_build
+        uses: docker/build-push-action@v2
+        with:
+          context: images/nginx/1.18
+          platforms: linux/amd64,linux/arm64
+          push: true
+          tags: |
+            markoshust/magento-nginx:1.18
+            markoshust/magento-nginx:1.18-4

+ 91 - 0
.github/workflows/build-php.yml

@@ -0,0 +1,91 @@
+name: build-php
+
+on: workflow_dispatch
+
+jobs:
+  php-7-3:
+    runs-on: ubuntu-latest
+    steps:
+      -
+        name: Checkout
+        uses: actions/checkout@v2
+      -
+        name: Set up QEMU
+        uses: docker/setup-qemu-action@v1
+      -
+        name: Set up Docker Buildx
+        uses: docker/setup-buildx-action@v1
+      -
+        name: Login to DockerHub
+        uses: docker/login-action@v1
+        with:
+          username: ${{ secrets.DOCKERHUB_USERNAME }}
+          password: ${{ secrets.DOCKERHUB_TOKEN }}
+      -
+        name: Build and push
+        id: docker_build
+        uses: docker/build-push-action@v2
+        with:
+          context: images/php/7.3
+          platforms: linux/amd64,linux/arm64
+          push: true
+          tags: |
+            markoshust/magento-php:7.3-fpm
+            markoshust/magento-php:7.3-fpm-16
+  php-7-4:
+    runs-on: ubuntu-latest
+    steps:
+      -
+        name: Checkout
+        uses: actions/checkout@v2
+      -
+        name: Set up QEMU
+        uses: docker/setup-qemu-action@v1
+      -
+        name: Set up Docker Buildx
+        uses: docker/setup-buildx-action@v1
+      -
+        name: Login to DockerHub
+        uses: docker/login-action@v1
+        with:
+          username: ${{ secrets.DOCKERHUB_USERNAME }}
+          password: ${{ secrets.DOCKERHUB_TOKEN }}
+      -
+        name: Build and push
+        id: docker_build
+        uses: docker/build-push-action@v2
+        with:
+          context: images/php/7.4
+          platforms: linux/amd64,linux/arm64
+          push: true
+          tags: |
+            markoshust/magento-php:7.4-fpm
+            markoshust/magento-php:7.4-fpm-9
+  php-8-0:
+    runs-on: ubuntu-latest
+    steps:
+      -
+        name: Checkout
+        uses: actions/checkout@v2
+      -
+        name: Set up QEMU
+        uses: docker/setup-qemu-action@v1
+      -
+        name: Set up Docker Buildx
+        uses: docker/setup-buildx-action@v1
+      -
+        name: Login to DockerHub
+        uses: docker/login-action@v1
+        with:
+          username: ${{ secrets.DOCKERHUB_USERNAME }}
+          password: ${{ secrets.DOCKERHUB_TOKEN }}
+      -
+        name: Build and push
+        id: docker_build
+        uses: docker/build-push-action@v2
+        with:
+          context: images/php/8.0
+          platforms: linux/amd64,linux/arm64
+          push: true
+          tags: |
+            markoshust/magento-php:8.0-fpm-develop

+ 30 - 0
.github/workflows/shellcheck.yml

@@ -0,0 +1,30 @@
+name: 'ShellCheck'
+
+on: 
+  push:
+    paths:
+    - 'compose/bin/**'
+    branches:
+    - "master"
+
+  pull_request:
+    paths:
+    - 'compose/bin/**'
+
+jobs:
+  shellcheck:
+    name: shellcheck
+    runs-on: ubuntu-latest
+    steps:
+
+    - name: Checkout
+      uses: actions/checkout@v2
+
+    - name: Run ShellCheck
+      uses: ludeeus/action-shellcheck@master
+      id: check
+      env:
+        SHELLCHECK_OPTS: -x -e SC2181 -P compose/bin -P compose/env
+      with:
+        check_together: true
+        scandir: './compose/bin'

+ 148 - 1
CHANGELOG.md

@@ -6,7 +6,154 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
 
 ## [Unreleased]
 
-N/A
+- PHP image `8.0-fpm-develop` now available for testing purposes.
+
+## [39.1.0] - 2021-09-21
+
+### Updated
+- Replace MailHog with Mailcatcher for multi-arch compatibility [#511](https://github.com/markshust/docker-magento/issues/511).
+
+## [39.0.2] - 2021-09-21
+
+### Fixed
+- Fixed placement of enabling developer mode within bin/setup.
+
+## [39.0.1] - 2021-09-21
+
+### Fixed
+- Connection to Redis fails without php-redis extension [#474](https://github.com/markshust/docker-magento/issues/474).
+
+## [39.0.0] - 2021-09-21
+
+### Added
+- New Elasticsearch Docker images `7.9`, `7.9.3-0` [#488](https://github.com/markshust/docker-magento/issues/488).
+
+### Updated
+- Replace Percona DB with MariaDB 10.4 [#514](https://github.com/markshust/docker-magento/issues/514).
+- Updated RabbitMQ image to 3.8.
+
+### Fixed
+- Resolve cron install script not in bin/setup [#420](https://github.com/markshust/docker-magento/issues/420).
+- Update Elasticsearch settings to fix catalog search index error [#488](https://github.com/markshust/docker-magento/issues/488).
+
+## [38.0.0] - 2021-07-27
+
+### Added
+- Composer 2 support [#409](https://github.com/markshust/docker-magento/issues/409).
+
+### Fixed
+- Composer `auth.json` not properly set after installation [#42](https://github.com/markshust/docker-magento/issues/42).
+- `bin/remove` not removing containers in newer versions of Docker Compose.
+- Invalid template error with Docker 3.5.1 [#486](https://github.com/markshust/docker-magento/issues/486).
+
+## [37.0.2] - 2021-02-17
+
+### Added
+- New `bin/setup-composer-auth` file to setup Composer auth creds.
+
+## [37.0.1] - 2021-02-15
+
+### Fixed
+- Fix onelinesetup script bug.
+
+## [37.0.0] - 2021-02-14
+
+### Added
+- Official support for Xdebug 3 [#390](https://github.com/markshust/docker-magento/issues/390). The new PHP images are `7.3-fpm-12` & `7.4-fpm-5`.
+- If you need to still use Xdebug 2, update your docker-compose.yml files to instead look at PHP image `7.3-fpm-11` or `7.4-fpm-4`. These images are exactly the same other than being pegged to Xdebug 2.
+
+## [36.0.2] - 2021-02-14
+
+### Updated
+- Reverted Xdebug to version 2 for backwards-compatible support [#390](https://github.com/markshust/docker-magento/issues/390).
+
+## [36.0.1] - 2021-02-04
+
+### Updated
+- Reverted DB image back to `percona:5.7` until issues with MySQL 8.0 image are resolved.
+
+## [36.0.0] - 2021-02-04
+
+### Added
+- New Elasticsearch Docker images `7.7`, `7.7.1-0` [#392](https://github.com/markshust/docker-magento/issues/392).
+- SpellCheck GitHub Action for continuous integration checks of shell scripts [#387](https://github.com/markshust/docker-magento/pull/387), [#388](https://github.com/markshust/docker-magento/pull/388).
+
+### Fixed
+- Support filesystem paths with spaces [e5f22e56](https://github.com/markshust/docker-magento/commit/e5f22e56fcd382b8339d5804a9d236dd6b238a3d).
+- Added missing `bin/cache-clean` file [f0e57202](https://github.com/markshust/docker-magento/commit/f0e5720281cd9f536f163bd5bdfe5bd66a956dc6).
+
+### Updated
+- Updated PHP images to NodeJS version 14 LTS [4a81f2b8](https://github.com/markshust/docker-magento/commit/4a81f2b8c61674b261ee7b42752e21fc8d5e945d).
+- Changed `db` service to use MySQL 8.0 Docker image.
+
+## [35.0.0] - 2021-01-29
+
+### Added
+- Automatically purge caches for a better dev experience [#380](https://github.com/markshust/docker-magento/issues/380).
+- Stop script execution on error [#363](https://github.com/markshust/docker-magento/pull/363/).
+- Make xdebug command understand partials [#371](https://github.com/markshust/docker-magento/pull/371).
+- Extended functionality for `bin/xdebug`, including new `status` and `toggle` commands [#332](https://github.com/markshust/docker-magento/pull/332).
+- Check Elasticsearch connection before setup:install [#326](https://github.com/markshust/docker-magento/pull/326).
+
+### Updated
+- The onelinesetup now accepts a `community` or `enterprise` param to pick version to install [b2399ff1](https://github.com/markshust/docker-magento/commit/ad573f6f3c8d2f7066034cbde936a86eb2399ff1).
+- Fix bin/start for macOS Big Sur [#355](https://github.com/markshust/docker-magento/pull/355/).
+
+## [34.2.0] - 2020-10-15
+
+### Updated
+- Updated Composer to version `1.10.15` to avoid nag update messages in new PHP Docker images `7.3-fpm-9`, `7.4-fpm-2`.
+
+## [34.1.0] - 2020-10-15
+
+### Added
+- HTTP/2 added to Nginx image `1.18-4`
+
+### Updated
+- `bin/download` falls back to using Composer if archive download fails or is not found.
+
+## [34.0.0] - 2020-10-11
+
+### Added
+- New `bin/setup-integration-tests` script to setup integration tests [3c021ff](https://github.com/markshust/docker-magento/commit/3c021ff6c92e49fad669deed0805cceae26bdccf).
+- Added `MYSQL_HOST` environment variable to `env/db.env` file.
+- New Nginx `1.18-3` Docker images uses Alpine as base image [PR #306](https://github.com/markshust/docker-magento/pull/306).
+
+### Updated
+- Prevent containers from starting if volume mapping doesn't exist, validate volumes to avoid empty folder creation [PR #256](https://github.com/markshust/docker-magento/pull/256).
+- Setup script uses MySQL `env/db.env` file for database connection credentials [PR #302](https://github.com/markshust/docker-magento/pull/302).
+- Increased MySQL's `max_allowed_packet` to `64M` in `docker-compose.yml` file [PR #303](https://github.com/markshust/docker-magento/pull/303).
+- `docker-compose.yml` now uses Alpine images for Redis and RabbitMQ [#305](https://github.com/markshust/docker-magento/pull/305).
+- `docker-compose.yml` file now uses new Alpine images for Redis, RabbitMQ & Nginx.
+- `bin/setup` script updated to use Redis for cache and session directly in installer script [PR #304](https://github.com/markshust/docker-magento/pull/304).
+- `bin/setup` script sets Admin URL to `/admin` [PR #304](https://github.com/markshust/docker-magento/pull/304).
+- Enabling/disabling Xdebug now only restarts `phpfpm` container rather than all containers [PR #314](https://github.com/markshust/docker-magento/pull/314).
+- `bin/setup` script moves `.vscode` directory to `src` after install [846d02c](https://github.com/markshust/docker-magento/commit/846d02c12c5af8005fe0cbb0b167b97f501db0c9).
+
+### Fixed
+- Exception while running integration tests [#292](https://github.com/markshust/docker-magento/pull/292).
+- Nested files not copying in copytocontainer script [#295](https://github.com/markshust/docker-magento/pull/295) [#296](https://github.com/markshust/docker-magento/pull/295).
+- Ubuntu unable to start because of missing volumes [#309](https://github.com/markshust/docker-magento/issues/309).
+
+## [33.0.0] - 2020-07-30
+
+### Added
+- The `php:7.4-fpm` Docker image has been setup with full support for Magento 2.4 (see [images/php/7.4](https://github.com/markshust/docker-magento/tree/master/images/php/7.4)).
+- Added easy way to mount an SSH key to the container (see [#89](https://github.com/markshust/docker-magento/issues/89)).
+- The `bin/download` script now falls back to Hypernode's Magento Download mirror in the event the archive doesn't exist or fails to download from Nexcess.
+
+### Updated
+- All Docker volumes now use `:cached` rather than `:delegated`. The `delegated` volume functionality is changing in a future version of Docker for Mac to use Mutagen volumes, and the implementation is very buggy & awkward. Using the `cached` flag retains the current functionality we've been using in `delegated` without any changes (confirmed in [docker/for-mac#1592](https://github.com/docker/for-mac/issues/1592#issuecomment-662504816)).
+- Updated `bin/setup-ssl-ca` so SSL generation works on Linux ([#222](https://github.com/markshust/docker-magento/issues/222))
+- Updated `php` Docker images to use most recent version of Composer (1.10.9).
+- The `bin/setup` script now runs `composer update` rather than `composer install`. There was an error happening with `composer install`, and with the start of the project it's best to just get the most recent Composer packages anyway.
+- The `bin/setup` script now sets Elasticsearch 7 as the default catalog search engine directly when executing `bin/magento setup:install`.
+
+### Removed
+- All `latest` tags have been removed on all Docker images. It is bad practice to not use a specific version. The `latest` tag will no longer be recompiled when new images are released.
+- The `php:7.2` Docker images have been deprecated, as that version is no longer supported in Magento.
+- The `elasticsearch:6` Docker images have been deprecated, as those versions are no longer supported in Magento.
+- Removed invalid checksum hack fix in `bin/setup` for `google-shopping-api` package, as that is only applicable to older versions of Magento.
 
 ## [32.0.1] - 2020-05-12
 

+ 165 - 159
README.md

@@ -3,6 +3,7 @@
 <div align="center">
   <p>Mark Shust's Docker Configuration for Magento</p>
   <img src="https://img.shields.io/badge/magento-2.X-brightgreen.svg?logo=magento&longCache=true&style=flat-square" alt="Supported Magento Versions" />
+  <img src="https://img.shields.io/badge/apple%20silicon%20support-coming%20soon-yellow" alt="Apple Silicon Support" />
   <a href="https://hub.docker.com/r/markoshust/magento-nginx/" target="_blank"><img src="https://img.shields.io/docker/pulls/markoshust/magento-nginx.svg?label=nginx%20docker%20pulls" alt="Docker Hub Pulls - Nginx" /></a>
   <a href="https://hub.docker.com/r/markoshust/magento-php/" target="_blank"><img src="https://img.shields.io/docker/pulls/markoshust/magento-php.svg?label=php%20docker%20pulls" alt="Docker Hub Pulls - PHP" /></a>
   <a href="https://GitHub.com/Naereen/StrapDown.js/graphs/commit-activity" target="_blank"><img src="https://img.shields.io/badge/maintained%3F-yes-brightgreen.svg?style=flat-square" alt="Maintained - Yes" /></a>
@@ -11,8 +12,8 @@
 
 ## Table of contents
 
-- [Free Course](#free-course)
 - [Docker Hub](#docker-hub)
+- [Free Course](#free-course)
 - [Usage](#usage)
 - [Prerequisites](#prerequisites)
 - [Setup](#setup)
@@ -22,99 +23,107 @@
 - [Credits](#credits)
 - [License](#license)
 
+## Docker Hub
+
+View Dockerfiles:
+
+- [markoshust/magento-nginx (Docker Hub)](https://hub.docker.com/r/markoshust/magento-nginx/)
+  - 1.18
+      - [`1.18`, `1.18-4`](https://github.com/markshust/docker-magento/tree/master/images/nginx/1.18)
+      - [`1.18-3`](https://github.com/markshust/docker-magento/tree/34.0.0/images/nginx/1.18)
+      - [`1.18-2`](https://github.com/markshust/docker-magento/tree/33.0.0/images/nginx/1.18)
+      - [`1.18-1`](https://github.com/markshust/docker-magento/tree/31.0.1/images/nginx/1.18)
+      - [`1.18-0`](https://github.com/markshust/docker-magento/tree/31.0.0/images/nginx/1.18)
+- [markoshust/magento-php (Docker Hub)](https://hub.docker.com/r/markoshust/magento-php/)
+  - 8.0 (available for alpha testing)
+      - [`8.0-fpm-develop`](https://github.com/markshust/docker-magento/tree/master/images/php/8.0)
+  - 7.4
+      - [`7.4-fpm`, `7.4-fpm-9`](https://github.com/markshust/docker-magento/tree/master/images/php/7.4)
+      - [`7.4-fpm-8`](https://github.com/markshust/docker-magento/tree/39.0.2/images/php/7.4)
+      - [`7.4-fpm-7`](https://github.com/markshust/docker-magento/tree/39.0.0/images/php/7.4)
+      - [`7.4-fpm-6`](https://github.com/markshust/docker-magento/tree/38.0.0/images/php/7.4)
+      - [`7.4-fpm-5`](https://github.com/markshust/docker-magento/tree/37.0.2/images/php/7.4)
+      - [`7.4-fpm-4`](https://github.com/markshust/docker-magento/tree/36.0.2/images/php/7.4)
+      - [`7.4-fpm-3`](https://github.com/markshust/docker-magento/tree/36.0.1/images/php/7.4)
+      - [`7.4-fpm-2`](https://github.com/markshust/docker-magento/tree/34.2.0/images/php/7.4)
+      - [`7.4-fpm-1`](https://github.com/markshust/docker-magento/tree/34.1.0/images/php/7.4)
+      - [`7.4-fpm-0`](https://github.com/markshust/docker-magento/tree/33.0.0/images/php/7.4)
+  - 7.3
+      - [`7.3-fpm`, `7.3-fpm-16`](https://github.com/markshust/docker-magento/tree/master/images/php/7.3)
+      - [`7.3-fpm-15`](https://github.com/markshust/docker-magento/tree/39.0.2/images/php/7.3)
+      - [`7.3-fpm-14`](https://github.com/markshust/docker-magento/tree/39.0.0/images/php/7.3)
+      - [`7.3-fpm-13`](https://github.com/markshust/docker-magento/tree/38.0.0/images/php/7.3)
+      - [`7.3-fpm-12`](https://github.com/markshust/docker-magento/tree/37.0.2/images/php/7.3)
+      - [`7.3-fpm-11`](https://github.com/markshust/docker-magento/tree/36.0.2/images/php/7.3)
+      - [`7.3-fpm-10`](https://github.com/markshust/docker-magento/tree/36.0.1/images/php/7.3)
+      - [`7.3-fpm-9`](https://github.com/markshust/docker-magento/tree/34.2.0/images/php/7.3)
+      - [`7.3-fpm-8`](https://github.com/markshust/docker-magento/tree/34.1.0/images/php/7.3)
+      - [`7.3-fpm-7`](https://github.com/markshust/docker-magento/tree/33.0.0/images/php/7.3)
+      - [`7.3-fpm-6`](https://github.com/markshust/docker-magento/tree/32.0.1/images/php/7.3)
+      - [`7.3-fpm-5`](https://github.com/markshust/docker-magento/tree/30.0.0/images/php/7.3)
+      - [`7.3-fpm-4`](https://github.com/markshust/docker-magento/tree/29.0.0/images/php/7.3)
+      - [`7.3-fpm-3`](https://github.com/markshust/docker-magento/tree/28.0.0/images/php/7.3)
+      - [`7.3-fpm-2`](https://github.com/markshust/docker-magento/tree/27.2.0/images/php/7.3)
+      - [`7.3-fpm-1`](https://github.com/markshust/docker-magento/tree/26.0.0/images/php/7.3)
+      - [`7.3-fpm-0`](https://github.com/markshust/docker-magento/tree/24.2.0/images/php/7.3)
+- [markoshust/magento-elasticsearch (Docker Hub)](https://hub.docker.com/r/markoshust/magento-elasticsearch/)
+  - 7
+      - [`7.9`, `7.9.3-0`](https://github.com/markshust/docker-magento/tree/master/images/elasticsearch/7.9)
+      - [`7.7`, `7.7.1-0`](https://github.com/markshust/docker-magento/tree/master/images/elasticsearch/7.7)
+      - [`7.6`, `7.6.2-2`](https://github.com/markshust/docker-magento/tree/35.0.0/images/elasticsearch/7.6)
+      - [`7.6.2-1`](https://github.com/markshust/docker-magento/tree/32.0.0/images/elasticsearch/7.6)
+      - [`7.6.2-0`](https://github.com/markshust/docker-magento/tree/31.0.2/images/elasticsearch/7.6)
+
 ## Free Course
 
-This course is sponsored by <a href="https://m.academy" target="_blank">M.academy</a>. Level up your Magento 2 skills with a collection of resources including lessons, courses & more.
+This course is sponsored by <a href="https://m.academy" target="_blank">M.academy</a>, the simplest way to learn Magento.
 
 <a href="https://m.academy" target="_blank"><img src="https://raw.githubusercontent.com/markshust/docker-magento/master/docs/macademy-logo.png" alt="M.academy"></a>
 
-A free screencast course is available, which details the basic usage of this project:
-
-<a href="https://m.academy/courses/setup-magento-2-development-environment-docker" target="_blank">
-<img src="https://raw.githubusercontent.com/markshust/docker-magento/master/docs/course.png" alt="Course image"><br />
-<br />
-Setup a Magento 2 Development Environment with Docker
+A free screencast course is available, which details the basic usage of this project: <a href="https://m.academy/courses/set-up-magento-2-development-environment-docker" target="_blank">
+Set Up a Magento 2 Development Environment with Docker
 </a>
 
 ### Course Curriculm
 
 #### Project Setup
 
-- <a href="https://courses.m.academy/courses/setup-magento-2-development-environment-docker/lectures/9205849" target="_blank">Setup Docker for Mac & configure preferences</a>
-- <a href="https://courses.m.academy/courses/setup-magento-2-development-environment-docker/lectures/9273365" target="_blank">Setup global Composer auth credentials</a>
-- <a href="https://courses.m.academy/courses/setup-magento-2-development-environment-docker/lectures/8974570" target="_blank">Automated setup for new installs</a>
+- <a href="https://courses.m.academy/courses/set-up-magento-2-development-environment-docker/lectures/9205849" target="_blank">Setup Docker for Mac & configure preferences</a>
+- <a href="https://courses.m.academy/courses/set-up-magento-2-development-environment-docker/lectures/9273365" target="_blank">Setup global Composer auth credentials</a>
+- <a href="https://courses.m.academy/courses/set-up-magento-2-development-environment-docker/lectures/8974570" target="_blank">Automated setup for new installs</a>
 
 #### Helper Scripts
 
-- <a href="https://courses.m.academy/courses/setup-magento-2-development-environment-docker/lectures/9064258" target="_blank">Run CLI commands within containers</a>
-- <a href="https://courses.m.academy/courses/setup-magento-2-development-environment-docker/lectures/9331008" target="_blank">Stop, start & restart containers</a>
-- <a href="https://courses.m.academy/courses/setup-magento-2-development-environment-docker/lectures/9064269" target="_blank">Run binaries within containers</a>
+- <a href="https://courses.m.academy/courses/set-up-magento-2-development-environment-docker/lectures/9064258" target="_blank">Run CLI commands within containers</a>
+- <a href="https://courses.m.academy/courses/set-up-magento-2-development-environment-docker/lectures/9331008" target="_blank">Stop, start & restart containers</a>
+- <a href="https://courses.m.academy/courses/set-up-magento-2-development-environment-docker/lectures/9064269" target="_blank">Run binaries within containers</a>
 
 #### Docker Filesystem & Volumes
 
-- <a href="https://courses.m.academy/courses/setup-magento-2-development-environment-docker/lectures/9064334" target="_blank">Understand volumes & host bind mounts</a>
-- <a href="https://courses.m.academy/courses/setup-magento-2-development-environment-docker/lectures/9064338" target="_blank">Manage files & folders on containers</a>
+- <a href="https://courses.m.academy/courses/set-up-magento-2-development-environment-docker/lectures/9064334" target="_blank">Understand volumes & host bind mounts</a>
+- <a href="https://courses.m.academy/courses/set-up-magento-2-development-environment-docker/lectures/9064338" target="_blank">Manage files & folders on containers</a>
 
 #### Customize Server Configuration
 
-- <a href="https://courses.m.academy/courses/setup-magento-2-development-environment-docker/lectures/9064349" target="_blank">Customize the Nginx configuration</a>
-- <a href="https://courses.m.academy/courses/setup-magento-2-development-environment-docker/lectures/9064356" target="_blank">Quickly switch PHP versions</a>
-- <a href="https://courses.m.academy/courses/setup-magento-2-development-environment-docker/lectures/9064350" target="_blank">Install extensions & packages</a>
-- <a href="https://courses.m.academy/courses/setup-magento-2-development-environment-docker/lectures/9064477" target="_blank">Run additional services as containers</a>
-- <a href="https://courses.m.academy/courses/setup-magento-2-development-environment-docker/lectures/14780970" target="_blank">Configure multi-store instances</a>
+- <a href="https://courses.m.academy/courses/set-up-magento-2-development-environment-docker/lectures/9064349" target="_blank">Customize the Nginx configuration</a>
+- <a href="https://courses.m.academy/courses/set-up-magento-2-development-environment-docker/lectures/9064356" target="_blank">Quickly switch PHP versions</a>
+- <a href="https://courses.m.academy/courses/set-up-magento-2-development-environment-docker/lectures/9064350" target="_blank">Install extensions & packages</a>
+- <a href="https://courses.m.academy/courses/set-up-magento-2-development-environment-docker/lectures/9064477" target="_blank">Run additional services as containers</a>
+- <a href="https://courses.m.academy/courses/set-up-magento-2-development-environment-docker/lectures/14780970" target="_blank">Configure multi-store instances</a>
 
 #### PHPStorm & Xdebug
 
-- <a href="https://courses.m.academy/courses/setup-magento-2-development-environment-docker/lectures/9748834" target="_blank">Setup PHPStorm for a Magento Docker project</a>
-- <a href="https://courses.m.academy/courses/setup-magento-2-development-environment-docker/lectures/9763893" target="_blank">Generate XML URNs for a Magento Docker project</a>
-- <a href="https://courses.m.academy/courses/setup-magento-2-development-environment-docker/lectures/9064478" target="_blank">Install Xdebug browser plugin</a>
-- <a href="https://courses.m.academy/courses/setup-magento-2-development-environment-docker/lectures/9064482" target="_blank">Enable, disable, & check Xdebug</a>
-- <a href="https://courses.m.academy/courses/setup-magento-2-development-environment-docker/lectures/9064615" target="_blank">Configure PHPStorm for Xdebug</a>
-- <a href="https://courses.m.academy/courses/setup-magento-2-development-environment-docker/lectures/9064617" target="_blank">Trigger Xdebug breakpoints with PHPStorm</a>
+- <a href="https://courses.m.academy/courses/set-up-magento-2-development-environment-docker/lectures/9748834" target="_blank">Setup PHPStorm for a Magento Docker project</a>
+- <a href="https://courses.m.academy/courses/set-up-magento-2-development-environment-docker/lectures/9763893" target="_blank">Generate XML URNs for a Magento Docker project</a>
+- <a href="https://courses.m.academy/courses/set-up-magento-2-development-environment-docker/lectures/9064478" target="_blank">Install Xdebug browser plugin</a>
+- <a href="https://courses.m.academy/courses/set-up-magento-2-development-environment-docker/lectures/9064482" target="_blank">Enable, disable, & check Xdebug</a>
+- <a href="https://courses.m.academy/courses/set-up-magento-2-development-environment-docker/lectures/9064615" target="_blank">Configure PHPStorm for Xdebug</a>
+- <a href="https://courses.m.academy/courses/set-up-magento-2-development-environment-docker/lectures/9064617" target="_blank">Trigger Xdebug breakpoints with PHPStorm</a>
 
 #### Manual Setup (Optional)
 
-- <a href="https://courses.m.academy/courses/setup-magento-2-development-environment-docker/lectures/9064259" target="_blank">Manual setup for new Magento installs</a>
-- <a href="https://courses.m.academy/courses/setup-magento-2-development-environment-docker/lectures/9283467" target="_blank">Manual setup for an existing Magento instance</a>
-
-## Docker Hub
-
-View Dockerfiles:
-
-- [markoshust/magento-nginx (Docker Hub)](https://hub.docker.com/r/markoshust/magento-nginx/)
-  - 1.18
-      - [`latest`, `1.18`, `1.18-2`](https://github.com/markshust/docker-magento/tree/master/images/nginx/1.18)
-      - [`1.18-1`](https://github.com/markshust/docker-magento/tree/31.0.1/images/nginx/1.18)
-      - [`1.18-0`](https://github.com/markshust/docker-magento/tree/31.0.0/images/nginx/1.18)
-- [markoshust/magento-php (Docker Hub)](https://hub.docker.com/r/markoshust/magento-php/)
-  - 7.3
-      - [`latest`, `7.3-fpm`, `7.3-fpm-6`](https://github.com/markshust/docker-magento/tree/master/images/php/7.3)
-      - [`7.3-fpm-5`](https://github.com/markshust/docker-magento/tree/30.0.0/images/php/7.3)
-      - [`7.3-fpm-4`](https://github.com/markshust/docker-magento/tree/29.0.0/images/php/7.3)
-      - [`7.3-fpm-3`](https://github.com/markshust/docker-magento/tree/28.0.0/images/php/7.3)
-      - [`7.3-fpm-2`](https://github.com/markshust/docker-magento/tree/27.2.0/images/php/7.3)
-      - [`7.3-fpm-1`](https://github.com/markshust/docker-magento/tree/26.0.0/images/php/7.3)
-      - [`7.3-fpm-0`](https://github.com/markshust/docker-magento/tree/24.2.0/images/php/7.3)
-  - 7.2
-      - [`7.2-fpm`, `7.2-fpm-9`](https://github.com/markshust/docker-magento/tree/master/images/php/7.2)
-      - [`7.2-fpm-8`](https://github.com/markshust/docker-magento/tree/30.0.0/images/php/7.2)
-      - [`7.2-fpm-7`](https://github.com/markshust/docker-magento/tree/29.0.0/images/php/7.2)
-      - [`7.2-fpm-6`](https://github.com/markshust/docker-magento/tree/28.0.0/images/php/7.2)
-      - [`7.2-fpm-5`](https://github.com/markshust/docker-magento/tree/27.2.0/images/php/7.2)
-      - [`7.2-fpm-4`](https://github.com/markshust/docker-magento/tree/26.0.0/images/php/7.2)
-      - [`7.2-fpm-3`](https://github.com/markshust/docker-magento/tree/24.2.0/images/php/7.2)
-      - [`7.2-fpm-2`](https://github.com/markshust/docker-magento/tree/23.2.1/images/php/7.2)
-      - [`7.2-fpm-1`](https://github.com/markshust/docker-magento/tree/23.1.1/images/php/7.2)
-      - [`7.2-fpm-0`](https://github.com/markshust/docker-magento/tree/23.0.0/images/php/7.2)
-- [markoshust/magento-elasticsearch (Docker Hub)](https://hub.docker.com/r/markoshust/magento-elasticsearch/)
-  - 7
-      - [`latest`, `7.6`, `7.6.2-2`](https://github.com/markshust/docker-magento/tree/master/images/elasticsearch/7.6)
-      - [`7.6.2-1`](https://github.com/markshust/docker-magento/tree/32.0.0/images/elasticsearch/7.6)
-      - [`7.6.2-0`](https://github.com/markshust/docker-magento/tree/31.0.2/images/elasticsearch/7.6)
-  - 6
-      - [`6.8`, `6.8.8-1`](https://github.com/markshust/docker-magento/tree/master/images/elasticsearch/6.8)
-      - [`6.8`, `6.8.8-0`](https://github.com/markshust/docker-magento/tree/32.0.0/images/elasticsearch/6.8)
-      - [`6.5`, `6.5.4-0`](https://github.com/markshust/docker-magento/tree/31.0.2/images/elasticsearch/6.5)
+- <a href="https://courses.m.academy/courses/set-up-magento-2-development-environment-docker/lectures/9064259" target="_blank">Manual setup for new Magento installs</a>
+- <a href="https://courses.m.academy/courses/set-up-magento-2-development-environment-docker/lectures/9283467" target="_blank">Manual setup for an existing Magento instance</a>
 
 ## Usage
 
@@ -129,7 +138,7 @@ Folders:
 
 ## Prerequisites
 
-This setup assumes you are running Docker on a computer with at least 4GB of allocated RAM, a dual-core, and an SSD hard drive. [Download & Install Docker Desktop](https://www.docker.com/products/docker-desktop).
+This setup assumes you are running Docker on a computer with at least 6GB of RAM allocated to Docker, a dual-core, and an SSD hard drive. [Download & Install Docker Desktop](https://www.docker.com/products/docker-desktop).
 
 This configuration has been tested on Mac & Linux. Windows is supported through the use of Docker on WSL.
 
@@ -139,27 +148,26 @@ This configuration has been tested on Mac & Linux. Windows is supported through
 
 Run this automated one-liner from the directory you want to install your project.
 
-#### No sample data
-
 ```bash
-curl -s https://raw.githubusercontent.com/markshust/docker-magento/master/lib/onelinesetup | bash -s -- magento2.test 2.3.5-p1
+curl -s https://raw.githubusercontent.com/markshust/docker-magento/master/lib/onelinesetup | bash -s -- magento.test 2.4.3
 ```
 
-#### With sample data
+The `magento.test` above defines the hostname to use, and the `2.4.3` defines the Magento version to install. Note that since we need a write to `/etc/hosts` for DNS resolution, you will be prompted for your system password during setup.
 
-```bash
-curl -s https://raw.githubusercontent.com/markshust/docker-magento/master/lib/onelinesetup | bash -s -- magento2.test with-samples-2.3.5-p1
-```
+After the one-liner above completes running, you should be able to access your site at `https://magento.test`.
 
-The `magento2.test` above defines the hostname to use, and the `2.3.5-p1` defines the Magento version to install. Note that since we need a write to `/etc/hosts` for DNS resolution, you will be prompted for your system password during setup.
+#### Install sample data
 
-Prefix the version with `with-samples-` if you would like to automatically install sample data along with Magento.
+After the above installation is complete, run the following lines to install sample data:
 
-After the one-liner above completes running, you should be able to access your site at `https://magento2.test`.
+```bash
+bin/magento sampledata:deploy
+bin/magento setup:upgrade
+```
 
 ### Manual Setup
 
-Same result as the one-liner above. Just replace `magento2.test` references with the hostname that you wish to use.
+Same result as the one-liner above. Just replace `magento.test` references with the hostname that you wish to use.
 
 #### New Projects
 
@@ -168,27 +176,18 @@ Same result as the one-liner above. Just replace `magento2.test` references with
 curl -s https://raw.githubusercontent.com/markshust/docker-magento/master/lib/template | bash
 
 # Download the version of Magento you want to use with:
-bin/download 2.3.5-p1
-
-# or if you'd rather install with Composer, run:
-#
-# OPEN SOURCE:
-#
-# rm -rf src
-# composer create-project --repository=https://repo.magento.com/ --ignore-platform-reqs magento/project-community-edition=2.3.5-p1 src
-#
-# COMMERCE:
-#
-# rm -rf src
-# composer create-project --repository=https://repo.magento.com/ --ignore-platform-reqs magento/project-enterprise-edition=2.3.5-p1 src
-
-# Create a DNS host entry for the site:
-echo "127.0.0.1 ::1 magento2.test" | sudo tee -a /etc/hosts
+bin/download 2.4.3
+
+# or for Magento core development:
+# docker-compose -f docker-compose.yml up -d
+# bin/setup-composer-auth
+# bin/cli git clone git@github.com:magento/magento2.git .
+# bin/cli git checkout 2.4-develop
 
 # Run the setup installer for Magento:
-bin/setup magento2.test
+bin/setup magento.test
 
-open https://magento2.test
+open https://magento.test
 ```
 
 #### Existing Projects
@@ -197,27 +196,16 @@ open https://magento2.test
 # Download the Docker Compose template:
 curl -s https://raw.githubusercontent.com/markshust/docker-magento/master/lib/template | bash
 
-# Remove existing src directory:
-rm -rf src
-
 # Replace with existing source code of your existing Magento instance:
 cp -R ~/Sites/existing src
 # or: git clone git@github.com:myrepo.git src
 
-# Create a DNS host entry for the site:
-echo "127.0.0.1 ::1 yoursite.test" | sudo tee -a /etc/hosts
-
-# Start some containers, copy files ot them and then restart the containers:
-docker-compose up -d
-rm -rf src/vendor
+# Start some containers, copy files to them and then restart the containers:
+docker-compose -f docker-compose.yml up -d
 bin/copytocontainer --all ## Initial copy will take a few minutes...
 
-# Install composer dependencies, then copy artifacts back to the host (for debugging purposes):
-bin/composer install
-bin/copyfromcontainer vendor
-
 # Import existing database:
-bin/clinotty mysql -hdb -umagento -pmagento magento < existing/magento.sql
+bin/mysql < backups/magento.sql
 
 # Update database connection details to use the above Docker MySQL credentials:
 # Also note: creds for the MySQL server are defined at startup from env/db.env
@@ -226,13 +214,12 @@ bin/clinotty mysql -hdb -umagento -pmagento magento < existing/magento.sql
 # Import app-specific environment settings:
 bin/magento app:config:import
 
-# Set base URLs to local environment URL (if not defined in env.php file):
-bin/magento config:set web/secure/base_url https://yoursite.test/
-bin/magento config:set web/unsecure/base_url https://yoursite.test/
+# Create a DNS host entry and setup Magento base url
+bin/setup-domain yoursite.test
 
 bin/restart
 
-open https://magento2.test
+open https://magento.test
 ```
 
 > For more details on how everything works, see the extended [setup readme](https://github.com/markshust/docker-magento/blob/master/SETUP.md).
@@ -249,34 +236,27 @@ We recommend keeping your docker config files in version control, so you can mon
 
 It is recommended to keep your root docker config files in one repository, and your Magento code setup in another. This ensures the Magento base path lives at the top of one specific repository, which makes automated build pipelines and deployments easy to manage, and maintains compatibility with projects such as Magento Cloud.
 
-### Older Versions
-
-Versions older than `24.0.0` did not include a `bin/update` helper script, and versions older than `26.0.0` had a different directory structure. For both of these situations, you can download the most recent file to your project by running:
-
-```
-(cd bin && curl -OL https://raw.githubusercontent.com/markshust/docker-magento/master/compose/bin/update && chmod +x update)
-```
-
-You'll now have an updated `bin/update` helper script, and can run it to update your project.
-
 ## Custom CLI Commands
 
 - `bin/bash`: Drop into the bash prompt of your Docker container. The `phpfpm` container should be mainly used to access the filesystem within Docker.
+- `bin/cache-clean`: Access the [cache-clean](https://github.com/mage2tv/magento-cache-clean) CLI. Note the watcher is automatically started at startup in `bin/start`. Ex. `bin/cache-clean config full_page`
 - `bin/cli`: Run any CLI command without going into the bash prompt. Ex. `bin/cli ls`
 - `bin/clinotty`: Run any CLI command with no TTY. Ex. `bin/clinotty chmod u+x bin/magento`
+- `bin/cliq`: The same as `bin/cli`, but pipes all output to `/dev/null`. Useful for a quiet CLI, or implementing long-running processes.
 - `bin/composer`: Run the composer binary. Ex. `bin/composer install`
 - `bin/copyfromcontainer`: Copy folders or files from container to host. Ex. `bin/copyfromcontainer vendor`
 - `bin/copytocontainer`: Copy folders or files from host to container. Ex. `bin/copytocontainer --all`
 - `bin/dev-urn-catalog-generate`: Generate URN's for PHPStorm and remap paths to local host. Restart PHPStorm after running this command.
 - `bin/devconsole`: Alias for `bin/n98-magerun2 dev:console`
-- `bin/download`: Download & extract specific Magento version to the `src` directory. Ex. `bin/download 2.3.3`
+- `bin/download`: Download specific Magento version from Composer to `/var/www/html` directory within the container. Ex. `bin/download 2.4.3 community`
 - `bin/fixowns`: This will fix filesystem ownerships within the container.
 - `bin/fixperms`: This will fix filesystem permissions within the container.
 - `bin/grunt`: Run the grunt binary. Ex. `bin/grunt exec`
 - `bin/magento`: Run the Magento CLI. Ex: `bin/magento cache:flush`
 - `bin/mftf`: Run the Magento MFTF. Ex: `bin/mftf build:project`
-- `bin/mysql`: Run the MySQL CLI with database config from env/db.env. Ex `bin/mysql -e "EXPLAIN core_config_data"`
-- `bin/n98-magerun2`: Access the n98 magerun CLI. Ex: `bin/n98-magerun2 dev:console`
+- `bin/mysql`: Run the MySQL CLI with database config from `env/db.env`. Ex. `bin/mysql -e "EXPLAIN core_config_data"` or`bin/mysql < backups/magento.sql`
+- `bin/mysqldump`: Backup the Magento database. Ex. `bin/mysqldump > backups/magento.sql`
+- `bin/n98-magerun2`: Access the [n98-magerun2](https://github.com/netz98/n98-magerun2) CLI. Ex: `bin/n98-magerun2 dev:console`
 - `bin/node`: Run the node binary. Ex. `bin/node --version`
 - `bin/npm`: Run the npm binary. Ex. `bin/npm install`
 - `bin/pwa-studio`: (BETA) Start the PWA Studio server. Note that Chrome will throw SSL cert errors and not allow you to view the site, but Firefox will.
@@ -287,10 +267,12 @@ You'll now have an updated `bin/update` helper script, and can run it to update
 - `bin/restart`: Stop and then start all containers.
 - `bin/root`: Run any CLI command as root without going into the bash prompt. Ex `bin/root apt-get install nano`
 - `bin/rootnotty`: Run any CLI command as root with no TTY. Ex `bin/rootnotty chown -R app:app /var/www/html`
-- `bin/setup`: Run the Magento setup process to install Magento from the source code, with optional domain name. Defaults to `magento2.test`. Ex. `bin/setup magento2.test`
+- `bin/setup`: Run the Magento setup process to install Magento from the source code, with optional domain name. Defaults to `magento.test`. Ex. `bin/setup magento.test`
+- `bin/setup-composer-auth`: Setup authentication credentials for Composer.
+- `bin/setup-domain`: Setup Magento domain name. Ex: `bin/setup-domain magento.test`
 - `bin/setup-grunt`: Install and configure Grunt JavaScript task runner to compile .less files
-- `bin/setup-pwa-studio`: (BETA) Install PWA Studio (requires NodeJS and Yarn to be installed on the host machine). Pass in your base site domain, otherwise the default `master-7rqtwti-mfwmkrjfqvbjk.us-4.magentosite.cloud` will be used. Ex: `bin/setup-pwa-studio magento2.test`
-- `bin/setup-ssl`: Generate an SSL certificate for one or more domains. Ex. `bin/setup-ssl magento2.test magento3.test`
+- `bin/setup-pwa-studio`: (BETA) Install PWA Studio (requires NodeJS and Yarn to be installed on the host machine). Pass in your base site domain, otherwise the default `master-7rqtwti-mfwmkrjfqvbjk.us-4.magentosite.cloud` will be used. Ex: `bin/setup-pwa-studio magento.test`
+- `bin/setup-ssl`: Generate an SSL certificate for one or more domains. Ex. `bin/setup-ssl magento.test foo.test`
 - `bin/setup-ssl-ca`: Generate a certificate authority and copy it to the host.
 - `bin/start`: Start all containers, good practice to use this instead of `docker-compose up -d`, as it may contain additional helpers.
 - `bin/status`: Check the container status.
@@ -300,31 +282,52 @@ You'll now have an updated `bin/update` helper script, and can run it to update
 
 ## Misc Info
 
+### Caching
+
+For an improved developer experience, caches are automatically refreshed when related files are updated, courtesy of [cache-clean](https://github.com/mage2tv/magento-cache-clean). This means you can keep all of the standard Magento caches enabled, and this script will only clear the specific caches needed, and only when necessary.
+
+To disable this functionality, uncomment the last line in the `bin/start` file to disable the watcher.
+
 ### Database
 
 The hostname of each service is the name of the service within the `docker-compose.yml` file. So for example, MySQL's hostname is `db` (not `localhost`) when accessing it from within a Docker container. Elasticsearch's hostname is `elasticsearch`.
 
-Here's an example of how to connect to the MySQL cli tool of the Docker instance:
+To connect to the MySQL CLI tool of the Docker instance, run:
+
+```
+bin/mysql
+```
+
+You can use the `bin/mysql` script to import a database, for example a file stored in your local host directory at `backups/magento.sql`:
 
 ```
-bin/cli mysql -h db -umagento -pmagento magento
+bin/mysql < backups/magento.sql
 ```
 
-You can use the `bin/clinotty` helper script to import a database. This example uses the root MySQL user, and looks for the `dbdump.sql` file in your local host directory:
+You also can use `bin/mysqldump` to export the database. The file will appear in your local host directory at `backups/magento.sql`:
 
 ```
-bin/clinotty mysql -h db -u root -pmagento magento < dbdump.sql
+bin/mysqldump > backups/magento.sql
 ```
 
+> Getting an "Access denied, you need (at least one of) the SUPER privilege(s) for this operation." message when running one of the above lines? Try running it as root with:
+> ```
+> bin/clinotty mysql -hdb -uroot -pmagento magento < src/backup.sql
+> ```
+> You can also remove the DEFINER lines from the MySQL backup file with:
+> ```
+> sed 's/\sDEFINER=`[^`]*`@`[^`]*`//g' -i src/backup.sql
+> ```
+
 ### Composer Authentication
 
 First setup Magento Marketplace authentication (details in the [DevDocs](http://devdocs.magento.com/guides/v2.0/install-gde/prereq/connect-auth.html)).
 
 Copy `src/auth.json.sample` to `src/auth.json`. Then, update the username and password values with your Magento public and private keys, respectively. Finally, copy the file to the container by running `bin/copytocontainer auth.json`.
 
-### Email / Mailhog
+### Email / Mailcatcher
 
-View emails sent locally through Mailhog by visiting [http://{yourdomain}:8025](http://{yourdomain}:8025)
+View emails sent locally through Mailcatcher by visiting [http://{yourdomain}:1080](http://{yourdomain}:1080). During development, it's easiest to test emails using a third-party module such as [https://github.com/mageplaza/magento-2-smtp](Mageplaza's SMTP module). Set the mailserver host to `mailcatcher` and port to `1080`.
 
 ### Redis
 
@@ -334,19 +337,19 @@ Use the following lines to enable Redis on existing installs:
 
 **Enable for Cache:**
 
-`bin/magento setup:config:set --cache-backend=redis --cache-backend-redis-server=redis --cache-backend-redis-db=0`
+`bin/magento config:set --cache-backend=redis --cache-backend-redis-server=redis --cache-backend-redis-db=0`
 
 **Enable for Full Page Cache:**
 
-`bin/magento setup:config:set --page-cache=redis --page-cache-redis-server=redis --page-cache-redis-db=1`
+`bin/magento config:set --page-cache=redis --page-cache-redis-server=redis --page-cache-redis-db=1`
 
 **Enable for Session:**
 
-`bin/magento setup:config:set --session-save=redis --session-save-redis-host=redis --session-save-redis-log-level=4 --session-save-redis-db=2`
+`bin/magento config:set --session-save=redis --session-save-redis-host=redis --session-save-redis-log-level=4 --session-save-redis-db=2`
 
 You may also monitor Redis by running: `bin/redis redis-cli monitor`
 
-For more information about Redis usage with Magento, <a href="https://devdocs.magento.com/guides/v2.3/config-guide/redis/redis-session.html" target="_blank">see the DevDocs</a>.
+For more information about Redis usage with Magento, <a href="https://devdocs.magento.com/guides/v2.4/config-guide/redis/redis-session.html" target="_blank">see the DevDocs</a>.
 
 ### Xdebug & VS Code
 
@@ -373,25 +376,31 @@ Otherwise, this project now automatically sets up Xdebug support with VS Code. I
         * Remove any pre-existing volume bindings.
         * Ensure a volume binding has been setup for Container path of `/var/www/html` mapped to the Host path of `./src`.
 
-4. Open `PHPStorm > Preferences > Languages & Frameworks > PHP > Debug` and set Debug Port to `9001`.
+4. Open `PHPStorm > Preferences > Languages & Frameworks > PHP > Debug` and set Debug Port to `9001,9003`.
 
 5. Open `PHPStorm > Preferences > Languages & Frameworks > PHP > DBGp Proxy` and set Port to `9001`.
 
 6. Open `PHPStorm > Preferences > Languages & Frameworks > PHP > Servers` and create a new server:
 
-    * Set Name and Host to your domain name (ex. `magento2.test`)
+    * Set Name and Host to your domain name (ex. `magento.test`)
     * Keep port set to `80`
     * Check the Path Mappings box and map `src` to the absolute path of `/var/www/html`
 
-7. Go to `Run > Edit Configurations` and create a new `PHP Remote Debug` configuration by clicking the plus sign and selecting it. Set the Name to your domain (ex. `magento2.test`). Check the `Filter debug connection by IDE key` checkbox, select the server you just setup, and under IDE Key enter `PHPSTORM`. This IDE Key should match the IDE Key set by the Chrome Xdebug Helper. Then click OK to finish setting up the remote debugger in PHPStorm.
+7. Go to `Run > Edit Configurations` and create a new `PHP Remote Debug` configuration by clicking the plus sign and selecting it. Set the Name to your domain (ex. `magento.test`). Check the `Filter debug connection by IDE key` checkbox, select the server you just setup, and under IDE Key enter `PHPSTORM`. This IDE Key should match the IDE Key set by the Chrome Xdebug Helper. Then click OK to finish setting up the remote debugger in PHPStorm.
 
-8. Open up `src/pub/index.php`, and set a breakpoint near the end of the file. Go to `Run > Debug 'magento2.test'`, and open up a web browser. Ensure the Chrome Xdebug helper is enabled by clicking on it > Debug. Navigate to your Magento store URL, and Xdebug within PHPStorm should now trigger the debugger and pause at the toggled breakpoint.
+8. Open up `src/pub/index.php`, and set a breakpoint near the end of the file. Go to `Run > Debug 'magento.test'`, and open up a web browser. Ensure the Chrome Xdebug helper is enabled by clicking on it > Debug. Navigate to your Magento store URL, and Xdebug within PHPStorm should now trigger the debugger and pause at the toggled breakpoint.
 
 ### Linux
 
 Running Docker on Linux should be pretty straight-forward. Note that you need to run some [post install commands](https://docs.docker.com/install/linux/linux-postinstall/) as well as [installing Docker Compose](https://docs.docker.com/compose/install/). These steps are taken care of automatically with Docker Desktop, but not on Linux.
 
-You may have to increase a virtual memory map count on the host system. It is required by [Elasticsearch](https://www.elastic.co/guide/en/elasticsearch/reference/current/vm-max-map-count.html).
+The `host.docker.internal` hostname is [hard-coded in the php.ini file](https://github.com/markshust/docker-magento/blob/master/images/php/7.4/conf/php.ini#L8), but this hostname does not exist on Linux. To make this hostname resolve, uncomment the `extra_hosts` param in the `docker-compose.dev.yml` file, and replace `IP` with result of:
+
+```
+docker run --rm alpine ip route | awk 'NR==1 {print $3}'
+```
+
+You may also have to increase a virtual memory map count on the host system. It is required by [Elasticsearch](https://www.elastic.co/guide/en/elasticsearch/reference/current/vm-max-map-count.html).
 
 Add following line to `/etc/sysctl.conf`:
 
@@ -399,6 +408,12 @@ Add following line to `/etc/sysctl.conf`:
 vm.max_map_count=262144
 ```
 
+To enable Xdebug on Linux, you'll also need to open port 9001 on the firewall by running:
+
+```
+sudo iptables -A INPUT -p tcp --dport 9001 -j ACCEPT
+```
+
 ### Blackfire.io
 
 These docker images have built-in support for Blackfire.io. To use it, first register your server ID and token with the Blackfire agent:
@@ -446,24 +461,15 @@ You can also run `bin/mftf doctor` to validate all sections are setup correctly.
 
 ### M.academy
 
-This course is sponsored by <a href="https://m.academy" target="_blank">M.academy</a>. Level up your Magento 2 skills.
+This course is sponsored by <a href="https://m.academy" target="_blank">M.academy</a>, the simplest way to learn Magento.
 
 <a href="https://m.academy" target="_blank"><img src="https://raw.githubusercontent.com/markshust/docker-magento/master/docs/macademy-logo.png" alt="M.academy"></a>
 
-#### Available Courses:
-
-- <a href="https://m.academy/courses/setup-magento-2-development-environment-docker" target="_blank">Setup a Magento 2 Development Environment with Docker</a> (FREE!) - The easiest way to install, manage, configure & standardize Magento development environments across your team.
-- <a href="https://m.academy/courses/magento-2-coding-kickstart" target="_blank">Magento 2 Coding Kickstart</a> - Start to become productive in Magento 2 programming within one week with no prior experience.
-
-Also available is the <a href="https://m.academy/library" target="_blank">M.academy Library</a>, a collection of resources including lessons, courses & more.
-
 ### Mark Shust
 
-I'm a <a href="https://u.magento.com/certification/directory/dev/883/" target="_blank">Certified Magento Developer & Architect</a> & <a href="http://www.zend.com/en/yellow-pages/ZEND014633" target="_blank">Zend Certified Engineer</a>, and available for consulting & development of your next project 🤓. You can read my blog at <a href="https://markshust.com" target="_blank">markshust.com</a> or contact me directly at <a href="mailto:mark@shust.com">mark@shust.com</a>.
-
-### Nexcess
+My name is Mark Shust and I'm the creator of this repo. I'm a <a href="http://www.zend.com/en/yellow-pages/ZEND014633" target="_blank">Zend Certified Engineer</a> and <a href="https://www.youracclaim.com/users/mark-shust" target="_blank">Adobe Certified Magento Developer</a>, and have been involved since the early days of Magento (0.8!). I'm no longer available for consulting, but am creating course content full-time at <a href="https://m.academy" target="_blank">M.academy</a>.
 
-A special thanks goes out to <a href="https://www.nexcess.net/" target="_blank">Nexcess</a> for hosting <a href="http://pubfiles.nexcess.net/magento/ce-packages/" target="_blank">public archives of every version of Magento</a> 💙. I've used their Magento hosting services in the past also (both <a href="https://www.nexcess.net/magento/hosting/" target="_blank">shared</a> and <a href="https://www.nexcess.net/magento/enterprise-hosting/" target="_blank">enteprise</a> offerings) and they're great, ...highly recommended!
+You can follow me on Twitter <a href="https://twitter.com/MarkShust" target="_blank">@MarkShust</a>, connect with me on LinkedIn <a href="https://www.linkedin.com/in/MarkShust/" target="_blank">@MarkShust</a>, read my blog at <a href="https://markshust.com" target="_blank">markshust.com</a>, or contact me directly at <a href="mailto:mark@shust.com">mark@shust.com</a>.
 
 ## License
 

+ 1 - 5
compose/.vscode/launch.json

@@ -1,5 +1,4 @@
 {
-  "version": "0.2.0",
   "configurations": [
     {
       "name": "Listen for XDebug",
@@ -8,10 +7,7 @@
       "pathMappings": {
         "/var/www/html": "${workspaceFolder}"
       },
-      "port": 9001,
-      "xdebugSettings": {
-        "idekey": "VSCODE"
-      }
+      "port": 9003,
     }
   ]
 }

+ 24 - 0
compose/bin/cache-clean

@@ -0,0 +1,24 @@
+#!/bin/bash
+COMPOSER_GLOBAL=/var/www/.composer-global
+CACHE_CLEAN=${COMPOSER_GLOBAL}/vendor/bin/cache-clean.js
+
+if ! bin/cliq ls $CACHE_CLEAN; then
+  echo "Installing devtools metapackage, just a moment..."
+  bin/cliq mkdir -p ${COMPOSER_GLOBAL}
+  bin/composer init --working-dir=${COMPOSER_GLOBAL} --quiet --no-interaction
+  bin/composer require --working-dir=${COMPOSER_GLOBAL} --quiet markshust/magento2-metapackage-devtools-cli:^1.0
+  echo "Devtools installed."
+fi
+
+if [ "$1" == "--watch" ]; then
+  # Kill duplicate watch process
+  WATCH_PID=$(bin/clinotty ps -eaf | grep "$CACHE_CLEAN --quiet --watch" | grep -v grep | awk '{print $2}')
+  if [[ "" !=  "$WATCH_PID" ]]; then
+    bin/cliq kill -9 "$WATCH_PID"
+  fi
+
+  # Run watch mode in the background
+  bin/cliq $CACHE_CLEAN --quiet --watch &
+else
+  bin/cli $CACHE_CLEAN "$@"
+fi

+ 1 - 0
compose/bin/clinotty

@@ -1,3 +1,4 @@
 #!/bin/bash
 [ -z "$1" ] && echo "Please specify a CLI command (ex. ls)" && exit
+# -T: Disable pseudo-tty allocation
 docker-compose exec -T phpfpm "$@"

+ 4 - 0
compose/bin/cliq

@@ -0,0 +1,4 @@
+#!/bin/bash
+[ -z "$1" ] && echo "Please specify a CLI command (ex. ls)" && exit
+# Without stdout and stderr
+bin/clinotty "$@" >/dev/null 2>&1

+ 6 - 2
compose/bin/copyfromcontainer

@@ -3,9 +3,13 @@
 
 REAL_SRC=$(cd -P "src" && pwd)
 if [ "$1" == "--all" ]; then
-  docker cp $(docker-compose ps -q phpfpm|awk '{print $1}'):/var/www/html/./ $REAL_SRC/
+  docker cp "$(docker-compose ps -q phpfpm|awk '{print $1}')":/var/www/html/./ "$REAL_SRC/"
   echo "Completed copying all files from container to host"
 else
-  docker cp $(docker-compose ps -q phpfpm|awk '{print $1}'):/var/www/html/$1 $REAL_SRC/
+  if [ -f "$1" ] ; then
+    docker cp "$(docker-compose ps -q phpfpm|awk '{print $1}')":/var/www/html/"$1" "$REAL_SRC/$1"
+  else
+    docker cp "$(docker-compose ps -q phpfpm|awk '{print $1}')":/var/www/html/"$1" "$REAL_SRC/$(dirname "$1")"
+  fi
   echo "Completed copying $1 from container to host"
 fi

+ 8 - 4
compose/bin/copytocontainer

@@ -3,13 +3,17 @@
 
 REAL_SRC=$(cd -P "src" && pwd)
 if [ "$1" == "--all" ]; then
-  docker cp $REAL_SRC/./ $(docker-compose ps -q phpfpm|awk '{print $1}'):/var/www/html/
+  docker cp "$REAL_SRC/./" "$(docker-compose ps -q phpfpm|awk '{print $1}')":/var/www/html/
   echo "Completed copying all files from host to container"
   bin/fixowns
   bin/fixperms
 else
-  docker cp $REAL_SRC/$1 $(docker-compose ps -q phpfpm|awk '{print $1}'):/var/www/html/
+  if [ -f "$REAL_SRC/$1" ]; then
+    docker cp "$REAL_SRC/${1}" "$(docker-compose ps -q phpfpm|awk '{print $1}')":/var/www/html/"$1"
+  else
+    docker cp "$REAL_SRC/${1}" "$(docker-compose ps -q phpfpm|awk '{print $1}')":/var/www/html/"$(dirname "$1")"
+  fi
   echo "Completed copying $1 from host to container"
-  bin/fixowns $1
-  bin/fixperms $1
+  bin/fixowns "$1"
+  bin/fixperms "$1"
 fi

+ 7 - 0
compose/bin/dev-test-run

@@ -0,0 +1,7 @@
+#!/bin/bash
+
+[ -z "$1" ] && echo "Please specify test type (ex. integration)" && exit
+
+TEST_TYPE="$1"
+shift
+bin/clinotty bash -c "cd dev/tests/${TEST_TYPE} && ../../../vendor/bin/phpunit -c phpunit.xml.dist $*"

+ 12 - 8
compose/bin/download

@@ -1,9 +1,13 @@
 #!/bin/bash
-[ -z "$1" ] && echo "Please specify the version to download (ex. 2.0.0)" && exit
-if [ ! -f ~/.docker-magento/magento2-$1.tar.gz ]; then
-    mkdir -p ~/.docker-magento
-    (cd ~/.docker-magento && curl -OL http://pubfiles.nexcess.net/magento/ce-packages/magento2-$1.tar.gz)
-fi
-
-echo "Extracting magento2-$1.tar.gz to ./src"
-mkdir -p src && tar xzf ~/.docker-magento/magento2-$1.tar.gz -o -C src
+set -o errexit
+
+VERSION=${1:-2.4.2}
+EDITION=${2:-community}
+
+bin/stop
+docker-compose -f docker-compose.yml up -d
+[ $? != 0 ] && echo "Failed to start Docker services" && exit
+
+bin/setup-composer-auth
+
+bin/clinotty composer create-project --repository=https://repo.magento.com/ magento/project-"${EDITION}"-edition="${VERSION}" .

+ 3 - 3
compose/bin/fixowns

@@ -1,10 +1,10 @@
 #!/bin/bash
-echo "Correcting filesystem ownerships..."
+echo "Fixing filesystem ownerships..."
 
 if [ -z "$1" ]; then
   bin/rootnotty chown -R app:app /var/www/
 else
-  bin/rootnotty chown -R app:app /var/www/html/$1
+  bin/rootnotty chown -R app:app /var/www/html/"$1"
 fi
 
-echo "Filesystem ownerships corrected."
+echo "Filesystem ownerships fixed."

+ 4 - 6
compose/bin/fixperms

@@ -1,13 +1,11 @@
 #!/bin/bash
-echo "Correcting filesystem permissions..."
+echo "Fixing filesystem permissions..."
 
 if [ -z "$1" ]; then
-  bin/clinotty find var vendor pub/static pub/media app/etc -type f -exec chmod u+w {} \;
-  bin/clinotty find var vendor pub/static pub/media app/etc -type d -exec chmod u+w {} \;
+  bin/clinotty find var vendor pub/static pub/media app/etc \( -type f -or -type d \) -exec chmod u+w {} +;
   bin/clinotty chmod u+x bin/magento
 else
-  bin/clinotty find $1 -type f -exec chmod u+w {} \;
-  bin/clinotty find $1 -type d -exec chmod u+w {} \;
+  bin/clinotty find "$1" \( -type f -or -type d \) -exec chmod u+w {} +;
 fi
 
-echo "Filesystem permissions corrected."
+echo "Filesystem permissions fixed."

+ 9 - 1
compose/bin/mysql

@@ -1,3 +1,11 @@
 #!/bin/bash
+
+# shellcheck source=../env/db.env
 source env/db.env
-bin/cli mysql -hdb -u${MYSQL_USER} -p${MYSQL_PASSWORD} ${MYSQL_DATABASE} "$@"
+if [ -t 0 ]; then
+  # Need tty to run mysql shell
+  bin/cli mysql -h"${MYSQL_HOST}" -u"${MYSQL_USER}" -p"${MYSQL_PASSWORD}" "${MYSQL_DATABASE}" "$@"
+else
+  # Read from stdin, ex: bin/mysql < dbdump.sql
+  bin/clinotty mysql -h"${MYSQL_HOST}" -u"${MYSQL_USER}" -p"${MYSQL_PASSWORD}" "${MYSQL_DATABASE}" "$@"
+fi

+ 2 - 0
compose/bin/mysqldump

@@ -0,0 +1,2 @@
+#!/bin/bash
+bin/n98-magerun2 db:dump --stdout "$@"

+ 11 - 5
compose/bin/n98-magerun2

@@ -1,8 +1,14 @@
 #!/bin/bash
-if ! bin/clinotty ls bin/n98-magerun2.phar 1> /dev/null 2>&1; then
-    bin/clinotty curl -O https://files.magerun.net/n98-magerun2.phar
-    bin/clinotty chmod +x n98-magerun2.phar
-    bin/clinotty mkdir -p bin
-    bin/clinotty mv n98-magerun2.phar bin/n98-magerun2.phar
+if ! bin/cliq ls bin/n98-magerun2.phar; then
+  echo "Downloading n98-magerun2.phar, just a moment..."
+  bin/clinotty curl -sS -O https://files.magerun.net/n98-magerun2.phar
+  bin/clinotty curl -sS -o n98-magerun2.phar.sha256 https://files.magerun.net/sha256.php?file=n98-magerun2.phar
+  bin/clinotty shasum -a 256 -c n98-magerun2.phar.sha256
+  [ $? != 0 ] && echo "sha256 checksum do not match!" && exit
+
+  bin/cliq chmod +x n98-magerun2.phar
+  bin/cliq mkdir -p bin
+  bin/cliq mv n98-magerun2.phar bin
 fi
+
 bin/cli bin/n98-magerun2.phar "$@"

+ 2 - 0
compose/bin/pwa-studio

@@ -1,4 +1,6 @@
 #!/bin/bash
+set -o errexit
+
 if [ ! -d pwa-studio ]; then
     echo "PWA studio must first be installed by running bin/setup-pwa-studio"
     exit

+ 1 - 1
compose/bin/remove

@@ -1,2 +1,2 @@
 #!/bin/bash
-docker-compose -f docker-compose.yml -f docker-compose.dev.yml rm --stop
+docker-compose -f docker-compose.yml -f docker-compose.dev.yml rm

+ 6 - 6
compose/bin/removevolumes

@@ -1,8 +1,8 @@
 #!/bin/bash
 current_folder=${PWD##*/}
-volume_prefix=`echo $current_folder | awk '{print tolower($0)}' | sed 's/\.//g'`
-docker volume rm ${volume_prefix}_appdata
-docker volume rm ${volume_prefix}_dbdata
-docker volume rm ${volume_prefix}_rabbitmqdata
-docker volume rm ${volume_prefix}_sockdata
-docker volume rm ${volume_prefix}_ssldata
+volume_prefix=$(echo "$current_folder" | awk '{print tolower($0)}' | sed 's/\.//g')
+docker volume rm "${volume_prefix}"_appdata
+docker volume rm "${volume_prefix}"_dbdata
+docker volume rm "${volume_prefix}"_rabbitmqdata
+docker volume rm "${volume_prefix}"_sockdata
+docker volume rm "${volume_prefix}"_ssldata

+ 2 - 2
compose/bin/restart

@@ -1,3 +1,3 @@
 #!/bin/bash
-bin/stop
-bin/start
+bin/stop "$@"
+bin/start "$@"

+ 60 - 77
compose/bin/setup

@@ -1,107 +1,90 @@
 #!/bin/bash
-BASE_URL=${1:-magento2.test}
+set -o errexit
 
-bin/stop
+# shellcheck source=../env/db.env
+source env/db.env
+# shellcheck source=../env/magento.env
+source env/magento.env
 
-# fix for invalid google-shopping-api checksum contained in archive installs (temporary fix until nexcess archive is patched)
-sed -e 's/5f5929ef9f2ec4ca048a2add261d22c92807630f/ce31e720d60451784b9fdb3769e43e149f50d436/' src/composer.lock > composer.lock && mv composer.lock src/composer.lock
+DOMAIN=${1:-magento.test}
+ES_HOST=elasticsearch
+ES_PORT=9200
 
-docker-compose -f docker-compose.yml up -d
-sleep 1 #Ensure containers are started...
+bin/stop
 
-echo "Copying all files from host to container..."
-rm -rf src/vendor #Clear for step below
-bin/copytocontainer --all
+docker-compose -f docker-compose.yml up -d
+[ $? != 0 ] && echo "Failed to start Docker services" && exit
 
 bin/clinotty chmod u+x bin/magento
+mv .vscode src
 
-if hash composer 2>/dev/null; then
-    PUBLIC_KEY="$(composer config -gl | grep '\[http-basic.repo.magento.com.username\]' | cut -c40-)"
-    PRIVATE_KEY="$(composer config -gl | grep '\[http-basic.repo.magento.com.password\]' | cut -c40-)"
-fi
-
-if [ -z "$PUBLIC_KEY" ] || [ -z "$PRIVATE_KEY" ]; then
-    exec < /dev/tty
-    echo
-    echo
-    echo "    Authentication required (repo.magento.com, public_key and private_key):"
-    read -p "        Username: " PUBLIC_KEY
-    read -p "        Password: " PRIVATE_KEY
-    echo
-    if [ -n "$PUBLIC_KEY" ] && [ -n "$PRIVATE_KEY" ] && hash composer 2>/dev/null; then
-        read -p "    Add authentication information to host composer config? y/n: " ADD_AUTH
-        echo
-        if [[ $ADD_AUTH =~ ^[Yy]$ ]]; then
-            composer global config http-basic.repo.magento.com $PUBLIC_KEY $PRIVATE_KEY
-        fi
-        ADD_AUTH=''
-    fi
-    exec <&-
-fi
-
-if [ -n "$PUBLIC_KEY" ] && [ -n "$PRIVATE_KEY" ]; then
-    bin/clinotty composer config http-basic.repo.magento.com $PUBLIC_KEY $PRIVATE_KEY
-    PUBLIC_KEY=''
-    PRIVATE_KEY=''
-fi
-
-echo "Forcing reinstall of composer deps to ensure perms & reqs..."
-bin/clinotty composer global require hirak/prestissimo
-bin/clinotty composer install
+echo "Waiting for connection to Elasticsearch..."
+bin/clinotty timeout 100 bash -c "
+    until curl --silent --output /dev/null http://$ES_HOST:$ES_PORT/_cat/health?h=st; do
+        printf '.'
+        sleep 2
+    done"
+[ $? != 0 ] && echo "Failed to connect to Elasticsearch" && exit
 
 bin/clinotty bin/magento setup:install \
-  --db-host=db \
-  --db-name=magento \
-  --db-user=magento \
-  --db-password=magento \
-  --base-url=https://$BASE_URL/ \
-  --admin-firstname=John \
-  --admin-lastname=Smith \
-  --admin-email=john.smith@gmail.com \
-  --admin-user=john.smith \
-  --admin-password=password123 \
-  --language=en_US \
-  --currency=USD \
-  --timezone=America/New_York \
+  --db-host="$MYSQL_HOST" \
+  --db-name="$MYSQL_DATABASE" \
+  --db-user="$MYSQL_USER" \
+  --db-password="$MYSQL_PASSWORD" \
+  --base-url=https://"$DOMAIN"/ \
+  --base-url-secure=https://"$DOMAIN"/ \
+  --backend-frontname="$MAGENTO_ADMIN_FRONTNAME" \
+  --admin-firstname="$MAGENTO_ADMIN_FIRST_NAME" \
+  --admin-lastname="$MAGENTO_ADMIN_LAST_NAME" \
+  --admin-email="$MAGENTO_ADMIN_EMAIL" \
+  --admin-user="$MAGENTO_ADMIN_USER" \
+  --admin-password="$MAGENTO_ADMIN_PASSWORD" \
+  --language="$MAGENTO_LOCALE" \
+  --currency="$MAGENTO_CURRENCY" \
+  --timezone="$MAGENTO_TIMEZONE" \
   --amqp-host=rabbitmq \
   --amqp-port=5672 \
   --amqp-user=guest \
   --amqp-password=guest \
   --amqp-virtualhost=/ \
+  --cache-backend=redis \
+  --cache-backend-redis-server=redis \
+  --cache-backend-redis-db=0 \
+  --page-cache=redis \
+  --page-cache-redis-server=redis \
+  --page-cache-redis-db=1 \
+  --session-save=redis \
+  --session-save-redis-host=redis \
+  --session-save-redis-log-level=4 \
+  --session-save-redis-db=2 \
+  --search-engine=elasticsearch7 \
+  --elasticsearch-host=$ES_HOST \
+  --elasticsearch-port=$ES_PORT \
   --use-rewrites=1
 
-echo "Turning on developer mode.."
-bin/clinotty bin/magento deploy:mode:set developer
-
-bin/clinotty bin/magento indexer:reindex
+echo "Copying files from container to host after install..."
+bin/copyfromcontainer --all
 
 echo "Forcing deploy of static content to speed up initial requests..."
 bin/clinotty bin/magento setup:static-content:deploy -f
 
-echo "Enabling Redis for cache..."
-bin/clinotty bin/magento setup:config:set --no-interaction --cache-backend=redis --cache-backend-redis-server=redis --cache-backend-redis-db=0
-
-echo "Enabling Redis for Full Page Cache..."
-bin/clinotty bin/magento setup:config:set --no-interaction  --page-cache=redis --page-cache-redis-server=redis --page-cache-redis-db=1
-
-echo "Enabling Redis for session..."
-bin/clinotty bin/magento setup:config:set --no-interaction --session-save=redis --session-save-redis-host=redis --session-save-redis-log-level=4 --session-save-redis-db=2
-
-echo "Enabling Elasticsearch..."
-bin/clinotty bin/magento config:set catalog/search/elasticsearch7_server_hostname elasticsearch
-
 echo "Re-indexing with Elasticsearch..."
 bin/clinotty bin/magento indexer:reindex
 
+echo "Setting basic URL and generating SSL certificate..."
+bin/setup-domain "${DOMAIN}"
+
 echo "Clearing the cache to apply updates..."
 bin/clinotty bin/magento cache:flush
 
-echo "Copying files from container to host after install..."
-bin/copyfromcontainer app
-bin/copyfromcontainer vendor
+echo "Ensuring Composer auth.json is setup..."
+bin/setup-composer-auth
+
+echo "Installing cron (see docker-compose.yml to enable)..."
+bin/magento cron:install
 
-echo "Generating SSL certificate..."
-bin/setup-ssl $BASE_URL
+echo "Turning on developer mode.."
+bin/clinotty bin/magento deploy:mode:set developer
 
 echo "Docker development environment setup complete."
-echo "You may now access your Magento instance at https://${BASE_URL}/"
+echo "You may now access your Magento instance at https://${DOMAIN}/"

+ 31 - 0
compose/bin/setup-composer-auth

@@ -0,0 +1,31 @@
+#!/bin/bash
+MAGENTO_USERNAME_PROP="http-basic.repo.magento.com.username"
+MAGENTO_PASSWORD_PROP="http-basic.repo.magento.com.password"
+hash composer 2>/dev/null && IS_COMPOSER_ON_HOST=true
+
+if [ $IS_COMPOSER_ON_HOST ]; then
+    PUBLIC_KEY="$(composer config --global $MAGENTO_USERNAME_PROP 2>/dev/null)"
+    PRIVATE_KEY="$(composer config --global $MAGENTO_PASSWORD_PROP 2>/dev/null)"
+fi
+
+if [ -z "$PUBLIC_KEY" ] || [ -z "$PRIVATE_KEY" ]; then
+    exec < /dev/tty
+    echo
+    echo "Composer authentication required (repo.magento.com public and private keys):"
+    read -r -p "    Username: " PUBLIC_KEY
+    read -r -p "    Password: " PRIVATE_KEY
+    echo
+    exec <&-
+fi
+
+if [ -z "$PUBLIC_KEY" ] || [ -z "$PRIVATE_KEY" ]; then
+    echo "Please setup Composer auth for repo.magento.com to continue." && exit 1
+fi
+
+# Output must be piped otherwise file descriptor errors occur. Carriage returns?
+echo "composer config --global http-basic.repo.magento.com ${PUBLIC_KEY} ${PRIVATE_KEY}" | bin/clinotty bash -
+
+# Also make sure alternate auth.json is setup (Magento uses this internally)
+bin/clinotty cp /var/www/.composer/auth.json ./var/composer_home/auth.json
+
+echo "Composer auth has been setup."

+ 16 - 0
compose/bin/setup-domain

@@ -0,0 +1,16 @@
+#!/bin/bash
+set -o errexit
+
+[ -z "$1" ] && echo "Please specify a domain name (ex. magento.test)" && exit
+
+DOMAIN=$1
+
+echo "Your system password has been requested to add an entry to /etc/hosts..."
+echo "127.0.0.1 ::1 $DOMAIN" | sudo tee -a /etc/hosts
+
+echo "Set https://${DOMAIN}/ to web/secure/base_url and web/secure/base_url"
+bin/magento config:set web/secure/base_url https://"$DOMAIN"/
+bin/magento config:set web/unsecure/base_url https://"$DOMAIN"/
+
+echo "Generating SSL certificate..."
+bin/setup-ssl "$DOMAIN"

+ 3 - 3
compose/bin/setup-grunt

@@ -1,11 +1,11 @@
 #!/bin/bash
 DEFAULT_THEME_ID="select value from core_config_data where path = 'design/theme/theme_id'"
 THEME_PATH="select theme_path from theme where theme_id in ($DEFAULT_THEME_ID);"
-VENDOR_THEME=`bin/n98-magerun2 db:query "$THEME_PATH" | sed -n 2p | cut -d$'\r' -f1`
-THEME=`echo $VENDOR_THEME | cut -d'/' -f2`
+VENDOR_THEME=$(bin/n98-magerun2 db:query "$THEME_PATH" | sed -n 2p | cut -d$'\r' -f1)
+THEME=$(echo "$VENDOR_THEME" | cut -d'/' -f2)
 
 # Generate local-theme.js for custom theme
-read -d '' GEN_THEME_JS << EOM
+read -r -d '' GEN_THEME_JS << EOM
 var fs = require('fs');
 var util = require('util');
 var theme = require('./dev/tools/grunt/configs/themes');

+ 22 - 0
compose/bin/setup-integration-tests

@@ -0,0 +1,22 @@
+#!/bin/bash
+
+# shellcheck source=../env/db.env
+source env/db.env
+
+MYSQL_INTEGRATION_CONFIG=dev/tests/integration/etc/install-config-mysql.php
+
+# If database doesn't exist, create it and add user permissions
+bin/clinotty mysql -h"${MYSQL_INTEGRATION_HOST}" -uroot -p"${MYSQL_ROOT_PASSWORD}" "${MYSQL_INTEGRATION_DATABASE}" -e exit &> /dev/null ||
+  bin/clinotty mysqladmin -h"${MYSQL_INTEGRATION_HOST}" -uroot -p"${MYSQL_ROOT_PASSWORD}" create "${MYSQL_INTEGRATION_DATABASE}" &&
+  echo "Database ${MYSQL_INTEGRATION_DATABASE} created." &&
+  bin/cli mysql -uroot -p"${MYSQL_ROOT_PASSWORD}" -h"${MYSQL_INTEGRATION_HOST}" \
+    -e "GRANT ALL PRIVILEGES ON ${MYSQL_INTEGRATION_DATABASE}.* TO '${MYSQL_INTEGRATION_USER}'@'%';FLUSH PRIVILEGES;"
+
+if [[ ! -f "src/${MYSQL_INTEGRATION_CONFIG}" ]]; then
+  MAGENTO_VERSION=$(bin/magento --version --no-ansi | cut -d" " -f 3)
+  IFS=. read -r -a MAGENTO_VERSION_SEGMENTS <<< "${MAGENTO_VERSION}"
+  MAGENTO_MAJOR="${MAGENTO_VERSION_SEGMENTS[0]}.${MAGENTO_VERSION_SEGMENTS[1]}"
+  cp template/"${MYSQL_INTEGRATION_CONFIG}"."${MAGENTO_MAJOR}".dist src/${MYSQL_INTEGRATION_CONFIG}
+fi
+
+bin/copytocontainer ${MYSQL_INTEGRATION_CONFIG}

+ 1 - 0
compose/bin/setup-pwa-studio

@@ -1,4 +1,5 @@
 #!/bin/bash
+set -o errexit
 echo "Install NodeJS and Yarn on host machine, otherwise setup will fail"
 
 BASE_URL=${1:-master-7rqtwti-mfwmkrjfqvbjk.us-4.magentosite.cloud}

+ 12 - 3
compose/bin/setup-ssl-ca

@@ -1,6 +1,15 @@
 #!/bin/bash
+set -o errexit
+# Generate a new local CA "/root/.local/share/mkcert"
 docker-compose exec -T -u root app mkcert -install
-docker cp $(docker-compose ps -q app|awk '{print $1}'):/root/.local/share/mkcert/rootCA.pem .
+
+docker cp "$(docker-compose ps -q app|awk '{print $1}')":/root/.local/share/mkcert/rootCA.pem .
 echo "System password requested to install certificate authority on host..."
-sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain rootCA.pem
-rm rootCA.pem
+
+if [ "$(uname)" == "Darwin" ]; then
+  sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain rootCA.pem
+  rm rootCA.pem
+else
+  sudo mv rootCA.pem /usr/local/share/ca-certificates/rootCA.pem
+  sudo update-ca-certificates
+fi

+ 53 - 2
compose/bin/start

@@ -1,9 +1,60 @@
 #!/bin/bash
-docker-compose -f docker-compose.yml -f docker-compose.dev.yml up -d --remove-orphans
+set -o errexit
+
+# Ref: https://stackoverflow.com/a/51789677/9821321
+function parseYaml {
+  local s
+  local w
+  local fs
+  s='[[:space:]]*'
+  w='[a-zA-Z0-9_]*'
+  fs=$(echo @|tr @ '\034')
+  sed -ne "s|,$s\]$s\$|]|" \
+      -e "s|^\($s\)\($w\)$s:$s\[$s\(.*\)$s\]|\1\2:\n\1  - \3|;p" "$1" | \
+  sed -ne "s|,$s}$s\$|}|" \
+      -e "s|^\($s\)-$s{$s\(.*\)$s}|\1-\n\1  \2|;p" | \
+  sed -ne "s|^\($s\):|\1|" \
+      -e "s|^\($s\)-$s{[\"']\(.*\)[\"']}$s\$|\1$fs$fs\2|p" \
+      -e "s|^\($s\)-$s\(.*\)$s\$|\1$fs$fs\2|p" \
+      -e "s|^\($s\)\($w\)$s:$s{[\"']\(.*\)[\"']}$s\$|\1$fs\2$fs\3|p" \
+      -e "s|^\($s\)\($w\)$s:$s\(.*\)$s\$|\1$fs\2$fs\3|p" | \
+  awk -F"$fs" '{
+    indent = length($1)/2;
+    vname[indent] = $2;
+    for (i in vname) {if (i > indent) {delete vname[i]; idx[i]=0}}
+    if (length($2) == 0) {vname[indent] = ++idx[indent] };
+    if (length($3) > 0) {
+      vn=""; for (i=0; i<indent; i++) {vn = (vn)(vname[i])("_")}
+      if ("'"$2"'_" == vn) {
+         print substr($3 ,1 , match($3,":")-1)
+      }
+    }
+  }'
+}
+
+# Check if volume files exist to avoid creating an empty folder
+VOLUME_LIST=$(parseYaml docker-compose.dev.yml services_app_volumes)
+IGNORE_LIST="./src/app/code ./src/m2-hotfixes ./src/patches ./src/var/log ./src/var/report ./src"
+IS_VALID=true
+
+# Loop through all files missing from the docker-compose.dev.yml file
+for file in $VOLUME_LIST; do
+  if [ ! -e "$file" ] && [[ ! " $IGNORE_LIST " =~ $file ]]; then
+    echo "$file: No such file or directory"
+    IS_VALID=false
+  fi
+done
+
+# Wait to exit until all missing files have been outputted to the user
+[ $IS_VALID = false ] && echo "Failed to start docker for missing volume files" && exit
+
+docker-compose -f docker-compose.yml -f docker-compose.dev.yml up -d --remove-orphans "$@"
 
 ## Blackfire support
-# ------------------
+## ------------------
 ## First register the blackfire agent with:
 #bin/root blackfire-agent --register --server-id={YOUR_SERVER_ID} --server-token={YOUR_SERVER_TOKEN}
 ## Then uncomment the below line (and leave uncommented) to start the agent automatically with bin/start:
 #bin/root /etc/init.d/blackfire-agent start
+
+bin/cache-clean --watch

+ 1 - 1
compose/bin/stop

@@ -1,2 +1,2 @@
 #!/bin/bash
-docker-compose -f docker-compose.yml -f docker-compose.dev.yml stop
+docker-compose -f docker-compose.yml -f docker-compose.dev.yml stop "$@"

+ 2 - 1
compose/bin/update

@@ -1,5 +1,6 @@
 #!/bin/bash
-mkdir -p tmpupdate && cd $_
+set -o errexit
+mkdir -p tmpupdate && cd "$_"
 curl -s https://raw.githubusercontent.com/markshust/docker-magento/master/lib/template | bash
 rm -rf .git
 rsync -av ./ ../

+ 52 - 9
compose/bin/xdebug

@@ -1,12 +1,55 @@
 #!/bin/bash
-if [ "$1" == "disable" ]; then
-  bin/cli sed -i -e 's/^zend_extension/\;zend_extension/g' /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini
-  bin/restart
-  echo "Xdebug has been disabled."
-elif [ "$1" == "enable" ]; then
-  bin/cli sed -i -e 's/^\;zend_extension/zend_extension/g' /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini
-  bin/restart
-  echo "Xdebug has been enabled."
+
+S=$(bin/cli cat /usr/local/etc/php/php.ini | grep -iGc 'xdebug.mode = off');
+
+xdebug_status() {
+    if [[ $S == 1 ]]; then
+        echo "Xdebug debug mode is disabled."
+    else
+        echo "Xdebug debug mode is enabled."
+    fi
+}
+
+xdebug_toggle() {
+    if [[ $S == 1 ]]; then
+        xdebug_enable
+    else
+        xdebug_disable
+    fi
+}
+
+xdebug_enable() {
+    if [[ $S == 1 ]]; then
+        bin/root sed -i -e 's/^xdebug.mode = off/xdebug.mode = debug/g' /usr/local/etc/php/php.ini
+        sleep 1
+        bin/restart phpfpm
+        echo "Xdebug debug mode has been enabled."
+    else
+        echo "Xdebug debug mode is already enabled."
+    fi
+}
+
+xdebug_disable() {
+    if [[ $S == 0 ]]; then
+        bin/root sed -i -e 's/^xdebug.mode = debug/xdebug.mode = off/g' /usr/local/etc/php/php.ini
+        sleep 1
+        bin/restart phpfpm
+        echo "Xdebug debug mode has been disabled."
+    else
+        echo "Xdebug debug mode is already disabled."
+    fi
+}
+
+firstArgLetter="$(echo "$1" | head -c 1)"
+
+if [[ $firstArgLetter == "d" ]]; then
+    xdebug_disable
+elif [[ $firstArgLetter == "e" ]]; then
+    xdebug_enable
+elif [[ $firstArgLetter == "t" ]]; then
+    xdebug_toggle
+elif [[ $firstArgLetter == "s" ]]; then
+    xdebug_status
 else
-  echo "Please specify either 'enable' or 'disable' as an argument"
+    printf "Please specify either 'disable', 'enable', 'status' or 'toggle' as an argument.\nEx: bin/xdebug status\n"
 fi

+ 22 - 22
compose/docker-compose.dev.yml

@@ -1,42 +1,42 @@
 # Mark Shust's Docker Configuration for Magento
 # (https://github.com/markshust/docker-magento)
 #
-# Version 32.0.1
+# Version 39.1.0
 
 version: "3"
 
 services:
   app:
     volumes: &appvolumes
-      # Host mounts with performance penalty, only put what is necessary here
-      - ./src/app/code:/var/www/html/app/code:delegated
-      - ./src/app/design:/var/www/html/app/design:delegated
-      - ./src/app/etc:/var/www/html/app/etc:delegated
-      - ./src/composer.json:/var/www/html/composer.json:delegated
-      - ./src/composer.lock:/var/www/html/composer.lock:delegated
-      - ./src/nginx.conf.sample:/var/www/html/nginx.conf:delegated
-      #- ./src/auth.json:/var/www/html/auth.json:delegated
-      #- ./src/m2-hotfixes:/var/www/html/m2-hotfixes:delegated
-      #- ./src/patches:/var/www/html/patches:delegated
-      #- ./src/var/log:/var/www/html/var/log:delegated
-      #- ./src/var/report:/var/www/html/var/report:delegated
-      # Linux only: remove the above lines and mount the entire src directory with:
-      #- ./src:/var/www/html:delegated
+      ## Host mounts with performance penalty, only put what is necessary here
+      - ./src/app/code:/var/www/html/app/code:cached
+      - ./src/app/design:/var/www/html/app/design:cached
+      - ./src/app/etc:/var/www/html/app/etc:cached
+      - ./src/composer.json:/var/www/html/composer.json:cached
+      - ./src/composer.lock:/var/www/html/composer.lock:cached
+      - ./src/nginx.conf.sample:/var/www/html/nginx.conf:cached
+      #- ./src/auth.json:/var/www/html/auth.json:cached
+      #- ./src/m2-hotfixes:/var/www/html/m2-hotfixes:cached
+      #- ./src/patches:/var/www/html/patches:cached
+      #- ./src/var/log:/var/www/html/var/log:cached
+      #- ./src/var/report:/var/www/html/var/report:cached
+      ## To sync your SSH to the container, uncomment the following line:
+      #- ~/.ssh/id_rsa:/var/www/.ssh/id_rsa:cached
+      ## Linux only: remove the above lines (except nginx.conf line) and mount the entire src directory with:
+      #- ./src:/var/www/html:cached
 
   phpfpm:
     volumes: *appvolumes
-    # Linux only: host.docker.internal doesn't exist https://github.com/docker/for-linux/issues/264
-    # Uncomment two lines below & replace IP with result of: docker run --rm alpine ip route | awk 'NR==1 {print $3}'
+    ## Linux users, see https://github.com/markshust/docker-magento#linux for updates needed below
     #extra_hosts:
     #  - "host.docker.internal:IP"
 
-  mailhog:
-    image: mailhog/mailhog
+  mailcatcher:
+    image: sj26/mailcatcher
     ports:
-      - "1025"
-      - "8025:8025"
+      - "1080:1080"
 
-  # Disabling cron by default as it uses higher CPU, enable if needed
+  ## Disabling cron by default as it uses higher CPU, enable if needed
   #cron:
   #  volumes: *appvolumes
 

+ 17 - 10
compose/docker-compose.yml

@@ -1,13 +1,13 @@
 # Mark Shust's Docker Configuration for Magento
 # (https://github.com/markshust/docker-magento)
 #
-# Version 32.0.1
+# Version 39.1.0
 
 version: "3"
 
 services:
   app:
-    image: markoshust/magento-nginx:1.18-2
+    image: markoshust/magento-nginx:1.18-4
     ports:
       - "80:8000"
       - "443:8443"
@@ -15,19 +15,20 @@ services:
       - db
       - phpfpm
     volumes: &appvolumes
-      - ~/.composer:/var/www/.composer:delegated
+      - ~/.composer:/var/www/.composer:cached
       - appdata:/var/www/html
       - sockdata:/sock
       - ssldata:/etc/nginx/certs
 
   phpfpm:
-    image: markoshust/magento-php:7.3-fpm-6
+    image: markoshust/magento-php:7.4-fpm-9
     links:
       - db
     volumes: *appvolumes
 
   db:
-    image: percona:5.7
+    image: mariadb:10.4
+    command: --max_allowed_packet=64M
     ports:
       - "3306:3306"
     env_file: env/db.env
@@ -35,27 +36,33 @@ services:
       - dbdata:/var/lib/mysql
 
   redis:
-    image: redis:5.0
+    image: redis:5.0-alpine
 
   elasticsearch:
-    image: markoshust/magento-elasticsearch:7.6.2-2
+    image: markoshust/magento-elasticsearch:7.9.3-0
     ports:
       - "9200:9200"
       - "9300:9300"
     environment:
       - "discovery.type=single-node"
+      # Set custom heap size to avoid memory errors
+      - "ES_JAVA_OPTS=-Xms1g -Xmx1g"
+      # Avoid test failures due to small disks
+      # More info at https://github.com/markshust/docker-magento/issues/488
+      - "cluster.routing.allocation.disk.threshold_enabled=false"
+      - "index.blocks.read_only_allow_delete"
 
   rabbitmq:
-    image: rabbitmq:3.7-management
+    image: rabbitmq:3.8.22-management-alpine
     ports:
       - "15672:15672"
       - "5672:5672"
     volumes:
       - rabbitmqdata:/var/lib/rabbitmq
 
-  # Disabling cron by default as it uses higher CPU, enable if needed
+  ## Disabling cron by default as it uses higher CPU, enable if needed
   #cron:
-  #  image: markoshust/magento-php:7.3-fpm-6
+  #  image: markoshust/magento-php:7.4-fpm-9
   #  user: root
   #  command: /usr/local/bin/cronstart
   #  tty: true

+ 7 - 0
compose/env/db.env

@@ -1,4 +1,11 @@
+MYSQL_HOST=db
 MYSQL_ROOT_PASSWORD=magento
 MYSQL_DATABASE=magento
 MYSQL_USER=magento
 MYSQL_PASSWORD=magento
+
+MYSQL_INTEGRATION_ROOT_PASSWORD=magento
+MYSQL_INTEGRATION_DATABASE=magento_integration_tests
+MYSQL_INTEGRATION_USER=magento
+MYSQL_INTEGRATION_PASSWORD=magento
+MYSQL_INTEGRATION_HOST=db

+ 9 - 0
compose/env/magento.env

@@ -0,0 +1,9 @@
+MAGENTO_ADMIN_EMAIL=john.smith@gmail.com
+MAGENTO_ADMIN_FIRST_NAME=john
+MAGENTO_ADMIN_LAST_NAME=smith
+MAGENTO_ADMIN_USER=john.smith
+MAGENTO_ADMIN_PASSWORD=password123
+MAGENTO_ADMIN_FRONTNAME=admin
+MAGENTO_LOCALE=en_US
+MAGENTO_CURRENCY=USD
+MAGENTO_TIMEZONE=America/New_York

+ 22 - 0
compose/template/dev/tests/integration/etc/install-config-mysql.php.2.3.dist

@@ -0,0 +1,22 @@
+<?php
+/**
+ * Copyright © Magento, Inc. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+return [
+    'db-host' => 'db',
+    'db-user' => 'magento',
+    'db-password' => 'magento',
+    'db-name' => 'magento_integration_tests',
+    'db-prefix' => '',
+    'backend-frontname' => 'backend',
+    'admin-user' => \Magento\TestFramework\Bootstrap::ADMIN_NAME,
+    'admin-password' => \Magento\TestFramework\Bootstrap::ADMIN_PASSWORD,
+    'admin-email' => \Magento\TestFramework\Bootstrap::ADMIN_EMAIL,
+    'admin-firstname' => \Magento\TestFramework\Bootstrap::ADMIN_FIRSTNAME,
+    'admin-lastname' => \Magento\TestFramework\Bootstrap::ADMIN_LASTNAME,
+    'amqp-host' => 'rabbitmq',
+    'amqp-port' => '5672',
+    'amqp-user' => 'guest',
+    'amqp-password' => 'guest',
+];

+ 24 - 0
compose/template/dev/tests/integration/etc/install-config-mysql.php.2.4.dist

@@ -0,0 +1,24 @@
+<?php
+/**
+ * Copyright © Magento, Inc. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+return [
+    'db-host' => 'db',
+    'db-user' => 'magento',
+    'db-password' => 'magento',
+    'db-name' => 'magento_integration_tests',
+    'db-prefix' => '',
+    'backend-frontname' => 'backend',
+    'search-engine' => 'elasticsearch7',
+    'elasticsearch-host' => 'elasticsearch',
+    'admin-user' => \Magento\TestFramework\Bootstrap::ADMIN_NAME,
+    'admin-password' => \Magento\TestFramework\Bootstrap::ADMIN_PASSWORD,
+    'admin-email' => \Magento\TestFramework\Bootstrap::ADMIN_EMAIL,
+    'admin-firstname' => \Magento\TestFramework\Bootstrap::ADMIN_FIRSTNAME,
+    'admin-lastname' => \Magento\TestFramework\Bootstrap::ADMIN_LASTNAME,
+    'amqp-host' => 'rabbitmq',
+    'amqp-port' => '5672',
+    'amqp-user' => 'guest',
+    'amqp-password' => 'guest',
+];

TEMPAT SAMPAH
docs/course.png


TEMPAT SAMPAH
docs/macademy-logo.png


TEMPAT SAMPAH
docs/set-up-magento-2-development-environment-docker-og.png


+ 4 - 0
images/elasticsearch/7.7/Dockerfile

@@ -0,0 +1,4 @@
+FROM elasticsearch:7.7.1
+
+RUN /usr/share/elasticsearch/bin/elasticsearch-plugin install analysis-icu
+RUN /usr/share/elasticsearch/bin/elasticsearch-plugin install analysis-phonetic

+ 4 - 0
images/elasticsearch/7.9/Dockerfile

@@ -0,0 +1,4 @@
+FROM elasticsearch:7.9.3
+
+RUN /usr/share/elasticsearch/bin/elasticsearch-plugin install analysis-icu
+RUN /usr/share/elasticsearch/bin/elasticsearch-plugin install analysis-phonetic

+ 8 - 6
images/nginx/1.18/Dockerfile

@@ -1,22 +1,24 @@
-FROM nginx:1.18
+FROM nginx:1.18-alpine
 MAINTAINER Mark Shust <mark@shust.com>
 
-RUN groupadd -g 1000 app \
- && useradd -g 1000 -u 1000 -d /var/www -s /bin/bash app
+RUN addgroup -g 1000 app \
+ && adduser -G app -u 1000 -h /var/www -s /bin/bash -S app
 RUN touch /var/run/nginx.pid
 RUN mkdir /sock
 
-RUN apt-get update && apt-get install -y \
+RUN apk add --no-cache \
   curl \
-  libnss3-tools \
+  nss-tools \
   openssl
 
 RUN mkdir /etc/nginx/certs \
   && echo -e "\n\n\n\n\n\n\n" | openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/nginx/certs/nginx.key -out /etc/nginx/certs/nginx.crt
 
+ARG TARGETARCH
+
 RUN ( \
   cd /usr/local/bin/ \
-  && curl -L https://github.com/FiloSottile/mkcert/releases/download/v1.4.1/mkcert-v1.4.1-linux-amd64 -o mkcert \
+  && curl -L https://github.com/FiloSottile/mkcert/releases/download/v1.4.3/mkcert-v1.4.3-linux-$TARGETARCH -o mkcert \
   && chmod +x mkcert \
   )
 

+ 2 - 1
images/nginx/1.18/conf/default.conf

@@ -8,7 +8,8 @@ server {
 }
 
 server {
-  listen 8443 ssl;
+  listen [::]:8443 ssl http2 ipv6only=on;
+  listen 8443 ssl http2;
 
   ssl_certificate /etc/nginx/certs/nginx.crt;
   ssl_certificate_key /etc/nginx/certs/nginx.key;

+ 18 - 25
images/php/7.3/Dockerfile

@@ -18,7 +18,8 @@ RUN apt-get update && apt-get install -y \
   lsof \
   default-mysql-client \
   vim \
-  zip
+  zip \
+  procps
 
 RUN docker-php-ext-configure \
   gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/
@@ -45,58 +46,50 @@ RUN docker-php-ext-install \
   xsl \
   zip
 
+ARG TARGETARCH
+
 RUN cd /tmp \
-  && curl -O https://downloads.ioncube.com/loader_downloads/ioncube_loaders_lin_x86-64.tar.gz \
-  && tar zxvf ioncube_loaders_lin_x86-64.tar.gz \
+  && ARCH=$(if [ "$TARGETARCH" = "arm64" ]; then echo aarch64; else echo x86-64; fi;) \
+  && curl -O https://downloads.ioncube.com/loader_downloads/ioncube_loaders_lin_$ARCH.tar.gz \
+  && tar zxvf ioncube_loaders_lin_$ARCH.tar.gz \
   && export PHP_VERSION=$(php -r "echo PHP_MAJOR_VERSION.'.'.PHP_MINOR_VERSION;") \
   && export PHP_EXT_DIR=$(php-config --extension-dir) \
   && cp "./ioncube/ioncube_loader_lin_${PHP_VERSION}.so" "${PHP_EXT_DIR}/ioncube.so" \
   && rm -rf ./ioncube \
-  && rm ioncube_loaders_lin_x86-64.tar.gz \
+  && rm ioncube_loaders_lin_$ARCH.tar.gz \
   && docker-php-ext-enable ioncube
 
 RUN pecl channel-update pecl.php.net \
-  && pecl install xdebug
-
-RUN docker-php-ext-enable xdebug \
-  && sed -i -e 's/^zend_extension/\;zend_extension/g' /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini
+  && pecl install xdebug \
+  && docker-php-ext-enable xdebug
 
-## Replace next lines with below commented out version once issue is resolved
-# https://github.com/php/pecl-networking-ssh2/pull/36
-# https://bugs.php.net/bug.php?id=78560
-RUN curl -o /tmp/ssh2-1.2.tgz https://pecl.php.net/get/ssh2 \
-  && pear install /tmp/ssh2-1.2.tgz \
-  && rm /tmp/ssh2-1.2.tgz \
+RUN pecl install ssh2-1.2 \
   && docker-php-ext-enable ssh2
-#RUN pecl install ssh2-1.2 \
-#  && docker-php-ext-enable ssh2
+
+RUN pecl install redis \
+  && docker-php-ext-enable redis
 
 RUN groupadd -g 1000 app \
  && useradd -g 1000 -u 1000 -d /var/www -s /bin/bash app
 
 RUN apt-get install -y gnupg \
-  && curl -sL https://deb.nodesource.com/setup_10.x | bash - \
+  && curl -sL https://deb.nodesource.com/setup_14.x | bash - \
   && apt-get install -y nodejs \
   && mkdir /var/www/.config /var/www/.npm \
   && chown app:app /var/www/.config /var/www/.npm \
   && npm install -g grunt-cli
 
-RUN curl -sSLO https://github.com/mailhog/mhsendmail/releases/download/v0.2.0/mhsendmail_linux_amd64 \
-  && chmod +x mhsendmail_linux_amd64 \
-  && mv mhsendmail_linux_amd64 /usr/local/bin/mhsendmail
+RUN apt-get install -y msmtp mailutils
+COPY conf/msmtprc /etc/msmtprc
 
 RUN curl -sS https://getcomposer.org/installer | \
-  php -- --version=1.9.0 --install-dir=/usr/local/bin --filename=composer
+  php -- --install-dir=/usr/local/bin --filename=composer
 
 RUN curl -s https://packages.blackfire.io/gpg.key | apt-key add - \
   && echo "deb http://packages.blackfire.io/debian any main" | tee /etc/apt/sources.list.d/blackfire.list \
   && apt-get update \
   && apt-get install blackfire-agent blackfire-php
 
-RUN printf '* *\t* * *\tapp\t%s/usr/local/bin/php /var/www/html/update/cron.php\n' >> /etc/crontab \
-  && printf '* *\t* * *\tapp\t%s/usr/local/bin/php /var/www/html/bin/magento cron:run\n' >> /etc/crontab \
-  && printf '* *\t* * *\tapp\t%s/usr/local/bin/php /var/www/html/bin/magento setup:cron:run\n#\n' >> /etc/crontab
-
 COPY conf/www.conf /usr/local/etc/php-fpm.d/
 COPY conf/php.ini /usr/local/etc/php/
 COPY conf/php-fpm.conf /usr/local/etc/

+ 4 - 0
images/php/7.3/conf/msmtprc

@@ -0,0 +1,4 @@
+account default
+host mailcatcher
+port 1025
+from "user@domain.com"

+ 2 - 4
images/php/7.3/conf/php.ini

@@ -4,10 +4,8 @@ zlib.output_compression = On
 cgi.fix_pathinfo = 0
 date.timezone = UTC
 
-xdebug.remote_autostart = 1
-xdebug.remote_enable = 1
-xdebug.remote_host = host.docker.internal
-xdebug.remote_port = 9001
+xdebug.mode = debug
+xdebug.client_host = host.docker.internal
 xdebug.idekey = PHPSTORM
 
 upload_max_filesize = 100M

+ 24 - 22
images/php/7.2/Dockerfile → images/php/7.4/Dockerfile

@@ -1,4 +1,4 @@
-FROM php:7.2-fpm-buster
+FROM php:7.4-fpm-buster
 MAINTAINER Mark Shust <mark@shust.com>
 
 RUN apt-get update && apt-get install -y \
@@ -10,17 +10,19 @@ RUN apt-get update && apt-get install -y \
   libicu-dev \
   libjpeg62-turbo-dev \
   libmcrypt-dev \
+  libonig-dev \
   libpng-dev \
   libsodium-dev \
   libssh2-1-dev \
   libxslt1-dev \
+  libzip-dev \
   lsof \
   default-mysql-client \
   vim \
-  zip
+  zip \
+  procps
 
-RUN docker-php-ext-configure \
-  gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/
+RUN docker-php-ext-configure gd --with-freetype --with-jpeg
 
 RUN docker-php-ext-install \
   bcmath \
@@ -44,50 +46,50 @@ RUN docker-php-ext-install \
   xsl \
   zip
 
+ARG TARGETARCH
+
 RUN cd /tmp \
-  && curl -O https://downloads.ioncube.com/loader_downloads/ioncube_loaders_lin_x86-64.tar.gz \
-  && tar zxvf ioncube_loaders_lin_x86-64.tar.gz \
+  && ARCH=$(if [ "$TARGETARCH" = "arm64" ]; then echo aarch64; else echo x86-64; fi;) \
+  && curl -O https://downloads.ioncube.com/loader_downloads/ioncube_loaders_lin_$ARCH.tar.gz \
+  && tar zxvf ioncube_loaders_lin_$ARCH.tar.gz \
   && export PHP_VERSION=$(php -r "echo PHP_MAJOR_VERSION.'.'.PHP_MINOR_VERSION;") \
   && export PHP_EXT_DIR=$(php-config --extension-dir) \
   && cp "./ioncube/ioncube_loader_lin_${PHP_VERSION}.so" "${PHP_EXT_DIR}/ioncube.so" \
   && rm -rf ./ioncube \
-  && rm ioncube_loaders_lin_x86-64.tar.gz \
+  && rm ioncube_loaders_lin_$ARCH.tar.gz \
   && docker-php-ext-enable ioncube
 
 RUN pecl channel-update pecl.php.net \
-  && pecl install ssh2-1.1.2 \
-  && pecl install xdebug
+  && pecl install xdebug \
+  && docker-php-ext-enable xdebug
 
-RUN docker-php-ext-enable ssh2 \
-  && docker-php-ext-enable xdebug \
-  && sed -i -e 's/^zend_extension/\;zend_extension/g' /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini
+RUN pecl install ssh2-1.2 \
+  && docker-php-ext-enable ssh2
+
+RUN pecl install redis \
+  && docker-php-ext-enable redis
 
 RUN groupadd -g 1000 app \
-  && useradd -g 1000 -u 1000 -d /var/www -s /bin/bash app
+ && useradd -g 1000 -u 1000 -d /var/www -s /bin/bash app
 
 RUN apt-get install -y gnupg \
-  && curl -sL https://deb.nodesource.com/setup_10.x | bash - \
+  && curl -sL https://deb.nodesource.com/setup_14.x | bash - \
   && apt-get install -y nodejs \
   && mkdir /var/www/.config /var/www/.npm \
   && chown app:app /var/www/.config /var/www/.npm \
   && npm install -g grunt-cli
 
-RUN curl -sSLO https://github.com/mailhog/mhsendmail/releases/download/v0.2.0/mhsendmail_linux_amd64 \
-  && chmod +x mhsendmail_linux_amd64 \
-  && mv mhsendmail_linux_amd64 /usr/local/bin/mhsendmail
+RUN apt-get install -y msmtp mailutils
+COPY conf/msmtprc /etc/msmtprc
 
 RUN curl -sS https://getcomposer.org/installer | \
-  php -- --version=1.9.0 --install-dir=/usr/local/bin --filename=composer
+  php -- --install-dir=/usr/local/bin --filename=composer
 
 RUN curl -s https://packages.blackfire.io/gpg.key | apt-key add - \
   && echo "deb http://packages.blackfire.io/debian any main" | tee /etc/apt/sources.list.d/blackfire.list \
   && apt-get update \
   && apt-get install blackfire-agent blackfire-php
 
-RUN printf '* *\t* * *\tapp\t%s/usr/local/bin/php /var/www/html/update/cron.php\n' >> /etc/crontab \
-  && printf '* *\t* * *\tapp\t%s/usr/local/bin/php /var/www/html/bin/magento cron:run\n' >> /etc/crontab \
-  && printf '* *\t* * *\tapp\t%s/usr/local/bin/php /var/www/html/bin/magento setup:cron:run\n#\n' >> /etc/crontab
-
 COPY conf/www.conf /usr/local/etc/php-fpm.d/
 COPY conf/php.ini /usr/local/etc/php/
 COPY conf/php-fpm.conf /usr/local/etc/

+ 0 - 0
images/php/7.2/bin/cronstart → images/php/7.4/bin/cronstart


+ 4 - 0
images/php/7.4/conf/msmtprc

@@ -0,0 +1,4 @@
+account default
+host mailcatcher
+port 1025
+from "user@domain.com"

+ 0 - 0
images/php/7.2/conf/php-fpm.conf → images/php/7.4/conf/php-fpm.conf


+ 15 - 0
images/php/7.4/conf/php.ini

@@ -0,0 +1,15 @@
+memory_limit = 4G
+max_execution_time = 1800
+zlib.output_compression = On
+cgi.fix_pathinfo = 0
+date.timezone = UTC
+
+xdebug.mode = off
+xdebug.client_host = host.docker.internal
+xdebug.idekey = PHPSTORM
+
+upload_max_filesize = 100M
+post_max_size = 100M
+max_input_vars = 10000
+
+sendmail_path = "/usr/local/bin/mhsendmail --smtp-addr=mailhog:1025"

+ 0 - 0
images/php/7.2/conf/www.conf → images/php/7.4/conf/www.conf


+ 90 - 0
images/php/8.0/Dockerfile

@@ -0,0 +1,90 @@
+FROM php:8.0-fpm-buster
+MAINTAINER Mark Shust <mark@shust.com>
+
+RUN apt-get update && apt-get install -y \
+  cron \
+  default-mysql-client \
+  git \
+  gzip \
+  libbz2-dev \
+  libfreetype6-dev \
+  libicu-dev \
+  libjpeg62-turbo-dev \
+  libmcrypt-dev \
+  libonig-dev \
+  libpng-dev \
+  libsodium-dev \
+  libxslt1-dev \
+  libzip-dev \
+  lsof \
+  procps \
+  vim \
+  zip
+
+RUN docker-php-ext-configure gd --with-freetype --with-jpeg
+
+RUN docker-php-ext-install \
+  bcmath \
+  bz2 \
+  calendar \
+  exif \
+  gd \
+  gettext \
+  intl \
+  mbstring \
+  mysqli \
+  opcache \
+  pcntl \
+  pdo_mysql \
+  soap \
+  sockets \
+  sodium \
+  sysvmsg \
+  sysvsem \
+  sysvshm \
+  xsl \
+  zip
+
+RUN pecl channel-update pecl.php.net \
+  && pecl install xdebug \
+  && docker-php-ext-enable xdebug
+
+RUN pecl install redis \
+  && docker-php-ext-enable redis
+
+RUN groupadd -g 1000 app \
+ && useradd -g 1000 -u 1000 -d /var/www -s /bin/bash app
+
+RUN apt-get install -y gnupg \
+  && curl -sL https://deb.nodesource.com/setup_14.x | bash - \
+  && apt-get install -y nodejs \
+  && mkdir /var/www/.config /var/www/.npm \
+  && chown app:app /var/www/.config /var/www/.npm \
+  && npm install -g grunt-cli
+
+RUN apt-get install -y msmtp mailutils
+COPY conf/msmtprc /etc/msmtprc
+
+RUN curl -sS https://getcomposer.org/installer | \
+  php -- --install-dir=/usr/local/bin --filename=composer
+
+RUN curl -s https://packages.blackfire.io/gpg.key | apt-key add - \
+  && echo "deb http://packages.blackfire.io/debian any main" | tee /etc/apt/sources.list.d/blackfire.list \
+  && apt-get update \
+  && apt-get install blackfire-agent blackfire-php
+
+COPY conf/www.conf /usr/local/etc/php-fpm.d/
+COPY conf/php.ini /usr/local/etc/php/
+COPY conf/php-fpm.conf /usr/local/etc/
+COPY bin/cronstart /usr/local/bin/
+
+RUN mkdir -p /etc/nginx/html /var/www/html /sock \
+  && chown -R app:app /etc/nginx /var/www /usr/local/etc/php/conf.d /sock
+
+USER app:app
+
+VOLUME /var/www
+
+WORKDIR /var/www/html
+
+EXPOSE 9001

+ 7 - 0
images/php/8.0/bin/cronstart

@@ -0,0 +1,7 @@
+#!/bin/bash
+service cron start
+
+touch /var/www/html/var/.setup_cronjob_status /var/www/html/var/.update_cronjob_status
+chown app:app /var/www/html/var/.setup_cronjob_status /var/www/html/var/.update_cronjob_status
+
+/usr/bin/crontab

+ 4 - 0
images/php/8.0/conf/msmtprc

@@ -0,0 +1,4 @@
+account default
+host mailcatcher
+port 1025
+from "user@domain.com"

+ 31 - 0
images/php/8.0/conf/php-fpm.conf

@@ -0,0 +1,31 @@
+; This file was initially adapated from the output of: (on PHP 5.6)
+;   grep -vE '^;|^ *$' /usr/local/etc/php-fpm.conf.default
+
+[global]
+
+error_log = /proc/self/fd/2
+daemonize = no
+
+[www]
+
+; if we send this to /proc/self/fd/1, it never appears
+access.log = /proc/self/fd/2
+
+;user = app
+;group = app
+
+listen = /sock/docker.sock
+listen.owner = app
+listen.group = app
+listen.mode = 0660
+
+pm = dynamic
+pm.max_children = 10
+pm.start_servers = 4
+pm.min_spare_servers = 2
+pm.max_spare_servers = 6
+
+clear_env = no
+
+; Ensure worker stdout and stderr are sent to the main error log.
+catch_workers_output = yes

+ 0 - 0
images/php/7.2/conf/php.ini → images/php/8.0/conf/php.ini


+ 413 - 0
images/php/8.0/conf/www.conf

@@ -0,0 +1,413 @@
+; Start a new pool named 'www'.
+; the variable $pool can we used in any directive and will be replaced by the
+; pool name ('www' here)
+[www]
+
+; Per pool prefix
+; It only applies on the following directives:
+; - 'access.log'
+; - 'slowlog'
+; - 'listen' (unixsocket)
+; - 'chroot'
+; - 'chdir'
+; - 'php_values'
+; - 'php_admin_values'
+; When not set, the global prefix (or NONE) applies instead.
+; Note: This directive can also be relative to the global prefix.
+; Default Value: none
+;prefix = /path/to/pools/$pool
+
+; Unix user/group of processes
+; Note: The user is mandatory. If the group is not set, the default user's group
+;       will be used.
+user = app
+group = app
+
+; The address on which to accept FastCGI requests.
+; Valid syntaxes are:
+;   'ip.add.re.ss:port'    - to listen on a TCP socket to a specific IPv4 address on
+;                            a specific port;
+;   '[ip:6:addr:ess]:port' - to listen on a TCP socket to a specific IPv6 address on
+;                            a specific port;
+;   'port'                 - to listen on a TCP socket to all addresses
+;                            (IPv6 and IPv4-mapped) on a specific port;
+;   '/path/to/unix/socket' - to listen on a unix socket.
+; Note: This value is mandatory.
+listen = 127.0.0.1:9000
+
+; Set listen(2) backlog.
+; Default Value: 511 (-1 on FreeBSD and OpenBSD)
+;listen.backlog = 511
+
+; Set permissions for unix socket, if one is used. In Linux, read/write
+; permissions must be set in order to allow connections from a web server. Many
+; BSD-derived systems allow connections regardless of permissions.
+; Default Values: user and group are set as the running user
+;                 mode is set to 0660
+;listen.owner = www-data
+;listen.group = www-data
+;listen.mode = 0660
+; When POSIX Access Control Lists are supported you can set them using
+; these options, value is a comma separated list of user/group names.
+; When set, listen.owner and listen.group are ignored
+;listen.acl_users =
+;listen.acl_groups =
+
+; List of addresses (IPv4/IPv6) of FastCGI clients which are allowed to connect.
+; Equivalent to the FCGI_WEB_SERVER_ADDRS environment variable in the original
+; PHP FCGI (5.2.2+). Makes sense only with a tcp listening socket. Each address
+; must be separated by a comma. If this value is left blank, connections will be
+; accepted from any ip address.
+; Default Value: any
+;listen.allowed_clients = 127.0.0.1
+
+; Specify the nice(2) priority to apply to the pool processes (only if set)
+; The value can vary from -19 (highest priority) to 20 (lower priority)
+; Note: - It will only work if the FPM master process is launched as root
+;       - The pool processes will inherit the master process priority
+;         unless it specified otherwise
+; Default Value: no set
+; process.priority = -19
+
+; Choose how the process manager will control the number of child processes.
+; Possible Values:
+;   static  - a fixed number (pm.max_children) of child processes;
+;   dynamic - the number of child processes are set dynamically based on the
+;             following directives. With this process management, there will be
+;             always at least 1 children.
+;             pm.max_children      - the maximum number of children that can
+;                                    be alive at the same time.
+;             pm.start_servers     - the number of children created on startup.
+;             pm.min_spare_servers - the minimum number of children in 'idle'
+;                                    state (waiting to process). If the number
+;                                    of 'idle' processes is less than this
+;                                    number then some children will be created.
+;             pm.max_spare_servers - the maximum number of children in 'idle'
+;                                    state (waiting to process). If the number
+;                                    of 'idle' processes is greater than this
+;                                    number then some children will be killed.
+;  ondemand - no children are created at startup. Children will be forked when
+;             new requests will connect. The following parameter are used:
+;             pm.max_children           - the maximum number of children that
+;                                         can be alive at the same time.
+;             pm.process_idle_timeout   - The number of seconds after which
+;                                         an idle process will be killed.
+; Note: This value is mandatory.
+pm = dynamic
+
+; The number of child processes to be created when pm is set to 'static' and the
+; maximum number of child processes when pm is set to 'dynamic' or 'ondemand'.
+; This value sets the limit on the number of simultaneous requests that will be
+; served. Equivalent to the ApacheMaxClients directive with mpm_prefork.
+; Equivalent to the PHP_FCGI_CHILDREN environment variable in the original PHP
+; CGI. The below defaults are based on a server without much resources. Don't
+; forget to tweak pm.* to fit your needs.
+; Note: Used when pm is set to 'static', 'dynamic' or 'ondemand'
+; Note: This value is mandatory.
+pm.max_children = 5
+
+; The number of child processes created on startup.
+; Note: Used only when pm is set to 'dynamic'
+; Default Value: min_spare_servers + (max_spare_servers - min_spare_servers) / 2
+pm.start_servers = 2
+
+; The desired minimum number of idle server processes.
+; Note: Used only when pm is set to 'dynamic'
+; Note: Mandatory when pm is set to 'dynamic'
+pm.min_spare_servers = 1
+
+; The desired maximum number of idle server processes.
+; Note: Used only when pm is set to 'dynamic'
+; Note: Mandatory when pm is set to 'dynamic'
+pm.max_spare_servers = 3
+
+; The number of seconds after which an idle process will be killed.
+; Note: Used only when pm is set to 'ondemand'
+; Default Value: 10s
+;pm.process_idle_timeout = 10s;
+
+; The number of requests each child process should execute before respawning.
+; This can be useful to work around memory leaks in 3rd party libraries. For
+; endless request processing specify '0'. Equivalent to PHP_FCGI_MAX_REQUESTS.
+; Default Value: 0
+;pm.max_requests = 500
+
+; The URI to view the FPM status page. If this value is not set, no URI will be
+; recognized as a status page. It shows the following informations:
+;   pool                 - the name of the pool;
+;   process manager      - static, dynamic or ondemand;
+;   start time           - the date and time FPM has started;
+;   start since          - number of seconds since FPM has started;
+;   accepted conn        - the number of request accepted by the pool;
+;   listen queue         - the number of request in the queue of pending
+;                          connections (see backlog in listen(2));
+;   max listen queue     - the maximum number of requests in the queue
+;                          of pending connections since FPM has started;
+;   listen queue len     - the size of the socket queue of pending connections;
+;   idle processes       - the number of idle processes;
+;   active processes     - the number of active processes;
+;   total processes      - the number of idle + active processes;
+;   max active processes - the maximum number of active processes since FPM
+;                          has started;
+;   max children reached - number of times, the process limit has been reached,
+;                          when pm tries to start more children (works only for
+;                          pm 'dynamic' and 'ondemand');
+; Value are updated in real time.
+; Example output:
+;   pool:                 www
+;   process manager:      static
+;   start time:           01/Jul/2011:17:53:49 +0200
+;   start since:          62636
+;   accepted conn:        190460
+;   listen queue:         0
+;   max listen queue:     1
+;   listen queue len:     42
+;   idle processes:       4
+;   active processes:     11
+;   total processes:      15
+;   max active processes: 12
+;   max children reached: 0
+;
+; By default the status page output is formatted as text/plain. Passing either
+; 'html', 'xml' or 'json' in the query string will return the corresponding
+; output syntax. Example:
+;   http://www.foo.bar/status
+;   http://www.foo.bar/status?json
+;   http://www.foo.bar/status?html
+;   http://www.foo.bar/status?xml
+;
+; By default the status page only outputs short status. Passing 'full' in the
+; query string will also return status for each pool process.
+; Example:
+;   http://www.foo.bar/status?full
+;   http://www.foo.bar/status?json&full
+;   http://www.foo.bar/status?html&full
+;   http://www.foo.bar/status?xml&full
+; The Full status returns for each process:
+;   pid                  - the PID of the process;
+;   state                - the state of the process (Idle, Running, ...);
+;   start time           - the date and time the process has started;
+;   start since          - the number of seconds since the process has started;
+;   requests             - the number of requests the process has served;
+;   request duration     - the duration in µs of the requests;
+;   request method       - the request method (GET, POST, ...);
+;   request URI          - the request URI with the query string;
+;   content length       - the content length of the request (only with POST);
+;   user                 - the user (PHP_AUTH_USER) (or '-' if not set);
+;   script               - the main script called (or '-' if not set);
+;   last request cpu     - the %cpu the last request consumed
+;                          it's always 0 if the process is not in Idle state
+;                          because CPU calculation is done when the request
+;                          processing has terminated;
+;   last request memory  - the max amount of memory the last request consumed
+;                          it's always 0 if the process is not in Idle state
+;                          because memory calculation is done when the request
+;                          processing has terminated;
+; If the process is in Idle state, then informations are related to the
+; last request the process has served. Otherwise informations are related to
+; the current request being served.
+; Example output:
+;   ************************
+;   pid:                  31330
+;   state:                Running
+;   start time:           01/Jul/2011:17:53:49 +0200
+;   start since:          63087
+;   requests:             12808
+;   request duration:     1250261
+;   request method:       GET
+;   request URI:          /test_mem.php?N=10000
+;   content length:       0
+;   user:                 -
+;   script:               /home/fat/web/docs/php/test_mem.php
+;   last request cpu:     0.00
+;   last request memory:  0
+;
+; Note: There is a real-time FPM status monitoring sample web page available
+;       It's available in: /usr/local/share/php/fpm/status.html
+;
+; Note: The value must start with a leading slash (/). The value can be
+;       anything, but it may not be a good idea to use the .php extension or it
+;       may conflict with a real PHP file.
+; Default Value: not set
+;pm.status_path = /status
+
+; The ping URI to call the monitoring page of FPM. If this value is not set, no
+; URI will be recognized as a ping page. This could be used to test from outside
+; that FPM is alive and responding, or to
+; - create a graph of FPM availability (rrd or such);
+; - remove a server from a group if it is not responding (load balancing);
+; - trigger alerts for the operating team (24/7).
+; Note: The value must start with a leading slash (/). The value can be
+;       anything, but it may not be a good idea to use the .php extension or it
+;       may conflict with a real PHP file.
+; Default Value: not set
+;ping.path = /ping
+
+; This directive may be used to customize the response of a ping request. The
+; response is formatted as text/plain with a 200 response code.
+; Default Value: pong
+;ping.response = pong
+
+; The access log file
+; Default: not set
+;access.log = log/$pool.access.log
+
+; The access log format.
+; The following syntax is allowed
+;  %%: the '%' character
+;  %C: %CPU used by the request
+;      it can accept the following format:
+;      - %{user}C for user CPU only
+;      - %{system}C for system CPU only
+;      - %{total}C  for user + system CPU (default)
+;  %d: time taken to serve the request
+;      it can accept the following format:
+;      - %{seconds}d (default)
+;      - %{miliseconds}d
+;      - %{mili}d
+;      - %{microseconds}d
+;      - %{micro}d
+;  %e: an environment variable (same as $_ENV or $_SERVER)
+;      it must be associated with embraces to specify the name of the env
+;      variable. Some exemples:
+;      - server specifics like: %{REQUEST_METHOD}e or %{SERVER_PROTOCOL}e
+;      - HTTP headers like: %{HTTP_HOST}e or %{HTTP_USER_AGENT}e
+;  %f: script filename
+;  %l: content-length of the request (for POST request only)
+;  %m: request method
+;  %M: peak of memory allocated by PHP
+;      it can accept the following format:
+;      - %{bytes}M (default)
+;      - %{kilobytes}M
+;      - %{kilo}M
+;      - %{megabytes}M
+;      - %{mega}M
+;  %n: pool name
+;  %o: output header
+;      it must be associated with embraces to specify the name of the header:
+;      - %{Content-Type}o
+;      - %{X-Powered-By}o
+;      - %{Transfert-Encoding}o
+;      - ....
+;  %p: PID of the child that serviced the request
+;  %P: PID of the parent of the child that serviced the request
+;  %q: the query string
+;  %Q: the '?' character if query string exists
+;  %r: the request URI (without the query string, see %q and %Q)
+;  %R: remote IP address
+;  %s: status (response code)
+;  %t: server time the request was received
+;      it can accept a strftime(3) format:
+;      %d/%b/%Y:%H:%M:%S %z (default)
+;      The strftime(3) format must be encapsuled in a %{<strftime_format>}t tag
+;      e.g. for a ISO8601 formatted timestring, use: %{%Y-%m-%dT%H:%M:%S%z}t
+;  %T: time the log has been written (the request has finished)
+;      it can accept a strftime(3) format:
+;      %d/%b/%Y:%H:%M:%S %z (default)
+;      The strftime(3) format must be encapsuled in a %{<strftime_format>}t tag
+;      e.g. for a ISO8601 formatted timestring, use: %{%Y-%m-%dT%H:%M:%S%z}t
+;  %u: remote user
+;
+; Default: "%R - %u %t \"%m %r\" %s"
+;access.format = "%R - %u %t \"%m %r%Q%q\" %s %f %{mili}d %{kilo}M %C%%"
+
+; The log file for slow requests
+; Default Value: not set
+; Note: slowlog is mandatory if request_slowlog_timeout is set
+;slowlog = log/$pool.log.slow
+
+; The timeout for serving a single request after which a PHP backtrace will be
+; dumped to the 'slowlog' file. A value of '0s' means 'off'.
+; Available units: s(econds)(default), m(inutes), h(ours), or d(ays)
+; Default Value: 0
+;request_slowlog_timeout = 0
+
+; The timeout for serving a single request after which the worker process will
+; be killed. This option should be used when the 'max_execution_time' ini option
+; does not stop script execution for some reason. A value of '0' means 'off'.
+; Available units: s(econds)(default), m(inutes), h(ours), or d(ays)
+; Default Value: 0
+;request_terminate_timeout = 0
+
+; Set open file descriptor rlimit.
+; Default Value: system defined value
+;rlimit_files = 1024
+
+; Set max core size rlimit.
+; Possible Values: 'unlimited' or an integer greater or equal to 0
+; Default Value: system defined value
+;rlimit_core = 0
+
+; Chroot to this directory at the start. This value must be defined as an
+; absolute path. When this value is not set, chroot is not used.
+; Note: you can prefix with '$prefix' to chroot to the pool prefix or one
+; of its subdirectories. If the pool prefix is not set, the global prefix
+; will be used instead.
+; Note: chrooting is a great security feature and should be used whenever
+;       possible. However, all PHP paths will be relative to the chroot
+;       (error_log, sessions.save_path, ...).
+; Default Value: not set
+;chroot =
+
+; Chdir to this directory at the start.
+; Note: relative path can be used.
+; Default Value: current directory or / when chroot
+;chdir = /var/www
+
+; Redirect worker stdout and stderr into main error log. If not set, stdout and
+; stderr will be redirected to /dev/null according to FastCGI specs.
+; Note: on highloaded environement, this can cause some delay in the page
+; process time (several ms).
+; Default Value: no
+;catch_workers_output = yes
+
+; Clear environment in FPM workers
+; Prevents arbitrary environment variables from reaching FPM worker processes
+; by clearing the environment in workers before env vars specified in this
+; pool configuration are added.
+; Setting to "no" will make all environment variables available to PHP code
+; via getenv(), $_ENV and $_SERVER.
+; Default Value: yes
+;clear_env = no
+
+; Limits the extensions of the main script FPM will allow to parse. This can
+; prevent configuration mistakes on the web server side. You should only limit
+; FPM to .php extensions to prevent malicious users to use other extensions to
+; exectute php code.
+; Note: set an empty value to allow all extensions.
+; Default Value: .php
+;security.limit_extensions = .php .php3 .php4 .php5 .php7
+
+; Pass environment variables like LD_LIBRARY_PATH. All $VARIABLEs are taken from
+; the current environment.
+; Default Value: clean env
+;env[HOSTNAME] = $HOSTNAME
+;env[PATH] = /usr/local/bin:/usr/bin:/bin
+;env[TMP] = /tmp
+;env[TMPDIR] = /tmp
+;env[TEMP] = /tmp
+
+; Additional php.ini defines, specific to this pool of workers. These settings
+; overwrite the values previously defined in the php.ini. The directives are the
+; same as the PHP SAPI:
+;   php_value/php_flag             - you can set classic ini defines which can
+;                                    be overwritten from PHP call 'ini_set'.
+;   php_admin_value/php_admin_flag - these directives won't be overwritten by
+;                                     PHP call 'ini_set'
+; For php_*flag, valid values are on, off, 1, 0, true, false, yes or no.
+
+; Defining 'extension' will load the corresponding shared extension from
+; extension_dir. Defining 'disable_functions' or 'disable_classes' will not
+; overwrite previously defined php.ini values, but will append the new value
+; instead.
+
+; Note: path INI options can be relative and will be expanded with the prefix
+; (pool, global or /usr/local)
+
+; Default Value: nothing is defined by default except the values in php.ini and
+;                specified at startup with the -d argument
+;php_admin_value[sendmail_path] = /usr/sbin/sendmail -t -i -f www@my.domain.com
+;php_flag[display_errors] = off
+;php_admin_value[error_log] = /var/log/fpm-php.www.log
+;php_admin_flag[log_errors] = on
+;php_admin_value[memory_limit] = 32M

+ 7 - 6
lib/onelinesetup

@@ -1,11 +1,12 @@
 #!/bin/bash
-DOMAIN=${1:-magento2.test}
-VERSION=${2:-2.3.5-p1}
+set -o errexit
+
+DOMAIN=${1:-magento.test}
+VERSION=${2:-2.4.3}
+EDITION=${3:-community}
 
 curl -s https://raw.githubusercontent.com/markshust/docker-magento/master/lib/template | bash
-bin/download $VERSION
 
-echo "Your system password has been requested to add an entry to /etc/hosts..."
-echo "127.0.0.1 ::1 $DOMAIN" | sudo tee -a /etc/hosts
+bin/download "${VERSION}" "${EDITION}"
 
-bin/setup $DOMAIN
+bin/setup ${DOMAIN}

+ 1 - 0
lib/template

@@ -4,6 +4,7 @@ git remote add origin https://github.com/markshust/docker-magento
 git fetch origin -qqq
 git checkout origin/master -- compose
 mv compose/* ./
+mv compose/.gitignore ./
 mv compose/.vscode ./
 rm -rf compose .git
 git init