Skip to content

Instantly share code, notes, and snippets.

@zanbaldwin
Last active February 13, 2022 13:02
Show Gist options
  • Save zanbaldwin/239adf21e2175e4eb17a2ff0e2a0da8a to your computer and use it in GitHub Desktop.
Save zanbaldwin/239adf21e2175e4eb17a2ff0e2a0da8a to your computer and use it in GitHub Desktop.
Quick and dirty script to pull a specific version of the PHP Docker image, much less hassle than having multiple PHP versions installed locally. You won't be able to install any extensions though because you won't be root (remove the --user flag if you're okay with creating files in your working tree belonging to root).
#!/bin/sh
if [ $# -eq 0 ]; then
echo 2>&1 "You must specify the PHP version as the first argument."
exit 1
fi
###################################################################################
### ENVIRONMENT HELPER ###
### --------------------------------------------------------------------------- ###
### Run this script to create a one-off container based on the PHP service for ###
### CLI work. It will auto-detect if you have Composer installed on your host; ###
### if so it will mount Composer as a binary inside the container and also ###
### Composer's cache directory to reduce the amount of downloading required. ###
### ###
### Useful if you have differing PHP versions between host and container. ###
###################################################################################
# Standardize Paths
realpath() {
# Can't be bothered to refactor this. If you're not using Bash on macOS then
# I'm not going to bother making sure this is compatible.
[[ $1 = /* ]] && echo "$1" || echo "${PWD}/${1#./}"
}
readlink -f "$0" >/dev/null 2>&1
if [ $? -ne 0 ]; then
DIR="$(dirname "$(realpath "$0")")"
else
DIR="$(dirname "$(readlink -f "$0")")"
fi
# Check for Docker Permissions
DOCKER="${DOCKER:-"docker"}"
command -v "${DOCKER}" >/dev/null 2>&1 || {
echo >&2 "$(tput setaf 1)Docker Client \"${DOCKER}\" not available on \$PATH.$(tput sgr0)";
exit 1;
}
INFO=$("${DOCKER}" info >/dev/null 2>&1)
if [ $? -ne 0 ]; then
echo >&2 "$(tput setaf 1)Docker Daemon unavailable.$(tput sgr0)"
if [ "$(id -u 2>/dev/null)" -ne "0" ]; then
echo >&2 "$(tput setaf 1)Perhaps retry as root?$(tput sgr0)"
fi
exit 1
fi
################################################################################
### DETECTING COMPOSER BINARY AND CACHE DIRECTORIES ###
### ------------------------------------------------------------------------ ###
### The following is a little unweildy because it will: ###
### - Attempt to detect the globally-installed Composer binary, but fallback ###
### onto a "composer.phar" file installed inside the "bin/" project ###
### directory. ###
### - Set appropriate "COMPOSER_HOME" env variable (falling back to a tmpfs ###
### folder in case Composer doesn't exist so that the non-root user can ###
### still create it if needed). ###
### - Figure out Composer's home (cache directory) and load it as a volume, ###
### falling back to creating one inside the "var/" project directory if it ###
### can't find it. ###
################################################################################
COMPOSER=""
# Use this default when no Composer binary is added, because without it set it will try to create on the root filesystem
# which the non-root user cannot create directories in.
COMPOSER_HOME="/tmp/composer"
# Set the default cache directory to be inside the "var/" project directory (project-specific rather than global).
COMPOSER_HOST_CACHE="/tmp/.composer"
# Try loading the local, project-specific composer.phar first (in case we're on macOS which won't allow mounting
# /private (/usr, /var, etc). If it does not exist, try mounting the globally installed Composer binary.
COMPOSER_BINARY="$(command -v composer 2>/dev/null)"
if [ -f "${COMPOSER_BINARY}" ]; then
# Assuming that PHP is installed on the host machine, try determine Composer's global home (cache) directory.
COMPOSER_HOST_HOMEDIR="$(php "${COMPOSER_BINARY}" global config home 2>/dev/null)"
if [ $? -eq 0 ] && [ -d "${COMPOSER_HOST_HOMEDIR}" ]; then
COMPOSER_HOST_CACHE="${COMPOSER_HOST_HOMEDIR}"
elif [ ! -d "${COMPOSER_HOST_CACHE}" ]; then
# Create the cache directory now as the host machine user, rather than let Docker create the volume
# bind as the root user (because then permissions would be all out of whack).
echo "$(tput setaf 2)Creating Composer cache directory...$(tput sgr0)"
mkdir -p "${COMPOSER_HOST_CACHE}"
fi
COMPOSER="--volume \"${COMPOSER_BINARY}:/bin/composer:ro\" --volume \"${COMPOSER_HOST_CACHE}:${COMPOSER_HOME}\" -e \"COMPOSER_HOME=${COMPOSER_HOME}\""
fi
PHP_VERSION="$1-alpine"
shift
COMMAND="sh"
# This little snippet wraps every command-line argument (after "bin/env") in quotes so that arguments with spaces in
# them (such as `bin/env bin/console oauth2:client:create "My Client Name"`) do not get turned into separate arguments
# (such as `bin/env bin/console oauth2:client:create "My" "Client" "Name"`).
if [ $# -gt 0 ]; then
COMMAND=""
for ARG in "$@"; do
COMMAND="${COMMAND} \"${ARG}\""
done
fi
SCRIPT="\"${DOCKER}\" run --rm -it --volume=\"$(pwd):/srv\" --workdir=\"/srv\" --user=\"$(id -u):$(id -g)\" ${COMPOSER} -e \"TERM=xterm\" "php:${PHP_VERSION}" ${COMMAND}"
"${SHELL:-"sh"}" -c "${SCRIPT}"
exit $?
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment