QNetworkDiskCache::prepare() unable to open temporary file
Closed this issue · 6 comments
Testing the image in a Kubernetes setup, we mount /cache als cache / tmp dir.
Using
QGIS_SERVER_CACHE_DIRECTORY=/cache
as env variable for QGIS server
And I see qgisserver writing all familiar files and dir's to that dir.
But I keep getting:
QNetworkDiskCache::prepare() unable to open temporary file
messages in the log
Anybody has a hint on how to fix this?
I am experiencing similar problems. Have you found any solution, @rduivenvoorde? I'm also facing difficulties due to the read-only filesystem usage. Consequently, sed
is unable to create temporary files in the /etc/apache2/sites-enabled/
directory.
Hi @rduivenvoorde,
Here is my updated Dockerfile, along with related files, which is functioning within the Kubernetes cluster. The following adjustments had to be made:
- The image was updated to run under a non-root user.
- All temporary files were identified and mounted as tmpfs.
- All pertinent environment variables were located to configure PID file creation, etc.
- HEALTHCHECK
- Entry-point is now customized shell script (mine included some extra logic outside of this issue)
I must confess, I haven't encountered your exact error message ("QNetworkDiskCache::prepare() unable to open temporary file"). However, I suspect it may stem from the mounting of the /tmp
directory as tmpfs. Please review my updated files below, as well as the final Dockerfile. Admittedly, it's a bit of a hack, but it should suffice in resolving your issue.
Files
Dockerfile
FROM camptocamp/qgis-server
RUN echo "Mutex posixsem" >> /etc/apache2/apache2.conf
RUN sed -i -e 's/<VirtualHost \*:80>/<VirtualHost *:8080>/' /etc/apache2/sites-enabled/000-default.conf
RUN sed -i -e 's/Listen 80$/Listen 8080/' /etc/apache2/ports.conf
RUN rm -rf /etc/apache2/conf-enabled/other-vhosts-access-log.conf
# Permissions
RUN useradd --user-group --system -u 1500 --create-home --no-log-init qgis-server
RUN usermod -aG www-data qgis-server
RUN chown -R qgis-server:www-data ${APACHE_CONFDIR} ${APACHE_RUN_DIR} ${APACHE_LOCK_DIR} ${APACHE_LOG_DIR} /var/lib/apache2/fcgid /var/log /var/www/.qgis3 /var/www/plugins /usr/bin/fc-cache /etc/qgisserver
RUN chmod -R g+rw ${APACHE_CONFDIR} ${APACHE_RUN_DIR} ${APACHE_LOCK_DIR} ${APACHE_LOG_DIR} /var/lib/apache2/fcgid /var/log /var/www/.qgis3 /var/www/plugins /usr/bin/fc-cache /etc/qgisserver
RUN chgrp -R qgis-server ${APACHE_LOG_DIR} /var/lib/apache2/fcgid
USER 1500
WORKDIR /etc/qgisserver
# Entry point will create SQL structures
COPY setup setup
USER 0
RUN chown -R qgis-server:www-data setup
RUN chmod +x setup/entrypoint.sh
RUN chmod +x setup
# /usr/local/bin/start-server
RUN rm -rf /usr/local/bin/start-server
RUN mv setup/start-server /usr/local/bin/start-server
# /etc/apache2/mods-enabled/fcgid.conf
RUN rm -rf /etc/apache2/mods-enabled/fcgid.conf
RUN mv setup/fcgid.conf /etc/apache2/mods-enabled/fcgid.conf
RUN chmod +x /usr/local/bin/start-server
USER 1500
CMD ["setup/entrypoint.sh"]
HEALTHCHECK CMD curl --fail http://localhost:8080/index.json || exit 1
EXPOSE 8080
setup/entrypoint.sh
#!/bin/sh
exec /usr/local/bin/start-server
setup/fcgid.conf
All temporary files must be inside the /tmp
or under mounted tmpfs
because of the read-only nature of the image inside the Kubernetes.
<IfModule mod_fcgid.c>
FcgidConnectTimeout 20
FcgidIPCDir /tmp/mod_fcgid
FcgidProcessTableFile /tmp/fcgid_shm
<IfModule mod_mime.c>
AddHandler fcgid-script .fcgi
</IfModule>
</IfModule>
setup/start-server
I had to remove the original fallback to port 8080 from 80 if the program is not running under root
user. It was implemented using a sed
command which was creating temporary files in funky locations.
#!/bin/bash -e
# Be able to install fonts without creating a new image
if [ -e /etc/qgisserver/fonts/ ]; then
fc-cache --really-force --system-only
fi
# save the environment to be able to restore it in the FCGI daemon (used
# in /usr/local/bin/qgis_mapsev_wrapper) for the startup code.
${GET_ENV} ${FILTER_ENV} | sed -e 's/^\([^=]*\)=.*/PassEnv \1/' > /tmp/pass-env
# Save the list of variables to be passed along with the FCGI requests (used in
# /etc/apache2/conf-enabled/qgis.conf).
${GET_ENV} ${FILTER_ENV} | sed -e 's/.\+/export "\0"/' > /tmp/init-env
trap 'echo "caught a SIGTERM"; kill -TERM $PID2; wait $PID2; kill -TERM $PID1; wait $PID1' TERM
trap '' WINCH
rm -f $APACHE_RUN_DIR/apache2.pid
exec apache2 -DFOREGROUND
Environment variables
Variable | Example content |
---|---|
QGIS_SERVER_CACHE_DIRECTORY | /cache |
QGIS_SERVER_LOG_STDERR | 1 |
APACHE_RUN_DIR | /tmp |
APACHE_PID_FILE | /tmp/apache2.pid |
Mounting
Container path | Description |
---|---|
/cache |
Cache location (the path should be according to the QGIS_SERVER_CACHE_DIRECTORY variable) |
/tmp |
Temporary data (mount as tmpfs ) |
Execution
docker run -p 8080:8080 --read-only -v ./volumes/cache:/cache --tmpfs /tmp --env APACHE_RUN_DIR=/tmp --env APACHE_PID_FILE=/tmp/apache2.pid --env QGIS_SERVER_CACHE_DIRECTORY=/cache --name pamis-qgis-server pamis-qgis-server
If you have any questions, feel free to write me or create a comment :)
@sbrunner I am not sure if I have resolved issue in the right way. If you are alright with the changes in the comment above I can offer a PR.
I didn't succeed to seeing the issue, on which query, do you have an issue?
Do you have something like an external layer in the project?
The whole problem was to execute the image with the --read-only
docker flag which is sometimes required for the k8s deployments. Also the container currently runs as root user which is also not cool in some k8s scenarios. If you want to switch to non-root user you need to do some little enhancements in scripts such as start-server
because the sed
commands creates temporary files which could not be created in read-only file systems.