Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@

### Minor changes

* **2026-11-05**
* The *apache* and *fpm* images stop right away when a `docker stop` is requested during a long startup step (e.g. a `STARTUP_COMMAND_*`, or the configuration of the extensions on a loaded host): they were killed after the stop timeout (exit code 137 after 10 s)

* **2026-11-03**
* The `php` command is about 20 ms faster on each call: it detects the changes of the `PHP_*` environment variables without starting PHP a first time. The configuration is now also regenerated when a `PHP_*` variable is removed
* The README recommends the fpm variant with its built-in Apache to serve a web application, and links to the v6 roadmap. The php2shell fix is now mentioned in the supported versions
Expand Down
17 changes: 17 additions & 0 deletions tests-suite/tool-startup-command.sh
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,20 @@ test_phpStartupWarning() {
assert_equals "0" "$?" "Docker run failed"
assert_equals "startup-ok" "$RESULT"
}
############################################################
## A docker stop during a long startup command stops the container right away
############################################################
test_stopDuringStartupCommand() {
NAME="test-startup-stop-$(unused_port)"
docker run --name "${NAME}" ${RUN_OPTIONS} -d -e STARTUP_COMMAND_1="sleep 30" \
"${REPO}:${TAG_PREFIX}${PHP_VERSION}-${BRANCH}-slim-${BRANCH_VARIANT}${ARCH_SUFFIX}" sleep 300 > /dev/null
for _ in $(seq 1 60); do
docker exec "${NAME}" pgrep -fx "sleep 30" > /dev/null 2>&1 && break
sleep 0.5
done
START=$(date +%s)
docker stop "${NAME}" > /dev/null 2>&1
DURATION=$(( $(date +%s) - START ))
docker rm -f "${NAME}" > /dev/null 2>&1
assert "test ${DURATION} -lt 5" "Stopping during the startup command took ${DURATION}s (killed by timeout?)"
}
23 changes: 15 additions & 8 deletions utils/docker-entrypoint-as-root.sh
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,13 @@ if [[ "$IMAGE_VARIANT" == "apache" ]]; then
trap 'exit 0' WINCH
fi

# Runs a startup step in the background and waits for it, so that a stop signal interrupts a long step (e.g. a
# STARTUP_COMMAND): bash only runs a trap once the foreground command ends
startup_step() {
"$@" <&0 &
wait $!
}

# Let's write a file saying the container is started (we are no longer in build mode, useful for php_proxy.sh)
touch /opt/container_started

Expand Down Expand Up @@ -152,34 +159,34 @@ unset REMOTE_HOST_FOUND
source /usr/local/bin/php_env_fingerprint.sh
php_env_fingerprint > /opt/php_env_fingerprint

/usr/bin/real_php -d display_errors=stderr /usr/local/bin/generate_conf.php > /etc/php/${PHP_VERSION}/mods-available/generated_conf.ini
PHP_VERSION="${PHP_VERSION}" /usr/bin/real_php -d display_errors=stderr /usr/local/bin/setup_extensions.php | sudo bash
startup_step /usr/bin/real_php -d display_errors=stderr /usr/local/bin/generate_conf.php > /etc/php/${PHP_VERSION}/mods-available/generated_conf.ini
startup_step bash -c '/usr/bin/real_php -d display_errors=stderr /usr/local/bin/setup_extensions.php | sudo bash'

if [[ -n "$COMPOSER_VERSION" ]]; then
/usr/local/bin/select_composer_version.sh "$COMPOSER_VERSION"
startup_step /usr/local/bin/select_composer_version.sh "$COMPOSER_VERSION"
fi

if [[ -n "$LOCALES" ]]; then
if ! command -v locale-gen > /dev/null; then
echo 'Locales are not available in this image. If you are using the thecodingmachine/php "slim" variant, do not forget to add "ARG INSTALL_LOCALES=1" in your Dockerfile. Check the documentation for more details.' >&2
exit 1
fi
locale-gen --keep-existing $LOCALES > /dev/null
startup_step locale-gen --keep-existing $LOCALES > /dev/null
fi

# output on the logs can be done by writing on the "tini" PID. Useful for CRONTAB
TINI_PID=`ps -e | grep tini | awk '{print $1;}'`
/usr/bin/real_php -d display_errors=stderr /usr/local/bin/generate_cron.php $TINI_PID > /tmp/generated_crontab
startup_step /usr/bin/real_php -d display_errors=stderr /usr/local/bin/generate_cron.php $TINI_PID > /tmp/generated_crontab
chmod 0644 /tmp/generated_crontab

if [[ "$WITH_APACHE" == "1" ]]; then
/usr/bin/real_php -d display_errors=stderr /usr/local/bin/enable_apache_mods.php | bash
startup_step bash -c '/usr/bin/real_php -d display_errors=stderr /usr/local/bin/enable_apache_mods.php | bash'
fi

if [ -e /etc/container/startup.sh ]; then
sudo -E -u "#$DOCKER_USER_ID" /etc/container/startup.sh
startup_step sudo -E -u "#$DOCKER_USER_ID" /etc/container/startup.sh
fi
sudo -E -u "#$DOCKER_USER_ID" sh -c "/usr/bin/real_php -d display_errors=stderr /usr/local/bin/startup_commands.php | bash"
startup_step sudo -E -u "#$DOCKER_USER_ID" sh -c "/usr/bin/real_php -d display_errors=stderr /usr/local/bin/startup_commands.php | bash"

if [[ "$APACHE_DOCUMENT_ROOT" == /* ]]; then
export ABSOLUTE_APACHE_DOCUMENT_ROOT="$APACHE_DOCUMENT_ROOT"
Expand Down