clean install

This commit is contained in:
2024-12-10 15:08:16 +01:00
commit e14eb2d8fd
31193 changed files with 3555714 additions and 0 deletions

View File

@@ -0,0 +1,150 @@
##
# Alias the Drupal base image for use in other build stages.
# We do this so that the Drupal image version only needs to be updated here.
FROM drupal:10.3 as baseimage
# Define common paths.
# BUILD_PATH is where the farmOS codebase will be built.
# DRUPAL_PATH is where the farmOS codebase will be copied to after build.
# We keep these separate to faciliate the docker-entrypoint.sh script's logic
# for populating empty bind-mounted host directories.
# The Drupal base image symlinks /var/www/html to /opt/drupal and configures
# /opt/drupal/web as the DocumentRoot.
ENV BUILD_PATH=/var/farmOS
ENV DRUPAL_PATH=/opt/drupal
##
# Build/install PHP extensions.
FROM baseimage as php-dependencies
# Build and install the GEOS PHP extension.
# See https://git.osgeo.org/gitea/geos/php-geos
ARG PHP_GEOS_VERSION=e77d5a16abbf89a59d947d1fe49381a944762c9d
ADD https://github.com/libgeos/php-geos/archive/${PHP_GEOS_VERSION}.tar.gz /opt/php-geos.tar.gz
RUN apt-get update && apt-get install -y libgeos-dev \
&& ( tar xzf /opt/php-geos.tar.gz -C /opt/ \
&& cd /opt/php-geos-${PHP_GEOS_VERSION} \
&& ./autogen.sh \
&& ./configure \
&& make \
&& make install \
)
# Install the BCMath PHP extension.
RUN docker-php-ext-install bcmath
##
# Build common requirements for production and development images.
FROM baseimage as common
# Set the farmOS and composer project repository URLs and versions.
ARG FARMOS_REPO=https://github.com/farmOS/farmOS.git
ARG FARMOS_VERSION=3.x
ARG PROJECT_REPO=https://github.com/farmOS/composer-project.git
ARG PROJECT_VERSION=3.x
# Set Apache ServerName directive globally to suppress AH00558 message.
RUN echo "ServerName localhost" >> /etc/apache2/apache2.conf
# Enable PHP dependencies.
COPY --from=php-dependencies /usr/local/lib/php/extensions/ /usr/local/lib/php/extensions/
RUN docker-php-ext-enable geos bcmath
# Add custom PHP configurations.
COPY conf.d/ /usr/local/etc/php/conf.d
# Install apt dependencies.
RUN apt-get update && apt-get install -y \
# Install git and unzip (needed by Composer).
git unzip \
# Install postgresql-client so Drush can connect to the database.
postgresql-client \
# Install libgeos-c1v5 so geos php extension can use libgeos_c.so.1.
libgeos-c1v5 \
&& rm -rf /var/lib/apt/lists/* \
&& apt-get clean
# Set the COMPOSER_MEMORY_LIMIT environment variable to unlimited.
ENV COMPOSER_MEMORY_LIMIT=-1
# Set COMPOSER_ALLOW_SUPERUSER=1 to allow plugins to run as root/super user.
ENV COMPOSER_ALLOW_SUPERUSER=1
# Add the build-farmOS.sh script.
COPY build-farmOS.sh /usr/local/bin/
RUN chmod a+x /usr/local/bin/build-farmOS.sh
# Set the entrypoint.
COPY docker-entrypoint.sh /usr/local/bin/
ENTRYPOINT ["docker-entrypoint.sh"]
CMD ["apache2-foreground"]
##
# Build the production image.
FROM common as production
# Build the farmOS codebase in ${BUILD_PATH} with the --no-dev flag.
# Change the ownership of the sites directory and copy the farmOS codebase into ${DRUPAL_PATH}.
RUN mkdir ${BUILD_PATH} \
&& /usr/local/bin/build-farmOS.sh --no-dev \
&& chown -R www-data:www-data ${BUILD_PATH}/web/sites \
&& rm -r ${DRUPAL_PATH} && cp -rp ${BUILD_PATH} ${DRUPAL_PATH}
## Build the development image.
FROM common as dev
# Install and enable XDebug extension.
RUN yes | pecl install xdebug \
&& docker-php-ext-enable xdebug
# Add opcache revalidation frequency configuration.
COPY dev/conf.d/ /usr/local/etc/php/conf.d
# Change the user/group IDs of www-data inside the image to match the ID of the
# developer's user on the host machine. This allows Composer to create files
# owned by www-data inside the container, while keeping those files editable by
# the developer outside of the container.
# This defaults to 1000, based on the assumption that the developer is running
# as UID 1000 on the host machine. It can be overridden at image build time with:
# --build-arg WWW_DATA_ID=$(id -u)
ARG WWW_DATA_ID=1000
RUN usermod -u ${WWW_DATA_ID} www-data && groupmod -g ${WWW_DATA_ID} www-data
# Create a ${BUILD_PATH} directory owned by www-data.
RUN mkdir ${BUILD_PATH} && chown www-data:www-data ${BUILD_PATH}
# Change to the www-data user.
USER www-data
# Build the farmOS codebase in ${BUILD_PATH}.
RUN /usr/local/bin/build-farmOS.sh
# Add dev configurartions for PHP CodeSniffer and PHPStan.
COPY --chown=www-data ./dev/files/ ${BUILD_PATH}/
# Configure PHPUnit.
RUN cp -p ${BUILD_PATH}/web/core/phpunit.xml.dist ${BUILD_PATH}/phpunit.xml \
&& sed -i 's|bootstrap="tests/bootstrap.php"|bootstrap="web/core/tests/bootstrap.php"|g' ${BUILD_PATH}/phpunit.xml \
&& sed -i '/failOnWarning="true"/a \ failOnIncomplete="true"' ${BUILD_PATH}/phpunit.xml \
&& sed -i '/failOnWarning="true"/a \ failOnSkipped="true"' ${BUILD_PATH}/phpunit.xml \
&& sed -i 's|name="SIMPLETEST_BASE_URL" value=""|name="SIMPLETEST_BASE_URL" value="http://www"|g' ${BUILD_PATH}/phpunit.xml \
&& sed -i 's|name="SIMPLETEST_DB" value=""|name="SIMPLETEST_DB" value="pgsql://farm:farm@db/farm"|g' ${BUILD_PATH}/phpunit.xml \
&& sed -i 's|name="BROWSERTEST_OUTPUT_DIRECTORY" value=""|name="BROWSERTEST_OUTPUT_DIRECTORY" value="/var/www/html/sites/simpletest/browser_output"|g' ${BUILD_PATH}/phpunit.xml \
&& sed -i 's|name="MINK_DRIVER_ARGS_WEBDRIVER" value='\'''\''|name="MINK_DRIVER_ARGS_WEBDRIVER" value='\''["chrome", { "chromeOptions": { "w3c": false, "args": ["--disable-gpu","--headless", "--no-sandbox"] } }, "http://chrome:4444/wd/hub"]'\''|g' ${BUILD_PATH}/phpunit.xml \
&& sed -i 's|\./|\./web/core/|g' ${BUILD_PATH}/phpunit.xml \
&& sed -i 's|\.\./web/core/|\./web/|g' ${BUILD_PATH}/phpunit.xml \
&& sed -i 's| </php>| <env name="SYMFONY_DEPRECATIONS_HELPER" value="disabled"/>'"\n"' </php>|g' ${BUILD_PATH}/phpunit.xml \
&& mkdir -p ${BUILD_PATH}/web/sites/simpletest/browser_output
# Change back to the root user.
USER root
# Copy the farmOS codebase into ${DRUPAL_PATH}.
RUN rm -r ${DRUPAL_PATH} && cp -rp ${BUILD_PATH} ${DRUPAL_PATH}
# Create a Composer config directory for the www-data user.
RUN mkdir /var/www/.composer && chown www-data:www-data /var/www/.composer
##
# Build the final production image.
FROM production

View File

@@ -0,0 +1,33 @@
# Running farmOS with Docker
This directory contains files necessary to build the farmOS Docker image, along
with example `docker-compose.yml` files that can be used for running farmOS in
Docker containers.
## Development environment
To run a farmOS development environment, copy `docker-compose.development.yml`
into a new directory on your server, rename it to `docker-compose.yml` and run
`docker compose up`.
This example mounts a local `www` directory on the host as a volume in the
container at `/opt/drupal`, which allows for local development with an IDE.
## Production environment
To run a farmOS production environment, use `docker-compose.production.yml` as
an example for building your own configuration. It references a non-existent
`farmos/farmos:x.y.z` image version tag, which should be replaced with the most
recent farmOS stable release version.
This example mounts a local `sites` directory on the host as a volume in the
container at `/opt/drupal/web/sites`, which contains the site-specific settings
and uploaded files. This allows a production farmOS instance to be updated by
simply pulling a new image (and then manually running database updates via Drush
or `/update.php`). Everything outside of the `sites` directory will not be
preserved and will be replaced with the new official farmOS files.
Note that this example does not include a database. It is assumed that in
production environments the database will be managed outside of Docker.
For more information, see https://farmOS.org/hosting.

View File

@@ -0,0 +1,78 @@
#!/bin/bash
set -e
###
# This script will build the farmOS codebase in ${BUILD_PATH}.
# The default path is /var/farmOS.
###
# If ${BUILD_PATH} is not empty, bail.
if [ "$(ls -A ${BUILD_PATH})" ]; then
echo "The build path ${BUILD_PATH} is not empty, terminating."
exit 1
fi
# Make ${BUILD_PATH} the working directory.
cd ${BUILD_PATH}
# Generate an empty Composer project project and checkout a specific version.
git clone ${PROJECT_REPO} project
mv project/.git ./.git
rm -rf project
git checkout ${PROJECT_VERSION}
git reset --hard
# Create a temporary Composer cache directory.
export COMPOSER_HOME="$(mktemp -d)"
# If FARMOS_VERSION is a valid semantic versioning string, we assume that it is
# a tagged version.
IS_TAGGED_RELEASE=false
if [[ "${FARMOS_VERSION}" =~ ^(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)(-((0|[1-9][0-9]*|[0-9]*[a-zA-Z-][0-9a-zA-Z-]*)(\.(0|[1-9][0-9]*|[0-9]*[a-zA-Z-][0-9a-zA-Z-]*))*))?(\+([0-9a-zA-Z-]+(\.[0-9a-zA-Z-]+)*))?$ ]]; then
IS_TAGGED_RELEASE=true
fi
# Add the farmOS repository to composer.json (if this is not a tagged release).
if [ "${IS_TAGGED_RELEASE}" = false ]; then
composer config repositories.farmos git ${FARMOS_REPO}
fi
# Require the correct farmOS version in composer.json.
# If FARMOS_VERSION is 3.x, we will require 3.x-dev.
if [ "${FARMOS_VERSION}" = "3.x" ]; then
FARMOS_COMPOSER_VERSION="3.x-dev"
# Or, if this is a tagged release, require the tag version.
elif [ "${IS_TAGGED_RELEASE}" = true ]; then
FARMOS_COMPOSER_VERSION="${FARMOS_VERSION}"
# Otherwise, we assume that FARMOS_VERSION is a branch, and prepend "dev-".
else
FARMOS_COMPOSER_VERSION="dev-${FARMOS_VERSION}"
fi
composer require farmos/farmos:${FARMOS_COMPOSER_VERSION} --no-install
# Add allow-plugins config.
allowedPlugins=(
"composer/installers"
"cweagans/composer-patches"
"dealerdirect/phpcodesniffer-composer-installer"
"drupal/core-composer-scaffold"
"oomphinc/composer-installers-extender"
"phpstan/extension-installer"
"wikimedia/composer-merge-plugin"
)
for plugin in ${allowedPlugins[@]}; do
composer config --no-plugins allow-plugins.$plugin true
done
# Run composer install with optional arguments passed into this script.
if [ $# -eq 0 ]; then
composer install
else
composer install "$*"
fi
# Set the version in farm.info.yml.
sed -i "s|version: 3.x|version: ${FARMOS_VERSION}|g" ${BUILD_PATH}/web/profiles/farm/farm.info.yml
# Remove the Composer cache directory.
rm -rf "$COMPOSER_HOME"

View File

@@ -0,0 +1,9 @@
# Set recommended PHP settings for farmOS.
# See https://farmos.org/hosting/install/#server-requirements
memory_limit=256M
max_execution_time=240
max_input_time=240
max_input_vars=5000
post_max_size=100M
upload_max_filesize=100M
expose_php=Off

View File

@@ -0,0 +1,5 @@
# Set recommended OPcache for maximum performance in Symfony applications.
# See https://symfony.com/doc/current/performance.html#configure-opcache-for-maximum-performance
# @todo https://github.com/docker-library/drupal/issues/155
opcache.memory_consumption=256
opcache.max_accelerated_files=20000

View File

@@ -0,0 +1,4 @@
# Set recommended realpath_cache settings.
# See https://www.drupal.org/docs/7/managing-site-performance/tuning-phpini-for-drupal
realpath_cache_size=4096K
realpath_cache_ttl=3600

View File

@@ -0,0 +1,3 @@
# Set OPcache's revalidation frequency to 0 seconds for development.
# See https://www.php.net/manual/en/opcache.configuration.php#ini.opcache.revalidate-freq
opcache.revalidate_freq=0

View File

@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<ruleset name="farmOS">
<description>PHP CodeSniffer configuration for farmOS development.</description>
<file>.</file>
<arg name="extensions" value="php,module,inc,install,test,profile,theme,css,info,txt,yml"/>
<config name="drupal_core_version" value="10"/>
<rule ref="Drupal">
<exclude name="Drupal.InfoFiles.AutoAddedKeys.Project"/>
<exclude name="Drupal.InfoFiles.AutoAddedKeys.Version"/>
<exclude name="Drupal.Arrays.Array.LongLineDeclaration"/>
# @todo https://www.drupal.org/project/coder/issues/2159253
<exclude name="Drupal.Commenting.InlineComment.SpacingAfter"/>
</rule>
<rule ref="DrupalPractice">
# @todo https://www.drupal.org/project/coder/issues/2159253
<exclude name="DrupalPractice.Commenting.CommentEmptyLine.SpacingAfter"/>
</rule>
<rule ref="PHPCompatibility"/>
<config name="testVersion" value="8.2-"/>
<rule ref="Internal.Tokenizer.Exception"><severity>0</severity></rule>
</ruleset>

View File

@@ -0,0 +1,8 @@
parameters:
level: 1
ignoreErrors:
# new static() is a best practice in Drupal, so we cannot fix that.
- '#^Unsafe usage of new static#'
scanDirectories:
# Tell PHPStan where to find GeoPHP classes.
- vendor/itamair/geophp

View File

@@ -0,0 +1,35 @@
services:
db:
image: postgres:13
volumes:
- './db:/var/lib/postgresql/data'
ports:
- '5432:5432'
environment:
POSTGRES_USER: farm
POSTGRES_PASSWORD: farm
POSTGRES_DB: farm
www:
depends_on:
- db
image: farmos/farmos:3.x-dev
volumes:
- './www:/opt/drupal'
ports:
- '80:80'
extra_hosts:
- host.docker.internal:host-gateway
environment:
XDEBUG_MODE: debug
XDEBUG_CONFIG: client_host=host.docker.internal
# Enable this for PHPStorm:
#XDEBUG_SESSION: PHPSTORM
#PHP_IDE_CONFIG: serverName=localhost
# Enable this service when executing javascript tests.
# chrome:
# Tests are failing on later versions of this image.
# See https://github.com/farmOS/farmOS/issues/514
# image: selenium/standalone-chrome:4.1.2-20220217

View File

@@ -0,0 +1,9 @@
services:
www:
# Update this to the latest stable version before deploying.
image: farmos/farmos:3.x.y
volumes:
- './sites:/opt/drupal/web/sites'
ports:
- '80:80'
restart: always

View File

@@ -0,0 +1,14 @@
services:
www:
image: farmos/farmos:3.x-dev
volumes:
- './www:/opt/drupal'
environment:
FARMOS_FS_READY_SENTINEL_FILENAME: /opt/drupal/www-container-fs-ready
SIMPLETEST_DB: $DB_URL
XDEBUG_MODE: 'off'
chrome:
# Tests are failing on later versions of this image.
# See https://github.com/farmOS/farmOS/issues/514
image: selenium/standalone-chrome:4.1.2-20220217

View File

@@ -0,0 +1,25 @@
# Inherits from docker-compose.testing.common.yml
services:
db:
image: mariadb:10
volumes:
- './db:/var/lib/mysql'
ports:
- '3306:3306'
environment:
MYSQL_ROOT_PASSWORD: farm
MYSQL_DATABASE: farm
MYSQL_USER: farm
MYSQL_PASSWORD: farm
healthcheck:
test: [ "CMD", "healthcheck.sh", "--connect", "--innodb_initialized" ]
start_period: 1m
start_interval: 10s
interval: 1m
timeout: 5s
retries: 3
www:
depends_on:
db:
condition: service_healthy

View File

@@ -0,0 +1,16 @@
# Inherits from docker-compose.testing.common.yml
services:
db:
image: postgres:13
volumes:
- './db:/var/lib/postgresql/data'
ports:
- '5432:5432'
environment:
POSTGRES_USER: farm
POSTGRES_PASSWORD: farm
POSTGRES_DB: farm
www:
depends_on:
- db

View File

@@ -0,0 +1,2 @@
# Inherits from docker-compose.testing.common.yml
services: { }

View File

@@ -0,0 +1,28 @@
#!/bin/bash
set -e
###
# This entrypoint script will check to see if certain directories are empty
# (as is the case when a directory is bind-mounted from the host), and will
# populate them from the pre-built farmOS codebase in the image.
###
# If the Drupal directory is empty, populate it from pre-built files.
if [ -d ${DRUPAL_PATH} ] && ! [ "$(ls -A ${DRUPAL_PATH}/)" ]; then
echo "farmOS codebase not detected. Copying from pre-built files in the Docker image."
cp -rp ${BUILD_PATH}/. ${DRUPAL_PATH}
fi
# If the sites directory is empty, populate it from pre-built files.
if [ -d ${DRUPAL_PATH}/web/sites ] && ! [ "$(ls -A ${DRUPAL_PATH}/web/sites/)" ]; then
echo "farmOS sites directory not detected. Copying from pre-built files in the Docker image."
cp -rp ${BUILD_PATH}/web/sites/. ${DRUPAL_PATH}/web/sites
fi
if [ -n "$FARMOS_FS_READY_SENTINEL_FILENAME" ]; then
echo "ready" > "$FARMOS_FS_READY_SENTINEL_FILENAME"
fi
# Execute the arguments passed into this script.
echo "Attempting: $@"
exec "$@"