diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..92bc551 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +*.iml +*.idea + diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..3afd9e3 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,87 @@ +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 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/ + +# 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" + +# init +RUN apt update && \ + 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/* + +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 + +WORKDIR /tmp + +# install geoserver +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 + +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 purge -y && \ + apt autoremove --purge -y && \ + rm -rf /tmp/* + +# copy scripts +COPY *.sh /opt/ +RUN chmod +x /opt/*.sh + +ENTRYPOINT /opt/startup.sh + +WORKDIR /opt diff --git a/README.md b/README.md index 0d2e45c..93d48b6 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,80 @@ -# docker -GeoServer docker image +# A geoserver docker image + +This Dockerfile can be used to create images for all geoserver versions since 2.5. + +* Debian based Linux +* OpenJDK 11 +* Tomcat 9 +* GeoServer + * Support of custom fonts (e.g. for SLD styling) + * CORS support + +**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` + +## How to build? + +`docker build -t {YOUR_TAG} .` + +## 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` 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 new file mode 100644 index 0000000..8ea844e --- /dev/null +++ b/docker-compose-demo.yml @@ -0,0 +1,21 @@ +version: '3' +services: + geoserver: + build: + context: . + args: + - GEOSERVER_VERSION=2.21.0 + - CORS_ENABLED=true + - CORS_ALLOWED_METHODS=GET,POST,PUT,HEAD,OPTIONS + ports: + - 8080:8080 + environment: + - INSTALL_EXTENSIONS=true + - STABLE_EXTENSIONS=wps,csw + - INITIAL_MEMORY=1G + - MAXIMUM_MEMORY=2G + - JAIEXT_ENABLED=true + - GEOSERVER_DATA_DIR=/opt/geoserver_data/ + volumes: + - ./demo_data/geoserver_data:/opt/geoserver_data/:Z + - ./demo_data/additional_libs:/opt/additional_libs:Z # by mounting this we can install libs from host on startup 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/install-extensions.sh b/install-extensions.sh new file mode 100644 index 0000000..541cbd3 --- /dev/null +++ b/install-extensions.sh @@ -0,0 +1,47 @@ +#!/bin/bash +# Inspired by https://github.com/kartoza/docker-geoserver + +function download_extension() { + URL=$1 + EXTENSION=$2 + DOWNLOAD_FILE="${ADDITIONAL_LIBS_DIR}geoserver-${GEOSERVER_VERSION}-${EXTENSION}-plugin.zip" + + if [ -e "$DOWNLOAD_FILE" ]; then + 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} 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 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" + download_extension ${URL} ${EXTENSION} + done + echo "Finished download of extensions" +fi + +# Install the extensions +echo "Starting installation of extensions" +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 ${GEOSERVER_LIB_DIR} ${ADDITIONAL_LIB} "*.jar" + echo "Installed all jar files from ${ADDITIONAL_LIB}" + elif [[ $ADDITIONAL_LIB == *.jar ]]; then + cp ${ADDITIONAL_LIB} ${GEOSERVER_LIB_DIR} + echo "Installed ${ADDITIONAL_LIB}" + else + echo "Skipping ${ADDITIONAL_LIB}: unknown file extension." + fi +done +echo "Finished installation of extensions" 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