Drupal 8. Docker, composer, bootstrap, laravel-mix boilerplate. CI on GitLab
I’ve created a simple boilerplate to rapidly develop Drupal application based on the technological stack we work day-to-day. Purpose of that was to implement new programmers in Drupal 8 environment in easy way.
The whole stack contains
- Drupal 8 installed from composer based on https://github.com/drupal-composer/drupal-project
- Drupal docker based on https://github.com/wodby/docker4drupal
- Bootstrap 4 theme and custom subtheme https://www.drupal.org/project/bootstrap_barrio
Laravel-mix
that compilesscss
andes6
javascript withnpm
scriptsBrowsersync
to refresh css and javascript changes at once without need of refreshing the window.
Installation. Step by step
Start by creating new Drupal 8 instance from composer by calling
composer create-project drupal-composer/drupal-project:8.x-dev helloworld --stability dev --no-interaction
where helloworld
is name of folder where the website will be stored.
Then we would merge this with a docker environment by cloning from docker4drupal
and then copy the content of the drupal_docker_server
into the helloworld
folder
git clone git@github.com:wodby/docker4drupal.git drupal_docker_server
rm -R drupal_docker_server/.git
cp -R drupal_docker_server helloworld
Lets amend the volumes sections in drupal_docker_server/docker-compose.yml
into
volumes:
- ./../:/var/www/html
and setup localhost by changing traefik.frontend.rule
- 'traefik.frontend.rule=Host:localhost'
Now docker is ready to by launch
cd helloworld
docker-compose up -d
Visit http://localhost:8888/
to continue installation process. For database use the following settings
DB_HOST: mariadb
DB_USER: drupal
DB_PASSWORD: drupal
DB_NAME: drupal
DB_DRIVER: mysql
Drupal is installed now lets continue with setting up the frontend environment.
Docker composer and drush.
To call composer
just run docker-compose exec php composer …
and to run drush
just call docker-compose exec php drush …
for instance
docker-compose exec php composer update
or
docker-compose exec php drush config-export
Bootstrap 4 sub-theme.
Lets install bootstrap 4 Drupal theme
docker-compose exec php composer require drupal/bootstrap_barrio
now you need to copy files from subtheme
folder into new custom theme. This way you would have sub-theme that extends main theme.
cp -R web/themes/contrib/bootstrap_barrio/subtheme web/themes/custom/helloworld
where helloworld
is custom name of your theme
Rename the following files from bootstrap_barrio_subtheme
to helloworld
:bootstrap_barrio_subtheme.theme
to helloworld.theme
bootstrap_barrio_subtheme.info.yml
to helloworld.info.yml
bootstrap_barrio_subtheme.libraries.yml
to helloworld.libraries.yml
/config/install/bootstrap_barrio_subtheme.settings
to /config/install/helloworld.settings
/config/schema/bootstrap_barrio_subtheme.schema
to /config/schema/helloworld.schema
Edit the file helloworld.info.yml
name: YourName
type: theme
description: 'Your Description.'
version: VERSION
core: 8.x
base theme: bootstrap_barrio
libraries:
- helloworld/global-styling
Delete the following:
# Information added by Drupal.org packaging script on 2015-11-29
# version: '8.x-4.0-beta1'
# core: '8.x'
# project: 'bootstrap_barrio'
# datestamp: 1448759945
# Information added by Drupal.org packaging script on 2018-04-30
# version: '8.x-4.9'
# core: '8.x'
# project: 'bootstrap_barrio'
# datestamp: 1525127885
# Information added by Drupal.org packaging script on 2018-05-27
version: '8.x-4.12'
core: '8.x'
project: 'bootstrap_barrio'
datestamp: 1527445384
Edit /config/schema/helloworld.schema.yml
# Schema for the configuration files of the Bootstrap Barrio Subtheme.helloworld.settings:
type: theme_settings
label: 'YourTheme settings'
Edit /color/color.inc
line 117
// Preview files.
'preview_library' => 'helloworld/color.preview',
'preview_html' => 'color/preview.html',
Edit helloworld.theme
Rename the function from:
function bootstrap_barrio_subtheme_form_system_theme_settings_alter($form, FormStateInterface $form_state)
to:
function helloworld_form_system_theme_settings_alter($form, FormStateInterface $form_state)
visit http://localhost:8888
login into admin panel, and enable the new theme.
Laravel-mix boilerplate
Once empty bootstrap sub-theme is installed lets establish scss
and es6
deployment. We’re going to use superb laravel-mix
package
Laravel Mix provides a fluent API for defining Webpack build steps for your Laravel application using several common CSS and JavaScript pre-processors. Through simple method chaining, you can fluently define your asset pipeline. For example:
mix
.js('resources/js/app.js', 'public/js')
.sass('resources/sass/app.scss', 'public/css');If you’ve ever been confused and overwhelmed about getting started with Webpack and asset compilation, you will love Laravel Mix. However, you are not required to use it while developing your application. Of course, you are free to use any asset pipeline tool you wish, or even none at all.
To init the laravel-mix
create new npm package and get the dependencies by calling
npm init
npm i laravel-mix -s
We need to establish webpack
settings and deploy scripts. Lest create in main folder next to package.json
new file webpack.mix.js
and put there the following contents
const THEMEDIR = "./web/themes/custom/helloworld";
let mix = require('laravel-mix');mix
.browserSync({
proxy: 'localhost:8888',
files: [
`${THEMEDIR}/js/global.js`,
`${THEMEDIR}/css/*`,
]
})
.sass(`${THEMEDIR}/scss/style.scss`, `${THEMEDIR}/css`)
.js(`${THEMEDIR}/js/es6/global.js`, `${THEMEDIR}/js`)
.options({
processCssUrls: false
})
.sourceMaps();
and in package.json
amend scripts section
"scripts": {
"dev": "NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
"watch": "NODE_ENV=development node_modules/webpack/bin/webpack.js --watch --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
"hot": "NODE_ENV=development webpack-dev-server --inline --hot --config=node_modules/laravel-mix/setup/webpack.config.js",
"production": "NODE_ENV=production node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js"
},
and lets create web/themes/custom/helloworld/es6/global.js
js file, which would be entry file for all out js scripts.
Once this is setup, calling scripts npm run watch
launches browser sync at available port (most likely http://localhost:3000
) and watches all the css and js changes. It runs browsersync so all the css changes are replaced without refreshing and all the js changes would refresh the browser. You change change browsersync
settings in the webpack.mix.js
file.
Script npm run prod
compress css
& js
into production ready files.
Continuous Integration
Note that the following setup is good only for staging or test server, not for production use.
We’re going to use CI based on Gitlab. Basically after you push a code to develop
branch this builds stage server by doing the following
- pulls all the data from the git server, and merge files
- update composer dependencies
- clear drupal cache
- import config from
yaml
files - deploy
javascript
andscss
on the server by callingnpm
You would need
- install the drupal instance on the server — this differs on each machine
- have
composer
andnpm
installed (or you could usercomposer.phar
file like in example below) - have access to the server by ssh key and add this key into GitLab variables. Ssh key is saved into
$SSH_PRIVATE_KEY
variable
First lets create deploy script build.sh
. This is just an example you would have to change the values on your machine.
#!/bin/sh
cd /home/qunabu/webapps/helloworld
git fetch
git reset --hard HEAD
git checkout develop
git pull
php72 composer.phar update
php72 /home/qunabu/helloworld/vendor/drush/drush/drush cache-rebuild
php72 /home/qunabu/helloworld/vendor/drush/drush/drush config-import --yes
npm i
npm run dev
echo "success
Change access rights with chmod 700 build.sh
and test with ./build.sh
to see if everything works fine.
Once this step is ready what is left is to have GitLab to call it each time code on develop branch is pushed. Here is and example .gitlab-ci.yaml file
image: epcallan/php7-testing-phpunit:7.1-phpunit5deploy_stage:
stage: deploy
variables:
GIT_STRATEGY: none
environment:
name: stage
url: http://helloworld.qunabu.com/
before_script:
- 'which ssh-agent || ( apt-get update -y && apt-get install openssh-client -y )'
- eval $(ssh-agent -s)
- ssh-add <(echo "$SSH_PRIVATE_KEY")
- mkdir -p ~/.ssh
- echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > ~/.ssh/configscript:
- echo "Deploy to staging server"
- ssh qunabu@qunabu.webfactional.com 'exec /home/qunabu/helloworld/mbps/build.sh' only:
- develop
Here is example from Gitlab console of successful build.