Created
June 25, 2021 14:47
-
-
Save pwillis-els/b9568db8bbb1e1bba7000e79fbde9ac4 to your computer and use it in GitHub Desktop.
Best practice for building and running Wordpress + Bedrock + Apache2 + PHP-FPM + MariaDB in an Alpine container with docker-compose
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
FROM alpine:3.13.5 AS php7 | |
ENV PHP_VER=7.4 | |
ENV RUNTIME_USER=www-data | |
ENV RUNTIME_GROUP=www-data | |
# Alpine www-data UID/GID is 82 | |
ARG RUNTIME_UID=82 | |
ENV RUNTIME_UID=$RUNTIME_UID | |
ARG RUNTIME_GID=82 | |
ENV RUNTIME_GID=$RUNTIME_GID | |
RUN apk add -u --no-cache aws-cli bash curl ca-certificates jq sudo tini shadow ; \ | |
[ -e /usr/bin/tini ] || ln -sf /sbin/tini /usr/bin/tini | |
# install the PHP extensions we need | |
# - https://make.wordpress.org/hosting/handbook/handbook/server-environment/#php-extensions) | |
# - https://wiki.alpinelinux.org/wiki/WordPress | |
RUN set -eux; \ | |
apk add -u --no-cache \ | |
php7 php7-fpm php7-common php7-session php7-iconv php7-json php7-gd php7-curl php7-xml php7-mysqli php7-imap php7-cgi \ | |
php7-pdo php7-pdo_mysql php7-soap php7-xmlrpc php7-posix php7-mcrypt php7-gettext php7-ldap php7-ctype php7-dom \ | |
php7-mbstring php7-zip php7-pecl-imagick php7-pecl-ssh2 php7-intl php7-phar php7-tokenizer php7-xmlwriter php7-simplexml \ | |
libxml2 fcgi wget curl mysql-client ghostscript gnupg openssl ; \ | |
getent group www-data || addgroup -g ${RUNTIME_GID} -S www-data ; \ | |
getent passwd www-data || adduser -u ${RUNTIME_UID} -D -S -G www-data www-data ; \ | |
mkdir -p /run/php ; \ | |
chown -R ${RUNTIME_USER}:${RUNTIME_GROUP} /run/php ; \ | |
# Create a symlink to this Unix socket so we don't have to write configs against a single version | |
ln -sf /run/php/php${PHP_VER}-fpm.sock /run/php/php-fpm.sock ; \ | |
ln -sf /run/php/php${PHP_VER}-fpm.pid /run/php/php-fpm.pid | |
FROM php7 AS php7-apache2 | |
ENV RUNTIME_USER=www-data | |
ENV RUNTIME_GROUP=www-data | |
RUN set -eux; \ | |
apk add -u --no-cache \ | |
apache2 apache2-proxy apache2-proxy-html apache2-ctl apache2-ssl apr apr-util \ | |
apr-util-dbd_sqlite3 apr-util-ldap brotli-libs && \ | |
mkdir -p /var/run/apache2 /var/log/apache2 /var/lock/apache2 && \ | |
chown -R ${RUNTIME_USER}:${RUNTIME_GROUP} /var/run/apache2 /var/log/apache2 /var/lock/apache2 && \ | |
# Add www-data to the ssl-cert group to read the /etc/ssl/private/ keys | |
if getent group ssl-cert ; then usermod -aG ssl-cert www-data ; fi && \ | |
if getent passwd apache ; then usermod -aG www-data apache ; fi | |
ARG TLS_HOST | |
ENV TLS_HOST=$TLS_HOST | |
RUN openssl req \ | |
-new -newkey rsa:4096 -days 3650 -nodes -x509 \ | |
-subj "/C=US/ST=City/L=State/O=O/CN=$TLS_HOST" \ | |
-keyout domain.key -out domain.crt \ | |
&& mv domain.key domain.crt /etc/apache2/ | |
FROM php7 AS php7-bedrock | |
ENV BEDROCK_DIR=/app | |
# Download and install composer.phar | |
RUN set -eux && \ | |
php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" && \ | |
php -r "if (hash_file('sha384', 'composer-setup.php') === '756890a4488ce9024fc62c56153228907f1545c228516cbf63f885e036d37e9a59d27d63f46af1d4d07ee0f76181c7d3') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;" && \ | |
php composer-setup.php --install-dir=/usr/local/bin --filename=composer --version=2.0.8 && \ | |
php -r "unlink('composer-setup.php');" && \ | |
# Make sure we can write the composer cache as the user | |
homedir=`getent passwd ${RUNTIME_USER} | cut -d : -f 6` && \ | |
mkdir -p $homedir/.composer $homedir/.cache/composer ${BEDROCK_DIR} && \ | |
chown -R ${RUNTIME_USER}:${RUNTIME_GROUP} $homedir/.composer $homedir/.cache/composer ${BEDROCK_DIR} | |
# Change to Bedrock dir to copy files and run composer | |
USER ${RUNTIME_USER} | |
WORKDIR ${BEDROCK_DIR} | |
COPY --chown=${RUNTIME_USER}:${RUNTIME_GROUP} composer.json composer.lock ./ | |
RUN set -eux && \ | |
composer install --no-scripts --no-autoloader && \ | |
homedir=`getent passwd ${RUNTIME_USER} | cut -d : -f 6` && \ | |
rm -rf $homedir/.composer/* $homedir/.cache/composer/* | |
# Then copy anything else which might have invalidated the cache. | |
# This way dependencies are cached in the step above. | |
COPY --chown=${RUNTIME_USER}:${RUNTIME_GROUP} wp-cli.yml plugins.txt phpcs.xml ./ | |
COPY --chown=${RUNTIME_USER}:${RUNTIME_GROUP} web web | |
COPY --chown=${RUNTIME_USER}:${RUNTIME_GROUP} config config | |
RUN set -eux ; composer dump-autoload --optimize | |
FROM php7-apache2 AS production-bedrock | |
ENV BEDROCK_DIR=/app | |
ENV PHP_VER=7.4 | |
ENV HTTPD_PREFIX=/etc/apache2 | |
ARG HTTPD_LOGLEVEL=debug | |
ENV HTTPD_LOGLEVEL=$HTTPD_LOGLEVEL | |
ARG PHP_FPM_LOGLEVEL=notice | |
ENV PHP_FPM_LOGLEVEL=$PHP_FPM_LOGLEVEL | |
# This is the Apache2 docroot, so it must end in '/web'. | |
# The WP_SITEURL must then set to include '/wp'. | |
# If both are not done, the site will not load correctly. | |
ENV PHP_APP_DIR=/app/web | |
ENV PHP_PORT=9000 | |
ENV RUNTIME_USER=www-data | |
ENV RUNTIME_GROUP=www-data | |
# Alpine www-data UID/GID is 82 | |
ARG RUNTIME_UID=82 | |
ENV RUNTIME_UID=$RUNTIME_UID | |
ARG RUNTIME_GID=82 | |
ENV RUNTIME_GID=$RUNTIME_GID | |
WORKDIR ${BEDROCK_DIR} | |
COPY --from=php7-bedrock /usr/local/bin/composer /usr/local/bin/composer | |
COPY --from=php7-bedrock --chown=${RUNTIME_USER}:${RUNTIME_GROUP} ${BEDROCK_DIR} ${BEDROCK_DIR} | |
USER root | |
# This is mostly for calling /usr/sbin/php7.4-fpm and its sub-processes | |
ENV PATH=$PATH:/sbin:/usr/sbin:/usr/local/sbin | |
# add the user to the tty group so it can write to /dev/pts/0 | |
# (stdout and stderr are all /dev/pts/0 in docker) | |
RUN set -eux ; usermod -aG tty ${RUNTIME_USER} | |
# used by Bedrock | |
ARG WP_ENV=development | |
ENV WP_ENV=$WP_ENV | |
RUN rm -rf /etc/apache2/* | |
# Uncomment these to copy Apache and PHP-FPM configuration into the container | |
#COPY --chown=${RUNTIME_USER}:${RUNTIME_GROUP} .deploy/etc/ /etc/ | |
#COPY --chown=${RUNTIME_USER}:${RUNTIME_GROUP} .deploy/usr/ /usr/ | |
# Note: this command includes a sanity check of apache and php | |
RUN set -eux ; \ | |
[ -e /etc/apache2/conf.d/proxy-html.conf ] && sed -i -e 's/libxml2\.so$/libxml2.so.2/' /etc/apache2/conf.d/proxy-html.conf ; \ | |
ln -sf /etc/apache2/envvars /usr/sbin/envvars ; \ | |
[ ! -e /usr/lib/apache2/modules ] && ln -sf /usr/lib/apache2 /usr/lib/apache2/modules ; \ | |
[ ! -e /etc/mime.types ] && ln -sf /etc/apache2/mime.types /etc/mime.types ; \ | |
touch /usr/share/apache2/ask-for-passphrase ; \ | |
apachectl -t ; \ | |
cp -a /etc/php/phpenmod /etc/php/phpdismod /etc/php/phpquery /usr/sbin/ ; \ | |
/etc/php/phpenmod `cd /etc/php/${PHP_VER}/mods-available/; ls *.ini | sed -e 's/\.ini//g'` ; \ | |
[ ! -e /usr/sbin/php-fpm${PHP_VER} ] && [ -e /usr/sbin/php-fpm7 ] && ln -sf /usr/sbin/php-fpm7 /usr/sbin/php-fpm${PHP_VER} ; \ | |
php-fpm${PHP_VER} -t ; \ | |
chown ${RUNTIME_USER}:${RUNTIME_GROUP} ${BEDROCK_DIR} | |
EXPOSE 8080 | |
EXPOSE 8443 | |
# https://httpd.apache.org/docs/2.4/stopping.html#gracefulstop | |
#STOPSIGNAL SIGWINCH | |
STOPSIGNAL SIGQUIT | |
COPY entrypoint.sh /usr/local/bin/entrypoint.sh | |
COPY apache-wordpress.sh /usr/local/bin/apache-wordpress.sh | |
CMD [ "/usr/local/bin/apache-wordpress.sh" ] | |
# Look up AWS secrets on start-up | |
ENTRYPOINT ["/usr/bin/tini", "--", "/usr/local/bin/entrypoint.sh"] | |
HEALTHCHECK --interval=10s --timeout=30s --retries=3 CMD curl -iLf http://localhost:8080/ || exit 1 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env bash | |
# Start PHP-FPM and Apache in the Docker container | |
# | |
# Set PHP_VER and PHP_APP_DIR in your Docker container's ENV settings. | |
# | |
[ "${DEBUG:-0}" = "1" ] && set -x | |
set -eu | |
_cmd_start-php () { | |
echo "$0: Running: /usr/sbin/php-fpm${PHP_VER} in ${PHP_APP_DIR}" | |
( cd ${PHP_APP_DIR} && /usr/sbin/php-fpm${PHP_VER} -F ) & | |
} | |
_cmd_start-apache () { | |
echo "$0: Running: apache2-foreground &" | |
apache2-foreground & | |
} | |
_cmd_start () { | |
_cmd_start-php | |
_cmd_start-apache | |
} | |
# default command | |
CMD="start" | |
if [ "${1:-}" = "--help" ] ; then | |
cat <<EOUSAGE | |
Usage: $0 [CMD] | |
Runs a command, and waits for any background process to exit. | |
Commands: | |
start Start PHP-FPM and Apache | |
start-php Start PHP-FPM | |
start-apache Start Apache | |
EOUSAGE | |
exit 1 | |
fi | |
if [ $# -gt 0 ] ; then | |
CMD="$1"; shift | |
fi | |
_cmd_"$CMD" | |
# Wait for any background process to die | |
wait -n |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
version: "3" | |
services: | |
mysql: | |
container_name: wordpress-mysql | |
image: mariadb/server:10.4 | |
restart: always | |
volumes: | |
- wordpress-mysql:/var/lib/mysql | |
wordpress: | |
container_name: wordpress | |
depends_on: | |
- mysql | |
restart: always | |
build: | |
context: . | |
dockerfile: alpine.Dockerfile | |
args: | |
- BEDROCK_DIR=${BEDROCK_DIR} | |
- HTTPD_LOGLEVEL=${HTTPD_LOGLEVEL} | |
- PHP_FPM_LOGLEVEL=${PHP_FPM_LOGLEVEL} | |
- RUNTIME_GROUP=${RUNTIME_GROUP} | |
- RUNTIME_USER=${RUNTIME_USER} | |
- TLS_HOST=${TLS_HOST} | |
ports: | |
- 80:8080 | |
- 443:8443 | |
volumes: | |
wordpress-mysql: {} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/sh | |
[ "${DEBUG:-0}" = "1" ] && set -x | |
echo "$0: Running as: $(id -un) ($(id -u))" | |
echo "" | |
# Set PHP-FPM defaults at runtime | |
if [ "${ENV:-}" = "production" ] ; then | |
cp -f /usr/lib/php/${PHP_VER}/php.ini-production /etc/php/${PHP_VER}/fpm/php.ini | |
fi | |
# Set PHP-FPM log level at runtime | |
PHP_FPM_LOGLEVEL="${PHP_FPM_LOGLEVEL:-notice}" | |
sed -i -e "s/log_level.*/log_level = $PHP_FPM_LOGLEVEL/g" /etc/php/${PHP_VER}/fpm/php-fpm.conf | |
# Modify the UID and GID of the runtime user (if they changed at runtime) | |
OLDUID=$(id -u $RUNTIME_USER) | |
OLDGID=$(id -g $RUNTIME_USER) | |
if [ ! "$OLDUID" = "$RUNTIME_UID" ] || [ ! "$OLDGID" = "$RUNTIME_GID" ] ; then | |
usermod -u $RUNTIME_UID $RUNTIME_USER | |
groupmod -g $RUNTIME_GID $RUNTIME_USER | |
echo "$0: Please wait, changing filesystem ownership (this will take a while)..." | |
find /var/ /run/ -uid $OLDUID -exec chown -hR $RUNTIME_USER:$RUNTIME_GID {} \; | |
chown -hR $RUNTIME_USER:$(id -g $RUNTIME_USER) /app/ | |
fi | |
chown $RUNTIME_USER:$RUNTIME_GROUP /proc/self/fd/* | |
exec sudo -H -E -u $RUNTIME_USER -s /bin/bash "$@" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment