Hi, the ownCloud Docker base image currently starts Apache through the Debian/Ubuntu apachectl wrapper:
exec apachectl -f /etc/apache2/apache2.conf -DFOREGROUND
Source: https://github.com/owncloud-docker/base/blob/master/v24.04/overlay/usr/bin/server#L21
apachectl is a shell script. It starts /usr/sbin/apache2 without replacing itself via exec. As a result, the process tree inside the container looks like this:
PID 1 /bin/sh /usr/sbin/apachectl -f /etc/apache2/apache2.conf -DFOREGROUND
PID 143 /usr/sbin/apache2 -f /etc/apache2/apache2.conf -DFOREGROUND
Docker sends the container stop signal to PID 1. In this process layout, SIGTERM reaches the apachectl shell, but not the actual Apache process.
Apache therefore continues running until Docker reaches the configured stop timeout and sends SIGKILL.
This appears to be the same underlying problem reported previously in:
Reproduction, Tested with:
owncloud/server:11.0.0
Base image: Ubuntu 24.04
Stop timeout: 60 seconds
The Docker events were:
kill owncloud signal=15
kill owncloud signal=9
die owncloud
Measured timing:
SIGTERM -> SIGKILL: 60.113 seconds
SIGKILL -> die: 0.203 seconds
During those 60 seconds, Apache continued to serve successful health checks.
On the next start, Apache reported:
AH00098: pid file /var/run/apache2/apache2.pid overwritten -- Unclean shutdown of previous Apache run?
The signal dispositions also showed that the apachectl shell running as PID 1 did not catch SIGTERM, while the Apache child process did.
Proposed change
Start Apache directly instead of using apachectl as the final process:
echo "Starting apache daemon directly..."
exec /usr/sbin/apache2 -f /etc/apache2/apache2.conf -D FOREGROUND
The resulting process tree is:
PID 1 /usr/sbin/apache2 -f /etc/apache2/apache2.conf -D FOREGROUND
Docker can then deliver SIGTERM directly to Apache:
docker stop
|
v
SIGTERM
|
v
apache2 (PID 1)
|
v
Apache shuts down
|
v
container exits
I tested this change first in an isolated fresh container and then in a production ownCloud 11.0.0 container using the normal ownCloud entrypoint and initialization path.
After the change, the Docker events were:
kill owncloud signal=15
die owncloud
Result:
Stop duration: 0.227 seconds
Exit code: 0
OOMKilled: false
SIGKILL: not sent
Apache logged the expected shutdown:
AH00169: caught SIGTERM, shutting down
The container then started normally:
installed: true
version: 11.0.0.0
maintenance: false
needsDbUpgrade: false
health: healthy
There was no AH00098 unclean-shutdown warning after the restart.
The test was repeated twice in an isolated container, with stop durations of 0.238 and 0.191 seconds.
Tested workaround:
I tested the change without rebuilding the image by replacing /usr/bin/server with a read-only bind mount:
services:
owncloud:
volumes:
- ${OWNCLOUD_DATA_PATH:?Set OWNCLOUD_DATA_PATH in .env}:/mnt/data:Z
- ./overrides/server:/usr/bin/server:ro,Z
The replacement script keeps the existing entrypoint initialization and pre-server hooks. Only the final Apache invocation changes from:
exec apachectl -f /etc/apache2/apache2.conf -DFOREGROUND
to:
exec /usr/sbin/apache2 -f /etc/apache2/apache2.conf -D FOREGROUND
This bind mount is only a workaround used to validate the proposed upstream change. The preferred fix would be in the base image itself.
Reference implementation:
The official Apache Docker image follows the same process model. Its httpd-foreground script performs the required setup and then replaces itself with the actual Apache daemon:
exec httpd -DFOREGROUND "$@"
https://github.com/docker-library/httpd/blob/master/2.4/httpd-foreground
The exact setup differs because ownCloud uses the Ubuntu/Debian Apache packages, but the process-management principle is the same: the actual web server should be the container's main process.
Compatibility consideration
Starting /usr/sbin/apache2 directly bypasses setup performed by the Debian/Ubuntu apachectl wrapper, such as runtime-directory preparation and ulimit handling.
In the tested ownCloud startup path, the required Apache environment was already prepared and exported by the existing entrypoint scripts, and both a fresh container and the production container started successfully.
The base image should nevertheless verify that all required runtime directories, environment variables, permissions, and limits are prepared before the final exec /usr/sbin/apache2.
Hi, the ownCloud Docker base image currently starts Apache through the Debian/Ubuntu apachectl wrapper:
exec apachectl -f /etc/apache2/apache2.conf -DFOREGROUNDSource: https://github.com/owncloud-docker/base/blob/master/v24.04/overlay/usr/bin/server#L21
apachectl is a shell script. It starts /usr/sbin/apache2 without replacing itself via exec. As a result, the process tree inside the container looks like this:
Docker sends the container stop signal to PID 1. In this process layout, SIGTERM reaches the apachectl shell, but not the actual Apache process.
Apache therefore continues running until Docker reaches the configured stop timeout and sends SIGKILL.
This appears to be the same underlying problem reported previously in:
Reproduction, Tested with:
owncloud/server:11.0.0
Base image: Ubuntu 24.04
Stop timeout: 60 seconds
The Docker events were:
kill owncloud signal=15
kill owncloud signal=9
die owncloud
Measured timing:
SIGTERM -> SIGKILL: 60.113 seconds
SIGKILL -> die: 0.203 seconds
During those 60 seconds, Apache continued to serve successful health checks.
On the next start, Apache reported:
AH00098: pid file /var/run/apache2/apache2.pid overwritten -- Unclean shutdown of previous Apache run?
The signal dispositions also showed that the apachectl shell running as PID 1 did not catch SIGTERM, while the Apache child process did.
Proposed change
Start Apache directly instead of using apachectl as the final process:
The resulting process tree is:
PID 1 /usr/sbin/apache2 -f /etc/apache2/apache2.conf -D FOREGROUNDDocker can then deliver SIGTERM directly to Apache:
docker stop
|
v
SIGTERM
|
v
apache2 (PID 1)
|
v
Apache shuts down
|
v
container exits
I tested this change first in an isolated fresh container and then in a production ownCloud 11.0.0 container using the normal ownCloud entrypoint and initialization path.
After the change, the Docker events were:
Result:
Apache logged the expected shutdown:
AH00169: caught SIGTERM, shutting down
The container then started normally:
There was no AH00098 unclean-shutdown warning after the restart.
The test was repeated twice in an isolated container, with stop durations of 0.238 and 0.191 seconds.
Tested workaround:
I tested the change without rebuilding the image by replacing /usr/bin/server with a read-only bind mount:
The replacement script keeps the existing entrypoint initialization and pre-server hooks. Only the final Apache invocation changes from:
exec apachectl -f /etc/apache2/apache2.conf -DFOREGROUNDto:
exec /usr/sbin/apache2 -f /etc/apache2/apache2.conf -D FOREGROUNDThis bind mount is only a workaround used to validate the proposed upstream change. The preferred fix would be in the base image itself.
Reference implementation:
The official Apache Docker image follows the same process model. Its httpd-foreground script performs the required setup and then replaces itself with the actual Apache daemon:
exec httpd -DFOREGROUND "$@"https://github.com/docker-library/httpd/blob/master/2.4/httpd-foreground
The exact setup differs because ownCloud uses the Ubuntu/Debian Apache packages, but the process-management principle is the same: the actual web server should be the container's main process.
Compatibility consideration
Starting /usr/sbin/apache2 directly bypasses setup performed by the Debian/Ubuntu apachectl wrapper, such as runtime-directory preparation and ulimit handling.
In the tested ownCloud startup path, the required Apache environment was already prepared and exported by the existing entrypoint scripts, and both a fresh container and the production container started successfully.
The base image should nevertheless verify that all required runtime directories, environment variables, permissions, and limits are prepared before the final exec /usr/sbin/apache2.