├── .gitignore ├── image ├── resources │ ├── root │ │ ├── set-timezone.sh │ │ ├── preinit │ │ │ ├── xml-transformations │ │ │ │ ├── opencms-system_activate_jsonapi.params │ │ │ │ └── opencms-system_activate_jsonapi.xslt │ │ │ ├── 90_message.sh │ │ │ ├── 07_jetty_setup.sh │ │ │ ├── 50_opencms_optimize_webxml_jetty.sh │ │ │ ├── 30_transform_opencms_configuration.sh │ │ │ ├── 10-create-setup-properties.sh │ │ │ ├── 50_opencms_optimize_webxml_tomcat.sh │ │ │ ├── 07_tomcat_setup.sh │ │ │ └── 20_check_install.sh │ │ ├── postinit │ │ │ ├── 10_create_timestamp.sh │ │ │ └── 99_message.sh │ │ ├── execute-opencms-shell.sh │ │ ├── opencms-fetch.sh │ │ ├── opencms-run.sh │ │ ├── process-script-dir.sh │ │ ├── jetty-webxml.xsl │ │ ├── wait-for.sh │ │ ├── opencms-restart.sh │ │ └── common.sh │ └── config │ │ ├── update-core-modules.ocsh │ │ └── server.xml └── Dockerfile ├── .project ├── scripts ├── docker-rm-all.sh ├── docker-enter.sh └── opencms-mount.sh ├── compose ├── postgres │ ├── custom-setup.properties │ └── docker-compose.yml └── build-tomcat │ └── docker-compose.yml ├── docker-compose.yml ├── README.md └── LICENSE /.gitignore: -------------------------------------------------------------------------------- 1 | # It never hurts to have a .gitignore file in the project :) -------------------------------------------------------------------------------- /image/resources/root/set-timezone.sh: -------------------------------------------------------------------------------- 1 | ln -snf /usr/share/zoneinfo/$1 /etc/localtime && echo $1 > /etc/timezone -------------------------------------------------------------------------------- /image/resources/root/preinit/xml-transformations/opencms-system_activate_jsonapi.params: -------------------------------------------------------------------------------- 1 | --stringparam jsonapi ${JSONAPI:-false} -------------------------------------------------------------------------------- /image/resources/root/postinit/10_create_timestamp.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo "Creating timestamp for the system start ..." 4 | 5 | date > ${OPENCMS_HOME}/WEB-INF/opencms-starttime -------------------------------------------------------------------------------- /image/resources/root/postinit/99_message.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | WORKDIR=$(dirname $(readlink -f $0)) 4 | 5 | echo "." 6 | echo "Post-init script folder ${WORKDIR} has been processed" 7 | echo "." 8 | -------------------------------------------------------------------------------- /image/resources/root/preinit/90_message.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | WORKDIR=$(dirname $(readlink -f $0)) 4 | 5 | echo "." 6 | echo "Pre-init script folder ${WORKDIR} has been processed" 7 | echo "." 8 | -------------------------------------------------------------------------------- /.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | opencms-docker 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /image/resources/config/update-core-modules.ocsh: -------------------------------------------------------------------------------- 1 | login Admin admin 2 | setSiteRoot "/" 3 | 4 | # Import the CORE modules 5 | replaceModule "/artifacts/org.opencms.base.zip" 6 | replaceModule "/artifacts/org.opencms.configuration.zip" 7 | 8 | exit 9 | 10 | 11 | -------------------------------------------------------------------------------- /image/resources/root/execute-opencms-shell.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo "=== START OPENCMS SHELL ===" 4 | echo "Installing modules from ${1}" 5 | 6 | # Install Modules using the OpenCms Shell 7 | java -classpath "$(shell_classpath)" \ 8 | org.opencms.main.CmsShell -script=${1} -base=${OPENCMS_HOME}/WEB-INF 9 | 10 | echo "=== END OPENCMS SHELL ===" -------------------------------------------------------------------------------- /image/resources/root/preinit/07_jetty_setup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ "$SERVLET_CONTAINER" != "jetty" ]; then 4 | echo "Skipping $0 because we are not using Jetty" 5 | exit 6 | fi 7 | 8 | cd $CONTAINER_BASE 9 | java -jar $JETTY_HOME/start.jar --add-modules=ee8-deploy,ee8-jsp,ee8-jstl,server,http,gzip 10 | echo "$JETTY_OPTS" > jetty-opts.txt -------------------------------------------------------------------------------- /image/resources/root/preinit/50_opencms_optimize_webxml_jetty.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ "${SERVLET_CONTAINER}" != "jetty" ] ; then 4 | echo "Skipping $0 because we are not using Jetty." 5 | exit 6 | fi 7 | 8 | WEB_XML=${OPENCMS_HOME}/WEB-INF/web.xml 9 | xsltproc --stringparam cookie_name "JSESSIONID_$HOSTNAME" -o "$WEB_XML" /root/jetty-webxml.xsl "$WEB_XML" 10 | 11 | echo "" 12 | echo "Modified web.xml configuration looks like this:" 13 | echo "=================================================================================================" 14 | cat "$WEB_XML" 15 | echo "" 16 | -------------------------------------------------------------------------------- /scripts/docker-rm-all.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo "=== START DOCKER CLEANUP SCRIPT ===" 4 | 5 | echo "Removing all stale containers:" 6 | STALE_CONTAINERS=$(docker ps -a | grep "Exited " | awk '{ print $1; }') 7 | COUNT=$(echo "$STALE_CONTAINERS" | wc -m) 8 | 9 | if [ $COUNT -gt 1 ]; then 10 | docker rm $STALE_CONTAINERS 11 | else 12 | echo "- No stale containers found." 13 | fi 14 | 15 | echo "Removing all stale images that have as name:" 16 | 17 | STALE_IMAGES=$(docker images | grep "^" | awk '{ print $3; }') 18 | COUNT=$(echo "$STALE_IMAGES" | wc -m) 19 | 20 | if [ $COUNT -gt 1 ]; then 21 | docker rmi $STALE_IMAGES 22 | else 23 | echo "- No stale images found." 24 | fi 25 | 26 | echo "=== END DOCKER CLEANUP SCRIPT ===" -------------------------------------------------------------------------------- /compose/postgres/custom-setup.properties: -------------------------------------------------------------------------------- 1 | setup.webapp.path=/container/webapps/ROOT 2 | setup.default.webapp= 3 | setup.install.components=workplace,demo 4 | setup.show.progress=true 5 | 6 | db.product=postgresql 7 | db.provider=postgresql 8 | db.create.user=root 9 | db.create.pwd=root 10 | db.worker.user=opencms 11 | db.worker.pwd=opencms 12 | db.connection.url=jdbc:postgresql://postgres:5432/ 13 | db.name=opencms 14 | db.create.db=true 15 | db.create.tables=true 16 | db.dropDb=true 17 | db.default.tablespace= 18 | db.index.tablespace= 19 | db.jdbc.driver=org.postgresql.Driver 20 | db.template.db=template1 21 | db.temporary.tablespace= 22 | 23 | server.url=http://localhost 24 | server.name=OpenCmsServer 25 | server.ethernet.address= 26 | server.servlet.mapping= 27 | -------------------------------------------------------------------------------- /image/resources/root/opencms-fetch.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | 4 | 5 | # Check if a file opencms.war is not available, if so download from the web 6 | if [ ! -s ${ARTIFACTS_FOLDER}opencms.war ] 7 | then 8 | 9 | if [ ! -s ${ARTIFACTS_FOLDER}opencms.zip ] 10 | then 11 | if [ ! -d ${ARTIFACTS_FOLDER} ]; then 12 | mkdir -v -p ${ARTIFACTS_FOLDER} 13 | fi 14 | echo "Downloading OpenCms from '$OPENCMS_URL'" 15 | wget -nv $OPENCMS_URL -O ${ARTIFACTS_FOLDER}opencms.zip 16 | echo "Download complete, unpacking war" 17 | fi 18 | 19 | if [ -s ${ARTIFACTS_FOLDER}opencms.zip ] 20 | then 21 | unzip -q ${ARTIFACTS_FOLDER}opencms.zip opencms.war -d $ARTIFACTS_FOLDER 22 | echo "Unziped WAR file" 23 | rm -fv ${ARTIFACTS_FOLDER}opencms.zip 24 | ls -la ${ARTIFACTS_FOLDER} 25 | else 26 | exit 1 27 | fi 28 | else 29 | echo "Using local WAR file" 30 | fi 31 | 32 | -------------------------------------------------------------------------------- /compose/postgres/docker-compose.yml: -------------------------------------------------------------------------------- 1 | services: 2 | postgres: 3 | image: postgres:latest 4 | container_name: postgres 5 | init: true 6 | # restart: always 7 | volumes: 8 | - ~/dockermount/opencms-docker-postgres:/var/lib/postgresql/data 9 | environment: 10 | - POSTGRES_PASSWORD=root 11 | - POSTGRES_USER=root 12 | opencms: 13 | image: alkacon/opencms-docker:latest 14 | container_name: opencms 15 | init: true 16 | # restart: always 17 | depends_on: [ "postgres" ] 18 | ports: 19 | - "80:8080" 20 | volumes: 21 | - ~/dockermount/opencms-docker-webapps:/container/webapps 22 | - ./custom-setup.properties:/custom-setup.properties 23 | command: ["/root/wait-for.sh", "postgres:5432", "-t", "30", "--", "/root/opencms-run.sh"] 24 | -------------------------------------------------------------------------------- /image/resources/root/opencms-run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # OpenCms startup script executed when Docker loads the image 4 | 5 | # Set the timezone 6 | echo "Adjusting the timezone" 7 | bash /root/set-timezone.sh ${TIME_ZONE} 8 | 9 | ls /root/preinit/ 10 | 11 | chmod -v +x /root/preinit/*.sh 12 | 13 | ls /root/postinit/ 14 | 15 | chmod -v +x /root/postinit/*.sh 16 | 17 | # Execute pre-init configuration scripts 18 | bash /root/process-script-dir.sh /root/preinit runonce 19 | 20 | start_container 21 | 22 | # Write startup time to file 23 | date > ${OPENCMS_HOME}/WEB-INF/opencms-starttime 24 | 25 | function kill_container_and_exit() { 26 | kill_container 27 | exit 28 | } 29 | trap "kill_container_and_exit" SIGTERM 30 | 31 | # Execute post-init configuration scripts 32 | bash /root/process-script-dir.sh /root/postinit runonce 33 | 34 | # We need a running process for docker 35 | # We use only sleep 1 to get kill_container() executed when SIGTERM is receive 36 | while true ; do 37 | sleep 1 38 | done 39 | -------------------------------------------------------------------------------- /compose/build-tomcat/docker-compose.yml: -------------------------------------------------------------------------------- 1 | services: 2 | mariadb: 3 | image: mariadb:latest 4 | container_name: mariadb 5 | init: true 6 | restart: always 7 | volumes: 8 | - ~/dockermount/opencms-docker-mysql:/var/lib/mysql 9 | environment: 10 | - "MYSQL_ROOT_PASSWORD=secretDBpassword" 11 | opencms: 12 | image: alkacon/opencms-docker:17.0-tomcat 13 | container_name: opencms 14 | build: 15 | context: ../../image 16 | args: 17 | SERVLET_CONTAINER: tomcat 18 | BASE_IMAGE: tomcat:9.0-jdk21 19 | init: true 20 | restart: always 21 | depends_on: [ "mariadb" ] 22 | links: 23 | - "mariadb:mysql" 24 | ports: 25 | - "80:8080" 26 | volumes: 27 | - ~/dockermount/opencms-docker-webapps:/container/webapps 28 | command: ["/root/wait-for.sh", "mysql:3306", "-t", "30", "--", "/root/opencms-run.sh"] 29 | environment: 30 | - "DB_PASSWD=secretDBpassword" 31 | -------------------------------------------------------------------------------- /image/resources/root/process-script-dir.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ -z "$1" ]; then 4 | echo "." 5 | echo "Usage: $0 {SCRIPT_DIR}" 6 | echo "." 7 | exit 1 8 | fi 9 | 10 | SCRIPT_DIR=$1 11 | 12 | echo "." 13 | echo "Executing scripts located in ${SCRIPT_DIR}." 14 | 15 | if [ -d "${SCRIPT_DIR}" ]; then 16 | for SCRIPT in ${SCRIPT_DIR}/*.sh; do 17 | echo "." 18 | echo "Executing OpenCms configuration script: ${SCRIPT}" 19 | echo "---------------------------------------------------" 20 | bash "${SCRIPT}" 21 | if [[ ${SCRIPT} = *.runonce.sh ]]; then 22 | echo "." 23 | echo "Disabling configuration script: ${SCRIPT}" 24 | mv -v "${SCRIPT}" "${SCRIPT}.executed" 25 | fi 26 | echo "---------------------------------------------------" 27 | done 28 | if [ "$2" = "runonce" ]; then 29 | echo "." 30 | echo "Disabling configuration script folder: ${SCRIPT_DIR}" 31 | mv -v "${SCRIPT_DIR}" "${SCRIPT_DIR}.executed" 32 | fi 33 | else 34 | echo "Directory ${SCRIPT_DIR} not available, ignoring!" 35 | fi 36 | 37 | echo "." -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | # Default build/run file for the OpenCms docker image. 2 | # The image uses Jetty and Java 21. 3 | # It connects to a MariaDB database, running as second container. 4 | # To persist data, volumes are defined. Adjust the mount points to your needs, 5 | # or remove the volumes if data should not be persisted. 6 | services: 7 | mariadb: 8 | image: mariadb:latest 9 | container_name: mariadb 10 | init: true 11 | restart: always 12 | volumes: 13 | - ~/dockermount/opencms-docker-mysql:/var/lib/mysql 14 | environment: 15 | - "MYSQL_ROOT_PASSWORD=secretDBpassword" 16 | opencms: 17 | image: alkacon/opencms-docker:20.1 18 | container_name: opencms 19 | build: 20 | context: ./image 21 | args: 22 | SERVLET_CONTAINER: jetty 23 | BASE_IMAGE: jetty:12-jdk21 24 | init: true 25 | restart: always 26 | depends_on: [ "mariadb" ] 27 | links: 28 | - "mariadb:mysql" 29 | ports: 30 | - "80:8080" 31 | volumes: 32 | - ~/dockermount/opencms-docker-webapps:/container/webapps 33 | command: ["/root/wait-for.sh", "mysql:3306", "-t", "30", "--", "/root/opencms-run.sh"] 34 | environment: 35 | - "DB_PASSWD=secretDBpassword" 36 | -------------------------------------------------------------------------------- /image/resources/config/server.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 22 | 23 | 24 | 25 | 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /image/resources/root/preinit/xml-transformations/opencms-system_activate_jsonapi.xslt: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /image/resources/root/jetty-webxml.xsl: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | 9 | 10 | 11 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 26 | 27 | 28 | ExpiresFilter 29 | org.opencms.main.CmsExportExpiresFilter 30 | 31 | 32 | 33 | ExpiresFilter 34 | /export/* 35 | REQUEST 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /scripts/docker-enter.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | if [ -e $(dirname "$0")/nsenter ]; then 4 | # with boot2docker, nsenter is not in the PATH but it is in the same folder 5 | NSENTER=$(dirname "$0")/nsenter 6 | else 7 | NSENTER=nsenter 8 | fi 9 | 10 | if [ -z "$1" ]; then 11 | echo "" 12 | echo "Usage: `basename "$0"` CONTAINER [COMMAND [ARG]...]" 13 | echo "" 14 | echo "Enters the Docker CONTAINER and executes the specified COMMAND." 15 | echo "If COMMAND is not specified, runs an interactive shell in CONTAINER." 16 | echo "" 17 | else 18 | PID=$(docker inspect --format "{{.State.Pid}}" "$1") 19 | [ -z "$PID" ] && exit 1 20 | shift 21 | 22 | if [ "$(id -u)" -ne "0" ]; then 23 | which sudo > /dev/null 24 | if [ "$?" -eq "0" ]; then 25 | LAZY_SUDO="sudo " 26 | else 27 | echo "Warning: Cannot find sudo; Invoking nsenter as the user $USER." >&2 28 | fi 29 | fi 30 | 31 | # Get environment variables from the container's root process 32 | 33 | ENV=$($LAZY_SUDO cat /proc/$PID/environ | xargs -0) 34 | 35 | # Prepare nsenter flags 36 | OPTS="--target $PID --mount --uts --ipc --net --pid --" 37 | 38 | # env is to clear all host environment variables and set then anew 39 | if [ $# -lt 1 ]; then 40 | # No arguments, default to `su` which executes the default login shell 41 | $LAZY_SUDO "$NSENTER" $OPTS env -i - $ENV su -m root 42 | else 43 | # Has command 44 | # "$@" is magic in bash, and needs to be in the invocation 45 | $LAZY_SUDO "$NSENTER" $OPTS env -i - $ENV "$@" 46 | fi 47 | fi -------------------------------------------------------------------------------- /image/resources/root/preinit/30_transform_opencms_configuration.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | CONFIG_FOLDER="${OPENCMS_HOME}/WEB-INF/config/" 4 | XSLT_DIR="/root/preinit/xml-transformations" 5 | echo "Executing XSL transformation of OpenCms config files." 6 | if [ -d "${XSLT_DIR}" ]; then 7 | for XSLT in "${XSLT_DIR}"/*.xslt; do 8 | echo "." 9 | echo "Executing XSL transformation: ${XSLT}" 10 | echo "---------------------------------------------------" 11 | XSLT_NAME=${XSLT##*/} 12 | CONFIG_NAME=$(echo "${XSLT_NAME}"| cut -d'_' -f 1) 13 | if [[ $CONFIG_NAME == "solr-schema" ]]; then 14 | # transformation of the SOLR schema 15 | XML_CONFIG_FILE="${OPENCMS_HOME}/WEB-INF/solr/configsets/default/conf/schema.xml" 16 | else 17 | XML_CONFIG_FILE="${CONFIG_FOLDER}${CONFIG_NAME}.xml" 18 | fi 19 | PARAM_FILE="${XSLT/%.xslt/.params}" 20 | if [ -f "${XML_CONFIG_FILE}" ]; then 21 | if [ -f "${PARAM_FILE}" ]; then 22 | extraparams=$(cat "${PARAM_FILE}") 23 | extraparams=$(eval echo $extraparams) 24 | cat "${XSLT}" | xsltproc --novalid --nonet $extraparams --output "${XML_CONFIG_FILE}" - "${XML_CONFIG_FILE}" 25 | else 26 | cat "${XSLT}" | xsltproc --novalid --nonet --output "${XML_CONFIG_FILE}" - "${XML_CONFIG_FILE}" 27 | fi 28 | else 29 | echo "XML config file ${XML_CONFIG_FILE} does not exist" 30 | fi 31 | echo "---------------------------------------------------" 32 | done 33 | else 34 | echo "Directory ${XSLT_DIR} not available, ignoring!" 35 | fi -------------------------------------------------------------------------------- /image/resources/root/preinit/10-create-setup-properties.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ -f /custom-setup.properties ]; then 4 | echo "Using custom setup properties file:" 5 | echo "OpenCms Setup: Copying /custom-setup.properties to '$CONFIG_FILE'" 6 | cp /custom-setup.properties "$CONFIG_FILE" 7 | else 8 | OCSERVER=${SERVER_URL:-http://localhost} 9 | HWADDR=$(cat /sys/class/net/eth0/address) 10 | 11 | DB_USER=$DB_USER 12 | DB_PWD=$(get_secret DB_PASSWD_FILE DB_PASSWD) 13 | DB_DB=$DB_NAME 14 | DB_PRODUCT=mysql 15 | DB_URL="jdbc:mysql://${DB_HOST}:3306/" 16 | DB_DRIVER=org.gjt.mm.mysql.Driver 17 | 18 | # Create setup.properties 19 | echo "OpenCms Setup: Writing configuration to '$CONFIG_FILE'" 20 | echo "-- Components: $OPENCMS_COMPONENTS" 21 | PROPERTIES=" 22 | 23 | setup.webapp.path=$OPENCMS_HOME 24 | setup.default.webapp= 25 | setup.install.components=$OPENCMS_COMPONENTS 26 | setup.show.progress=true 27 | 28 | db.product=$DB_PRODUCT 29 | db.provider=$DB_PRODUCT 30 | db.create.user=$DB_USER 31 | db.create.pwd=$DB_PWD 32 | db.worker.user=$DB_USER 33 | db.worker.pwd=$DB_PWD 34 | db.connection.url=$DB_URL 35 | db.name=$DB_DB 36 | db.create.db=true 37 | db.create.tables=true 38 | db.dropDb=true 39 | db.default.tablespace= 40 | db.index.tablespace= 41 | db.jdbc.driver=$DB_DRIVER 42 | db.template.db= 43 | db.temporary.tablespace= 44 | 45 | server.url=$OCSERVER 46 | server.name=OpenCmsServer 47 | server.ethernet.address=$HWADDR 48 | server.servlet.mapping= 49 | 50 | " 51 | echo "$PROPERTIES" > $CONFIG_FILE || { echo "Error: Couldn't write to '$CONFIG_FILE'!" ; exit 1 ; } 52 | fi -------------------------------------------------------------------------------- /image/resources/root/wait-for.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | TIMEOUT=15 4 | QUIET=0 5 | 6 | echoerr() { 7 | if [ "$QUIET" -ne 1 ]; then printf "%s\n" "$*" 1>&2; fi 8 | } 9 | 10 | usage() { 11 | exitcode="$1" 12 | cat << USAGE >&2 13 | Usage: 14 | $cmdname host:port [-t timeout] [-- command args] 15 | -q | --quiet Do not output any status messages 16 | -t TIMEOUT | --timeout=timeout Timeout in seconds, zero for no timeout 17 | -- COMMAND ARGS Execute command with args after the test finishes 18 | USAGE 19 | exit "$exitcode" 20 | } 21 | 22 | wait_for() { 23 | for i in `seq $TIMEOUT` ; do 24 | nc -z "$HOST" "$PORT" > /dev/null 2>&1 25 | 26 | result=$? 27 | if [ $result -eq 0 ] ; then 28 | if [ $# -gt 0 ] ; then 29 | exec "$@" 30 | fi 31 | exit 0 32 | fi 33 | sleep 1 34 | done 35 | echo "Operation timed out" >&2 36 | exit 1 37 | } 38 | 39 | while [ $# -gt 0 ] 40 | do 41 | case "$1" in 42 | *:* ) 43 | HOST=$(printf "%s\n" "$1"| cut -d : -f 1) 44 | PORT=$(printf "%s\n" "$1"| cut -d : -f 2) 45 | shift 1 46 | ;; 47 | -q | --quiet) 48 | QUIET=1 49 | shift 1 50 | ;; 51 | -t) 52 | TIMEOUT="$2" 53 | if [ "$TIMEOUT" = "" ]; then break; fi 54 | shift 2 55 | ;; 56 | --timeout=*) 57 | TIMEOUT="${1#*=}" 58 | shift 1 59 | ;; 60 | --) 61 | shift 62 | break 63 | ;; 64 | --help) 65 | usage 0 66 | ;; 67 | *) 68 | echoerr "Unknown argument: $1" 69 | usage 1 70 | ;; 71 | esac 72 | done 73 | 74 | if [ "$HOST" = "" -o "$PORT" = "" ]; then 75 | echoerr "Error: you need to provide a host and port to test." 76 | usage 2 77 | fi 78 | 79 | wait_for "$@" -------------------------------------------------------------------------------- /image/resources/root/opencms-restart.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # OpenCms server restart script 4 | 5 | # We must work around an isse here that exists with Docker and the default Tomcat startup scripts. 6 | # In short, the official "restart" script does not work in a Docker container. This is a known issue. 7 | # Full information on the issue: https://github.com/docker/docker/issues/6800 8 | 9 | WIDTH=$(stty size | cut -d" " -f2) 10 | 11 | echo "." 12 | echo "Restarting OpenCms!" 13 | echo "." 14 | 15 | CONTAINER_PID=$(ps -ef | egrep 'tomcat|jetty' | grep java | awk ' { print $2 } ') 16 | 17 | if [ -z "$CONTAINER_PID" ]; then 18 | echo "Servlet container was not running." 19 | else 20 | kill $(ps -ef | egrep 'tomcat|jetty' | grep java | awk ' { print $2 } ' ) 21 | echo "Killed servlet container." 22 | echo "." 23 | echo "Waiting for a clean shut down..." 24 | echo "." 25 | while kill -0 $CONTAINER_PID > /dev/null 2>&1; do 26 | echo "Servlet container still running ... Here are the last lines of the opencms.log" 27 | tail -20 ${OPENCMS_HOME}/WEB-INF/logs/opencms.log 28 | sleep 5 29 | done 30 | echo "." 31 | echo "Servlet container is shut down ... Here are the last lines of the opencms.log" 32 | tail -20 ${OPENCMS_HOME}/WEB-INF/logs/opencms.log 33 | echo "." 34 | echo "Shut down completed." 35 | fi 36 | echo "." 37 | echo "Starting servlet container again..." 38 | echo "." 39 | 40 | start_container 41 | echo "." 42 | sleep 1 43 | echo "Showing servlet container process via 'ps -ef | grep tomcat | grep java':" 44 | ps -ef | egrep 'tomcat|jetty' | grep java 45 | 46 | echo "." 47 | echo "The ps output above should contain a ${SERVLET_CONTAINER} process." 48 | echo "This means the servlet container is running, even though a [fail] message may have been displayed earlier!" 49 | echo "." 50 | -------------------------------------------------------------------------------- /image/resources/root/preinit/50_opencms_optimize_webxml_tomcat.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ "${SERVLET_CONTAINER}" != "tomcat" ] ; then 4 | echo "Skipping $0 because we are not using Tomcat." 5 | exit 6 | fi 7 | 8 | 9 | CONFIG_WEBXML="${OPENCMS_HOME}/WEB-INF/web.xml" 10 | CONFIG_TMPFILE="/tmp/webxml.txt" 11 | 12 | # Optimize web.xml configuration 13 | if ! grep -q "ExpiresFilter" "$CONFIG_WEBXML" ; then 14 | read -r -d '' REPLACE_WEBXML << EOM 15 | 16 | 21 | 22 | 23 | ExpiresFilter 24 | org.apache.catalina.filters.ExpiresFilter 25 | 26 | ExpiresByType text/css 27 | access plus 24 hours 28 | 29 | 30 | ExpiresByType application/javascript 31 | access plus 24 hours 32 | 33 | 34 | ExpiresDefault 35 | access plus 365 days 36 | 37 | 38 | 39 | 40 | ExpiresFilter 41 | /export/* 42 | REQUEST 43 | 44 | 45 | EOM 46 | 47 | echo "${REPLACE_WEBXML}" > "${CONFIG_TMPFILE}" 48 | 49 | sed -i "/OpenCms<\/display-name>/ r ${CONFIG_TMPFILE}" "${CONFIG_WEBXML}" 50 | 51 | echo "" 52 | echo "Modified web.xml configuration looks like this:" 53 | echo "=================================================================================================" 54 | cat "${CONFIG_WEBXML}" 55 | echo "" 56 | else 57 | echo "web.xml is already modified. Skipping repeated optimization." 58 | fi -------------------------------------------------------------------------------- /image/resources/root/preinit/07_tomcat_setup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ "$SERVLET_CONTAINER" != "tomcat" ]; then 4 | echo "Skipping $0 because we are not using Tomcat" 5 | exit 6 | fi 7 | # Tomcat server configuration 8 | # This is ON PURPOSE done in the init / run phase NOT during image installation phase! 9 | # In case you need a special Tomact configuration in a downsteam image, just overwrite this configuration script. 10 | # Or, you can add the configuration as environment variable TOMCAT_OPTS. 11 | if [ -z "${TOMCAT_OPTS}" ]; then 12 | TOMCAT_OPTS="-Xmx2g -Xms512m -server" 13 | else 14 | TOMCAT_OPTS="${TOMCAT_OPTS}" 15 | fi 16 | 17 | if [ "${DEBUG}" == "true" ]; then 18 | TOMCAT_OPTS="${TOMCAT_OPTS} -Xdebug -Xnoagent -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=*:8000 -Djava.compiler=NONE" 19 | fi 20 | 21 | # By default Tomcat will overwrite session cookies from multiple webapps on the same IP even different ports are used 22 | # With this little 'sed' magic, each running docker instance will attach the ID of the running container to the session cookie name 23 | echo "Making session cookie name unique and disabling web sockets ..." 24 | sed -i "s///" ${TOMCAT_HOME}/conf/context.xml 25 | 26 | # Increasing Tomcat webresources cache size 27 | echo "Setting webresources cache size to override defaults" 28 | sed -i "s/<\/Context>/<\/Context>/" ${TOMCAT_HOME}/conf/context.xml 29 | 30 | # Disabling session persistence 31 | # Disable JAR scanning for servlets and restrict TLD scanning to the JSTL JAR to speed up Tomcat start 32 | echo "Disabling session persistence and adding JAR scanner filter ..." 33 | sed -i "s/<\/Context>/<\/JarScanner><\/Context>/" ${TOMCAT_HOME}/conf/context.xml 34 | 35 | 36 | echo "Setting java opts for Tomcat to: ${TOMCAT_OPTS}" 37 | echo "JAVA_OPTS=\"-Djava.awt.headless=true -DDISPLAY=:0.0 ${TOMCAT_OPTS}\"" > ${TOMCAT_HOME}/bin/setenv.sh 38 | 39 | echo "Using OpenCms optimized server.xml configuration for Tomcat" 40 | mv -v /config/server.xml ${TOMCAT_HOME}/conf/server.xml -------------------------------------------------------------------------------- /image/Dockerfile: -------------------------------------------------------------------------------- 1 | ARG BASE_IMAGE=jetty:12-jdk21 2 | FROM $BASE_IMAGE 3 | LABEL org.opencontainers.image.authors="Alkacon Software GmbH & Co. KG" 4 | USER root 5 | ARG SERVLET_CONTAINER=jetty 6 | ENV SERVLET_CONTAINER=${SERVLET_CONTAINER} 7 | 8 | # 9 | # This Dockerfile installs a simple OpenCms demo system. 10 | # It downloads the OpenCms distro and installs it with all the standard demo modules. 11 | # 12 | # You should run it in combination with a mysql container, as specified in the docker-compose.yaml 13 | # coming with this repository. 14 | # 15 | 16 | # Variables used in the shell scripts loaded from the file system 17 | ENV DEBIAN_FRONTEND=noninteractive \ 18 | TMPDIR=/tmp 19 | 20 | ENV CONTAINER_BASE=/container \ 21 | TOMCAT_HOME=/usr/local/tomcat \ 22 | JETTY_HOME=/usr/local/jetty \ 23 | BASH_ENV=/root/common.sh 24 | 25 | ENV TOMCAT_LIB=${TOMCAT_HOME}/lib \ 26 | JETTY_LIB=${JETTY_HOME}/lib \ 27 | WEBAPPS_HOME=${CONTAINER_BASE}/webapps \ 28 | OPENCMS_HOME=${CONTAINER_BASE}/webapps/ROOT \ 29 | ARTIFACTS_FOLDER=/artifacts/ \ 30 | CONFIG_FILE=/config/setup.properties \ 31 | OPENCMS_URL=https://github.com/alkacon/opencms-core/releases/download/build_20_0_0/opencms-20.0-distribution.zip \ 32 | OPENCMS_COMPONENTS=workplace,demo \ 33 | UPDATE_CONFIG_FILES="WEB-INF/web.xml WEB-INF/opencms.tld WEB-INF/config/opencms-search.xml WEB-INF/config/opencms-system.xml WEB-INF/config/opencms-vfs.xml WEB-INF/config/opencms-workplace.xml WEB-INF/solr/configsets/default/conf/solrconfig.xml WEB-INF/solr/spellcheck/conf/solrconfig.xml"\ 34 | TIME_ZONE=Europe/Berlin \ 35 | JETTY_OPTS="-Xmx2g" \ 36 | TOMCAT_OPTS= \ 37 | ADMIN_PASSWD=admin \ 38 | ADMIN_PASSWD_FILE= \ 39 | DB_HOST=mysql \ 40 | DB_NAME=opencms \ 41 | DB_USER=root \ 42 | DB_PASSWD= \ 43 | DB_PASSWD_FILE= \ 44 | WEBRESOURCES_CACHE_SIZE=200000 \ 45 | DEBUG=false 46 | 47 | RUN \ 48 | echo "Update the apt packet repos" && \ 49 | apt-get update && \ 50 | echo "Install utils" && \ 51 | apt-get install -yq --no-install-recommends procps wget unzip xsltproc netcat-openbsd && \ 52 | echo "Clean up apt" && \ 53 | rm -rf /var/lib/apt/lists/* && \ 54 | apt-get autoremove && \ 55 | apt-get clean 56 | 57 | # Create the setup configuration file 58 | COPY resources / 59 | 60 | RUN \ 61 | echo "Make scripts under /root/ executable" && \ 62 | chmod +x /root/*.sh && \ 63 | echo "Update .bashrc" && \ 64 | echo "source /root/common.sh" >> /root/.bashrc && \ 65 | bash /root/opencms-fetch.sh && \ 66 | rm -rf ${WEBAPPS_HOME}/* 67 | 68 | # Expose port 8080 for Tomcat and define the startup script 69 | EXPOSE 8080 70 | WORKDIR $CONTAINER_BASE 71 | CMD ["/root/opencms-run.sh"] 72 | -------------------------------------------------------------------------------- /image/resources/root/common.sh: -------------------------------------------------------------------------------- 1 | # common shell functions for use in other scripts 2 | # (Included via BASH_ENV for noninteractive bash shells and is sourced in .bashrc for interactive ones) 3 | 4 | function get_secret() { 5 | if [ -z "${1+x}" ] || [ -z "${2+x}" ]; then 6 | echo "Two args required." 7 | return 1 8 | fi 9 | if [[ "$1" != *_FILE ]]; then 10 | echo "Arg 1 must end with the _FILE suffix." 11 | return 1 12 | fi 13 | local sec_file="$1" 14 | local sec_env="$2" 15 | if [[ -n "${!sec_file}" ]]; then 16 | if [[ -f "${!sec_file}" ]]; then 17 | local password 18 | password=$(<"${!sec_file}") 19 | echo "${password}" | xargs 20 | else 21 | echo "File ${sec_file}=${!sec_file} not found." 22 | fi 23 | elif [[ -n "${!sec_env}" ]]; then 24 | echo "${!sec_env}" 25 | else 26 | echo "Either ${sec_file} or ${sec_env} must be set." 27 | return 1 28 | fi 29 | } 30 | 31 | function shell_classpath() { 32 | if [ "${SERVLET_CONTAINER}" == "tomcat" ]; then 33 | echo "${OPENCMS_HOME}/WEB-INF/lib/*:${OPENCMS_HOME}/WEB-INF/classes:${TOMCAT_LIB}/*" 34 | elif [ "${SERVLET_CONTAINER}" == "jetty" ]; then 35 | # Jetty libraries in OpenCms which are needed for Solr would cause a version conflict with the libraries included in Jetty, 36 | # so we have to specifically only include the servlet/JSP API libs in the CmsShell classpath. 37 | local SERVLET_API=$(find ${JETTY_LIB} -maxdepth 1 -name 'jetty-servlet-api*.jar' | head -1) 38 | echo "${OPENCMS_HOME}/WEB-INF/lib/*:${OPENCMS_HOME}/WEB-INF/classes:$SERVLET_API:${JETTY_HOME}/lib/ee8-apache-jsp/*" 39 | fi 40 | } 41 | 42 | function start_container() { 43 | if [ "${SERVLET_CONTAINER}" == "tomcat" ] ; then 44 | start_tomcat 45 | elif [ "${SERVLET_CONTAINER}" == "jetty" ] ; then 46 | start_jetty 47 | fi 48 | } 49 | 50 | function start_tomcat() { 51 | ${TOMCAT_HOME}/bin/catalina.sh run >> ${TOMCAT_HOME}/logs/catalina.out 2>&1 & 52 | } 53 | 54 | function start_jetty() { 55 | cd $CONTAINER_BASE 56 | java $(jetty_opts) -jar $JETTY_HOME/start.jar >> ${CONTAINER_BASE}/jetty.out 2>&1 & 57 | } 58 | 59 | function kill_container() { 60 | local pid="" 61 | if [ -d $TOMCAT_HOME ] ; then 62 | pid=$(pgrep -f org.apache.catalina.startup.Bootstrap) 63 | else 64 | pid=$(pgrep -f $JETTY_HOME/start.jar) 65 | fi 66 | if [[ ! -z "$pid" ]] ; then 67 | kill -TERM "$pid" 68 | wait "$pid" >/dev/null 69 | fi 70 | } 71 | 72 | function jetty_opts() { 73 | local OPTS="-server -Djava.awt.headless=true -XX:-OmitStackTraceInFastThrow -DDISPLAY=:0.0" 74 | if [ "$DEBUG" == "true" ]; then 75 | OPTS="$OPTS -Xdebug -Xnoagent -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=*:8000 -Djava.compiler=NONE" 76 | fi 77 | OPTS="$OPTS $(cat $CONTAINER_BASE/jetty-opts.txt)" 78 | echo "$OPTS" 79 | } 80 | 81 | 82 | 83 | -------------------------------------------------------------------------------- /scripts/opencms-mount.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Mount OpenCms with SAMBA. 4 | # 5 | 6 | 7 | ################## 8 | # 9 | # Display usage info. 10 | # 11 | showUsage() { 12 | echo "" 13 | echo "${red}Usage: `basename "${0}"` ${bold}[OPTIONS]${normal}" 14 | echo "" 15 | echo "Supported command line ${bold}[OPTION]${normal}s:" 16 | echo "${bold} -f FILENAME ${normal}Process given file for parameters, e.g. '~/docker-1'." 17 | echo "${bold} -t TARGET ${normal}Mount on the given target folder '/mnt/mymount/' (${OCMOUNT_TARGET})." 18 | echo "${bold} -s SOURCE ${normal}Mount the given remote folter, e.g. '//docker-1/OCMOUNTS' (${OCMOUNT_SOURCE})." 19 | echo "${bold} -u USER ${normal}Username to use for login, eg. 'Admin' (${OCMOUNT_USER})." 20 | echo "${bold} -p PASSWORD ${normal}Password to use for login, eg. 'admin' (${OCMOUNT_PWD})." 21 | echo "${bold} -i ID ${normal}Used as user and group name for local mounting, e.g. 'root' (${OCMOUNT_ID})." 22 | echo "${bold} -o PORT ${normal}Port to connect to, eg. '1445' (${OCMOUNT_PORT})." 23 | echo "${normal}" 24 | exit 1 25 | } 26 | 27 | ################## 28 | # 29 | # Check for empty parameter. 30 | # 31 | checkEmpty() { 32 | for i in "$@"; do 33 | eval local PARAM="\${${i}}" 34 | if [ -z "${PARAM}" ]; then 35 | showUsage 36 | fi 37 | shift 38 | done 39 | } 40 | 41 | ################## 42 | # 43 | # Set env variable for options. 44 | # 45 | setOptions() { 46 | 47 | # check if stdout is a terminal... 48 | if test -t 1; then 49 | # see if it supports colors... 50 | NCOLORS=$(tput colors) 51 | if test -n "${NCOLORS}" && test ${NCOLORS} -ge 8; then 52 | bold="$(tput bold)" 53 | underline="$(tput smul)" 54 | standout="$(tput smso)" 55 | normal="$(tput sgr0)" 56 | black="$(tput setaf 0)" 57 | red="$(tput setaf 1)" 58 | green="$(tput setaf 2)" 59 | yellow="$(tput setaf 3)" 60 | blue="$(tput setaf 4)" 61 | magenta="$(tput setaf 5)" 62 | cyan="$(tput setaf 6)" 63 | white="$(tput setaf 7)" 64 | fi 65 | fi 66 | 67 | # OCMOUNT_TARGET="${OCMOUNT_TARGET:-/mnt/opencms/vfs/}" 68 | # OCMOUNT_SOURCE="${OCMOUNT_SOURCE:-//localhost/OPENCMS}" 69 | OCMOUNT_USER="${OCMOUNT_USER:-Admin}" 70 | OCMOUNT_PWD="${OCMOUNT_PWD:-admin}" 71 | OCMOUNT_ID="${OCMOUNT_ID:-$USER}" 72 | OCMOUNT_PORT="${OCMOUNT_PORT:-445}" 73 | 74 | while true; do 75 | case "${1}" in 76 | -f | --file ) 77 | OCMOUNT_PARAMFILE="${2}" 78 | source ${OCMOUNT_PARAMFILE} 79 | shift 2 ;; 80 | -t | --target ) 81 | OCMOUNT_TARGET="${2}" 82 | shift 2 ;; 83 | -s | --source ) 84 | OCMOUNT_SOURCE="${2}" 85 | shift 2 ;; 86 | -u | --user ) 87 | OCMOUNT_USER="${2}" 88 | shift 2 ;; 89 | -p | --pwd | --password ) 90 | OCMOUNT_PWD="${2}" 91 | shift 2 ;; 92 | -i | --id ) 93 | OCMOUNT_ID="${2}" 94 | shift 2 ;; 95 | -o | --port ) 96 | OCMOUNT_PORT="${2}" 97 | shift 2 ;; 98 | "" ) break ;; 99 | * ) 100 | echo "Invalid [OPTION] \"${1}\" provided!" 101 | showUsage 102 | break ;; 103 | esac 104 | done 105 | 106 | checkEmpty "OCMOUNT_TARGET" "OCMOUNT_SOURCE" "OCMOUNT_USER" "OCMOUNT_PWD" "OCMOUNT_ID" "OCMOUNT_PORT" 107 | } 108 | 109 | setOptions "${@}" 110 | 111 | MNT_PARAM="-v -t cifs -o uid=${OCMOUNT_ID},gid=${OCMOUNT_ID},username=${OCMOUNT_USER},password=${OCMOUNT_PWD},port=${OCMOUNT_PORT} ${OCMOUNT_SOURCE} ${OCMOUNT_TARGET}" 112 | 113 | # the command to execute 114 | MNT_CMD="sudo mount ${MNT_PARAM}" 115 | 116 | echo "" 117 | echo "${green}${bold}Executing: ${cyan}" 118 | echo "sudo umount -v -l -f ${OCMOUNT_TARGET}" 119 | echo "${MNT_CMD}" 120 | echo "ls -la ${OCMOUNT_TARGET}" 121 | echo "${normal}" 122 | 123 | sudo umount -v -l -f ${OCMOUNT_TARGET} 124 | bash -c "${MNT_CMD}" 125 | ls -la ${OCMOUNT_TARGET} 126 | -------------------------------------------------------------------------------- /image/resources/root/preinit/20_check_install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | if [ ! -d ${ARTIFACTS_FOLDER}libs ]; then 3 | mkdir -v -p ${ARTIFACTS_FOLDER}libs 4 | fi 5 | 6 | echo "Writing properties file to contain list of JARs used by the OpenCms core, to be used in later updates." 7 | JAR_NAMES=$( zipinfo -1 ${ARTIFACTS_FOLDER}opencms.war *.jar | tr '\n' ',' ) 8 | JAR_NAMES_PROPERTIES="OPENCMS_CORE_LIBS=$JAR_NAMES" 9 | JAR_NAMES_PROPERTIES_FILE=${ARTIFACTS_FOLDER}libs/core-libs.properties 10 | echo "$JAR_NAMES_PROPERTIES" > $JAR_NAMES_PROPERTIES_FILE 11 | 12 | if [ -f "${OPENCMS_HOME}/WEB-INF/lib/opencms.jar" ] 13 | then 14 | echo "OpenCms already installed, updating modules and libs" 15 | 16 | admin_passwd=$(get_secret ADMIN_PASSWD_FILE ADMIN_PASSWD) 17 | if [ ! -z "$admin_passwd" ]; then 18 | echo "Changing Admin password for update" 19 | sed -i -- "s/Admin admin/\"Admin\" \"${admin_passwd}\"/g" /config/update* 20 | fi 21 | 22 | echo "Extract modules and libs" 23 | unzip -q -d ${ARTIFACTS_FOLDER}TEMP ${ARTIFACTS_FOLDER}opencms.war 24 | mv ${ARTIFACTS_FOLDER}TEMP/WEB-INF/packages/modules/* ${ARTIFACTS_FOLDER} 25 | 26 | mv ${ARTIFACTS_FOLDER}TEMP/WEB-INF/lib/* ${ARTIFACTS_FOLDER}libs 27 | echo "Renaming modules to remove version number" 28 | for file in ${ARTIFACTS_FOLDER}*.zip 29 | do 30 | if [[ $file =~ .*-.*\.zip ]]; then 31 | mv $file ${file%-*}".zip" 32 | fi 33 | done 34 | echo "Creating backup of opencms-modules.xml at ${OPENCMS_HOME}/WEB-INF/config/backups/opencms-modules-preinst.xml" 35 | if [ ! -d ${OPENCMS_HOME}/WEB-INF/config/backups ]; then 36 | mkdir -v -p ${OPENCMS_HOME}/WEB-INF/config/backups 37 | fi 38 | cp -f -v ${OPENCMS_HOME}/WEB-INF/config/opencms-modules.xml ${OPENCMS_HOME}/WEB-INF/config/backups/opencms-modules-preinst.xml 39 | 40 | echo "Updating config files with the version from the OpenCms WAR" 41 | unzip -q -d ${OPENCMS_HOME} ${ARTIFACTS_FOLDER}opencms.war WEB-INF/packages/modules/*.zip WEB-INF/lib/*.jar 42 | IFS=',' read -r -a FILES <<< "$UPDATE_CONFIG_FILES" 43 | for FILENAME in ${FILES[@]} 44 | do 45 | if [ -f "${OPENCMS_HOME}/${FILENAME}" ] 46 | then 47 | rm -rf "${OPENCMS_HOME}/${FILENAME}" 48 | fi 49 | echo "Moving file from \"${ARTIFACTS_FOLDER}TEMP/${FILENAME}\" to \"${OPENCMS_HOME}/${FILENAME}\" ..." 50 | mv "${ARTIFACTS_FOLDER}TEMP/${FILENAME}" "${OPENCMS_HOME}/${FILENAME}" 51 | done 52 | 53 | echo "Updating OpenCms core JARs" 54 | if [ -f ${OPENCMS_HOME}/WEB-INF/lib/core-libs.properties ]; then 55 | echo "Deleting old JARs first" 56 | while IFS='=' read -r key value 57 | do 58 | key=$(echo $key | tr '.' '_') 59 | eval ${key}=\${value} 60 | done < "${OPENCMS_HOME}/WEB-INF/lib/core-libs.properties" 61 | 62 | IFS=',' read -r -a CORE_LIBS <<< "$OPENCMS_CORE_LIBS" 63 | for CORE_LIB in ${CORE_LIBS[@]} 64 | do 65 | rm -f -v ${OPENCMS_HOME}/${CORE_LIB} 66 | done 67 | fi 68 | echo "Moving new JARs" 69 | mv ${ARTIFACTS_FOLDER}libs/* ${OPENCMS_HOME}/WEB-INF/lib/ 70 | 71 | echo "Update modules core" 72 | bash /root/execute-opencms-shell.sh /config/update-core-modules.ocsh 73 | else 74 | echo "OpenCms not installed yet, running setup" 75 | if [ ! -d ${WEBAPPS_HOME} ]; then 76 | mkdir -v -p ${WEBAPPS_HOME} 77 | fi 78 | 79 | if [ ! -d ${OPENCMS_HOME} ]; then 80 | mkdir -v -p ${OPENCMS_HOME} 81 | fi 82 | 83 | echo "Unzip the .war" 84 | unzip -q -d ${OPENCMS_HOME} ${ARTIFACTS_FOLDER}opencms.war 85 | mv ${ARTIFACTS_FOLDER}libs/core-libs.properties ${OPENCMS_HOME}/WEB-INF/lib 86 | if [ ! -z "$ADMIN_PASSWD" ]; then 87 | echo "Changing Admin password for setup" 88 | sed -i -- "s/login \"Admin\" \"admin\"/login \"Admin\" \"admin\"\nsetPassword \"Admin\" \"$ADMIN_PASSWD\"\nlogin \"Admin\" \"$ADMIN_PASSWD\"/g" "${OPENCMS_HOME}/WEB-INF/setupdata/cmssetup.txt" 89 | fi 90 | 91 | CLASSPATH="$(shell_classpath)" 92 | echo "Install OpenCms using org.opencms.setup.CmsAutoSetup with properties \"${CONFIG_FILE}\"" && \ 93 | echo "Classpath: $CLASSPATH" && \ 94 | java -classpath "${CLASSPATH}" org.opencms.setup.CmsAutoSetup -path ${CONFIG_FILE} 95 | 96 | echo "Deleting no longer used files" 97 | rm -rf ${OPENCMS_HOME}/setup 98 | rm -rf ${OPENCMS_HOME}/WEB-INF/packages/modules/*.zip 99 | fi 100 | 101 | echo "Deleting artifacts folder" 102 | rm -rf ${ARTIFACTS_FOLDER} 103 | rm -rf ${OPENCMS_HOME}/setup -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | OpenCms logo 4 | 5 |

6 | 7 | # Official OpenCms Docker Image 8 | 9 | Welcome to the official OpenCms Docker image maintained by [Alkacon](https://github.com/alkacon/). 10 | 11 | Here you find a Docker Compose setup with a ready to use OpenCms installation including Jetty and MariaDB. 12 | 13 | OpenCms can be used with other databases as described below. 14 | 15 | ## Available tags 16 | 17 | * [latest, 20.1](https://github.com/alkacon/opencms-docker/blob/20.1/image/Dockerfile) 18 | * [20.0](https://github.com/alkacon/opencms-docker/blob/20.0/image/Dockerfile) 19 | * [19.0](https://github.com/alkacon/opencms-docker/blob/19.0/image/Dockerfile) 20 | * [18.0](https://github.com/alkacon/opencms-docker/blob/18.0/image/Dockerfile) 21 | * [17.0](https://github.com/alkacon/opencms-docker/blob/17.0/image/Dockerfile) 22 | * [16.0](https://github.com/alkacon/opencms-docker/blob/16.0/image/Dockerfile) 23 | * [15.0](https://github.com/alkacon/opencms-docker/blob/15.0/image/Dockerfile) 24 | * [14.0](https://github.com/alkacon/opencms-docker/blob/14.0/image/Dockerfile) 25 | * [13.0](https://github.com/alkacon/opencms-docker/blob/13.0/image/Dockerfile) 26 | * [12.0](https://github.com/alkacon/opencms-docker/blob/12.0/image/Dockerfile) 27 | * [11.0.2](https://github.com/alkacon/opencms-docker/blob/11.0.2/image/Dockerfile) 28 | * [11.0.1](https://github.com/alkacon/opencms-docker/blob/11.0.1/image/Dockerfile) 29 | * [11.0.0](https://github.com/alkacon/opencms-docker/blob/11.0.0/image/Dockerfile) 30 | 31 | Images for older OpenCms versions are also available, see [here](https://github.com/alkacon/opencms-docker/blob/pre_11_images/README.md). 32 | 33 | ## How to use this image 34 | 35 | ### Step 1: docker-compose.yml 36 | 37 | Save the following *docker-compose.yml* file to your host machine. 38 | 39 | ``` 40 | services: 41 | mariadb: 42 | image: mariadb:latest 43 | container_name: mariadb 44 | init: true 45 | restart: always 46 | volumes: 47 | - ~/dockermount/opencms-docker-mysql:/var/lib/mysql 48 | environment: 49 | - "MYSQL_ROOT_PASSWORD=secretDBpassword" 50 | opencms: 51 | image: alkacon/opencms-docker:20.1 52 | container_name: opencms 53 | init: true 54 | restart: always 55 | depends_on: [ "mariadb" ] 56 | links: 57 | - "mariadb:mysql" 58 | ports: 59 | - "80:8080" 60 | volumes: 61 | - ~/dockermount/opencms-docker-webapps:/container/webapps 62 | command: ["/root/wait-for.sh", "mysql:3306", "-t", "30", "--", "/root/opencms-run.sh"] 63 | environment: 64 | - "DB_PASSWD=secretDBpassword" 65 | ``` 66 | 67 | Change the MariaDB root password `secretDBpassword`. 68 | 69 | ### Step 2: Persist data 70 | 71 | Adjust the following directories for your host system: 72 | 73 | * `~/dockermount/opencms-docker-mysql` the directory where all MariaDB data are persisted 74 | * `~/dockermount/opencms-docker-webapps` the Tomcat webapps directory that contains important configurations, caches and indices of OpenCms 75 | 76 | Configured in this way, it is possible to upgrade the `opencms` and `mariadb` containers while keeping all your OpenCms and MariaDB data. See the upgrade guide below. 77 | 78 | On the other hand, if you like to start with a completely fresh OpenCms installation, do not forget to delete both mounted directories before. 79 | 80 | ### Step 3: Start OpenCms and MariaDB 81 | 82 | Navigate to the folder with the *docker-compose.yml* file and execute `docker-compose up -d`. 83 | 84 | Startup will take a while since numerous modules are installed. 85 | 86 | You can follow the installation process with `docker-compose logs -f opencms`. 87 | 88 | ### Step 4: Login to OpenCms 89 | 90 | When the containers are set up, you can access the OpenCms workplace via `http://localhost/system/login`. 91 | 92 | The default account is username `Admin` with password `admin`. 93 | 94 | ## Environment variables 95 | 96 | In addition to `DB_PASSWD`, the following environment variables are supported: 97 | 98 | * `DB_HOST`, the database host name, defaults to `mysql` 99 | * `DB_USER`, the database user, default is `root` 100 | * `DB_PASSWD`, the database password, is not set by default 101 | * `DB_PASSWD_FILE`, file in the container where the database password is stored (`/run/secrets/`); to be used with docker compose `secrets` 102 | * `DB_NAME`, the database name, default is `opencms` 103 | * `ADMIN_PASSWD`, the admin password, defaults to `admin` 104 | * `ADMIN_PASSWD_FILE`, file in the container where the admin password is stored (`/run/secrets/`); to be used with docker compose `secrets` 105 | * `OPENCMS_COMPONENTS`, the OpenCms components to install, default is `workplace,demo`; to not install the demo template use `workplace` 106 | * `JETTY_OPTS`, the Jetty startup options (in addition to predefined options), default is `-Xmx2g` 107 | * `DEBUG`, flag indicating whether to enable verbose debug logging and allowing connections via {docker ip address}:8000, defaults to `false` 108 | * `JSONAPI`, flag indicating whether to enable the JSON API, default is `false` 109 | * `SERVER_URL`, the server URL, default is `http://localhost` 110 | 111 | The variables `DB_PASSWD` and `DB_PASSWD_FILE` respectively `ADMIN_PASSWD` and `ADMIN_PASSWD_FILE` are alternatives. Read more about docker compose secrets [here](https://docs.docker.com/compose/how-tos/use-secrets/). 112 | 113 | ## Upgrade the image 114 | 115 | *Before upgrading the image, make sure that you have persisted your OpenCms data and MariaDB data with Docker volumes as described above. Otherwise you will lose your data.* 116 | 117 | *When upgrading from an older version of this image, read the image history below at first.* 118 | 119 | Enter the target version of the OpenCms image in your docker-compose.yml file. 120 | 121 | ``` 122 | opencms: 123 | image: alkacon/opencms-docker:20.1 124 | ``` 125 | 126 | Navigate to the folder with the docker-compose.yml file and execute `docker-compose up -d`. 127 | 128 | During startup, the Docker setup will update several modules as well as JAR files and configurations in the `/container/webapps` directory. 129 | 130 | You can follow the installation process with `docker compose logs -f opencms`. 131 | 132 | *It is recommended to remove the* `/container/webapps/ROOT/WEB-INF/index` *folder after upgrade and do a full Solr reindex.* 133 | 134 | ## Support for other databases 135 | 136 | OpenCms uses a special configuration file called [setup.properties](https://github.com/alkacon/opencms-core/blob/master/src-setup/org/opencms/setup/setup.properties.example) to establish a database connection. 137 | 138 | In order to connect to a database other than MariaDB, this image supports connection via a custom *setup.properties* file. 139 | 140 | The file must be named `custom-setup.properties` and must be available in the root folder of the docker container. 141 | 142 | An example setup for PostgreSQL can be found [here](https://github.com/alkacon/opencms-docker/tree/master/compose/postgres). 143 | 144 | For more information on the DB configuration options, see the [OpenCms documentation](https://documentation.opencms.org/opencms-documentation/server-administration/headless-installation/). 145 | 146 | Note: when using a custom configuration file, the environment variables `DB_HOST, DB_USER, DB_PASSWD, DB_NAME, OPENCMS_COMPONENTS, SERVER_URL` are ignored. 147 | 148 | ## Building the image 149 | 150 | Since the image is available on Docker Hub, you do not need to build it yourself. If you want to build it anyway, here's how to do it: 151 | 152 | Download the [opencms-docker](https://github.com/alkacon/opencms-docker) repository. 153 | 154 | Go to the repository's main folder and type `docker compose build opencms`. 155 | 156 | ## License 157 | 158 | View the [licence information on GitHub](https://github.com/alkacon/opencms-docker/blob/master/LICENSE). 159 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 2.1, February 1999 3 | 4 | Copyright (C) 1991, 1999 Free Software Foundation, Inc. 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | (This is the first released version of the Lesser GPL. It also counts 10 | as the successor of the GNU Library Public License, version 2, hence 11 | the version number 2.1.) 12 | 13 | Preamble 14 | 15 | The licenses for most software are designed to take away your 16 | freedom to share and change it. By contrast, the GNU General Public 17 | Licenses are intended to guarantee your freedom to share and change 18 | free software--to make sure the software is free for all its users. 19 | 20 | This license, the Lesser General Public License, applies to some 21 | specially designated software packages--typically libraries--of the 22 | Free Software Foundation and other authors who decide to use it. You 23 | can use it too, but we suggest you first think carefully about whether 24 | this license or the ordinary General Public License is the better 25 | strategy to use in any particular case, based on the explanations below. 26 | 27 | When we speak of free software, we are referring to freedom of use, 28 | not price. Our General Public Licenses are designed to make sure that 29 | you have the freedom to distribute copies of free software (and charge 30 | for this service if you wish); that you receive source code or can get 31 | it if you want it; that you can change the software and use pieces of 32 | it in new free programs; and that you are informed that you can do 33 | these things. 34 | 35 | To protect your rights, we need to make restrictions that forbid 36 | distributors to deny you these rights or to ask you to surrender these 37 | rights. These restrictions translate to certain responsibilities for 38 | you if you distribute copies of the library or if you modify it. 39 | 40 | For example, if you distribute copies of the library, whether gratis 41 | or for a fee, you must give the recipients all the rights that we gave 42 | you. You must make sure that they, too, receive or can get the source 43 | code. If you link other code with the library, you must provide 44 | complete object files to the recipients, so that they can relink them 45 | with the library after making changes to the library and recompiling 46 | it. And you must show them these terms so they know their rights. 47 | 48 | We protect your rights with a two-step method: (1) we copyright the 49 | library, and (2) we offer you this license, which gives you legal 50 | permission to copy, distribute and/or modify the library. 51 | 52 | To protect each distributor, we want to make it very clear that 53 | there is no warranty for the free library. Also, if the library is 54 | modified by someone else and passed on, the recipients should know 55 | that what they have is not the original version, so that the original 56 | author's reputation will not be affected by problems that might be 57 | introduced by others. 58 | 59 | Finally, software patents pose a constant threat to the existence of 60 | any free program. We wish to make sure that a company cannot 61 | effectively restrict the users of a free program by obtaining a 62 | restrictive license from a patent holder. Therefore, we insist that 63 | any patent license obtained for a version of the library must be 64 | consistent with the full freedom of use specified in this license. 65 | 66 | Most GNU software, including some libraries, is covered by the 67 | ordinary GNU General Public License. This license, the GNU Lesser 68 | General Public License, applies to certain designated libraries, and 69 | is quite different from the ordinary General Public License. We use 70 | this license for certain libraries in order to permit linking those 71 | libraries into non-free programs. 72 | 73 | When a program is linked with a library, whether statically or using 74 | a shared library, the combination of the two is legally speaking a 75 | combined work, a derivative of the original library. The ordinary 76 | General Public License therefore permits such linking only if the 77 | entire combination fits its criteria of freedom. The Lesser General 78 | Public License permits more lax criteria for linking other code with 79 | the library. 80 | 81 | We call this license the "Lesser" General Public License because it 82 | does Less to protect the user's freedom than the ordinary General 83 | Public License. It also provides other free software developers Less 84 | of an advantage over competing non-free programs. These disadvantages 85 | are the reason we use the ordinary General Public License for many 86 | libraries. However, the Lesser license provides advantages in certain 87 | special circumstances. 88 | 89 | For example, on rare occasions, there may be a special need to 90 | encourage the widest possible use of a certain library, so that it becomes 91 | a de-facto standard. To achieve this, non-free programs must be 92 | allowed to use the library. A more frequent case is that a free 93 | library does the same job as widely used non-free libraries. In this 94 | case, there is little to gain by limiting the free library to free 95 | software only, so we use the Lesser General Public License. 96 | 97 | In other cases, permission to use a particular library in non-free 98 | programs enables a greater number of people to use a large body of 99 | free software. For example, permission to use the GNU C Library in 100 | non-free programs enables many more people to use the whole GNU 101 | operating system, as well as its variant, the GNU/Linux operating 102 | system. 103 | 104 | Although the Lesser General Public License is Less protective of the 105 | users' freedom, it does ensure that the user of a program that is 106 | linked with the Library has the freedom and the wherewithal to run 107 | that program using a modified version of the Library. 108 | 109 | The precise terms and conditions for copying, distribution and 110 | modification follow. Pay close attention to the difference between a 111 | "work based on the library" and a "work that uses the library". The 112 | former contains code derived from the library, whereas the latter must 113 | be combined with the library in order to run. 114 | 115 | GNU LESSER GENERAL PUBLIC LICENSE 116 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 117 | 118 | 0. This License Agreement applies to any software library or other 119 | program which contains a notice placed by the copyright holder or 120 | other authorized party saying it may be distributed under the terms of 121 | this Lesser General Public License (also called "this License"). 122 | Each licensee is addressed as "you". 123 | 124 | A "library" means a collection of software functions and/or data 125 | prepared so as to be conveniently linked with application programs 126 | (which use some of those functions and data) to form executables. 127 | 128 | The "Library", below, refers to any such software library or work 129 | which has been distributed under these terms. A "work based on the 130 | Library" means either the Library or any derivative work under 131 | copyright law: that is to say, a work containing the Library or a 132 | portion of it, either verbatim or with modifications and/or translated 133 | straightforwardly into another language. (Hereinafter, translation is 134 | included without limitation in the term "modification".) 135 | 136 | "Source code" for a work means the preferred form of the work for 137 | making modifications to it. For a library, complete source code means 138 | all the source code for all modules it contains, plus any associated 139 | interface definition files, plus the scripts used to control compilation 140 | and installation of the library. 141 | 142 | Activities other than copying, distribution and modification are not 143 | covered by this License; they are outside its scope. The act of 144 | running a program using the Library is not restricted, and output from 145 | such a program is covered only if its contents constitute a work based 146 | on the Library (independent of the use of the Library in a tool for 147 | writing it). Whether that is true depends on what the Library does 148 | and what the program that uses the Library does. 149 | 150 | 1. You may copy and distribute verbatim copies of the Library's 151 | complete source code as you receive it, in any medium, provided that 152 | you conspicuously and appropriately publish on each copy an 153 | appropriate copyright notice and disclaimer of warranty; keep intact 154 | all the notices that refer to this License and to the absence of any 155 | warranty; and distribute a copy of this License along with the 156 | Library. 157 | 158 | You may charge a fee for the physical act of transferring a copy, 159 | and you may at your option offer warranty protection in exchange for a 160 | fee. 161 | 162 | 2. You may modify your copy or copies of the Library or any portion 163 | of it, thus forming a work based on the Library, and copy and 164 | distribute such modifications or work under the terms of Section 1 165 | above, provided that you also meet all of these conditions: 166 | 167 | a) The modified work must itself be a software library. 168 | 169 | b) You must cause the files modified to carry prominent notices 170 | stating that you changed the files and the date of any change. 171 | 172 | c) You must cause the whole of the work to be licensed at no 173 | charge to all third parties under the terms of this License. 174 | 175 | d) If a facility in the modified Library refers to a function or a 176 | table of data to be supplied by an application program that uses 177 | the facility, other than as an argument passed when the facility 178 | is invoked, then you must make a good faith effort to ensure that, 179 | in the event an application does not supply such function or 180 | table, the facility still operates, and performs whatever part of 181 | its purpose remains meaningful. 182 | 183 | (For example, a function in a library to compute square roots has 184 | a purpose that is entirely well-defined independent of the 185 | application. Therefore, Subsection 2d requires that any 186 | application-supplied function or table used by this function must 187 | be optional: if the application does not supply it, the square 188 | root function must still compute square roots.) 189 | 190 | These requirements apply to the modified work as a whole. If 191 | identifiable sections of that work are not derived from the Library, 192 | and can be reasonably considered independent and separate works in 193 | themselves, then this License, and its terms, do not apply to those 194 | sections when you distribute them as separate works. But when you 195 | distribute the same sections as part of a whole which is a work based 196 | on the Library, the distribution of the whole must be on the terms of 197 | this License, whose permissions for other licensees extend to the 198 | entire whole, and thus to each and every part regardless of who wrote 199 | it. 200 | 201 | Thus, it is not the intent of this section to claim rights or contest 202 | your rights to work written entirely by you; rather, the intent is to 203 | exercise the right to control the distribution of derivative or 204 | collective works based on the Library. 205 | 206 | In addition, mere aggregation of another work not based on the Library 207 | with the Library (or with a work based on the Library) on a volume of 208 | a storage or distribution medium does not bring the other work under 209 | the scope of this License. 210 | 211 | 3. You may opt to apply the terms of the ordinary GNU General Public 212 | License instead of this License to a given copy of the Library. To do 213 | this, you must alter all the notices that refer to this License, so 214 | that they refer to the ordinary GNU General Public License, version 2, 215 | instead of to this License. (If a newer version than version 2 of the 216 | ordinary GNU General Public License has appeared, then you can specify 217 | that version instead if you wish.) Do not make any other change in 218 | these notices. 219 | 220 | Once this change is made in a given copy, it is irreversible for 221 | that copy, so the ordinary GNU General Public License applies to all 222 | subsequent copies and derivative works made from that copy. 223 | 224 | This option is useful when you wish to copy part of the code of 225 | the Library into a program that is not a library. 226 | 227 | 4. You may copy and distribute the Library (or a portion or 228 | derivative of it, under Section 2) in object code or executable form 229 | under the terms of Sections 1 and 2 above provided that you accompany 230 | it with the complete corresponding machine-readable source code, which 231 | must be distributed under the terms of Sections 1 and 2 above on a 232 | medium customarily used for software interchange. 233 | 234 | If distribution of object code is made by offering access to copy 235 | from a designated place, then offering equivalent access to copy the 236 | source code from the same place satisfies the requirement to 237 | distribute the source code, even though third parties are not 238 | compelled to copy the source along with the object code. 239 | 240 | 5. A program that contains no derivative of any portion of the 241 | Library, but is designed to work with the Library by being compiled or 242 | linked with it, is called a "work that uses the Library". Such a 243 | work, in isolation, is not a derivative work of the Library, and 244 | therefore falls outside the scope of this License. 245 | 246 | However, linking a "work that uses the Library" with the Library 247 | creates an executable that is a derivative of the Library (because it 248 | contains portions of the Library), rather than a "work that uses the 249 | library". The executable is therefore covered by this License. 250 | Section 6 states terms for distribution of such executables. 251 | 252 | When a "work that uses the Library" uses material from a header file 253 | that is part of the Library, the object code for the work may be a 254 | derivative work of the Library even though the source code is not. 255 | Whether this is true is especially significant if the work can be 256 | linked without the Library, or if the work is itself a library. The 257 | threshold for this to be true is not precisely defined by law. 258 | 259 | If such an object file uses only numerical parameters, data 260 | structure layouts and accessors, and small macros and small inline 261 | functions (ten lines or less in length), then the use of the object 262 | file is unrestricted, regardless of whether it is legally a derivative 263 | work. (Executables containing this object code plus portions of the 264 | Library will still fall under Section 6.) 265 | 266 | Otherwise, if the work is a derivative of the Library, you may 267 | distribute the object code for the work under the terms of Section 6. 268 | Any executables containing that work also fall under Section 6, 269 | whether or not they are linked directly with the Library itself. 270 | 271 | 6. As an exception to the Sections above, you may also combine or 272 | link a "work that uses the Library" with the Library to produce a 273 | work containing portions of the Library, and distribute that work 274 | under terms of your choice, provided that the terms permit 275 | modification of the work for the customer's own use and reverse 276 | engineering for debugging such modifications. 277 | 278 | You must give prominent notice with each copy of the work that the 279 | Library is used in it and that the Library and its use are covered by 280 | this License. You must supply a copy of this License. If the work 281 | during execution displays copyright notices, you must include the 282 | copyright notice for the Library among them, as well as a reference 283 | directing the user to the copy of this License. Also, you must do one 284 | of these things: 285 | 286 | a) Accompany the work with the complete corresponding 287 | machine-readable source code for the Library including whatever 288 | changes were used in the work (which must be distributed under 289 | Sections 1 and 2 above); and, if the work is an executable linked 290 | with the Library, with the complete machine-readable "work that 291 | uses the Library", as object code and/or source code, so that the 292 | user can modify the Library and then relink to produce a modified 293 | executable containing the modified Library. (It is understood 294 | that the user who changes the contents of definitions files in the 295 | Library will not necessarily be able to recompile the application 296 | to use the modified definitions.) 297 | 298 | b) Use a suitable shared library mechanism for linking with the 299 | Library. A suitable mechanism is one that (1) uses at run time a 300 | copy of the library already present on the user's computer system, 301 | rather than copying library functions into the executable, and (2) 302 | will operate properly with a modified version of the library, if 303 | the user installs one, as long as the modified version is 304 | interface-compatible with the version that the work was made with. 305 | 306 | c) Accompany the work with a written offer, valid for at 307 | least three years, to give the same user the materials 308 | specified in Subsection 6a, above, for a charge no more 309 | than the cost of performing this distribution. 310 | 311 | d) If distribution of the work is made by offering access to copy 312 | from a designated place, offer equivalent access to copy the above 313 | specified materials from the same place. 314 | 315 | e) Verify that the user has already received a copy of these 316 | materials or that you have already sent this user a copy. 317 | 318 | For an executable, the required form of the "work that uses the 319 | Library" must include any data and utility programs needed for 320 | reproducing the executable from it. However, as a special exception, 321 | the materials to be distributed need not include anything that is 322 | normally distributed (in either source or binary form) with the major 323 | components (compiler, kernel, and so on) of the operating system on 324 | which the executable runs, unless that component itself accompanies 325 | the executable. 326 | 327 | It may happen that this requirement contradicts the license 328 | restrictions of other proprietary libraries that do not normally 329 | accompany the operating system. Such a contradiction means you cannot 330 | use both them and the Library together in an executable that you 331 | distribute. 332 | 333 | 7. You may place library facilities that are a work based on the 334 | Library side-by-side in a single library together with other library 335 | facilities not covered by this License, and distribute such a combined 336 | library, provided that the separate distribution of the work based on 337 | the Library and of the other library facilities is otherwise 338 | permitted, and provided that you do these two things: 339 | 340 | a) Accompany the combined library with a copy of the same work 341 | based on the Library, uncombined with any other library 342 | facilities. This must be distributed under the terms of the 343 | Sections above. 344 | 345 | b) Give prominent notice with the combined library of the fact 346 | that part of it is a work based on the Library, and explaining 347 | where to find the accompanying uncombined form of the same work. 348 | 349 | 8. You may not copy, modify, sublicense, link with, or distribute 350 | the Library except as expressly provided under this License. Any 351 | attempt otherwise to copy, modify, sublicense, link with, or 352 | distribute the Library is void, and will automatically terminate your 353 | rights under this License. However, parties who have received copies, 354 | or rights, from you under this License will not have their licenses 355 | terminated so long as such parties remain in full compliance. 356 | 357 | 9. You are not required to accept this License, since you have not 358 | signed it. However, nothing else grants you permission to modify or 359 | distribute the Library or its derivative works. These actions are 360 | prohibited by law if you do not accept this License. Therefore, by 361 | modifying or distributing the Library (or any work based on the 362 | Library), you indicate your acceptance of this License to do so, and 363 | all its terms and conditions for copying, distributing or modifying 364 | the Library or works based on it. 365 | 366 | 10. Each time you redistribute the Library (or any work based on the 367 | Library), the recipient automatically receives a license from the 368 | original licensor to copy, distribute, link with or modify the Library 369 | subject to these terms and conditions. You may not impose any further 370 | restrictions on the recipients' exercise of the rights granted herein. 371 | You are not responsible for enforcing compliance by third parties with 372 | this License. 373 | 374 | 11. If, as a consequence of a court judgment or allegation of patent 375 | infringement or for any other reason (not limited to patent issues), 376 | conditions are imposed on you (whether by court order, agreement or 377 | otherwise) that contradict the conditions of this License, they do not 378 | excuse you from the conditions of this License. If you cannot 379 | distribute so as to satisfy simultaneously your obligations under this 380 | License and any other pertinent obligations, then as a consequence you 381 | may not distribute the Library at all. For example, if a patent 382 | license would not permit royalty-free redistribution of the Library by 383 | all those who receive copies directly or indirectly through you, then 384 | the only way you could satisfy both it and this License would be to 385 | refrain entirely from distribution of the Library. 386 | 387 | If any portion of this section is held invalid or unenforceable under any 388 | particular circumstance, the balance of the section is intended to apply, 389 | and the section as a whole is intended to apply in other circumstances. 390 | 391 | It is not the purpose of this section to induce you to infringe any 392 | patents or other property right claims or to contest validity of any 393 | such claims; this section has the sole purpose of protecting the 394 | integrity of the free software distribution system which is 395 | implemented by public license practices. Many people have made 396 | generous contributions to the wide range of software distributed 397 | through that system in reliance on consistent application of that 398 | system; it is up to the author/donor to decide if he or she is willing 399 | to distribute software through any other system and a licensee cannot 400 | impose that choice. 401 | 402 | This section is intended to make thoroughly clear what is believed to 403 | be a consequence of the rest of this License. 404 | 405 | 12. If the distribution and/or use of the Library is restricted in 406 | certain countries either by patents or by copyrighted interfaces, the 407 | original copyright holder who places the Library under this License may add 408 | an explicit geographical distribution limitation excluding those countries, 409 | so that distribution is permitted only in or among countries not thus 410 | excluded. In such case, this License incorporates the limitation as if 411 | written in the body of this License. 412 | 413 | 13. The Free Software Foundation may publish revised and/or new 414 | versions of the Lesser General Public License from time to time. 415 | Such new versions will be similar in spirit to the present version, 416 | but may differ in detail to address new problems or concerns. 417 | 418 | Each version is given a distinguishing version number. If the Library 419 | specifies a version number of this License which applies to it and 420 | "any later version", you have the option of following the terms and 421 | conditions either of that version or of any later version published by 422 | the Free Software Foundation. If the Library does not specify a 423 | license version number, you may choose any version ever published by 424 | the Free Software Foundation. 425 | 426 | 14. If you wish to incorporate parts of the Library into other free 427 | programs whose distribution conditions are incompatible with these, 428 | write to the author to ask for permission. For software which is 429 | copyrighted by the Free Software Foundation, write to the Free 430 | Software Foundation; we sometimes make exceptions for this. Our 431 | decision will be guided by the two goals of preserving the free status 432 | of all derivatives of our free software and of promoting the sharing 433 | and reuse of software generally. 434 | 435 | NO WARRANTY 436 | 437 | 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO 438 | WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. 439 | EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR 440 | OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY 441 | KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE 442 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 443 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE 444 | LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME 445 | THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 446 | 447 | 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN 448 | WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY 449 | AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU 450 | FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR 451 | CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE 452 | LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING 453 | RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A 454 | FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF 455 | SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 456 | DAMAGES. 457 | 458 | END OF TERMS AND CONDITIONS 459 | 460 | How to Apply These Terms to Your New Libraries 461 | 462 | If you develop a new library, and you want it to be of the greatest 463 | possible use to the public, we recommend making it free software that 464 | everyone can redistribute and change. You can do so by permitting 465 | redistribution under these terms (or, alternatively, under the terms of the 466 | ordinary General Public License). 467 | 468 | To apply these terms, attach the following notices to the library. It is 469 | safest to attach them to the start of each source file to most effectively 470 | convey the exclusion of warranty; and each file should have at least the 471 | "copyright" line and a pointer to where the full notice is found. 472 | 473 | {description} 474 | Copyright (C) {year} {fullname} 475 | 476 | This library is free software; you can redistribute it and/or 477 | modify it under the terms of the GNU Lesser General Public 478 | License as published by the Free Software Foundation; either 479 | version 2.1 of the License, or (at your option) any later version. 480 | 481 | This library is distributed in the hope that it will be useful, 482 | but WITHOUT ANY WARRANTY; without even the implied warranty of 483 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 484 | Lesser General Public License for more details. 485 | 486 | You should have received a copy of the GNU Lesser General Public 487 | License along with this library; if not, write to the Free Software 488 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 489 | USA 490 | 491 | Also add information on how to contact you by electronic and paper mail. 492 | 493 | You should also get your employer (if you work as a programmer) or your 494 | school, if any, to sign a "copyright disclaimer" for the library, if 495 | necessary. Here is a sample; alter the names: 496 | 497 | Yoyodyne, Inc., hereby disclaims all copyright interest in the 498 | library `Frob' (a library for tweaking knobs) written by James Random 499 | Hacker. 500 | 501 | {signature of Ty Coon}, 1 April 1990 502 | Ty Coon, President of Vice 503 | 504 | That's all there is to it! 505 | 506 | --------------------------------------------------------------------------------