Michaël Perrin
aka. the "Famous 5-minute install"
Why do we want to automate things?
Because developers are lazy? 🤔
docker-compose.yml
file at the root of the project:
services:
wordpress:
image: wordpress:5.2-php7.3-fpm-alpine
# ...
database:
image: mysql:5.7
# ...
webserver:
image: nginx:1.14-alpine
# ...
database:
image: mysql:5.7
restart: always
volumes:
- db_data:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
MYSQL_DATABASE: ${MYSQL_DATABASE}
MYSQL_USER: ${MYSQL_USER}
MYSQL_PASSWORD: ${MYSQL_USER_PASSWORD}
ports:
- 3306:3306
database:
image: mysql:5.7
restart: always
volumes:
- db_data:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
MYSQL_DATABASE: ${MYSQL_DATABASE}
MYSQL_USER: ${MYSQL_USER}
MYSQL_PASSWORD: ${MYSQL_USER_PASSWORD}
ports:
- 3306:3306
database:
image: mysql:5.7
restart: always
volumes:
- db_data:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
MYSQL_DATABASE: ${MYSQL_DATABASE}
MYSQL_USER: ${MYSQL_USER}
MYSQL_PASSWORD: ${MYSQL_USER_PASSWORD}
ports:
- 3306:3306
webserver:
image: nginx:1.14-alpine
links:
- wordpress
volumes:
- wordpress_data:/var/www/html
- ./docker/nginx/website.conf:/etc/nginx/conf.d/default.conf:ro
ports:
- ${WEBSERVER_PORT}:80
MYSQL_ROOT_PASSWORD=my_root_password
MYSQL_DATABASE=wordpress
MYSQL_USER=wordpress
MYSQL_USER_PASSWORD=wordpress_pwd
WEBSERVER_PORT=8000
.env
filedocker-compose up -d
All services are up and running:
WP-CLI provides a command-line interface for many actions you might perform in the WordPress admin.
wp-cli config create --dbhost=… --dbname=… <...>
wp-cli core install --url=… --title=…
wp-cli plugin install contact-form-7 --activate
wp-cli plugin install advanced-custom-fields --activate
Requirements for running WP-CLI:
Let's use a Docker container!
toolbox:
image: michaelperrin/wordpress-toolbox
volumes:
- wordpress_data:/wordpress
- ./Makefile:/scripts/Makefile
depends_on:
- database
environment:
MYSQL_HOST: ${MYSQL_HOST}
MYSQL_DATABASE: ${MYSQL_DATABASE}
MYSQL_USER: ${MYSQL_USER}
MYSQL_USER_PASSWORD: ${MYSQL_USER_PASSWORD}
WORDPRESS_ADMIN_EMAIL: ${WORDPRESS_ADMIN_EMAIL}
WORDPRESS_ADMIN_PASSWORD: ${WORDPRESS_ADMIN_PASSWORD}
WORDPRESS_ADMIN_USER: ${WORDPRESS_ADMIN_USERNAME}
WORDPRESS_DOMAIN_NAME: ${WORDPRESS_DOMAIN_NAME}
WORDPRESS_WEBSITE_URL: ${WORDPRESS_WEBSITE_URL}
WORDPRESS_LOCALE: en_US
WORDPRESS_WEBSITE_POST_URL_STRUCTURE: "/%year%/%monthnum%/%day%/%postname%/"
WORDPRESS_WEBSITE_TITLE: "My beautiful website"
task_one:
# ...
task_two:
# ...
task_three: task_one task_two
# ...
Run: make task_one
install: start configure install_plugins set_theme
start:
docker-compose up -d
stop:
docker-compose stop
configure:
# ... (several WP-CLI commands)
set_theme:
docker-compose run --rm toolbox wp-cli theme activate my-simple-theme
install_plugins:
# ... (one WP-CLI command per plugin)
make install
<?php
namespace Migration;
use WP\Migration\MigrationInterface;
class Migration201909221755 implements MigrationInterface
{
public function execute()
{
// ...
}
}
wp-content/migrations
class Migration201909221755 implements MigrationInterface {
use MigrationUtilitiesTrait;
public function execute() {
$pageData = [
'post_name' => 'about', // Permalink
'post_title' => 'About us',
'post_content' => '',
'post_status' => 'publish',
'post_author' => 1,
'post_type' => 'page',
'menu_order' => 1,
];
$postId = wp_insert_post($pageData);
$this->addToMenu($postId, 'About us');
}
}
class Migration201905311454 implements MigrationInterface {
public function execute() {
$this->setMailChimpApiKey(getenv('MAILCHIMP_API_KEY'));
}
private function setMailChimpApiKey(string $key) {
$options = get_option('mc4wp');
$options['api_key'] = $key;
update_option('mc4wp', $options);
}
}
make wordpress_migrations_execute
make wordpress_migrations_execute