“The factory of the future will have only two employees, a man, and a dog. The man will be there to feed the dog. The dog will be there to keep the man from touching the equipment.” Warren G. Bennis

This post requires basic knowledge of Docker, composer, bash linux. You need to have docker, docker-compose, composer installed on a linux-like environment.

Commerce (Here I refer to 2.x) is a set of Drupal 8 modules, which in turn depend on other best-of-breed modules and libraries. Commerce 2.x currently requires Drupal 8.5.0 or newer. Generally we require each minor release, as it contains improvements that we use, or to reduce our code base.

Alternative DDEV and Drupal VM. I tested them found them cool but too overwhelming and non so transparent.

You will need composer

PHP requirements: Drupal Commerce requires that you have the bcmath extension installed: php-bcmath

When using a Docker setup you now have a layer between you and your code, which means command line tools are a little harder. If you feel overwhelmed you can just log into the container and run your command. To log into the container use the following command docker exec -ti nameofcontainer /bin/bash then you’re in the root of your project on that server. From there you have drupal console, drush, composer, git and other normal command line tools.

I use an environment called .env file to manage all the version of the containers:

PROJECT_NAME=d8commerce
DRUPAL_VERSION=8.6.12
PHP_VERSION=7.2-fpm
NGINX_TAG=alpine
NGINX_PORT=8080:80
DRUPAL_TAG=8.6-fpm-alpine
MYSQL_VERSION=10.4
MYSQL_TAG=8
DB_NAME=drupal
DB_USER=drupal
DB_PASSWORD=drupal
DB_ROOT_PASSWORD=password

The constants are used in the docker-compose.yml file:

note: volumes are outer_volume:internal_volume. The internal_volume needs to match the Dockerfile filesystem. Check the image Dockerfile on hub.docker.io

You need to put docker-compose.yml file in a folder identically named as ${PROJECT_NAME}

version: "3.7"

services:

  web:
    image: nginx:$NGINX_TAG
    container_name: "${PROJECT_NAME}_nginx"
    ports:
      - $NGINX_PORT
    volumes:
      - "/var/www/html/${PROJECT_NAME}:/var/www/html/"
      - "/etc/nginx/conf.d/site.conf:/etc/nginx/conf.d/default.conf"
    depends_on:
      - php
      - mariadb
  php:
    image: php:$PHP_VERSION
    container_name: "${PROJECT_NAME}_php"
    volumes:
      - "/var/www/html/${PROJECT_NAME}:/var/www/html/"
    restart: always
    depends_on:
      - mysql   

  mariadb:
    image: mariadb:$MYSQL_VERSION
    container_name: "${PROJECT_NAME}_mysql"
    restart: always
    volumes:
      - mariadb-data:/var/lib/mysql
    environment:
      MYSQL_ROOT_PASSWORD: qwerty

  phpmyadmin:
    image: phpmyadmin/phpmyadmin:latest
    ports:
      - 8000:80
    environment:
      - PMA_ARBITRARY=1
      - PMA_HOST=mariadb
    depends_on:
      - mariadb

volumes:
  mariadb-data:

Data persistence. Data is stored in a created volume: mariadb-data. You can find it inside your project tree. This is where all db data will be stored, even if container is restarted, data will be there.

Environment variables: MYSQL_ROOT_PASSWORD: qwerty - sets root password for mariadb container.

Environment variable PMA_ARBITRARY=1 - adds “server” input field to phpmyadmin login page (this way you can use this phpmyadmin with an external MySQL DB, and not just this local setup) environment variable PMA_HOST=mariadb - told phpmyadmin how to connect to mariadb map ports for phpmyadmin - 8000:80 - this maps inner port 80 from inside the container, to port 8000 on my host machine “depends_on” - prevents container to start before other container, on which it depends

Manage the containers

After everything is ready, we can turn on the containers (nginx, php, and MySQL)

docker-compose up -d

You can now visit http://localhost:8080 and start to install a new Drupal 8 project.

composer create-project drupalcommerce/project-base mystore --prefer-source --stability dev

The bin folder contains any library binaries, such as Drupal Console, PHPUnit, Behat, etc. The web folder represents the document root. If you host your site on Acquia Cloud or another service that requires Drupal in a subdirectory other than web, these instructions describe how you can relocate the docroot. Composer commands are always run from the site root (mystore in this case). See the Composer template for Drupal projects README for more details.

You can run php -S localhost:8080 from within your Drupal site to allow the tests to run.

When you are done, you can turn off the containers: docker-compose down

Export and Import database

If you already have an existing project you can put the project under drupal/web folder without running the installation script. After that, you can export and import database by using these commands

Maintenance

For export database

docker exec drupal8_mysql /usr/bin/mysqldump -u root --password=password drupal > drupal/backup.sql

To import database

cat drupal/backup.sql  | docker exec -i drupal8_mysql /usr/bin/mysql -u root --password=password drupal

Enable Commerce

The instructions below use Drupal Console

drupal module:install commerce_product commerce_checkout commerce_cart

Update / upgrade Commerce

To update Drupal Commerce and all contributed projects extending Drupal Commerce:

composer update --with-dependencies "drupal/commerce*"

If you want to only upgrade Drupal Commerce, run this command:

composer update --with-dependencies drupal/commerce drupal/commerce_price drupal/commerce_product drupal/commerce_order drupal/commerce_payment drupal/commerce_payment_example drupal/commerce_checkout drupal/commerce_tax drupal/commerce_cart drupal/commerce_log drupal/commerce_store drupal/commerce_promotion drupal/commerce_number_pattern

Once the Drupal.org infrastructure issue is resolved, the command will be

composer update drupal/commerce --with-dependencies

Please note the --with-dependencies option. Without this option specified, any needed, contributed projects and libraries will not update. Only the Drupal Commerce module will be updated.

Run your Drupal updates once all of the dependencies are updated. We recommend running them on the command line rather than the update.php script. See the example below.

drupal debug:update
drupal update:execute

Composer update tips

If your composer update command isn’t working, you can try: Run composer why-not to check dependency issues. Run composer remove then composer require to reinstall the project. Delete the composer.lock file and entire /vendor directory from your project and then run composer install. Run composer clear-cache. Run composer self-update.

I can go to: myapp.loc/ - and still see phpinfo page myapp.loc:8000 - see phpmyadmin, I can login using root/qwerty credentials

  1. What if I need database to be up and running with some initial DB inside, and not empty? This can be achieved by modifying mariadb section with: command: “mysqld –init-file /data/application/init.sql”

and

volumes:
    - ./init.sql:/data/application/init.sql

init.sql - is an existing DB dump. using volumes I copy this file to container’s /data/application/init.sql location using “mysqld –init-file” command - I tell mysql to start and import init.sql

Once DB running, how to export/import DB?

To see list of containers and learn container id or name of mariadb container: docker container ls To import:

docker exec -i docker_mariadb_1 mysql -uroot -pqwerty DB_NAME < your_local_db_dump.sql

To export:

docker exec -i docker_mariadb_1 mysqldump -uroot -pqwerty DB_NAME > your_local_db_dump.sql