From 9357620d5526d90f04c2d10c62fdea7788bdf664 Mon Sep 17 00:00:00 2001 From: Timo Schwarzer Date: Sun, 23 Jun 2019 13:16:45 +0200 Subject: [PATCH 1/4] Add docker development environment --- .env.example.docker-development | 31 ++ app/Config/database.php | 12 + database/seeds/DummyContentSeeder.php | 11 + docker-compose.yml | 34 ++ docker/dev/Dockerfile | 15 + docker/dev/entrypoint.app.sh | 12 + docker/dev/entrypoint.node.sh | 8 + package-lock.json | 549 ++++++++++++++++++++++++++ readme.md | 23 ++ tests/Auth/AuthTest.php | 11 +- 10 files changed, 705 insertions(+), 1 deletion(-) create mode 100644 .env.example.docker-development create mode 100644 docker-compose.yml create mode 100644 docker/dev/Dockerfile create mode 100755 docker/dev/entrypoint.app.sh create mode 100755 docker/dev/entrypoint.node.sh diff --git a/.env.example.docker-development b/.env.example.docker-development new file mode 100644 index 000000000..0f5f193db --- /dev/null +++ b/.env.example.docker-development @@ -0,0 +1,31 @@ +# Application key +# Used for encryption where needed. +# Run `php artisan key:generate` to generate a valid key. +APP_KEY=SomeRandomString +DEV_PORT=8080 +APP_ENV=development +APP_DEBUG=true + +# Application URL +# Remove the hash below and set a URL if using BookStack behind +# a proxy, if using a third-party authentication option. +# This must be the root URL that you want to host BookStack on. +# All URL's in BookStack will be generated using this value. +#APP_URL=https://example.com + +# Database details +DB_CONNECTION=mysql_docker_dev + +# Mail system to use +# Can be 'smtp', 'mail' or 'sendmail' +MAIL_DRIVER=smtp + +# SMTP mail options +MAIL_HOST=localhost +MAIL_PORT=1025 +MAIL_USERNAME=null +MAIL_PASSWORD=null +MAIL_ENCRYPTION=null + + +# A full list of options can be found in the '.env.example.complete' file. \ No newline at end of file diff --git a/app/Config/database.php b/app/Config/database.php index 93a44854f..98063942d 100644 --- a/app/Config/database.php +++ b/app/Config/database.php @@ -92,6 +92,18 @@ return [ 'strict' => false, ], + 'mysql_docker_dev' => [ + 'driver' => 'mysql', + 'host' => 'db', + 'database' => 'bookstack-test', + 'username' => 'bookstack-test', + 'password' => 'bookstack-test', + 'charset' => 'utf8', + 'collation' => 'utf8_unicode_ci', + 'prefix' => '', + 'strict' => false, + ], + 'pgsql' => [ 'driver' => 'pgsql', 'host' => env('DB_HOST', 'localhost'), diff --git a/database/seeds/DummyContentSeeder.php b/database/seeds/DummyContentSeeder.php index ce3cd1307..52386691e 100644 --- a/database/seeds/DummyContentSeeder.php +++ b/database/seeds/DummyContentSeeder.php @@ -11,6 +11,17 @@ class DummyContentSeeder extends Seeder */ public function run() { + // Create admin user + $adminUser = new \BookStack\Auth\User(); + $adminUser->name = 'Admin User'; + $adminUser->email = 'admin@test.local'; + $adminUser->password = Hash::make('admin'); + $adminUser->email_confirmed = true; + $adminUser->setRememberToken(str_random(10)); + $adminUser->save(); + $adminRole = \BookStack\Auth\Role::getRole('admin'); + $adminUser->attachRole($adminRole); + // Create an editor user $editorUser = factory(\BookStack\Auth\User::class)->create(); $editorRole = \BookStack\Auth\Role::getRole('editor'); diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 000000000..63aa2b0c7 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,34 @@ +# This is a Docker Compose configuration +# intended for development purposes + +version: '3' + +volumes: + db: {} + +services: + db: + image: mysql:8 + environment: + MYSQL_DATABASE: bookstack-test + MYSQL_USER: bookstack-test + MYSQL_PASSWORD: bookstack-test + MYSQL_RANDOM_ROOT_PASSWORD: 'true' + command: --default-authentication-plugin=mysql_native_password + volumes: + - db:/var/lib/mysql + app: + build: + context: . + dockerfile: docker/dev/Dockerfile + ports: + - ${DEV_PORT}:80 + volumes: + - ./:/app + entrypoint: /app/docker/dev/entrypoint.app.sh + node: + image: node:alpine + working_dir: /app + volumes: + - ./:/app + entrypoint: /app/docker/dev/entrypoint.node.sh diff --git a/docker/dev/Dockerfile b/docker/dev/Dockerfile new file mode 100644 index 000000000..5830a5e80 --- /dev/null +++ b/docker/dev/Dockerfile @@ -0,0 +1,15 @@ +FROM php:7.3-apache + +ENV APACHE_DOCUMENT_ROOT /app/public +WORKDIR /app + +RUN apt-get update -y \ + && apt-get install -y libtidy-dev libpng-dev libxml++2.6-dev wait-for-it \ + && docker-php-ext-install pdo pdo_mysql tidy dom xml mbstring gd \ + && a2enmod rewrite \ + && sed -ri -e 's!/var/www/html!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/sites-available/*.conf \ + && sed -ri -e 's!/var/www/!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/apache2.conf /etc/apache2/conf-available/*.conf \ + && php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" \ + && php composer-setup.php \ + && mv composer.phar /usr/bin/composer \ + && php -r "unlink('composer-setup.php');" diff --git a/docker/dev/entrypoint.app.sh b/docker/dev/entrypoint.app.sh new file mode 100755 index 000000000..aa2144d81 --- /dev/null +++ b/docker/dev/entrypoint.app.sh @@ -0,0 +1,12 @@ +#!/bin/bash + +set -e + +if [[ "$1" == "composer" ]]; then + exec "$@" +else + wait-for-it db:3306 -t 45 + php artisan migrate --database=mysql_docker_dev + chown -R www-data:www-data storage + exec apache2-foreground +fi \ No newline at end of file diff --git a/docker/dev/entrypoint.node.sh b/docker/dev/entrypoint.node.sh new file mode 100755 index 000000000..e59e1e8a0 --- /dev/null +++ b/docker/dev/entrypoint.node.sh @@ -0,0 +1,8 @@ +#!/bin/sh + +set -e + +npm install +npm rebuild node-sass + +exec npm run watch \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 352ad5ce9..3330ad5c7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -833,6 +833,7 @@ "anymatch": "^2.0.0", "async-each": "^1.0.1", "braces": "^2.3.2", + "fsevents": "^1.2.7", "glob-parent": "^3.1.0", "inherits": "^2.0.3", "is-binary-path": "^1.0.0", @@ -1908,6 +1909,554 @@ "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", "dev": true }, + "fsevents": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.9.tgz", + "integrity": "sha512-oeyj2H3EjjonWcFjD5NvZNE9Rqe4UW+nQBU2HNeKw0koVLEFIhtyETyAakeAM3de7Z/SW5kcA+fZUait9EApnw==", + "dev": true, + "optional": true, + "requires": { + "nan": "^2.12.1", + "node-pre-gyp": "^0.12.0" + }, + "dependencies": { + "abbrev": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "ansi-regex": { + "version": "2.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "aproba": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "optional": true + }, + "are-we-there-yet": { + "version": "1.1.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "balanced-match": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "brace-expansion": { + "version": "1.1.11", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "chownr": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true, + "dev": true, + "optional": true + }, + "concat-map": { + "version": "0.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "console-control-strings": { + "version": "1.1.0", + "bundled": true, + "dev": true, + "optional": true + }, + "core-util-is": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "debug": { + "version": "4.1.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ms": "^2.1.1" + } + }, + "deep-extend": { + "version": "0.6.0", + "bundled": true, + "dev": true, + "optional": true + }, + "delegates": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "detect-libc": { + "version": "1.0.3", + "bundled": true, + "dev": true, + "optional": true + }, + "fs-minipass": { + "version": "1.2.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minipass": "^2.2.1" + } + }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "gauge": { + "version": "2.7.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "glob": { + "version": "7.1.3", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "has-unicode": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "iconv-lite": { + "version": "0.4.24", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ignore-walk": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minimatch": "^3.0.4" + } + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.3", + "bundled": true, + "dev": true, + "optional": true + }, + "ini": { + "version": "1.3.5", + "bundled": true, + "dev": true, + "optional": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "isarray": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "0.0.8", + "bundled": true, + "dev": true, + "optional": true + }, + "minipass": { + "version": "2.3.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" + } + }, + "minizlib": { + "version": "1.2.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minipass": "^2.2.1" + } + }, + "mkdirp": { + "version": "0.5.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "2.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "needle": { + "version": "2.3.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "debug": "^4.1.0", + "iconv-lite": "^0.4.4", + "sax": "^1.2.4" + } + }, + "node-pre-gyp": { + "version": "0.12.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "detect-libc": "^1.0.2", + "mkdirp": "^0.5.1", + "needle": "^2.2.1", + "nopt": "^4.0.1", + "npm-packlist": "^1.1.6", + "npmlog": "^4.0.2", + "rc": "^1.2.7", + "rimraf": "^2.6.1", + "semver": "^5.3.0", + "tar": "^4" + } + }, + "nopt": { + "version": "4.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "abbrev": "1", + "osenv": "^0.1.4" + } + }, + "npm-bundled": { + "version": "1.0.6", + "bundled": true, + "dev": true, + "optional": true + }, + "npm-packlist": { + "version": "1.4.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ignore-walk": "^3.0.1", + "npm-bundled": "^1.0.1" + } + }, + "npmlog": { + "version": "4.1.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "object-assign": { + "version": "4.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "once": { + "version": "1.4.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "wrappy": "1" + } + }, + "os-homedir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "os-tmpdir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "osenv": { + "version": "0.1.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "process-nextick-args": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "rc": { + "version": "1.2.8", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "readable-stream": { + "version": "2.3.6", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "rimraf": { + "version": "2.6.3", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "glob": "^7.1.3" + } + }, + "safe-buffer": { + "version": "5.1.2", + "bundled": true, + "dev": true, + "optional": true + }, + "safer-buffer": { + "version": "2.1.2", + "bundled": true, + "dev": true, + "optional": true + }, + "sax": { + "version": "1.2.4", + "bundled": true, + "dev": true, + "optional": true + }, + "semver": { + "version": "5.7.0", + "bundled": true, + "dev": true, + "optional": true + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "string-width": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "string_decoder": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "tar": { + "version": "4.4.8", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "chownr": "^1.1.1", + "fs-minipass": "^1.2.5", + "minipass": "^2.3.4", + "minizlib": "^1.1.1", + "mkdirp": "^0.5.0", + "safe-buffer": "^5.1.2", + "yallist": "^3.0.2" + } + }, + "util-deprecate": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "wide-align": { + "version": "1.1.3", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "string-width": "^1.0.2 || 2" + } + }, + "wrappy": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "yallist": { + "version": "3.0.3", + "bundled": true, + "dev": true, + "optional": true + } + } + }, "fstream": { "version": "1.0.12", "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz", diff --git a/readme.md b/readme.md index 62e2aa65d..ede6e5aa5 100644 --- a/readme.md +++ b/readme.md @@ -75,6 +75,29 @@ php artisan db:seed --class=DummyContentSeeder --database=mysql_testing Once done you can run `php vendor/bin/phpunit` in the application root directory to run all tests. +## Getting started with Development using Docker + +This repository ships with a Docker Compose configuration intended for development purposes. It'll build a PHP image with all needed extensions installed and start up a MySQL server and a Node image watching the UI assets. + +To get started, make sure you meet the following requirements: + +- Docker and Docker Compose are installed +- Your user is part of the `docker` group +- Composer is installed + +If all the conditions are met, you can proceed with the following steps: + +1. Install Composer dependencies with **`docker-compose run app composer install`** (first time can take a while because the image has to be built) +2. **Copy `.env.example.docker-development` to `.env`** and change `APP_KEY` to a random 32 char string +3. Make sure **port 8080 is unused** *or else* change `DEV_PORT` to a free port on your host +4. **Run `chgrp -R docker storage`**. The development container will chown the `storage` directory to the `www-data` user inside the container so BookStack can write to it. You need to change the group to your host's `docker` group here to not lose access to the `storage` directory +5. **Run `docker-compose up`** and wait until all database migrations have been done +6. **If you're starting the server for the first time**, seed the database in a separate terminal session: + ```php + docker-compose exec app php artisan db:seed --class=DummyContentSeeder --database=mysql_docker_dev + ``` +7. You can now login with `admin@test.local` and `admin` as password on `localhost:8080` (or another port if specified) + ## Translations All text strings can be found in the `resources/lang` folder where each language option has its own folder. To add a new language you should copy the `en` folder to an new folder (eg. `fr` for french) then go through and translate all text strings in those files, leaving the keys and file-names intact. If a language string is missing then the `en` translation will be used. To show the language option in the user preferences language drop-down you will need to add your language to the options found at the bottom of the `resources/lang/en/settings.php` file. A system-wide language can also be set in the `.env` file like so: `APP_LANG=en`. diff --git a/tests/Auth/AuthTest.php b/tests/Auth/AuthTest.php index 3d36d85b2..42b44c152 100644 --- a/tests/Auth/AuthTest.php +++ b/tests/Auth/AuthTest.php @@ -1,8 +1,8 @@ users; + if (count($adminUsers) > 1) { + foreach ($adminUsers->splice(1) as $user) { + $user->delete(); + } + } + // Ensure we currently only have 1 admin user $this->assertEquals(1, $adminRole->users()->count()); $user = $adminRole->users->first(); From b608bb885955d529a273e688d005acbf98727fbf Mon Sep 17 00:00:00 2001 From: Timo Schwarzer Date: Mon, 12 Aug 2019 16:59:51 +0200 Subject: [PATCH 2/4] Remove additional database connections and seeders in docker env --- .env.example.docker-development | 31 -------------- app/Config/database.php | 12 ------ database/seeds/DummyContentSeeder.php | 61 --------------------------- docker-compose.yml | 7 +++ readme.md | 8 +--- 5 files changed, 9 insertions(+), 110 deletions(-) delete mode 100644 .env.example.docker-development delete mode 100644 database/seeds/DummyContentSeeder.php diff --git a/.env.example.docker-development b/.env.example.docker-development deleted file mode 100644 index 0f5f193db..000000000 --- a/.env.example.docker-development +++ /dev/null @@ -1,31 +0,0 @@ -# Application key -# Used for encryption where needed. -# Run `php artisan key:generate` to generate a valid key. -APP_KEY=SomeRandomString -DEV_PORT=8080 -APP_ENV=development -APP_DEBUG=true - -# Application URL -# Remove the hash below and set a URL if using BookStack behind -# a proxy, if using a third-party authentication option. -# This must be the root URL that you want to host BookStack on. -# All URL's in BookStack will be generated using this value. -#APP_URL=https://example.com - -# Database details -DB_CONNECTION=mysql_docker_dev - -# Mail system to use -# Can be 'smtp', 'mail' or 'sendmail' -MAIL_DRIVER=smtp - -# SMTP mail options -MAIL_HOST=localhost -MAIL_PORT=1025 -MAIL_USERNAME=null -MAIL_PASSWORD=null -MAIL_ENCRYPTION=null - - -# A full list of options can be found in the '.env.example.complete' file. \ No newline at end of file diff --git a/app/Config/database.php b/app/Config/database.php index 98063942d..93a44854f 100644 --- a/app/Config/database.php +++ b/app/Config/database.php @@ -92,18 +92,6 @@ return [ 'strict' => false, ], - 'mysql_docker_dev' => [ - 'driver' => 'mysql', - 'host' => 'db', - 'database' => 'bookstack-test', - 'username' => 'bookstack-test', - 'password' => 'bookstack-test', - 'charset' => 'utf8', - 'collation' => 'utf8_unicode_ci', - 'prefix' => '', - 'strict' => false, - ], - 'pgsql' => [ 'driver' => 'pgsql', 'host' => env('DB_HOST', 'localhost'), diff --git a/database/seeds/DummyContentSeeder.php b/database/seeds/DummyContentSeeder.php deleted file mode 100644 index 52386691e..000000000 --- a/database/seeds/DummyContentSeeder.php +++ /dev/null @@ -1,61 +0,0 @@ -name = 'Admin User'; - $adminUser->email = 'admin@test.local'; - $adminUser->password = Hash::make('admin'); - $adminUser->email_confirmed = true; - $adminUser->setRememberToken(str_random(10)); - $adminUser->save(); - $adminRole = \BookStack\Auth\Role::getRole('admin'); - $adminUser->attachRole($adminRole); - - // Create an editor user - $editorUser = factory(\BookStack\Auth\User::class)->create(); - $editorRole = \BookStack\Auth\Role::getRole('editor'); - $editorUser->attachRole($editorRole); - - // Create a viewer user - $viewerUser = factory(\BookStack\Auth\User::class)->create(); - $role = \BookStack\Auth\Role::getRole('viewer'); - $viewerUser->attachRole($role); - - $byData = ['created_by' => $editorUser->id, 'updated_by' => $editorUser->id]; - - factory(\BookStack\Entities\Book::class, 5)->create($byData) - ->each(function($book) use ($editorUser, $byData) { - $chapters = factory(\BookStack\Entities\Chapter::class, 3)->create($byData) - ->each(function($chapter) use ($editorUser, $book, $byData){ - $pages = factory(\BookStack\Entities\Page::class, 3)->make(array_merge($byData, ['book_id' => $book->id])); - $chapter->pages()->saveMany($pages); - }); - $pages = factory(\BookStack\Entities\Page::class, 3)->make($byData); - $book->chapters()->saveMany($chapters); - $book->pages()->saveMany($pages); - }); - - $largeBook = factory(\BookStack\Entities\Book::class)->create(array_merge($byData, ['name' => 'Large book' . str_random(10)])); - $pages = factory(\BookStack\Entities\Page::class, 200)->make($byData); - $chapters = factory(\BookStack\Entities\Chapter::class, 50)->make($byData); - $largeBook->pages()->saveMany($pages); - $largeBook->chapters()->saveMany($chapters); - - $shelves = factory(\BookStack\Entities\Bookshelf::class, 10)->create($byData); - $largeBook->shelves()->attach($shelves->pluck('id')); - - app(\BookStack\Auth\Permissions\PermissionService::class)->buildJointPermissions(); - app(\BookStack\Entities\SearchService::class)->indexAllEntities(); - } -} diff --git a/docker-compose.yml b/docker-compose.yml index 63aa2b0c7..26f783cb6 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -21,6 +21,13 @@ services: build: context: . dockerfile: docker/dev/Dockerfile + environment: + DB_CONNECTION: mysql + DB_HOST: db + DB_PORT: 3306 + DB_DATABASE: bookstack-test + DB_USER: bookstack-test + DB_PASSWORD: bookstack-test ports: - ${DEV_PORT}:80 volumes: diff --git a/readme.md b/readme.md index ede6e5aa5..9587529da 100644 --- a/readme.md +++ b/readme.md @@ -88,15 +88,11 @@ To get started, make sure you meet the following requirements: If all the conditions are met, you can proceed with the following steps: 1. Install Composer dependencies with **`docker-compose run app composer install`** (first time can take a while because the image has to be built) -2. **Copy `.env.example.docker-development` to `.env`** and change `APP_KEY` to a random 32 char string +2. **Copy `.env.example` to `.env`** and change `APP_KEY` to a random 32 char string 3. Make sure **port 8080 is unused** *or else* change `DEV_PORT` to a free port on your host 4. **Run `chgrp -R docker storage`**. The development container will chown the `storage` directory to the `www-data` user inside the container so BookStack can write to it. You need to change the group to your host's `docker` group here to not lose access to the `storage` directory 5. **Run `docker-compose up`** and wait until all database migrations have been done -6. **If you're starting the server for the first time**, seed the database in a separate terminal session: - ```php - docker-compose exec app php artisan db:seed --class=DummyContentSeeder --database=mysql_docker_dev - ``` -7. You can now login with `admin@test.local` and `admin` as password on `localhost:8080` (or another port if specified) +6. You can now login with `admin@admin.com` and `password` as password on `localhost:8080` (or another port if specified) ## Translations From c6b1f36412435dc969183913e01de13b3e8fafca Mon Sep 17 00:00:00 2001 From: Timo Schwarzer Date: Mon, 12 Aug 2019 22:19:58 +0200 Subject: [PATCH 3/4] Alter docker paths --- docker-compose.yml => dev/docker-compose.yml | 16 ++++++++-------- {docker/dev => dev/docker}/Dockerfile | 0 {docker/dev => dev/docker}/entrypoint.app.sh | 6 ++++-- {docker/dev => dev/docker}/entrypoint.node.sh | 0 4 files changed, 12 insertions(+), 10 deletions(-) rename docker-compose.yml => dev/docker-compose.yml (72%) rename {docker/dev => dev/docker}/Dockerfile (100%) rename {docker/dev => dev/docker}/entrypoint.app.sh (60%) rename {docker/dev => dev/docker}/entrypoint.node.sh (100%) diff --git a/docker-compose.yml b/dev/docker-compose.yml similarity index 72% rename from docker-compose.yml rename to dev/docker-compose.yml index 26f783cb6..44560ad9d 100644 --- a/docker-compose.yml +++ b/dev/docker-compose.yml @@ -19,23 +19,23 @@ services: - db:/var/lib/mysql app: build: - context: . - dockerfile: docker/dev/Dockerfile + context: .. + dockerfile: ./dev/docker/Dockerfile environment: DB_CONNECTION: mysql DB_HOST: db DB_PORT: 3306 DB_DATABASE: bookstack-test - DB_USER: bookstack-test + DB_USERNAME: bookstack-test DB_PASSWORD: bookstack-test ports: - - ${DEV_PORT}:80 + - ${DEV_PORT:-8080}:80 volumes: - - ./:/app - entrypoint: /app/docker/dev/entrypoint.app.sh + - ../:/app + entrypoint: /app/dev/docker/entrypoint.app.sh node: image: node:alpine working_dir: /app volumes: - - ./:/app - entrypoint: /app/docker/dev/entrypoint.node.sh + - ../:/app + entrypoint: /app/dev/docker/entrypoint.node.sh diff --git a/docker/dev/Dockerfile b/dev/docker/Dockerfile similarity index 100% rename from docker/dev/Dockerfile rename to dev/docker/Dockerfile diff --git a/docker/dev/entrypoint.app.sh b/dev/docker/entrypoint.app.sh similarity index 60% rename from docker/dev/entrypoint.app.sh rename to dev/docker/entrypoint.app.sh index aa2144d81..ff44f0c8d 100755 --- a/docker/dev/entrypoint.app.sh +++ b/dev/docker/entrypoint.app.sh @@ -2,11 +2,13 @@ set -e -if [[ "$1" == "composer" ]]; then +env + +if [[ -n "$1" ]]; then exec "$@" else wait-for-it db:3306 -t 45 - php artisan migrate --database=mysql_docker_dev + php artisan migrate --database=mysql chown -R www-data:www-data storage exec apache2-foreground fi \ No newline at end of file diff --git a/docker/dev/entrypoint.node.sh b/dev/docker/entrypoint.node.sh similarity index 100% rename from docker/dev/entrypoint.node.sh rename to dev/docker/entrypoint.node.sh From 21f09a5920c7a3b7b9e0f4dde3db1159061e2593 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Mon, 26 Aug 2019 22:01:10 +0100 Subject: [PATCH 4/4] Added ldap and moved compose for docker-dev setup - Also tweaked readme a little to fit this is with more recent changes. --- dev/docker/Dockerfile | 5 +++-- dev/docker-compose.yml => docker-compose.yml | 8 ++++---- readme.md | 20 ++++++++++++-------- 3 files changed, 19 insertions(+), 14 deletions(-) rename dev/docker-compose.yml => docker-compose.yml (90%) diff --git a/dev/docker/Dockerfile b/dev/docker/Dockerfile index 5830a5e80..82ea2b6f6 100644 --- a/dev/docker/Dockerfile +++ b/dev/docker/Dockerfile @@ -4,8 +4,9 @@ ENV APACHE_DOCUMENT_ROOT /app/public WORKDIR /app RUN apt-get update -y \ - && apt-get install -y libtidy-dev libpng-dev libxml++2.6-dev wait-for-it \ - && docker-php-ext-install pdo pdo_mysql tidy dom xml mbstring gd \ + && apt-get install -y libtidy-dev libpng-dev libldap2-dev libxml++2.6-dev wait-for-it \ + && docker-php-ext-configure ldap --with-libdir=lib/x86_64-linux-gnu \ + && docker-php-ext-install pdo pdo_mysql tidy dom xml mbstring gd ldap \ && a2enmod rewrite \ && sed -ri -e 's!/var/www/html!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/sites-available/*.conf \ && sed -ri -e 's!/var/www/!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/apache2.conf /etc/apache2/conf-available/*.conf \ diff --git a/dev/docker-compose.yml b/docker-compose.yml similarity index 90% rename from dev/docker-compose.yml rename to docker-compose.yml index 44560ad9d..47f38184e 100644 --- a/dev/docker-compose.yml +++ b/docker-compose.yml @@ -1,5 +1,5 @@ # This is a Docker Compose configuration -# intended for development purposes +# intended for development purposes only version: '3' @@ -19,7 +19,7 @@ services: - db:/var/lib/mysql app: build: - context: .. + context: . dockerfile: ./dev/docker/Dockerfile environment: DB_CONNECTION: mysql @@ -31,11 +31,11 @@ services: ports: - ${DEV_PORT:-8080}:80 volumes: - - ../:/app + - ./:/app entrypoint: /app/dev/docker/entrypoint.app.sh node: image: node:alpine working_dir: /app volumes: - - ../:/app + - ./:/app entrypoint: /app/dev/docker/entrypoint.node.sh diff --git a/readme.md b/readme.md index 0e25f9791..6f0956eb5 100644 --- a/readme.md +++ b/readme.md @@ -79,7 +79,7 @@ Once done you can run `php vendor/bin/phpunit` in the application root directory PHP code within BookStack is generally to [PSR-2](http://www.php-fig.org/psr/psr-2/) standards. From the BookStack root folder you can run `./vendor/bin/phpcs` to check code is formatted correctly and `./vendor/bin/phpcbf` to auto-fix non-PSR-2 code. -### Getting started with Development using Docker +### 🐋 Development using Docker This repository ships with a Docker Compose configuration intended for development purposes. It'll build a PHP image with all needed extensions installed and start up a MySQL server and a Node image watching the UI assets. @@ -87,17 +87,21 @@ To get started, make sure you meet the following requirements: - Docker and Docker Compose are installed - Your user is part of the `docker` group -- Composer is installed If all the conditions are met, you can proceed with the following steps: -1. Install Composer dependencies with **`docker-compose run app composer install`** (first time can take a while because the image has to be built) -2. **Copy `.env.example` to `.env`** and change `APP_KEY` to a random 32 char string -3. Make sure **port 8080 is unused** *or else* change `DEV_PORT` to a free port on your host -4. **Run `chgrp -R docker storage`**. The development container will chown the `storage` directory to the `www-data` user inside the container so BookStack can write to it. You need to change the group to your host's `docker` group here to not lose access to the `storage` directory -5. **Run `docker-compose up`** and wait until all database migrations have been done -6. You can now login with `admin@admin.com` and `password` as password on `localhost:8080` (or another port if specified) +1. Install PHP/Composer dependencies with **`docker-compose run app composer install`** (first time can take a while because the image has to be built). +2. **Copy `.env.example` to `.env`** and change `APP_KEY` to a random 32 char string. +3. Make sure **port 8080 is unused** *or else* change `DEV_PORT` to a free port on your host. +4. **Run `chgrp -R docker storage`**. The development container will chown the `storage` directory to the `www-data` user inside the container so BookStack can write to it. You need to change the group to your host's `docker` group here to not lose access to the `storage` directory. +5. **Run `docker-compose up`** and wait until all database migrations have been done. +6. You can now login with `admin@admin.com` and `password` as password on `localhost:8080` (or another port if specified). +If needed, You'll be able to run any artisan commands via docker-compose like so: + + ```shell script +docker-compose run app php artisan list +``` ## 🌎 Translations