Skip to content

Commit 73850f6

Browse files
Merge pull request #936 from userfrosting/develop-jordan
ClassMapper and Docker improvements
2 parents 1abeb65 + 86821fb commit 73850f6

8 files changed

Lines changed: 83 additions & 66 deletions

File tree

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,12 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
1010
### Added
1111
- `sprinkle:list` bakery command
1212
- `NoCache` middleware to prevent caching of routes with dynamic content
13+
- Sample test environment for Docker
1314

1415
### Changed
1516
- Sprinkle list in the bakery `debug` command to uses the new `sprinkle:list` table
1617
- `routerCacheFile` config now only contains filename. Locator is used to find the full path
18+
- Updated Docker integration
1719
- Moved some constants from `app/defines.php` to `app/sprinkles/core/defines.php`
1820
- Move route initialization from system to core sprinkle as router service is located in the core sprinkle
1921

@@ -33,6 +35,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
3335
- Added specific tests for sprinkleManager with 100% test coverage
3436
- Ignore existing `package-lock.json` which caused incorrect dependencies to be installed when upgrading from older versions of UserFrosting.
3537
- Vendor assets not found in production mode
38+
- Various Docker specific edge cases and misconfigurations
3639
- Fix path issue on Windows
3740

3841
## 4.2.0-beta.1

app/sprinkles/core/src/Util/ClassMapper.php

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,7 @@ public function createInstance($identifier)
3737

3838
$params = array_slice(func_get_args(), 1);
3939

40-
// We must use reflection in PHP < 5.6. See http://stackoverflow.com/questions/8734522/dynamically-call-class-with-variable-number-of-parameters-in-the-constructor
41-
$reflection = new \ReflectionClass($className);
42-
43-
return $reflection->newInstanceArgs($params);
40+
return new $className(...$params);
4441
}
4542

4643
/**
@@ -90,6 +87,6 @@ public function staticMethod($identifier, $methodName)
9087

9188
$params = array_slice(func_get_args(), 2);
9289

93-
return call_user_func_array("$className::$methodName", $params);
90+
return $className::$methodName(...$params);
9491
}
9592
}

build/gulpfile.esm.js

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -261,29 +261,29 @@ export function bundle() {
261261
rawConfig.BundlesVirtualBasePath = "./assets/";
262262

263263
// Bundle results callback
264+
/**
265+
*
266+
* @param {Map<string, any[]} results
267+
*/
264268
function bundleResults(results) {
269+
// Compute possible asset base paths (for matching later)
270+
/** @type {string[]} */
271+
const assetBasePaths = [];
272+
assetBasePaths.push(resolvePath(vendorAssetsDir, "bower_components"));
273+
assetBasePaths.push(resolvePath(vendorAssetsDir, "node_modules"));
274+
for (const sprinkle of sprinkles) {
275+
assetBasePaths.push(resolvePath(sprinklesDir, sprinkle, "assets"));
276+
}
277+
278+
265279
/**
266280
* Resolves absolute path to gulp-uf-bundle-assets v2 style path
267281
* @param {string} path Absolute path to resolve.
268282
*/
269283
function resolveToAssetPath(path) {
270-
// TODO There is a significant amount of duplicated code here. We can do better.
271-
if (path.startsWith(resolvePath(sprinklesDir))) {
272-
// Handle sprinkle path
273-
for (const sprinkle of sprinkles) {
274-
const sprinklePath = resolvePath(sprinklesDir, sprinkle, "assets");
275-
if (path.startsWith(sprinklePath)) {
276-
return path.replace(sprinklePath, "").replace(/\\/g, "/").replace("/", "");
277-
}
278-
}
279-
}
280-
else {
281-
// Handle vendor path
282-
if (path.startsWith(resolvePath(vendorAssetsDir, "bower_components"))) {
283-
return path.replace(resolvePath(vendorAssetsDir, "bower_components"), "").replace(/\\/g, "/").replace("/", "");
284-
}
285-
else if (path.startsWith(resolvePath(vendorAssetsDir, "node_modules"))) {
286-
return path.replace(resolvePath(vendorAssetsDir, "node_modules"), "").replace(/\\/g, "/").replace("/", "");
284+
for (const basePath of assetBasePaths) {
285+
if (path.startsWith(basePath)) {
286+
return path.replace(basePath, "").replace(/\\/g, "/").replace("/", "");
287287
}
288288
}
289289

build/package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@
22
"private": true,
33
"dependencies": {
44
"@userfrosting/browserify-dependencies": "^1.0.0-beta.1",
5-
"@userfrosting/gulp-bundle-assets": "^3.0.0-rc.1",
5+
"@userfrosting/gulp-bundle-assets": "^3.0.0-rc.2",
66
"@userfrosting/merge-package-dependencies": "^1.2.1",
7-
"bower": "^1.8.4",
8-
"esm": "^3.0.84",
7+
"bower": "^1.8.8",
8+
"esm": "^3.2.5",
99
"del": "^3.0.0",
1010
"dotenv": "^6.2.0",
1111
"gulp": "^4.0.0",

docker-compose-testdb.yml

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ services:
2424
- ./docker/php/custom.ini:/usr/local/etc/php/conf.d/custom.ini
2525
networks:
2626
- backend
27+
2728
nginx:
2829
restart: unless-stopped
2930
tty: true
@@ -41,6 +42,7 @@ services:
4142
networks:
4243
- frontend
4344
- backend
45+
4446
ufmysql:
4547
image: mysql:5.7
4648
networks:
@@ -54,6 +56,7 @@ services:
5456
- 8593:3306
5557
volumes:
5658
- userfrosting-db:/var/lib/mysql
59+
5760
ufmysqltest:
5861
image: mysql:5.7
5962
networks:
@@ -67,25 +70,26 @@ services:
6770
- 8594:3306
6871
volumes:
6972
- userfrosting-test-db:/var/lib/mysql
73+
7074
composer:
7175
image: "composer"
7276
volumes:
7377
- .:/app
7478
working_dir: /app
75-
command: -V
79+
7680
node:
77-
image: node:alpine
7881
build:
7982
context: ./docker/node
8083
volumes:
8184
- .:/app
8285
working_dir: /app/build
83-
command: npm run uf-assets-install
86+
8487
volumes:
8588
userfrosting-db:
8689
driver: local
8790
userfrosting-test-db:
8891
driver: local
92+
8993
networks:
9094
frontend:
9195
backend:

docker-compose.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ services:
1717
- ./docker/php/custom.ini:/usr/local/etc/php/conf.d/custom.ini
1818
networks:
1919
- backend
20+
2021
nginx:
2122
restart: unless-stopped
2223
tty: true
@@ -33,6 +34,7 @@ services:
3334
networks:
3435
- frontend
3536
- backend
37+
3638
ufmysql:
3739
image: mysql:5.7
3840
networks:
@@ -46,21 +48,19 @@ services:
4648
- 8593:3306
4749
volumes:
4850
- userfrosting-db:/var/lib/mysql
51+
4952
composer:
5053
image: "composer"
5154
volumes:
5255
- .:/app
5356
working_dir: /app
54-
command: -V
5557

5658
node:
57-
image: node:alpine
5859
build:
5960
context: ./docker/node
6061
volumes:
6162
- .:/app
6263
working_dir: /app/build
63-
command: npm run uf-assets-install
6464

6565
volumes:
6666
userfrosting-db:

docker/README.md

Lines changed: 36 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,56 @@
11
# Docker Development Environment
22

3+
>This is also documented at [UserFrosting Learn](https://learn.userfrosting.com/installation/environment/docker).
4+
35
First, install [Docker Compose](https://docs.docker.com/compose/install/).
46

57
Second, initialize a new UserFrosting project:
6-
1. Clone the repository `git clone https://github.com/userfrosting/UserFrosting.git .` and change into that directory `cd userfrosting`
7-
1. Run `cp app/sprinkles.example.json app/sprinkles.json` or upload your own (also upload your sprinkles if you have some)
8-
2. Run `sudo chown -R 33 app/{logs,cache,sessions}` (Changes the user to the www-data user of the image, more information [here](https://serversforhackers.com/c/dckr-file-permissions) )
9-
2. Run `sudo docker-compose run composer install` to install all composer modules.
10-
3. Run `sudo docker-compose run node npm install` to install all npm modules.
8+
9+
1. Copy `app/sprinkles.example.json` to `app/sprinkles.json`
10+
2. Run `chmod 777 app/{logs,cache,sessions}` to fix file permissions for web server. (NOTE: File
11+
permissions should be properly secured in a production environment!)
12+
3. Run `docker-compose run composer install --ignore-platform-reqs --no-scripts` to install all composer modules. (https://hub.docker.com/_/composer) Sometimes dependencies or Composer scripts require the availability of certain PHP extensions. You can work around this as follows: Pass the `--ignore-platform-reqs and --no-scripts` flags to install or update
13+
4. Run `docker-compose run node npm install` to install all npm modules.
14+
5. Run `docker-compose run composer update --ignore-platform-reqs --no-scripts` to install remaining composer modules
15+
6. Run `docker-compose run node npm run uf-assets-install` to install all frontend vendor assets.
1116

1217
Now you can start up the entire Nginx + PHP + MySQL stack using docker with:
1318

14-
$ sudo docker-compose up -d
19+
$ docker-compose up -d
20+
21+
the `-d` flag will launch this in the background so you can continue to use the terminal window. On the first run you need to init the database (your container name may be different depending on the name of your root directory):
22+
23+
$ docker exec -it -u www-data userfrosting_php_1 sh -c 'php bakery migrate'
1524

16-
On the first run you need to init the database (Be sure to execute this in the same directory, `${PWD##*/}` is a statement to get your current working directorys name. Docker uses it to name your container):
25+
You also need to setup the first admin user (again, your container name may be different depending on the name of your root directory):
1726

18-
$ sudo docker exec -it -u www-data ${PWD##*/}_php_1 bash -c 'php bakery migrate'
19-
20-
You also need to setup the first admin user (again, `${PWD##*/}` is a statement to get your current working directorys name):
27+
$ docker exec -it -u www-data userfrosting_php_1 sh -c 'php bakery create-admin'
2128

22-
$ sudo docker exec -it -u www-data ${PWD##*/}_php_1 bash -c 'php bakery create-admin'
29+
Now visit `http://localhost:8591/` to see your UserFrosting homepage!
2330

24-
Now visit http://localhost:8570/ to see your UserFrosting homepage!
31+
**Paste these into a bash file and execute it!**
2532

26-
**This is not (yet) meant for production!!**
33+
```
34+
chmod 777 app/{logs,cache,sessions}
35+
docker-compose build --force-rm --no-cache
36+
docker-compose run composer install --ignore-platform-reqs --no-scripts
37+
docker-compose run node npm install
38+
docker-compose run composer update --ignore-platform-reqs --no-scripts
39+
docker-compose run node npm run uf-assets-install
40+
docker-compose up -d
41+
echo -n "Enter Docker Container Name --> "
42+
read docker_container
43+
docker exec -it -u www-data $docker_container sh -c 'php bakery migrate'
44+
docker exec -it -u www-data $docker_container sh -c 'php bakery create-admin'
45+
```
46+
47+
**This is not (yet) meant for production!**
2748

2849
You may be tempted to run with this in production but this setup has not been security-hardened. For example:
2950

30-
- Database is exposed on port 8571 so you can access MySQL using your favorite client at localhost:8571. However,
51+
- Database is exposed on port 8593 so you can access MySQL using your favorite client at localhost:8593. However,
3152
the way Docker exposes this actually bypasses common firewalls like `ufw` so this should not be exposed in production.
3253
- Database credentials are hard-coded so obviously not secure.
3354
- File permissions may be more open than necessary.
55+
- HTTPS not implemented fully
3456
- It just hasn't been thoroughly tested in the capacity of being a production system.
35-
36-
## Updating your code
37-
As you might guessed you will have to run
38-
39-
$ sudo docker exec -it -u www-data userfrosting_php_1 bash -c 'php bakery migrate'
40-
41-
again if you want to migrate tables.
42-
You can change `php bakery migrate` to other `bakery` commands as well.
43-
Be aware that the userfrosting container doesn't know about npm!
44-
Similary for composer:
45-
46-
$ sudo docker-compose run composer update
47-
48-
See the [Docker](https://docs.docker.com/engine) and [Docker-compose documentation](https://docs.docker.com/compose/) for more details.

docker/php/Dockerfile

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,17 @@
1-
FROM php:7.2-fpm
2-
RUN apt-get update && apt-get install -y \
3-
libfreetype6-dev \
4-
libjpeg62-turbo-dev \
1+
FROM php:7.2-fpm-alpine
2+
3+
# Update and install packages
4+
RUN apk update
5+
RUN apk add \
6+
freetype-dev \
7+
libjpeg-turbo-dev \
58
libpng-dev \
6-
zip \
7-
&& docker-php-ext-configure gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ \
9+
zip
10+
11+
# Install and configure PHP extensions
12+
RUN docker-php-ext-configure gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ \
813
&& docker-php-ext-install -j$(nproc) gd \
914
&& docker-php-ext-install -j$(nproc) pdo pdo_mysql \
1015
&& docker-php-ext-install -j$(nproc) zip
11-
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
16+
1217
WORKDIR /app

0 commit comments

Comments
 (0)