diff --git a/docker/geoserver/Dockerfile b/docker/geoserver/Dockerfile index cb22c8e..d98d14d 100644 --- a/docker/geoserver/Dockerfile +++ b/docker/geoserver/Dockerfile @@ -1,8 +1,7 @@ -ARG IMAGE_VERSION=9.0.106-jdk11-temurin-jammy -ARG JAVA_HOME=/usr/local/openjdk-11 +ARG IMAGE_VERSION=9.0.118-jdk17-temurin-jammy FROM tomcat:$IMAGE_VERSION -ARG GEOSERVER_VERSION=2.27.4 +ARG GEOSERVER_VERSION=2.28.4 ARG GEOSERVER_CORS_ENABLED=False ARG GEOSERVER_CORS_ALLOWED_ORIGINS=* ARG GEOSERVER_CORS_ALLOWED_METHODS=GET,POST,PUT,DELETE,HEAD,OPTIONS @@ -17,41 +16,34 @@ ENV GEOSERVER_CORS_ALLOWED_ORIGINS=$GEOSERVER_CORS_ALLOWED_ORIGINS ENV GEOSERVER_CORS_ALLOWED_METHODS=$GEOSERVER_CORS_ALLOWED_METHODS ENV GEOSERVER_CORS_ALLOWED_HEADERS=$GEOSERVER_CORS_ALLOWED_HEADERS +RUN apt-get update -y && apt-get -y install --no-install-recommends curl wget unzip procps less gettext-base && rm -rf /var/lib/apt/lists/* + # # Download and install GeoServer # -RUN apt-get update -y && apt-get install curl wget unzip -y RUN cd /usr/local/tomcat/webapps \ && wget --no-check-certificate --progress=bar:force:noscroll https://artifacts.geonode.org/geoserver/${GEOSERVER_VERSION}/geoserver.war -O geoserver.war \ && unzip -q geoserver.war -d geoserver \ && rm geoserver.war \ && mkdir -p $GEOSERVER_DATA_DIR -COPY applicationContext.xml /usr/local/tomcat/webapps/geoserver/WEB-INF/classes/applicationContext.xml - -VOLUME $GEOSERVER_DATA_DIR - -# copy the script and perform the run of scripts from entrypoint.sh -RUN mkdir -p /usr/local/tomcat/tmp -WORKDIR /usr/local/tomcat/tmp -COPY set_geoserver_auth.sh \ - entrypoint.sh \ - tasks.py \ - multidump.sh \ - multidump-alt.sh \ - /usr/local/tomcat/tmp/ - -COPY ./templates /templates +# +# Download datadir zip +# +ENV GEOSERVER_SHARE_DIR="/usr/local/share/geoserver" +RUN mkdir -p $GEOSERVER_SHARE_DIR $GEOSERVER_SHARE_DIR/templates +RUN wget --no-check-certificate --progress=bar:force:noscroll \ + https://artifacts.geonode.org/geoserver/$GEOSERVER_VERSION/geonode-geoserver-ext-web-app-data.zip \ + -O $GEOSERVER_SHARE_DIR/geoserver-data-skeleton.zip -RUN chmod +x \ - /usr/local/tomcat/tmp/set_geoserver_auth.sh \ - /usr/local/tomcat/tmp/entrypoint.sh -RUN apt-get install -y procps less && \ - apt-get install -y python3 python3-pip python3-dev +COPY ./templates $GEOSERVER_SHARE_DIR/templates +COPY ./files/applicationContext.xml /usr/local/tomcat/webapps/geoserver/WEB-INF/classes/applicationContext.xml +COPY ./scripts/ /usr/local/bin/ +RUN chmod +x /usr/local/bin/*.sh -RUN pip install j2cli invoke==2.2.0 requests==2.31.0 +VOLUME $GEOSERVER_DATA_DIR -ENV JAVA_OPTS="-Djava.awt.headless=true -Dgwc.context.suffix=gwc -XX:+UnlockDiagnosticVMOptions -XX:+LogVMOutput -XX:LogFile=/var/log/jvm.log -XX:MaxPermSize=512m -XX:PermSize=256m -Xms512m -Xmx2048m -XX:+UseConcMarkSweepGC -XX:ParallelGCThreads=4 -Dfile.encoding=UTF8 -Djavax.servlet.request.encoding=UTF-8 -Djavax.servlet.response.encoding=UTF-8 -Duser.timezone=GMT -Dorg.geotools.shapefile.datetime=false -DGS-SHAPEFILE-CHARSET=UTF-8 -DGEOSERVER_CSRF_DISABLED=true -DPRINT_BASE_URL=http://geoserver:8080/geoserver/pdf -Xbootclasspath/a:/usr/local/tomcat/webapps/geoserver/WEB-INF/lib/marlin-0.9.3.jar -Dsun.java2d.renderer=org.marlin.pisces.MarlinRenderingEngine" +ENV JAVA_OPTS="-Djava.awt.headless=true -Dgwc.context.suffix=gwc -XX:+UnlockDiagnosticVMOptions -XX:+LogVMOutput -XX:LogFile=/var/log/jvm.log -Xms2048m -Xmx2048m XX:ParallelGCThreads=4 -Dfile.encoding=UTF8 -Djavax.servlet.request.encoding=UTF-8 -Djavax.servlet.response.encoding=UTF-8 -Duser.timezone=GMT -Dorg.geotools.shapefile.datetime=false -DGS-SHAPEFILE-CHARSET=UTF-8 -DGEOSERVER_CSRF_DISABLED=true -DPRINT_BASE_URL=http://geoserver:8080/geoserver/pdf" -CMD ["/usr/local/tomcat/tmp/entrypoint.sh"] +CMD ["/usr/local/bin/entrypoint.sh"] diff --git a/docker/geoserver/README.md b/docker/geoserver/README.md index 352ccb2..c428384 100644 --- a/docker/geoserver/README.md +++ b/docker/geoserver/README.md @@ -35,21 +35,6 @@ Point your browser to `http://localhost:8080/geoserver` and login using GeoServe * Username: admin * Password: geoserver -## How to use different versions - -There are mainly two different versions of this image which are useful for running **GeoNode** with different authentication system types. These versions are released as specific tags for two authentication mechanisms: - -**Cookie based authn**: -- [geonode/geoserver:2.9.x](https://hub.docker.com/r/geonode/geoserver/builds/bx7ydhghnlrfnsppduyva73/) - -**Oauth2 based authn**: -- [geonode/geoserver:2.9.x-oauth2](https://hub.docker.com/r/geonode/geoserver/builds/bwca5rtexeoegzgroavftdr/) -- [geonode/geoserver:2.10.x](https://hub.docker.com/r/geonode/geoserver/builds/bjohcnc29vm69acqjrvndxf/) -- [geonode/geoserver:2.12.x](https://hub.docker.com/r/geonode/geoserver/builds/bh7pyw5atmkcljurwsnzbs7/) -- [geonode/geoserver:2.13.x](https://hub.docker.com/r/geonode/geoserver/builds/btmjctbuvrjfnnrxrs4wyrs/) -- [geonode/geoserver:2.14.x](https://hub.docker.com/r/geonode/geoserver/builds/bj53pi8he8uksz6ggvrs3wc/) - -You can declare what version to use along with the data directory tag which corresponds to the same version. ## Configuration @@ -64,15 +49,34 @@ You may want to map this volume to a directory on the host. It will also ease th -v /your/host/data/path:/geoserver_data/data ``` -### Data volume container +#### GeoServer Data Directory Initialization -In case you are running Compose for automatically having GeoServer up and running then a data volume container will be mounted with a default preloaded *GEOSERVER_DATA_DIR* at the configuration data directory of the container. -Make sure that the image from the repository [data-docker](https://github.com/GeoNode/data-docker) is available from the [GeoNode Docker Hub](https://hub.docker.com/u/geonode/) or has been built locally: +When running GeoNode via Docker Compose, the core `geoserver` container automatically manages its own persistent configurations. On the very first boot, if the assigned volume is completely empty, an internal initialization step automatically extracts a preconfigured data archive directly into the volume space. -```bash -docker build -t geonode/geoserver_data . +This setup contains the default preloaded `GEOSERVER_DATA_DIR` settings (including custom GeoNode extensions, workspaces, and security providers) required for GeoServer to communicate with Django and the database seamlessly. + +#### Customizing or Building the Base Data Directory Locally +If you need to change the base fallback configuration, alter the default zip asset reference built into the core geoserver image: + +```Bash +docker build --build-arg GEOSERVER_VERSION=2.24.x -t geonode/geoserver:latest ./docker/geoserver ``` +#### Storage and Persistence +Because the default configurations are extracted dynamically at runtime, your master `docker-compose.yml` must map a named volume or host directory to the target path: + +```YAML +services: + geoserver: + image: geonode/geoserver:latest + environment: + - GEOSERVER_DATA_DIR=/geoserver_data/data + volumes: + - geoserver-data-dir:/geoserver_data/data +``` +Subsequent container restarts will detect the existing configuration files (such as global.xml) and safely skip the extraction phase, ensuring all runtime additions, styles, and layer maps are completely preserved. + + #### Persistance behavior If you run: @@ -95,17 +99,6 @@ docker-compose down Data are completely gone but you can ever start from the base GeoServer Data Directory built for Geonode. -#### Data directory versions - -There has to be a correspondence one-to-one between the data directory version and the tag of the GeoServer image used in the Docker compose file. So at the end you can consume these images below: - -* **2.9.x**: [geonode/geoserver_data:2.9.x](https://hub.docker.com/r/geonode/geoserver_data/builds/bsus6alnddg4bc7icwymevp/) -* **2.9.x-oauth2**: [geonode/geoserver_data:2.9.x-oauth2](https://hub.docker.com/r/geonode/geoserver_data/builds/bwkxcupsunvuitzusi9gsnt/) -* **2.10.x**: [geonode/geoserver_data:2.10.x](https://hub.docker.com/r/geonode/geoserver_data/builds/b5jqhpzapkqxzyevjizccug/) -* **2.12.x**: [geonode/geoserver_data:2.12.x](https://hub.docker.com/r/geonode/geoserver_data/builds/byaaalw3lnasunpveyg3x4i/) -* **2.13.x**: [geonode/geoserver_data:2.13.x](https://hub.docker.com/r/geonode/geoserver_data/builds/bunuqzq7a7dk65iumjhkbtc/) -* **2.14.x**: [geonode/geoserver_data:2.14.x](https://hub.docker.com/r/geonode/geoserver_data/builds/blpdjzkrv7pm3stunzpn4pp/) - ### Database GeoServer recommends the usage of a spatial database diff --git a/docker/geoserver/docker-compose.yml b/docker/geoserver/docker-compose.yml index 9bfb578..99f24ed 100644 --- a/docker/geoserver/docker-compose.yml +++ b/docker/geoserver/docker-compose.yml @@ -15,7 +15,7 @@ services: restart: on-failure geoserver: - image: geonode/geoserver:2.24.4-latest + image: geonode/geoserver:2.28.4-latest build: context: . links: @@ -29,8 +29,6 @@ services: depends_on: postgis: condition: service_completed_successfully - data-dir-conf: - condition: service_healthy healthcheck: test: curl --fail -s http://localhost:8080/geoserver/rest/workspaces/geonode.html || exit 1 interval: 1m30s @@ -38,16 +36,6 @@ services: retries: 3 restart: on-failure - data-dir-conf: - image: geonode/geoserver_data:2.24.4-latest - container_name: geoserver_data_dir # named data container - entrypoint: sleep infinity - volumes: - - /geoserver_data/data - healthcheck: - test: "ls -A '/geoserver_data/data' | wc -l" - restart: on-failure - volumes: # reference to the named data container that holds the preloaded geoserver data directory geoserver_data_dir: diff --git a/docker/geoserver/applicationContext.xml b/docker/geoserver/files/applicationContext.xml similarity index 100% rename from docker/geoserver/applicationContext.xml rename to docker/geoserver/files/applicationContext.xml diff --git a/docker/geoserver/scripts/configure_geoserver.sh b/docker/geoserver/scripts/configure_geoserver.sh new file mode 100644 index 0000000..a9ef4be --- /dev/null +++ b/docker/geoserver/scripts/configure_geoserver.sh @@ -0,0 +1,50 @@ +#!/bin/bash + +echo "************************ Configuring GeoServer credentials *****************************" + +# Fallback values identical to the original python task +GEOSERVER_LB_PORT="${GEOSERVER_LB_PORT:-8080}" +GEOSERVER_ADMIN_USER="${GEOSERVER_ADMIN_USER:-admin}" +GEOSERVER_ADMIN_PASSWORD="${GEOSERVER_ADMIN_PASSWORD:-geoserver}" +GEOSERVER_FACTORY_PASSWORD="${GEOSERVER_FACTORY_PASSWORD:-geoserver}" +GEOSERVER_DATA_DIR="${GEOSERVER_DATA_DIR:-/geoserver_data/data/}" + +REST_URL="http://localhost:${GEOSERVER_LB_PORT}/geoserver/rest/security/self/password" + +XML_DATA="${GEOSERVER_ADMIN_PASSWORD}" + +# Retry loop: 1 to 28 attempts, sleeping 2 seconds between each (roughly ~1 minute total timeout) +for cnt in {1..28}; do + echo "...waiting for GeoServer to pop-up... Attempt ${cnt}" + + # Check if GeoServer is responding before attempting PUT + if curl -fsS -o /dev/null "http://localhost:${GEOSERVER_LB_PORT}/geoserver/"; then + # Execute the password update request using curl basic auth + RESPONSE_CODE=$(curl -s -o /dev/null -w "%{http_code}" -X PUT \ + -u "${GEOSERVER_ADMIN_USER}:${GEOSERVER_FACTORY_PASSWORD}" \ + -H "Content-Type: application/xml" \ + -H "Accept: application/xml" \ + -d "${XML_DATA}" \ + "${REST_URL}") + + echo "Response Code: ${RESPONSE_CODE}" + + if [ "$RESPONSE_CODE" -eq 200 ]; then + echo "GeoServer admin password updated SUCCESSFULLY!" + break + else + echo "WARNING: GeoServer admin password *NOT* updated: code [${RESPONSE_CODE}]" + fi + fi + + sleep 2 +done + +# Initialize the lock file only if configuration succeeded +if [ "${RESPONSE_CODE:-}" -eq 200 ] 2>/dev/null; then + echo "************************** Writing init lockfile ********************************" + mkdir -p "${GEOSERVER_DATA_DIR}" + date > "${GEOSERVER_DATA_DIR}/geoserver_init.lock" +else + echo "WARNING: GeoServer init lockfile not written because password update did not succeed." +fi diff --git a/docker/geoserver/entrypoint.sh b/docker/geoserver/scripts/entrypoint.sh similarity index 80% rename from docker/geoserver/entrypoint.sh rename to docker/geoserver/scripts/entrypoint.sh index e7d395f..63f61fc 100644 --- a/docker/geoserver/entrypoint.sh +++ b/docker/geoserver/scripts/entrypoint.sh @@ -15,6 +15,28 @@ invoke () { echo "$@ tasks done" } + +# create/populate the datadir +mkdir -p $GEOSERVER_DATA_DIR + +if [ ! -f "${GEOSERVER_DATA_DIR}/global.xml" ]; then + echo "${GEOSERVER_DATA_DIR}/global.xml not found." + + # needing a tmp extraction because the zip contains /data/ as root + echo "Extracting default data skeleton archive to temp dir..." + TMP_EXTRACT="/tmp/geoserver_unzip" + mkdir -p "$TMP_EXTRACT" + unzip -q "$GEOSERVER_SHARE_DIR/geoserver-data-skeleton.zip" -d "$TMP_EXTRACT" + echo "Moving default data skeleton archive directly to volume..." +# mv "$TMP_EXTRACT"/data/* "$TMP_EXTRACT"/data/.* "$GEOSERVER_DATA_DIR/" 2>/dev/null || true + mv -v "$TMP_EXTRACT"/data/* "$TMP_EXTRACT"/data/.* "$GEOSERVER_DATA_DIR/" || true + rm -rf "$TMP_EXTRACT" + + echo "Extraction complete." +else + echo "Existing GeoServer data configuration detected. Skipping extraction." +fi + # control the values of LB settings if present if [ -n "$GEONODE_LB_HOST_IP" ]; then @@ -161,13 +183,13 @@ else # backup geonodeAuthProvider config.xml cp ${GEOSERVER_DATA_DIR}/security/auth/geonodeAuthProvider/config.xml ${GEOSERVER_DATA_DIR}/security/auth/geonodeAuthProvider/config.xml.orig # run the setting script for geonodeAuthProvider - /usr/local/tomcat/tmp/set_geoserver_auth.sh ${GEOSERVER_DATA_DIR}/security/auth/geonodeAuthProvider/config.xml ${GEOSERVER_DATA_DIR}/security/auth/geonodeAuthProvider/ ${TAGNAME[@]} > /dev/null 2>&1 + /usr/local/bin/set_geoserver_auth.sh ${GEOSERVER_DATA_DIR}/security/auth/geonodeAuthProvider/config.xml ${GEOSERVER_DATA_DIR}/security/auth/geonodeAuthProvider/ ${TAGNAME[@]} > /dev/null 2>&1 fi # backup geonode REST role service config.xml cp "${GEOSERVER_DATA_DIR}/security/role/geonode REST role service/config.xml" "${GEOSERVER_DATA_DIR}/security/role/geonode REST role service/config.xml.orig" # run the setting script for geonode REST role service -/usr/local/tomcat/tmp/set_geoserver_auth.sh "${GEOSERVER_DATA_DIR}/security/role/geonode REST role service/config.xml" "${GEOSERVER_DATA_DIR}/security/role/geonode REST role service/" ${TAGNAME[@]} > /dev/null 2>&1 +/usr/local/bin/set_geoserver_auth.sh "${GEOSERVER_DATA_DIR}/security/role/geonode REST role service/config.xml" "${GEOSERVER_DATA_DIR}/security/role/geonode REST role service/" ${TAGNAME[@]} > /dev/null 2>&1 # set oauth2 filter tagname TAGNAME=( "cliendId" "clientSecret" "accessTokenUri" "userAuthorizationUri" "redirectUri" "checkTokenEndpointUrl" "logoutUri" ) @@ -175,7 +197,7 @@ TAGNAME=( "cliendId" "clientSecret" "accessTokenUri" "userAuthorizationUri" "red # backup geonode-oauth2 config.xml cp ${GEOSERVER_DATA_DIR}/security/filter/geonode-oauth2/config.xml ${GEOSERVER_DATA_DIR}/security/filter/geonode-oauth2/config.xml.orig # run the setting script for geonode-oauth2 -/usr/local/tomcat/tmp/set_geoserver_auth.sh ${GEOSERVER_DATA_DIR}/security/filter/geonode-oauth2/config.xml ${GEOSERVER_DATA_DIR}/security/filter/geonode-oauth2/ "${TAGNAME[@]}" > /dev/null 2>&1 +/usr/local/bin/set_geoserver_auth.sh ${GEOSERVER_DATA_DIR}/security/filter/geonode-oauth2/config.xml ${GEOSERVER_DATA_DIR}/security/filter/geonode-oauth2/ "${TAGNAME[@]}" > /dev/null 2>&1 # set global tagname TAGNAME=( "proxyBaseUrl" ) @@ -183,29 +205,24 @@ TAGNAME=( "proxyBaseUrl" ) # backup global.xml cp ${GEOSERVER_DATA_DIR}/global.xml ${GEOSERVER_DATA_DIR}/global.xml.orig # run the setting script for global configuration -/usr/local/tomcat/tmp/set_geoserver_auth.sh ${GEOSERVER_DATA_DIR}/global.xml ${GEOSERVER_DATA_DIR}/ ${TAGNAME[@]} > /dev/null 2>&1 - -# set correct amqp broker url -sed -i -e 's/localhost/rabbitmq/g' ${GEOSERVER_DATA_DIR}/notifier/notifier.xml +/usr/local/bin/set_geoserver_auth.sh ${GEOSERVER_DATA_DIR}/global.xml ${GEOSERVER_DATA_DIR}/ ${TAGNAME[@]} > /dev/null 2>&1 # exclude wrong dependencies sed -i -e 's/xom-\*\.jar/xom-\*\.jar,bcprov\*\.jar/g' /usr/local/tomcat/conf/catalina.properties -# J2 templating for this docker image we should also do it for other configuration files in /usr/local/tomcat/tmp +# templating for this docker image we should also do it for other configuration files in /usr/local/tomcat/tmp declare -a geoserver_datadir_template_dirs=("geofence") -for template in in ${geoserver_datadir_template_dirs[*]}; do - #Geofence templates +for template in ${geoserver_datadir_template_dirs[*]}; do if [ "$template" == "geofence" ]; then - cp -R /templates/$template/* ${GEOSERVER_DATA_DIR}/geofence - - for f in $(find ${GEOSERVER_DATA_DIR}/geofence/ -type f -name "*.j2"); do - echo -e "Evaluating template\n\tSource: $f\n\tDest: ${f%.j2}" - /usr/local/bin/j2 $f > ${f%.j2} - rm -f $f - done + cp -vR $GEOSERVER_SHARE_DIR/templates/$template/* ${GEOSERVER_DATA_DIR}/geofence + for f in $(find ${GEOSERVER_DATA_DIR}/geofence/ -type f -name "*.envsubst"); do + echo -e "Evaluating template\n\tSource: $f\n\tDest: ${f%.envsubst}" + envsubst < "$f" > "${f%.envsubst}" + rm -vf "$f" + done fi done @@ -240,10 +257,10 @@ if [ "${GEOSERVER_CORS_ENABLED}" = "true" ] || [ "${GEOSERVER_CORS_ENABLED}" = " fi fi -if [ ${FORCE_REINIT} = "true" ] || [ ${FORCE_REINIT} = "True" ] || [ ! -e "${GEOSERVER_DATA_DIR}/geoserver_init.lock" ]; then - # Run async configuration, it needs Geoserver to be up and running - # executes step configure-geoserver from task.py file - nohup sh -c "invoke configure-geoserver" & + +if [ "${FORCE_REINIT}" = "true" ] || [ "${FORCE_REINIT}" = "True" ] || [ ! -e "${GEOSERVER_DATA_DIR}/geoserver_init.lock" ]; then + # Run async configuration, it needs GeoServer to be up and running + nohup /usr/local/bin/configure_geoserver.sh & fi # start tomcat diff --git a/docker/geoserver/multidump-alt.sh b/docker/geoserver/scripts/multidump-alt.sh similarity index 100% rename from docker/geoserver/multidump-alt.sh rename to docker/geoserver/scripts/multidump-alt.sh diff --git a/docker/geoserver/multidump.sh b/docker/geoserver/scripts/multidump.sh similarity index 100% rename from docker/geoserver/multidump.sh rename to docker/geoserver/scripts/multidump.sh diff --git a/docker/geoserver/set_geoserver_auth.sh b/docker/geoserver/scripts/set_geoserver_auth.sh similarity index 64% rename from docker/geoserver/set_geoserver_auth.sh rename to docker/geoserver/scripts/set_geoserver_auth.sh index 023636d..5343276 100644 --- a/docker/geoserver/set_geoserver_auth.sh +++ b/docker/geoserver/scripts/set_geoserver_auth.sh @@ -42,6 +42,16 @@ done echo "DEBUG: Starting... [Ok]\n" +# Escape a string for safe use in sed's REGEX (pattern) side, given @ delimiter +escape_regex() { + printf '%s' "$1" | sed -e 's/[][\\.^$*+?(){}|@/-]/\\&/g' +} + +# Escape a string for safe use in sed's REPLACEMENT side, given @ delimiter +escape_replacement() { + printf '%s' "$1" | sed -e 's/[\\&@/]/\\&/g' +} + for i in "${tagname[@]}" do echo "DEBUG: Working on '$auth_conf_source' for tagname <$i>" @@ -54,27 +64,24 @@ do # Setting new substituted value case $i in authApiKey) - echo "DEBUG: Editing '$auth_conf_source' for tagname <$i> and replacing its value with '$OAUTH2_API_KEY'" - newvalue=`echo -ne "$tagvalue" | sed -re "s@.*@$OAUTH2_API_KEY@"`;; + newvalue="$OAUTH2_API_KEY";; cliendId) - echo "DEBUG: Editing '$auth_conf_source' for tagname <$i> and replacing its value with '$OAUTH2_CLIENT_ID'" - newvalue=`echo -ne "$tagvalue" | sed -re "s@.*@$OAUTH2_CLIENT_ID@"`;; + newvalue="$OAUTH2_CLIENT_ID";; clientSecret) - echo "DEBUG: Editing '$auth_conf_source' for tagname <$i> and replacing its value with '$OAUTH2_CLIENT_SECRET'" - newvalue=`echo -ne "$tagvalue" | sed -re "s@.*@$OAUTH2_CLIENT_SECRET@"`;; + newvalue="$OAUTH2_CLIENT_SECRET";; proxyBaseUrl | redirectUri | userAuthorizationUri | logoutUri ) - echo "DEBUG: Editing '$auth_conf_source' for tagname <$i> and replacing its value with '$GEOSERVER_LOCATION'" - newvalue=`echo -ne "$tagvalue" | sed -re "s@^(https?://[^/]+)@${GEOSERVER_LOCATION%/}@"`;; + newvalue=`printf '%s' "$tagvalue" | sed -re "s@^(https?://[^/]+)@${GEOSERVER_LOCATION%/}@"`;; baseUrl | accessTokenUri | checkTokenEndpointUrl ) - echo "DEBUG: Editing '$auth_conf_source' for tagname <$i> and replacing its value with '$GEONODE_LOCATION'" - newvalue=`echo -ne "$tagvalue" | sed -re "s@^(https?://[^/]+)@${GEONODE_LOCATION%/}@"`;; - *) echo -n "an unknown variable has been found";; + newvalue=`printf '%s' "$tagvalue" | sed -re "s@^(https?://[^/]+)@${GEONODE_LOCATION%/}@"`;; + *) echo "an unknown variable has been found"; continue;; esac echo "DEBUG: Found the new value for the element <$i> - '$newvalue'" - # Replacing element’s value with $SUBSTITUTION_URL - # echo -ne "<$i>$tagvalue" | xmlstarlet sel -t -m "//a" -v . -n - sed -e "s@<$i>$tagvalue<\/$i>@<$i>$newvalue<\/$i>@g" "$auth_conf_source" > "$temp_file" + + # Match the whole element (empty or not); only the tag name is interpolated, + # so the user-controlled content goes through the escapers. + new_esc=`escape_replacement "$newvalue"` + sed -E "s@(<$i>)[^<]*()@\1${new_esc}\2@g" "$auth_conf_source" > "$temp_file" cp "$temp_file" "$auth_conf_source" done # Writing our changes back to the original file ($auth_conf_source) diff --git a/docker/geoserver/tasks.py b/docker/geoserver/tasks.py deleted file mode 100644 index 5f6f9b3..0000000 --- a/docker/geoserver/tasks.py +++ /dev/null @@ -1,83 +0,0 @@ -# -*- coding: utf-8 -*- -######################################################################### -# -# Copyright (C) 2023 OSGeo -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . -# -######################################################################### -import os -import logging -import time -import base64 -import requests -from pathlib import Path -from invoke import task - -logger = logging.getLogger(__name__) - - -@task -def configure_geoserver(ctx): - _configure_geoserver_password() - _initialized(ctx) - - -def _configure_geoserver_password(): - print( - "************************configuring Geoserver credentials*****************************" - ) - GEOSERVER_LB_PORT = os.getenv("GEOSERVER_LB_PORT", 8080) - GEOSERVER_ADMIN_USER = os.getenv("GEOSERVER_ADMIN_USER", "admin") - GEOSERVER_ADMIN_PASSWORD = os.getenv("GEOSERVER_ADMIN_PASSWORD", "geoserver") - GEOSERVER_FACTORY_PASSWORD = os.getenv("GEOSERVER_FACTORY_PASSWORD", "geoserver") - geoserver_rest_baseurl = f"http://localhost:{GEOSERVER_LB_PORT}/geoserver/rest" - basic_auth_credentials = base64.b64encode( - f"{GEOSERVER_ADMIN_USER}:{GEOSERVER_FACTORY_PASSWORD}".encode() - ).decode() - headers = { - "Content-type": "application/xml", - "Accept": "application/xml", - "Authorization": f"Basic {basic_auth_credentials}", - } - data = f""" - - {GEOSERVER_ADMIN_PASSWORD} - """ - - for _cnt in range(1, 29): - try: - response = requests.put( - f"{geoserver_rest_baseurl}/security/self/password", - data=data, - headers=headers, - ) - print(f"Response Code: {response.status_code}") - if response.status_code == 200: - print("GeoServer admin password updated SUCCESSFULLY!") - else: - logger.warning( - f"WARNING: GeoServer admin password *NOT* updated: code [{response.status_code}]" - ) - break - except Exception: - print(f"...waiting for Geoserver to pop-up...{_cnt}") - time.sleep(2) - - -def _initialized(ctx): - print("**************************init file********************************") - GEOSERVER_DATA_DIR = os.getenv("GEOSERVER_DATA_DIR", "/geoserver_data/data/") - geoserver_init_lock = Path(GEOSERVER_DATA_DIR) / "geoserver_init.lock" - ctx.run(f"date > {geoserver_init_lock}") diff --git a/docker/geoserver/templates/geofence/geofence-datasource-ovr.properties.j2 b/docker/geoserver/templates/geofence/geofence-datasource-ovr.properties.envsubst similarity index 70% rename from docker/geoserver/templates/geofence/geofence-datasource-ovr.properties.j2 rename to docker/geoserver/templates/geofence/geofence-datasource-ovr.properties.envsubst index 3cd552c..ea58758 100644 --- a/docker/geoserver/templates/geofence/geofence-datasource-ovr.properties.j2 +++ b/docker/geoserver/templates/geofence/geofence-datasource-ovr.properties.envsubst @@ -1,9 +1,9 @@ geofenceVendorAdapter.databasePlatform=org.hibernate.spatial.dialect.postgis.PostgisDialect geofenceDataSource.driverClassName=org.postgresql.Driver -geofenceDataSource.url=jdbc:postgresql://{{ DATABASE_HOST }}:{{ DATABASE_PORT }}/{{ GEONODE_GEODATABASE }} -geofenceDataSource.username={{ GEONODE_GEODATABASE_USER }} -geofenceDataSource.password={{ GEONODE_GEODATABASE_PASSWORD }} -geofenceEntityManagerFactory.jpaPropertyMap[hibernate.default_schema]={{ GEONODE_GEODATABASE_SCHEMA }} +geofenceDataSource.url=jdbc:postgresql://${DATABASE_HOST}:${DATABASE_PORT}/${GEONODE_GEODATABASE} +geofenceDataSource.username=${GEONODE_GEODATABASE_USER} +geofenceDataSource.password=${GEONODE_GEODATABASE_PASSWORD} +geofenceEntityManagerFactory.jpaPropertyMap[hibernate.default_schema]=${GEONODE_GEODATABASE_SCHEMA} # avoid hibernate transaction issues geofenceDataSource.testOnBorrow=true diff --git a/docker/geoserver_data/Dockerfile b/docker/geoserver_data/Dockerfile deleted file mode 100644 index 3692e7d..0000000 --- a/docker/geoserver_data/Dockerfile +++ /dev/null @@ -1,25 +0,0 @@ -FROM alpine:latest -ARG GEOSERVER_VERSION=2.27.4 - -# Install curl in alpine 3.3+ -RUN apk --no-cache add curl - -# Download required files -RUN mkdir -p /tmp/geonode/downloaded -ENV TEMP_DOWNLOADED=/tmp/geonode/downloaded -WORKDIR ${TEMP_DOWNLOADED} - -ENV GEOSERVER_VERSION=${GEOSERVER_VERSION} - -ADD download.sh ${TEMP_DOWNLOADED} -RUN chmod +x ${TEMP_DOWNLOADED}/download.sh -RUN ${TEMP_DOWNLOADED}/download.sh $GEOSERVER_VERSION $TEMP_DOWNLOADED - -# for debugging -RUN ls -lart - -# preparing the volume -ENV BASE_GEOSERVER_DATA_DIR=/geoserver_data -RUN mkdir -p ${BASE_GEOSERVER_DATA_DIR} -RUN cp -r ${TEMP_DOWNLOADED}/data ${BASE_GEOSERVER_DATA_DIR} -VOLUME ${BASE_GEOSERVER_DATA_DIR}/data diff --git a/docker/geoserver_data/README.rst b/docker/geoserver_data/README.rst deleted file mode 100644 index f62746b..0000000 --- a/docker/geoserver_data/README.rst +++ /dev/null @@ -1,208 +0,0 @@ -***************************** -How to start with data-docker -***************************** - -What you can do with this docker container -========================================== - -The **data-docker** project can be your base data container volume to add data from scratch to GeoServer and PostGIS and then make them persisted when you want to stop your current containers. - -Quick introduction on creating persisted storage in Docker -========================================================== - -Data persistence strategies ---------------------------- - -The most commonly used approches in `Docker`_ are `Data volumes`_ and `Data volume containers`_ which essentially create a file system data volume rather than a dedicated data volume container. - -.. _Docker: https://www.docker.com/technologies/overview - -.. warning:: If you want to follow this readme and run the docker command you have to make sure that your docker host environment has been already set and your docker default machine has been started. - -.. note:: This is required by all developers who are using `Docker-Machine`_ for running containers. Those use native linux or vm like `Docker for Mac`_ and `Docker for Windows`_ don't need these checks. - -.. _Docker-Machine: https://docs.docker.com/machine/ -.. _Docker for Mac: https://www.docker.com/docker-mac -.. _Docker for Windows: https://www.docker.com/docker-windows - -Docker-Machine --------------- - -In order to verify base prerequirements please run this commands below: - -.. code-block:: console - - $ docker-machine env - -which should output something similar: - -.. code-block:: console - - export DOCKER_TLS_VERIFY="1" - export DOCKER_HOST="tcp://192.168.99.100:2376" - export DOCKER_CERT_PATH="/.docker/machine/machines/default" - export DOCKER_MACHINE_NAME="default" - -and then configure your shell environment - -.. code-block:: console - - $ eval $(docker-machine env) - -Data volumes ------------- - -You can easily add a data volume to a container using the option `-v` with the command `run` as the example below: - -.. code-block:: console - - $ docker run -d -P --name geonode-data-container -v /data geonode/geonode-data touch /data/test.txt - -Which creates a data volume within the new container in the `/data` directory. Data volumes are very useful because can be shared and included into other containers. It can be also remarked that the volume created will persist the `test.txt` file. - -Host data volumes -^^^^^^^^^^^^^^^^^ - -You can also mount a directory from your Docker daemon’s host into a container and this could be very useful for testing but even for production in case your host machine can share a storage mount point like a network file system (*NFS*). This approach despite its ease to implement nature has actually an heavy constraint that you have to pre-configure the mount point in your docker host. -This breaks two of the biggest Docker advantages: **container portability** and **applications run anywhere**. - -.. code-block:: console - - $ docker run -d -P --name geonode-data-container -v /geonode_data/data:/data geonode/geonode-data touch /data/test.txt - -In case of the GeoNode *data* for example you cannot start from scratch in development like you actually do with - -.. code-block:: console - - (venv)$ paver reset_hard - -Data volume containers ----------------------- -A data volume container is essentially a docker image that defines storage space. The container itself just defines a place inside docker's virtual file system where data is stored. The container doesn’t run a process and in fact *stops* immediately after `docker run` is called as the container exists in a stopped state, so along with its data. - -So let's create a dedicated container that holds all of GeoNode persistent shareable data resources, mounting the data inside of it and then eventually into other containers once created and setup: - -.. code-block:: console - - $ docker create -v /geonode-store --name geonode-data-container geonode/geonode-data /bin/true - -.. note:: `/bin/true` returns a `0` and does nothing if the command was successful. - -And the with the option `--volumes-from` you can mount the created volume `/geonode-store` within other containers by running: - -.. code-block:: console - - $ docker run -d --volumes-from geonode-data-container --name geoserver geonode/geoserver - -.. hint:: Notice that if you remove containers that mount volumes, the volume store and its data will not be deleted since docker preserves that. - -To completely delete a volume from the file system you have to run: - -.. code-block:: console - - $ docker rm -v geoserver - -How to start with docker-compose for geonode data volume container -================================================================== - -Start the creation of a volume with the **GEOSERVER_DATA_DIR** in the directory `/geoserver_data/data`: - -.. code-block:: console - - $ docker-compose up - -Run a geoserver container with such created volume: - -.. code-block:: console - - # need to having pulling geonode/geoserver:2.10.x from docker hub - $ docker run -d --volumes-from geoserver_data_dir --name geoserver geonode/geoserver - -Verify that the preloaded `GeoServer Data Directory for GeoServer 2.15.x`_ build from Jenkins is actually there: - -.. _GeoServer Data Directory for GeoServer 2.15.x: http://build.geonode.org/geoserver/latest/data-2.15.x.zip - -.. code-block:: console - - $ docker exec -it geoserver ls -lart /geoserver_data/data/ - -The output should be something similar: - -.. code-block:: console - - total 76 - drwxr-xr-x 3 root root 4096 Aug 27 16:51 workspaces - -rw-r--r-- 1 root root 1547 Aug 27 16:51 wms.xml - -rw-r--r-- 1 root root 2013 Aug 27 16:51 wfs.xml - -rw-r--r-- 1 root root 1285 Aug 27 16:51 wcs.xml - drwxr-xr-x 2 root root 4096 Aug 27 16:51 styles - drwxr-xr-x 8 root root 4096 Aug 27 16:51 security - drwxr-xr-x 2 root root 4096 Aug 27 16:51 printing - drwxr-xr-x 2 root root 4096 Aug 27 16:51 plugIns - drwxr-xr-x 2 root root 4096 Aug 27 16:51 palettes - drwxr-xr-x 2 root root 4096 Aug 27 16:51 logs - -rw-r--r-- 1 root root 144 Aug 27 16:51 logging.xml - drwxr-xr-x 2 root root 4096 Aug 27 16:51 images - -rw-r--r-- 1 root root 1111 Aug 27 16:51 gwc-gs.xml - -rw-r--r-- 1 root root 1374 Aug 27 16:51 global.xml - drwxr-xr-x 2 root root 4096 Aug 27 16:51 geonode - drwxr-xr-x 2 root root 4096 Aug 27 16:51 demo - -rw-r--r-- 1 root root 184 Aug 27 16:51 README.rst - drwxr-xr-x 12 root root 4096 Aug 27 16:51 . - drwxr-xr-x 7 root root 4096 Aug 27 17:08 .. - -How to define a docker-compose that uses data-docker ----------------------------------------------------- - -A docker-compose.yml can be defined in such a way with a service that mounts this data directory from a `tag of Docker Hub builds`_, in this case the version for `GeoServer-GeoNode 2.15.x`_: - -.. _tag of Docker Hub builds: https://hub.docker.com/r/geonode/geoserver_data/builds/ - -.. _GeoServer-GeoNode 2.15.x: https://github.com/GeoNode/geoserver-geonode-ext/tree/2.15.x - -.. code-block:: yaml - - version: '2' - - services: - geoserver: - build: . - ports: - - "8888:8080" - volumes_from: - # reference to the service which has the volume with the preloaded geoserver_data_dir - - data_dir_conf - data_dir_conf: - image: geonode/geoserver_data:2.15.x - container_name: geoserver_data_dir # named data container - command: /bin/true - volumes: - - /geoserver_data/data - - volumes: - # reference to the named data container that holds the preloaded geoserver data directory - geoserver_data_dir: - - -Available tags --------------- - -There are several different tags from the `Docker Hub builds`_: - -.. _Docker Hub builds: https://cloud.docker.com/u/geonode/repository/registry-1.docker.io/geonode/geoserver_data/builds/ - -* **2.9.x**: `geonode/geoserver_data:2.9.x`_ -* **2.9.x-oauth2**: `geonode/geoserver_data:2.9.x-oauth2`_ -* **2.10.x**: `geonode/geoserver_data:2.10.x`_ -* **2.12.x**: `geonode/geoserver_data:2.12.x`_ -* **2.13.x**: `geonode/geoserver_data:2.13.x`_ -* **2.14.x**: `geonode/geoserver_data:2.14.x`_ -* **2.15.x**: `geonode/geoserver_data:2.15.x`_ - -.. _geonode/geoserver_data:2.9.x: https://hub.docker.com/r/geonode/geoserver_data/builds/bsus6alnddg4bc7icwymevp/ -.. _geonode/geoserver_data:2.9.x-oauth2: https://hub.docker.com/r/geonode/geoserver_data/builds/bwkxcupsunvuitzusi9gsnt/ -.. _geonode/geoserver_data:2.10.x: https://hub.docker.com/r/geonode/geoserver_data/builds/b9vbumhwfcrti8bxnmpbpwi/ -.. _geonode/geoserver_data:2.12.x: https://hub.docker.com/r/geonode/geoserver_data/builds/byaaalw3lnasunpveyg3x4i/ -.. _geonode/geoserver_data:2.13.x: https://hub.docker.com/r/geonode/geoserver_data/builds/bunuqzq7a7dk65iumjhkbtc/ -.. _geonode/geoserver_data:2.14.x: https://cloud.docker.com/u/geonode/repository/registry-1.docker.io/geonode/geoserver_data/builds/545f08f9-75a3-4161-bcb0-895c1817dc8d -.. _geonode/geoserver_data:2.15.x: https://cloud.docker.com/u/geonode/repository/registry-1.docker.io/geonode/geoserver_data/builds/dce29f95-b6f7-4f5e-86f1-78d5e98fd866 diff --git a/docker/geoserver_data/docker-compose.yml b/docker/geoserver_data/docker-compose.yml deleted file mode 100644 index 883c041..0000000 --- a/docker/geoserver_data/docker-compose.yml +++ /dev/null @@ -1,14 +0,0 @@ -version: '2' - -services: - data_dir_conf: - build: . - image: geonode/geoserver_data:2.27.4-latest - container_name: geoserver_data_dir - command: /bin/true - volumes: - - /geoserver_data/data - -volumes: - # reference to the named data container that holds the preloaded geoserver data directory - geoserver_data_dir: diff --git a/docker/geoserver_data/download.sh b/docker/geoserver_data/download.sh deleted file mode 100644 index 04dcea6..0000000 --- a/docker/geoserver_data/download.sh +++ /dev/null @@ -1,18 +0,0 @@ -#!/usr/bin/env sh - -# Wait for version to come up before downloading it -# args $1 - version -# args $2 - temp directory - -echo "GeoServer Data Dir version is $1" -echo "-----------------------------------------------------------------------------------------------" -echo "Archive temporary directory is $2" - -GEOSERVER_VERSION=$1 -TEMP_DOWNLOADED=$2 - -echo "GeoServer Data Directory is going to be downloaded" -artifact_url="https://artifacts.geonode.org/geoserver/$GEOSERVER_VERSION/geonode-geoserver-ext-web-app-data.zip" -echo "Downloading: $artifact_url" -curl -k -L "$artifact_url" --output data.zip && unzip -x -d ${TEMP_DOWNLOADED} data.zip -echo "GeoServer Data Directory download has been completed"