Skip to content

Commit

Permalink
docker: Add script for selecting different PHP versions
Browse files Browse the repository at this point in the history
`jetpack docker select-php` (or `select-php` inside the container) is
now avalable to install and run a different version of PHP inside the
container.
  • Loading branch information
anomiex committed Sep 8, 2023
1 parent 60adf74 commit 42eabd8
Show file tree
Hide file tree
Showing 4 changed files with 137 additions and 27 deletions.
14 changes: 14 additions & 0 deletions tools/cli/commands/docker.js
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,8 @@ const buildExecCmd = argv => {
opts.push( 'bash' );
} else if ( cmd === 'db' ) {
opts.push( 'mysql', '--defaults-group-suffix=docker' );
} else if ( cmd === 'select-php' ) {
opts.push( 'select-php', argv.version );
} else if ( cmd === 'phpunit' ) {
// @todo: Make this scale.
console.warn( chalk.yellow( 'This currently only run tests for the Jetpack plugin.' ) );
Expand Down Expand Up @@ -624,6 +626,18 @@ export function dockerDefine( yargs ) {
builder: yargExec => defaultOpts( yargExec ),
handler: argv => execDockerCmdHandler( argv ),
} )
.command( {
command: 'select-php <version>',
description:
'Select the version of PHP for use inside the container. See documentation for important notes!',
builder: yargCmd => {
yargCmd.positional( 'version', {
describe: 'The version to select, or "default".',
type: 'string',
} );
},
handler: argv => execDockerCmdHandler( argv ),
} )
.command( {
command: 'phpunit',
description: 'Run PHPUnit tests inside container',
Expand Down
38 changes: 11 additions & 27 deletions tools/docker/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,13 @@ ENV LC_ALL en_US.UTF-8

WORKDIR /tmp

# Record ARGs
RUN \
echo "PHP_VERSION=$PHP_VERSION" > /etc/docker-args.sh \
&& echo "NODE_VERSION=$NODE_VERSION" >> /etc/docker-args.sh \
&& echo "COMPOSER_VERSION=$COMPOSER_VERSION" >> /etc/docker-args.sh \
&& echo "PNPM_VERSION=$PNPM_VERSION" >> /etc/docker-args.sh

# Install basic packages, including Apache.
RUN --mount=type=cache,target=/var/lib/apt/lists/,sharing=private \
export DEBIAN_FRONTEND=noninteractive \
Expand Down Expand Up @@ -41,31 +48,12 @@ RUN --mount=type=cache,target=/var/lib/apt/lists/,sharing=private \
RUN a2enmod rewrite

# Install requested version of PHP.
COPY ./bin/select-php.sh /usr/local/bin/select-php
RUN chmod +x /usr/local/bin/select-php
COPY ./config/php.ini /var/lib/jetpack-config/php.ini
RUN --mount=type=cache,target=/var/lib/apt/lists/,sharing=private \
: "${PHP_VERSION:?Build argument PHP_VERSION needs to be set and non-empty.}" \
&& export DEBIAN_FRONTEND=noninteractive \
&& apt-get install -y \
libapache2-mod-php${PHP_VERSION} \
php${PHP_VERSION} \
php${PHP_VERSION}-bcmath \
php${PHP_VERSION}-cli \
php${PHP_VERSION}-curl \
php${PHP_VERSION}-intl \
php${PHP_VERSION}-ldap \
php${PHP_VERSION}-mbstring \
php${PHP_VERSION}-mysql \
php${PHP_VERSION}-opcache \
php${PHP_VERSION}-pgsql \
php${PHP_VERSION}-soap \
php${PHP_VERSION}-sqlite3 \
php${PHP_VERSION}-xdebug \
php${PHP_VERSION}-xml \
php${PHP_VERSION}-xsl \
php${PHP_VERSION}-zip \
&& apt-get install -y --no-install-recommends \
php${PHP_VERSION}-apcu \
php${PHP_VERSION}-gd \
php${PHP_VERSION}-imagick \
&& /usr/local/bin/select-php "$PHP_VERSION" \
&& find /var/ -name '*-old' -delete && rm -rf /var/log/dpkg.log /var/log/alternatives.log /var/log/apt/ ~/.launchpadlib

# Install requested version of Composer.
Expand Down Expand Up @@ -109,10 +97,6 @@ RUN mkdir /usr/local/src/psysh \
# Copy a default config file for an apache host.
COPY ./config/apache_default /etc/apache2/sites-available/000-default.conf

# Copy a default set of settings for PHP (php.ini).
COPY ./config/php.ini /etc/php/${PHP_VERSION}/mods-available/jetpack-wordpress.ini
RUN phpenmod jetpack-wordpress

# Copy single site htaccess to /var/lib/jetpack-config. run.sh will move it to the site's base dir if there's none present.
COPY ./config/htaccess /var/lib/jetpack-config/htaccess
COPY ./config/htaccess-multi /var/lib/jetpack-config/htaccess-multi
Expand Down
19 changes: 19 additions & 0 deletions tools/docker/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,25 @@ wp> get_bloginfo( 'name' );

Note that each `wp shell` session counts as a single request, causing unexpected situations with WP cache. You might want to run [`wp_cache_flush()`](https://developer.wordpress.org/reference/functions/wp_cache_flush/) between requests you expect to get cached by WordPress.

### Changing PHP versions

You can select different versions of PHP. For example, to use PHP 8.0 inside the container:

```sh
jetpack docker select-php 8.0
```

If you're already inside the container after using `jetpack docker sh`, you can use `select-php 8.0` there too.

Note some caveats:

* Running `jetpack docker down` or otherwise recreating the containers will reset to the default PHP version.
* If you're wanting the new version of PHP to be used to serve web requests, you'll need to `jetpack docker stop && jetpack docker up -d` or the like.
* You may need to update Composer packages from inside the container before you can successfully run `phpunit` or the like, in order to install a version compatible with the new version of PHP.
* For example, `jetpack docker exec -- composer -d /usr/local/src/jetpack-monorepo/projects/plugins/jetpack update`
* Be careful not to commit any resulting changes to `composer.lock` files!
* On Linux systems, doing this may result in odd ownership of files in relevant `vendor/` and `jetpack_vendor/` directories. Removing them (probaby using `sudo`) is a valid fix.

## MySQL database

You can see your database files via local file system at `./tools/docker/data/mysql`
Expand Down
93 changes: 93 additions & 0 deletions tools/docker/bin/select-php.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
#!/bin/bash

set -eo pipefail

source /etc/docker-args.sh

VER=$1
if [[ "$1" == default ]]; then
VER="$PHP_VERSION"
elif [[ ! "$1" =~ ^[0-9]+\.[0-9]+$ ]]; then
cat <<-EOF
USAGE: $0 <version>
<version> may be "default" or a two-part version number like "$PHP_VERSION".
EOF
exit 1
fi

export DEBIAN_FRONTEND=noninteractive

# Determine packages to install.
PKGS=(
"libapache2-mod-php${VER}"
"php${VER}"
"php${VER}-bcmath"
"php${VER}-cli"
"php${VER}-curl"
"php${VER}-intl"
"php${VER}-ldap"
"php${VER}-mbstring"
"php${VER}-mysql"
"php${VER}-opcache"
"php${VER}-pgsql"
"php${VER}-soap"
"php${VER}-sqlite3"
"php${VER}-xdebug"
"php${VER}-xml"
"php${VER}-xsl"
"php${VER}-zip"
)
NO_RECOMMENDS_PKGS=(
"php${VER}-apcu"
"php${VER}-gd"
"php${VER}-imagick"
)

# php-json is built in in 8.0+.
if [[ "$VER" == [57].* ]]; then
PKGS+=( "php${VER}-json" )
fi

# Install selected packages.
printf '\e[1m== Installing PHP %s ==\e[0m\n' "$VER"
apt-get update -q
apt-get install -qy "${PKGS[@]}"
apt-get install -qy --no-install-recommends "${NO_RECOMMENDS_PKGS[@]}"

# Enable our custom config for the new version.
[[ -e "/etc/php/${VER}/mods-available/jetpack-wordpress.ini" ]] || ln -s /var/lib/jetpack-config/php.ini "/etc/php/${VER}/mods-available/jetpack-wordpress.ini"
phpenmod -v "$VER" jetpack-wordpress

# Upgrade or downgrade Composer if necessary.
if command -v composer &> /dev/null; then
printf '\n\e[1m== Installing Composer ==\e[0m\n'
if [[ "$VER" == 5.6 || "$VER" == 7.[01] ]]; then
CV=2.2.18
else
CV="$COMPOSER_VERSION"
fi
# Execute with whichever version of PHP is newer.
if php -r 'exit( version_compare( PHP_VERSION, $argv[1], ">" ) ? 0 : 1 );' "$PHP_VERSION"; then
composer self-update "$CV"
else
"php$VER" "$(command -v composer)" self-update "$CV"
fi
fi

# Select the new version to be used for stuff.
printf '\n\e[1m== Setting PHP %s as default ==\e[0m\n' "$VER"
for name in php phar phar.phar; do
update-alternatives --quiet --set "$name" "/usr/bin/$name$VER"
done
if a2query -m | grep -q "^php$VER "; then
:
else
if a2query -m | grep -q '^php'; then
a2dismod 'php*'
fi
a2enmod "php$VER"

printf '\n\e[30;43mThe web server is still running the old version of PHP!\e[0m\n'
printf '\e[30;43mRestart the docker container (e.g. `jetpack docker stop && jetpack docker up -d`) to use the new version.\e[0m\n'
fi

0 comments on commit 42eabd8

Please sign in to comment.