From 5d8ca42c091ef1b7e173aeb06a73d3e6a3ee4d6e Mon Sep 17 00:00:00 2001 From: Johannes Weskamm Date: Wed, 22 Jun 2022 17:01:25 +0200 Subject: [PATCH] Updating docker and scripts --- .gitignore | 1 - Dockerfile | 134 +++++++++--------- README.md | 122 +++++++++------- additional_fonts/.gitignore | 5 + additional_libs/.gitignore | 5 + docker-compose-demo.yml | 4 +- geoserver_data/.gitignore | 5 + ...all-extensions.sh => install-extensions.sh | 18 +-- scripts/entrypoint.sh | 21 --- startup.sh | 51 +++++++ 10 files changed, 218 insertions(+), 148 deletions(-) create mode 100644 additional_fonts/.gitignore create mode 100644 additional_libs/.gitignore create mode 100644 geoserver_data/.gitignore rename scripts/install-extensions.sh => install-extensions.sh (69%) delete mode 100644 scripts/entrypoint.sh create mode 100755 startup.sh diff --git a/.gitignore b/.gitignore index 00e37c1..92bc551 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,3 @@ *.iml *.idea -demo_data \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index f3c0c1f..3afd9e3 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,83 +1,87 @@ -FROM tomcat:9.0.41-jdk11-openjdk-slim AS base - -ARG GEOSERVER_VERSION=2.18.2 - -ARG GEOSERVER_WAR_SRC=https://downloads.sourceforge.net/project/geoserver/GeoServer/${GEOSERVER_VERSION}/geoserver-${GEOSERVER_VERSION}-war.zip -ARG STABLE_PLUGIN_URL=https://sourceforge.net/projects/geoserver/files/GeoServer/${GEOSERVER_VERSION}/extensions +FROM ubuntu:22.04 +# The GS_VERSION argument could be used like this to overwrite the default: +# docker build --build-arg GS_VERSION=2.11.3 -t geoserver:2.11.3 . +ARG TOMCAT_VERSION=9.0.64 +ARG GS_VERSION=2.21.0 +ARG GS_DATA_PATH=./geoserver_data/ +ARG ADDITIONAL_LIBS_PATH=./additional_libs/ +ARG ADDITIONAL_FONTS_PATH=./additional_fonts/ ARG CORS_ENABLED=false ARG CORS_ALLOWED_ORIGINS=* ARG CORS_ALLOWED_METHODS=GET,POST,PUT,DELETE,HEAD,OPTIONS ARG CORS_ALLOWED_HEADERS=* +ARG STABLE_PLUGIN_URL=https://sourceforge.net/projects/geoserver/files/GeoServer/${GS_VERSION}/extensions -# environment variables -ENV GEOSERVER_VERSION=${GEOSERVER_VERSION} \ - GEOSERVER_DIR=${CATALINA_HOME}/webapps/geoserver \ - STABLE_PLUGIN_URL=${STABLE_PLUGIN_URL} \ - INITIAL_MEMORY=2G \ - MAXIMUM_MEMORY=4G \ - JAIEXT_ENABLED=true \ - DOWNLOAD_EXTENSIONS=false \ - STABLE_EXTENSIONS='' \ - DEBIAN_FRONTEND=noninteractive \ - ADDITIONAL_LIBS_DIR=/opt/additional_libs/ \ - GEOSERVER_DATA_DIR=/opt/geoserver_data/ \ - GEOWEBCACHE_CACHE_DIR=/opt/geowebcache_data/ +# Environment variables +ENV CATALINA_HOME=/opt/apache-tomcat-${TOMCAT_VERSION} +ENV GEOSERVER_VERSION=$GS_VERSION +ENV GEOSERVER_DATA_DIR=/opt/geoserver_data/ +ENV GEOSERVER_LIB_DIR=$CATALINA_HOME/webapps/geoserver/WEB-INF/lib/ +ENV EXTRA_JAVA_OPTS="-Xms256m -Xmx1g" +ENV CORS_ENABLED=$CORS_ENABLED +ENV CORS_ALLOWED_ORIGINS=$CORS_ALLOWED_ORIGINS +ENV CORS_ALLOWED_METHODS=$CORS_ALLOWED_METHODS +ENV CORS_ALLOWED_HEADERS=$CORS_ALLOWED_HEADERS +ENV DEBIAN_FRONTEND=noninteractive +ENV INSTALL_EXTENSIONS=false +ENV STABLE_EXTENSIONS='' +ENV STABLE_PLUGIN_URL=$STABLE_PLUGIN_URL +ENV ADDITIONAL_LIBS_DIR=/opt/additional_libs/ +ENV ADDITIONAL_FONTS_DIR=/opt/additional_fonts/ -RUN mkdir ${ADDITIONAL_LIBS_DIR} ${GEOSERVER_DATA_DIR} ${GEOWEBCACHE_CACHE_DIR} +# see http://docs.geoserver.org/stable/en/user/production/container.html +ENV CATALINA_OPTS="\$EXTRA_JAVA_OPTS \ + -Djava.awt.headless=true -server \ + -Dfile.encoding=UTF-8 \ + -Djavax.servlet.request.encoding=UTF-8 \ + -Djavax.servlet.response.encoding=UTF-8 \ + -D-XX:SoftRefLRUPolicyMSPerMB=36000 \ + -Xbootclasspath/a:$CATALINA_HOME/lib/marlin.jar \ + -Xbootclasspath/a:$CATALINA_HOME/lib/marlin-sun-java2d.jar \ + -Dsun.java2d.renderer=org.marlin.pisces.PiscesRenderingEngine \ + -Dorg.geotools.coverage.jaiext.enabled=true" -# install required dependencies -# also clear the initial webapps +# init RUN apt update && \ - apt install -y curl wget openssl zip fontconfig libfreetype6 && \ - rm -rf ${CATALINA_HOME}/webapps/* + apt -y upgrade && \ + apt install -y --no-install-recommends openssl unzip gdal-bin wget curl openjdk-11-jdk && \ + rm -rf $CATALINA_HOME/webapps/* && \ + apt clean && \ + rm -rf /var/cache/apt/* && \ + rm -rf /var/lib/apt/lists/* -ADD "${GEOSERVER_WAR_SRC}" "/tmp/" +WORKDIR /opt/ +RUN wget -q https://dlcdn.apache.org/tomcat/tomcat-9/v${TOMCAT_VERSION}/bin/apache-tomcat-${TOMCAT_VERSION}.tar.gz && \ + tar xf apache-tomcat-${TOMCAT_VERSION}.tar.gz && \ + rm apache-tomcat-${TOMCAT_VERSION}.tar.gz && \ + rm -rf /opt/apache-tomcat-${TOMCAT_VERSION}/webapps/ROOT && \ + rm -rf /opt/apache-tomcat-${TOMCAT_VERSION}/webapps/docs && \ + rm -rf /opt/apache-tomcat-${TOMCAT_VERSION}/webapps/examples -# extract war from zip if necessary -RUN if [ "${GEOSERVER_WAR_SRC##*.}" = "zip" ]; then \ - unzip "/tmp/*zip" -d /tmp/; \ - ls -lah; \ - rm /tmp/*zip; \ - fi +WORKDIR /tmp # install geoserver -RUN mkdir -p ${GEOSERVER_DIR} && \ - unzip -q /tmp/*war -d ${GEOSERVER_DIR} && \ - rm /tmp/*war +RUN wget -q -O /tmp/geoserver.zip http://downloads.sourceforge.net/project/geoserver/GeoServer/$GEOSERVER_VERSION/geoserver-$GEOSERVER_VERSION-war.zip && \ + unzip geoserver.zip geoserver.war -d $CATALINA_HOME/webapps && \ + mkdir -p $CATALINA_HOME/webapps/geoserver && \ + unzip -q $CATALINA_HOME/webapps/geoserver.war -d $CATALINA_HOME/webapps/geoserver && \ + rm $CATALINA_HOME/webapps/geoserver.war && \ + mkdir -p $GEOSERVER_DATA_DIR -# configure CORS (inspired by https://github.com/oscarfonts/docker-geoserver) -RUN if [ "${CORS_ENABLED}" = "true" ]; then \ - sed -i "\::i\ \ - \n\ \ - CorsFilter\n\ \ - org.apache.catalina.filters.CorsFilter\n\ \ - \n\ \ - cors.allowed.origins\n\ \ - ${CORS_ALLOWED_ORIGINS}\n\ \ - \n\ \ - \n\ \ - cors.allowed.methods\n\ \ - ${CORS_ALLOWED_METHODS}\n\ \ - \n\ \ - \n\ \ - cors.allowed.headers\n\ \ - ${CORS_ALLOWED_HEADERS}\n\ \ - \n\ \ - \n\ \ - \n\ \ - CorsFilter\n\ \ - /*\n\ \ - " "${GEOSERVER_DIR}/WEB-INF/web.xml"; \ - fi - -# copy scripts -COPY scripts /scripts -RUN chmod +x /scripts/*.sh +COPY $GS_DATA_PATH $GEOSERVER_DATA_DIR +COPY $ADDITIONAL_LIBS_PATH $GEOSERVER_LIB_DIR +COPY $ADDITIONAL_FONTS_PATH /usr/share/fonts/truetype/ # cleanup -RUN apt clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* +RUN apt purge -y && \ + apt autoremove --purge -y && \ + rm -rf /tmp/* -WORKDIR ${CATALINA_HOME} +# copy scripts +COPY *.sh /opt/ +RUN chmod +x /opt/*.sh -CMD ["/bin/sh", "/scripts/entrypoint.sh"] +ENTRYPOINT /opt/startup.sh + +WORKDIR /opt diff --git a/README.md b/README.md index 6f4441e..93d48b6 100644 --- a/README.md +++ b/README.md @@ -1,58 +1,80 @@ -# Docker GeoServer image +# A geoserver docker image -This docker GeoServer image is based on the following proposal: - -https://github.com/geoserver/geoserver/wiki/GSIP-192 +This Dockerfile can be used to create images for all geoserver versions since 2.5. -Work is still in progress! +* Debian based Linux +* OpenJDK 11 +* Tomcat 9 +* GeoServer + * Support of custom fonts (e.g. for SLD styling) + * CORS support -## How it works +**IMPORTANT NOTE:** Please change the default geoserver master password! The default masterpw is located in this file (within the docker container): `/opt/geoserver_data/security/masterpw/default/masterpw` -1. The [Dockerfile](Dockerfile) - 1. installs dependencies - 1. installs the GeoServer by adding a ZIP and extracting the WAR from it - 1. the expected file name of the war in the zip is `geoserver.war` - 1. by default, the GeoServer URL from sourceforge is used, but you could also provide a custom URL with a zip in the `GEOSERVER_WAR_SRC` build argument. - 1. you can also use the `GEOSERVER_WAR_SRC` build argument to burn your custom WAR file from your local machine to the docker image, e.g. with something like `docker build -t geoserver:test --build-arg GEOSERVER_WAR_SRC="./resources/geoserver.zip" .` - 1. defines defaults for environment variables -1. The [entrypoint.sh](scripts/entrypoint.sh) startup script (in a running container) - 1. executes [install-extensions.sh](scripts/install-extensions.sh) to download and install GeoServer extensions based on the `STABLE_EXTENSIONS` environment variable. - 1. handles the `GEOSERVER_OPTS` - 1. starts the tomcat +## How to build? -## Quickstart +`docker build -t {YOUR_TAG} .` -You can quickstart by using the docker-compose demo +## How to quickstart? + +Build the image as described above, then: + +`docker run -it -p 80:8080 {YOUR_TAG}` + +or if you want to start the container daemonized: + +`docker run -d -p 80:8080 {YOUR_TAG}` + +Check http://localhost/geoserver to see the geoserver page and login with geoserver defaults `admin:geoserver` + +## How to build a specific GeoServer version? + +`docker build --build-arg GS_VERSION={YOUR_VERSION} -t {YOUR_TAG} .` + +## How to build with custom geoserver data? + +`docker build --build-arg GS_DATA_PATH={RELATIVE_PATH_TO_YOUR_GS_DATA} .` + +**Note:** The passed path **must not** be absolute! Instead, the path should be within the build context (e.g. next to the Dockerfile) and should be passed as a relative path, e.g. `GS_DATA_PATH=./my_data/` + +## Can I build a specific GS version with custom data? + +Yes! Just pass the `--build-arg` param twice, e.g. + +`... --build-arg GS_VERSION={VERSION} --build-arg GS_DATA_PATH={PATH} ...` + +## How to build with additional libs/extensions/plugins? + +Put your `*.jar` files (e.g. the WPS extension) in the `additional_libs` folder and build with one of the commands from above! (They will be copied to the GeoServer `WEB-INF/lib` folder during the build.) + +**Note:** Similar to the GeoServer data path from above, you can also configure the path to the additional libraries by passing the `ADDITIONAL_LIBS_PATH` argument when building: + +`--build-arg ADDITIONAL_LIBS_PATH={RELATIVE_PATH_TO_YOUR_LIBS}` + +## How to add additional libs using an existing docker image? + +If you want to add geoserver extensions/libs by using a mount, you can add something like + +``` +--mount src="/dir/with/libs/on/host",target=/opt/additional_libs,type=bind +``` + +## How to add additional fonts to the docker image (e.g. for SLD styling)? + +If you want to add custom fonts (the base image only contains 26 fonts) by using a mount, you can add something like + +``` +--mount src="/dir/with/fonts/on/host",target=/opt/additional_fonts,type=bind +``` + +to your `docker run` command. + +**Note:** Do not change the target value! + +## How to watch geoserver.log from host? + +`docker exec -it {CONTAINER_ID} tail -f /opt/geoserver_data/logs/geoserver.log` + +## How to use the docker-compose demo? `docker-compose -f docker-compose-demo.yml up --build` - -(use `sudo` if you get problems with mounted geoserver data dir) - -## Building - -`docker build -t geoserver:test .` - -## Running - -`docker run -it -e DOWNLOAD_EXTENSIONS='true' -e STABLE_EXTENSIONS='wps,csw' -p 8080:8080 geoserver:test` - -The extensions will be downloaded on startup of the image (before starting the tomcat). - -## Configuration - -Pass as environment variables. If not passed, the default values will be used. - -* `GEOSERVER_DATA_DIR` (default: /opt/geoserver_data) -* `INITIAL_MEMORY` (default: 2G) -* `MAXIMUM_MEMORY` (default: 4G) -* `JAIEXT_ENABLED` (default: true) -* `DOWNLOAD_EXTENSIONS` (default: false) - * `STABLE_EXTENSIONS` applies only if `DOWNLOAD_EXTENSIONS` is true: provide a comma separated list of extension identifiers and they will be downloaded and installed on startup (default: "") - -## TODOs - -* configuration of JNDI connections in the tomcat/custom tomcat configuration in general -* default data for gs datadir? -* log4j properties -* add possibility to add custom fonts -* starting from which version we want to provide geoserver images/backwards compatability? diff --git a/additional_fonts/.gitignore b/additional_fonts/.gitignore new file mode 100644 index 0000000..76bedae --- /dev/null +++ b/additional_fonts/.gitignore @@ -0,0 +1,5 @@ +# Ignore everything in this directory +* +# Except this file +!.gitignore + diff --git a/additional_libs/.gitignore b/additional_libs/.gitignore new file mode 100644 index 0000000..76bedae --- /dev/null +++ b/additional_libs/.gitignore @@ -0,0 +1,5 @@ +# Ignore everything in this directory +* +# Except this file +!.gitignore + diff --git a/docker-compose-demo.yml b/docker-compose-demo.yml index df67b48..8ea844e 100644 --- a/docker-compose-demo.yml +++ b/docker-compose-demo.yml @@ -4,13 +4,13 @@ services: build: context: . args: - - GEOSERVER_VERSION=2.18.2 + - GEOSERVER_VERSION=2.21.0 - CORS_ENABLED=true - CORS_ALLOWED_METHODS=GET,POST,PUT,HEAD,OPTIONS ports: - 8080:8080 environment: - - DOWNLOAD_EXTENSIONS=true + - INSTALL_EXTENSIONS=true - STABLE_EXTENSIONS=wps,csw - INITIAL_MEMORY=1G - MAXIMUM_MEMORY=2G diff --git a/geoserver_data/.gitignore b/geoserver_data/.gitignore new file mode 100644 index 0000000..76bedae --- /dev/null +++ b/geoserver_data/.gitignore @@ -0,0 +1,5 @@ +# Ignore everything in this directory +* +# Except this file +!.gitignore + diff --git a/scripts/install-extensions.sh b/install-extensions.sh similarity index 69% rename from scripts/install-extensions.sh rename to install-extensions.sh index 0338af6..541cbd3 100644 --- a/scripts/install-extensions.sh +++ b/install-extensions.sh @@ -10,16 +10,16 @@ function download_extension() { echo "$DOWNLOAD_FILE already exists. Skipping download." else if curl --output /dev/null --silent --head --fail "${URL}"; then - echo -e "\nDownloading ${EXTENSION}-extension from ${URL}" - wget --progress=bar:force:noscroll -c --no-chec k-certificate "${URL}" -O ${DOWNLOAD_FILE} + echo -e "\nDownloading ${EXTENSION}-extension from ${URL} to ${DOWNLOAD_FILE}" + wget --progress=bar:force:noscroll -c --no-check-certificate "${URL}" -O ${DOWNLOAD_FILE} else echo "URL does not exist: ${URL}" fi fi } -# Download stable plugins only if DOWNLOAD_EXTENSIONS is true -if [ "$DOWNLOAD_EXTENSIONS" = "true" ]; then +# Download stable plugins only if INSTALL_EXTENSIONS is true +if [ "$INSTALL_EXTENSIONS" = "true" ]; then echo "Starting download of extensions" for EXTENSION in $(echo "${STABLE_EXTENSIONS}" | tr ',' ' '); do URL="${STABLE_PLUGIN_URL}/geoserver-${GEOSERVER_VERSION}-${EXTENSION}-plugin.zip" @@ -28,17 +28,17 @@ if [ "$DOWNLOAD_EXTENSIONS" = "true" ]; then echo "Finished download of extensions" fi -TARGET_LIB_DIR="${CATALINA_HOME}/webapps/geoserver/WEB-INF/lib/" -# Install all extensions that are available in the additional lib dir now +# Install the extensions echo "Starting installation of extensions" -for ADDITIONAL_LIB in ${ADDITIONAL_LIBS_DIR}*; do +for EXTENSION in $(echo "${STABLE_EXTENSIONS}" | tr ',' ' '); do + ADDITIONAL_LIB=${ADDITIONAL_LIBS_DIR}geoserver-${GEOSERVER_VERSION}-${EXTENSION}-plugin.zip [ -e "$ADDITIONAL_LIB" ] || continue if [[ $ADDITIONAL_LIB == *.zip ]]; then - unzip -q -o -d ${TARGET_LIB_DIR} ${ADDITIONAL_LIB} "*.jar" + unzip -q -o -d ${GEOSERVER_LIB_DIR} ${ADDITIONAL_LIB} "*.jar" echo "Installed all jar files from ${ADDITIONAL_LIB}" elif [[ $ADDITIONAL_LIB == *.jar ]]; then - cp ${ADDITIONAL_LIB} ${TARGET_LIB_DIR} + cp ${ADDITIONAL_LIB} ${GEOSERVER_LIB_DIR} echo "Installed ${ADDITIONAL_LIB}" else echo "Skipping ${ADDITIONAL_LIB}: unknown file extension." diff --git a/scripts/entrypoint.sh b/scripts/entrypoint.sh deleted file mode 100644 index e49359f..0000000 --- a/scripts/entrypoint.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/bash -## Inspired by https://github.com/kartoza/docker-geoserver -set -e - -## install GeoServer extensions before starting the tomcat -/scripts/install-extensions.sh - -export GEOSERVER_OPTS="-Djava.awt.headless=true -server \ - -Dfile.encoding=UTF8 \ - -Djavax.servlet.request.encoding=UTF-8 \ - -Djavax.servlet.response.encoding=UTF-8 \ - -Xms${INITIAL_MEMORY} -Xmx${MAXIMUM_MEMORY} \ - -XX:SoftRefLRUPolicyMSPerMB=36000 \ - -XX:MaxGCPauseMillis=200 -XX:ParallelGCThreads=20 -XX:ConcGCThreads=5 \ - -Dorg.geotools.coverage.jaiext.enabled=${JAIEXT_ENABLED}" - -## JVM command line arguments -export JAVA_OPTS="${JAVA_OPTS} ${GEOSERVER_OPTS}" - -## Start the tomcat -exec /usr/local/tomcat/bin/catalina.sh run diff --git a/startup.sh b/startup.sh new file mode 100755 index 0000000..812e243 --- /dev/null +++ b/startup.sh @@ -0,0 +1,51 @@ +#!/bin/sh + +## install GeoServer extensions before starting the tomcat +/opt/install-extensions.sh + +# copy additional geoserver libs before starting the tomcat +# we also count whether at least one file with the extensions exists +count=`ls -1 $ADDITIONAL_LIBS_DIR/*.jar 2>/dev/null | wc -l` +if [ -d "$ADDITIONAL_LIBS_DIR" ] && [ $count != 0 ]; then + cp $ADDITIONAL_LIBS_DIR/*.jar $CATALINA_HOME/webapps/geoserver/WEB-INF/lib/ +fi + +# copy additional fonts before starting the tomcat +# we also count whether at least one file with the extensions exists +count=`ls -1 *.ttf 2>/dev/null | wc -l` +if [ -d "$ADDITIONAL_FONTS_DIR" ] && [ $count != 0 ]; then + cp $ADDITIONAL_FONTS_DIR/*.ttf /usr/share/fonts/truetype/ +fi + +# configure CORS (inspired by https://github.com/oscarfonts/docker-geoserver) +# if enabled, this will add the filter definitions +# to the end of the web.xml +# (this will only happen if our filter has not yet been added before) +if [ "${CORS_ENABLED}" = "true" ]; then + if ! grep -q DockerGeoServerCorsFilter "$CATALINA_HOME/webapps/geoserver/WEB-INF/web.xml"; then + sed -i "\::i\\ + \n\ + DockerGeoServerCorsFilter\n\ + org.apache.catalina.filters.CorsFilter\n\ + \n\ + cors.allowed.origins\n\ + ${CORS_ALLOWED_ORIGINS}\n\ + \n\ + \n\ + cors.allowed.methods\n\ + ${CORS_ALLOWED_METHODS}\n\ + \n\ + \n\ + cors.allowed.headers\n\ + ${CORS_ALLOWED_HEADERS}\n\ + \n\ + \n\ + \n\ + DockerGeoServerCorsFilter\n\ + /*\n\ + " "$CATALINA_HOME/webapps/geoserver/WEB-INF/web.xml"; + fi +fi + +# start the tomcat +$CATALINA_HOME/bin/catalina.sh run