diff --git a/.env b/.env new file mode 100644 index 0000000000..0b99a88cb5 --- /dev/null +++ b/.env @@ -0,0 +1,4 @@ +COURSES_DIRECTORY_ON_HOST=../ww-docker-data/courses +WEBWORK2_HTTP_PORT_ON_HOST=8080 +WEBWORK_DB_USER=webworkWrite +WEBWORK_DB_PASSWORD=passwordRWsetItBeforeFirstStartingTheDBcontainer diff --git a/Dockerfile b/Dockerfile index 13c9de0813..773277dc63 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,15 +1,84 @@ -FROM ubuntu:16.04 +# Optional things to change/configure below: +# +# 1. Which branch of webwork2/ and pg/ to install. +# +# 2. Installing the OPL in the Docker image itself. +# (almost 850MB: 290+MB for the main OPL, 90+MB for Pending, 460+MB for Contrib) +# +# By default this is NOT done, and it will instead be installed in +# a named Docker storage volume when the container is first started. +# +# Note: For typical use, we recommend that the OPL be either mounted from +# a local directory on the source or from a separate named data volume. +# That approach precludes needing to download the OPL for each update to +# the Docker image, and allows it to be easily upgraded using git in its +# persistent location. +# +# 3. Some things should be handled by setting environment variables which +# take effect at container startup. They can usually be set in +# docker-compose.yml. +# +# SSL=1 +# will turn on SSL at startup +# ADD_LOCALES="locale1,locale2,locale3" +# will build these locales at startup +# PAPERSIZE=a4 +# will set the system papersize to A4 +# SYSTEM_TIMEZONE=zone/city +# will set the system timezone to zone/city +# Make sure to use a valid setting. +# "/usr/bin/timedatectl list-timezones" on Ubuntu will find valid values +# ADD_PACKAGES="package1 package2 package3" +# will have these additional Ubuntu packages installed at startup. +# +# ================================================================== +# Phase 1 - download some Git repos for later use: +# as suggested by Nelson Moller in https://gist.github.com/nmoller/81bd8e149e6aa2a7cf051e0bf248b2e2 -ENV PG_BRANCH=develop \ - WEBWORK_URL=/webwork2 \ +FROM alpine/git AS base + +# build args specifying the branches for webwork2 and pg used to build the image + +# To use the master branches of webwork2 and pg +#ARG WEBWORK2_BRANCH=master +#ARG PG_BRANCH=master +# To use the 2.15 branches of webwork2 and pg +ARG WEBWORK2_BRANCH=WeBWorK-2.15 +ARG PG_BRANCH=PG-2.15 + +# assign the build args WEBWORK2_BRANCH and PG_BRANCH to the ENV WEBWORK2_BRANCH_ENV and PG_BRANCH_ENV, resp. +ENV WEBWORK2_BRANCH_ENV ${WEBWORK2_BRANCH} +ENV PG_BRANCH_ENV ${PG_BRANCH} + +WORKDIR /opt/base + +RUN echo Cloning branch $WEBWORK2_BRANCH_ENV from https://github.com/openwebwork/webwork2.git \ + && git clone --single-branch --branch ${WEBWORK2_BRANCH_ENV} --depth 1 https://github.com/openwebwork/webwork2.git \ + && rm -rf webwork2/.git webwork2/{*ignore,Dockerfile,docker-compose.yml,docker-config} + +RUN echo Cloning branch $PG_BRANCH_ENV branch from https://github.com/openwebwork/pg.git \ + && git clone --single-branch --branch ${PG_BRANCH_ENV} --depth 1 https://github.com/openwebwork/pg.git \ + && rm -rf pg/.git + +RUN git clone --single-branch --branch master --depth 1 https://github.com/mathjax/MathJax \ + && rm -rf MathJax/.git + +# Optional - include OPL (also need to uncomment further below when an included OPL is desired): +#RUN git clone --single-branch --branch master --depth 1 https://github.com/openwebwork/webwork-open-problem-library.git \ +# && rm -rf webwork-open-problem-library/.git + +# ================================================================== + +# Phase 2 - set ENV variables + +# we need to change FROM before setting the ENV variables + +FROM ubuntu:18.04 + +ENV WEBWORK_URL=/webwork2 \ WEBWORK_ROOT_URL=http://localhost \ - WEBWORK_DB_HOST=db \ - WEBWORK_DB_PORT=3306 \ - WEBWORK_DB_NAME=webwork \ - WEBWORK_DB_USER=webworkWrite \ - WEBWORK_DB_PASSWORD=passwordRW \ WEBWORK_SMTP_SERVER=localhost \ WEBWORK_SMTP_SENDER=webwork@example.com \ WEBWORK_TIMEZONE=America/New_York \ @@ -22,125 +91,196 @@ ENV PG_BRANCH=develop \ # Only /var/log/apache2 is handled by /etc/logrotate.d/apache2. APACHE_LOG_DIR=/var/log/apache2 \ APP_ROOT=/opt/webwork \ + DEBIAN_FRONTEND=noninteractive \ + DEBCONF_NONINTERACTIVE_SEEN=true \ DEV=0 -ENV WEBWORK_DB_DSN=DBI:mysql:${WEBWORK_DB_NAME}:${WEBWORK_DB_HOST}:${WEBWORK_DB_PORT} \ - WEBWORK_ROOT=$APP_ROOT/webwork2 \ +# Environment variables which depend on a prior environment variable must be set +# in an ENV call after the dependencies were defined. +ENV WEBWORK_ROOT=$APP_ROOT/webwork2 \ PG_ROOT=$APP_ROOT/pg \ PATH=$PATH:$APP_ROOT/webwork2/bin -# Ubuntu 18.04 should add libemail-address-xs-perl in the package list below. -# For Ubuntu 16.04 it is not packed in Ubuntu universe, so installed using CPANM below. +# ================================================================== + +# Phase 3 - Ubuntu 18.04 base image + required packages + +# Packages changes/added for ubuntu 18.04: + +# For ubuntu 18.04 libemail-address-xs-perl installed from Ubuntu, for 16.04 it would be installed using cpamn +# +# texlive-generic-recommended # For ubuntu 16.04 - contains path.sty +# texlive-plain-generic # For ubuntu 18.04 - contains path.sty + +# Do NOT include "apt-get -y upgrade" +# see: https://docs.docker.com/develop/develop-images/dockerfile_best-practices/ RUN apt-get update \ && apt-get install -y --no-install-recommends --no-install-suggests \ - apache2 \ - curl \ - dvipng \ - gcc \ - libapache2-request-perl \ - libcrypt-ssleay-perl \ - libdatetime-perl \ - libdancer-perl \ - libdancer-plugin-database-perl \ - libdbd-mysql-perl \ - libexception-class-perl \ - libextutils-xsbuilder-perl \ - libfile-find-rule-perl-perl \ - libgd-perl \ - libhtml-scrubber-perl \ - libjson-perl \ - liblocale-maketext-lexicon-perl \ - libmail-sender-perl \ - libmime-tools-perl \ - libnet-ip-perl \ - libnet-ldap-perl \ - libnet-oauth-perl \ - libossp-uuid-perl \ - libpadwalker-perl \ - libpath-class-perl \ - libphp-serialization-perl \ - libxml-simple-perl \ - libsoap-lite-perl \ - libsql-abstract-perl \ - libstring-shellquote-perl \ - libtemplate-perl \ - libtext-csv-perl \ - libtimedate-perl \ - libuuid-tiny-perl \ - libxml-parser-perl \ - libxml-writer-perl \ - libxmlrpc-lite-perl \ - libapache2-reload-perl \ - libxmlrpc-lite-perl \ - libxml-simple-perl \ - make \ - netpbm \ - preview-latex-style \ - texlive \ - texlive-latex-extra \ - libc6-dev \ - git \ - mysql-client \ - && rm -fr /var/lib/apt/lists/* - -# Warning - when I tried to include XML::Simple near the start of the first "cpanm install" line, there was an error: -# Building and testing XMLRPC-Lite-0.717 ... ! Installing XMLRPC::Lite failed. See /root/.cpanm/work/1551887935.125/build.log for details. Retry with --force to force install it. -# so it was put into a second "cpanm install" line. - -RUN curl -Lk https://cpanmin.us | perl - App::cpanminus \ - && cpanm install XML::Parser::EasyTree Iterator Iterator::Util Pod::WSDL Array::Utils HTML::Template Mail::Sender Email::Sender::Simple Data::Dump Statistics::R::IO Email::Address::XS - -##RUN cpanm install XML::Simple \ -# && rm -fr ./cpanm /root/.cpanm /tmp/* - - -RUN mkdir -p $APP_ROOT/courses $APP_ROOT/libraries $APP_ROOT/webwork2 - -# Block to include webwork2 in the container, when needed, instead of getting it from a bind mount. -# Uncomment when needed, and set the correct branch name on the following line. -#ENV WEBWORK_BRANCH=develop # need a valid branch name from https://github.com/openwebwork/webwork2 -#RUN curl -fSL https://github.com/openwebwork/webwork2/archive/${WEBWORK_BRANCH}.tar.gz -o /tmp/${WEBWORK_BRANCH}.tar.gz \ -# && cd /tmp \ -# && tar xzf /tmp/${WEBWORK_BRANCH}.tar.gz \ -# && mv webwork2-${WEBWORK_BRANCH} $APP_ROOT/webwork2 \ -# && rm -rf /tmp/${WEBWORK_BRANCH}.tar.gz /tmp/webwork2-${WEBWORK_BRANCH} - -RUN curl -fSL https://github.com/openwebwork/pg/archive/${PG_BRANCH}.tar.gz -o /tmp/${PG_BRANCH}.tar.gz \ - && tar xzf /tmp/${PG_BRANCH}.tar.gz \ - && mv pg-${PG_BRANCH} $APP_ROOT/pg \ - && rm /tmp/${PG_BRANCH}.tar.gz \ - && curl -fSL https://github.com/openwebwork/webwork-open-problem-library/archive/master.tar.gz -o /tmp/opl.tar.gz \ - && tar xzf /tmp/opl.tar.gz \ - && mv webwork-open-problem-library-master $APP_ROOT/libraries/webwork-open-problem-library \ - && rm /tmp/opl.tar.gz - -RUN curl -fSL https://github.com/mathjax/MathJax/archive/master.tar.gz -o /tmp/mathjax.tar.gz \ - && tar xzf /tmp/mathjax.tar.gz \ - && mv MathJax-master $APP_ROOT/MathJax \ - && rm /tmp/mathjax.tar.gz - #&& rm /tmp/VERSION - #curl -fSL https://github.com/openwebwork/webwork2/archive/WeBWorK-${WEBWORK_VERSION}.tar.gz -o /tmp/WeBWorK-${WEBWORK_VERSION}.tar.gz \ - #&& tar xzf /tmp/WeBWorK-${WEBWORK_VERSION}.tar.gz \ - #&& mv webwork2-WeBWorK-${WEBWORK_VERSION} $APP_ROOT/webwork2 \ - #&& rm /tmp/WeBWorK-${WEBWORK_VERSION}.tar.gz \ - - -RUN echo "PATH=$PATH:$APP_ROOT/webwork2/bin" >> /root/.bashrc - -COPY . $APP_ROOT/webwork2 - - -# Move these lines into docker-entrypoint.sh so the bind mount of courses -# will be available + apache2 \ + curl \ + dvipng \ + gcc \ + libapache2-request-perl \ + libcrypt-ssleay-perl \ + libdatetime-perl \ + libdancer-perl \ + libdancer-plugin-database-perl \ + libdbd-mysql-perl \ + libemail-address-xs-perl \ + libexception-class-perl \ + libextutils-xsbuilder-perl \ + libfile-find-rule-perl-perl \ + libgd-perl \ + libhtml-scrubber-perl \ + libjson-perl \ + liblocale-maketext-lexicon-perl \ + libmail-sender-perl \ + libmime-tools-perl \ + libnet-ip-perl \ + libnet-ldap-perl \ + libnet-oauth-perl \ + libossp-uuid-perl \ + libpadwalker-perl \ + libpath-class-perl \ + libphp-serialization-perl \ + libxml-simple-perl \ + libsoap-lite-perl \ + libsql-abstract-perl \ + libstring-shellquote-perl \ + libtemplate-perl \ + libtext-csv-perl \ + libtimedate-perl \ + libuuid-tiny-perl \ + libxml-parser-perl \ + libxml-writer-perl \ + libxmlrpc-lite-perl \ + libapache2-reload-perl \ + cpanminus \ + libxml-parser-easytree-perl \ + libiterator-perl \ + libiterator-util-perl \ + libpod-wsdl-perl \ + libtest-xml-perl \ + libmodule-build-perl \ + libxml-semanticdiff-perl \ + libxml-xpath-perl \ + libpath-tiny-perl \ + libarray-utils-perl \ + libhtml-template-perl \ + libtest-pod-perl \ + libemail-sender-perl \ + libmail-sender-perl \ + libmodule-pluggable-perl \ + libemail-date-format-perl \ + libcapture-tiny-perl \ + libthrowable-perl \ + libdata-dump-perl \ + libfile-sharedir-install-perl \ + libclass-tiny-perl \ + libtest-requires-perl \ + libtest-mockobject-perl \ + libtest-warn-perl \ + libsub-uplevel-perl \ + libtest-exception-perl \ + libuniversal-can-perl \ + libuniversal-isa-perl \ + libtest-fatal-perl \ + libjson-xs-perl \ + make \ + netpbm \ + preview-latex-style \ + texlive \ + texlive-latex-extra \ + texlive-plain-generic \ + texlive-xetex \ + texlive-latex-recommended \ + texlive-lang-other \ + texlive-lang-arabic \ + libc6-dev \ + git \ + mysql-client \ + tzdata \ + apt-utils \ + locales \ + debconf-utils \ + ssl-cert \ + ca-certificates \ + culmus \ + fonts-linuxlibertine \ + lmodern \ + && apt-get clean \ + && rm -fr /var/lib/apt/lists/* /tmp/* + +# Developers may want to add additional packages inside the image +# such as: telnet vimvim mc file + +# ================================================================== + +# Phase 4 - Install webwork2, pg, MathJaX which were downloaded to /opt/base/ in phase 1 +# Option: Install the OPL in the image also (about 850 MB) + +RUN mkdir -p $APP_ROOT/courses $APP_ROOT/libraries $APP_ROOT/libraries/webwork-open-problem-library $APP_ROOT/webwork2 /www/www/html + +COPY --from=base /opt/base/webwork2 $APP_ROOT/webwork2 +COPY --from=base /opt/base/pg $APP_ROOT/pg +COPY --from=base /opt/base/MathJax $APP_ROOT/MathJax + +# Optional - include OPL (also need to uncomment above to clone from GitHub when needed): +# ??? could/should this include the main OPL = /opt/base/webwork-open-problem-library/OpenProblemLibrary and not Contrib and Pending ??? +#COPY --from=base /opt/base/webwork-open-problem-library $APP_ROOT/libraries/webwork-open-problem-library + +# ================================================================== + +# Phase 5 - some configuration work + +# 1. Setup PATH. +# 2. Compiles color.c in the copy INSIDE the image, will also be done in docker-entrypoint.sh for externally mounted locations. +# 3. Some chown/chmod for material INSIDE the image. +# 4. Build some standard locales. +# 5. Set the default system timezone to be UTC. + +RUN echo "PATH=$PATH:$APP_ROOT/webwork2/bin" >> /root/.bashrc \ + && cd $APP_ROOT/pg/lib/chromatic && gcc color.c -o color \ + && cd $APP_ROOT/webwork2/ \ + && chown www-data DATA ../courses htdocs/applets logs tmp $APP_ROOT/pg/lib/chromatic \ + && chmod -R u+w DATA ../courses htdocs/applets logs tmp $APP_ROOT/pg/lib/chromatic \ + && echo "en_US ISO-8859-1\nen_US.UTF-8 UTF-8" > /etc/locale.gen \ + && /usr/sbin/locale-gen \ + && echo "locales locales/default_environment_locale select en_US.UTF-8\ndebconf debconf/frontend select Noninteractive" > /tmp/preseed.txt \ + && debconf-set-selections /tmp/preseed.txt \ + && rm /etc/localtime /etc/timezone && echo "Etc/UTC" > /etc/timezone \ + && dpkg-reconfigure -f noninteractive tzdata + +# These lines were moved into docker-entrypoint.sh so the bind mount of courses will be available #RUN cd $APP_ROOT/webwork2/courses.dist \ # && cp *.lst $APP_ROOT/courses/ \ # && cp -R modelCourse $APP_ROOT/courses/ -RUN cd $APP_ROOT/pg/lib/chromatic \ - && gcc color.c -o color +# ================================================================== + +# Phase 6 - install additional Perl modules from CPAN (not packaged for Ubuntu or outdated in Ubuntu) + +RUN cpanm install Statistics::R::IO \ + && rm -fr ./cpanm /root/.cpanm /tmp/* + +# Now installed from Ubuntu packages: +# XML::Parser::EasyTree Iterator Iterator::Util Pod::WSDL Array::Utils HTML::Template Mail::Sender Email::Sender::Simple Data::Dump +# For Ubuntu 16.04 would also need: +# Email::Address::XS + +# ================================================================== + +# Phase 7 - setup apache + +# Note we always create the /etc/ssl/local directory in case it will be needed, as +# the SSL config can also be done via a modified docker-entrypoint.sh script. + +# Always provide the dummy default-ssl.conf file: +COPY docker-config/ssl/default-ssl.conf /etc/apache2/sites-available/default-ssl.conf + +# However SSL will only be enabled at container startup via docker-entrypoint.sh. -# setup apache RUN cd $APP_ROOT/webwork2/conf \ && cp webwork.apache2.4-config.dist webwork.apache2.4-config \ && cp $APP_ROOT/webwork2/conf/webwork.apache2.4-config /etc/apache2/conf-enabled/webwork.conf \ @@ -148,30 +288,52 @@ RUN cd $APP_ROOT/webwork2/conf \ && a2enmod mpm_prefork \ && sed -i -e 's/Timeout 300/Timeout 1200/' /etc/apache2/apache2.conf \ && sed -i -e 's/MaxRequestWorkers 150/MaxRequestWorkers 20/' \ - -e 's/MaxConnectionsPerChild 0/MaxConnectionsPerChild 100/' \ - /etc/apache2/mods-available/mpm_prefork.conf \ + -e 's/MaxConnectionsPerChild 0/MaxConnectionsPerChild 100/' \ + /etc/apache2/mods-available/mpm_prefork.conf \ && cp $APP_ROOT/webwork2/htdocs/favicon.ico /var/www/html \ + && mkdir -p $APACHE_RUN_DIR $APACHE_LOCK_DIR $APACHE_LOG_DIR \ + && mkdir /etc/ssl/local \ + && a2enmod rewrite \ && sed -i -e 's/^$/\ - PerlPassEnv WEBWORK_URL\n\ - PerlPassEnv WEBWORK_ROOT_URL\n\ - PerlPassEnv WEBWORK_DB_DSN\n\ - PerlPassEnv WEBWORK_DB_USER\n\ - PerlPassEnv WEBWORK_DB_PASSWORD\n\ - PerlPassEnv WEBWORK_SMTP_SERVER\n\ - PerlPassEnv WEBWORK_SMTP_SENDER\n\ - PerlPassEnv WEBWORK_TIMEZONE\n\ - \n/' /etc/apache2/conf-enabled/webwork.conf - -RUN cd $APP_ROOT/webwork2/ \ - && chown www-data DATA ../courses htdocs/applets logs tmp $APP_ROOT/pg/lib/chromatic \ - && chmod -R u+w DATA ../courses htdocs/applets logs tmp $APP_ROOT/pg/lib/chromatic - -COPY docker-entrypoint.sh /usr/local/bin/ + PerlPassEnv WEBWORK_URL\n\ + PerlPassEnv WEBWORK_ROOT_URL\n\ + PerlPassEnv WEBWORK_DB_DSN\n\ + PerlPassEnv WEBWORK_DB_USER\n\ + PerlPassEnv WEBWORK_DB_PASSWORD\n\ + PerlPassEnv WEBWORK_SMTP_SERVER\n\ + PerlPassEnv WEBWORK_SMTP_SENDER\n\ + PerlPassEnv WEBWORK_TIMEZONE\n\ + \n/' /etc/apache2/conf-enabled/webwork.conf + +EXPOSE 80 +WORKDIR $APP_ROOT + +# Enabling SSL is NOT done here. +# Instead it is done by docker-entrypoint.sh at container startup when SSL=1 +# is set in the environment, for example by docker-compose.yml. +#RUN a2enmod ssl && a2ensite default-ssl +#EXPOSE 443 + +# ================================================================== + +# Phase 8 - prepare docker-entrypoint.sh +# Done near the end, so that an update to docker-entrypoint.sh can be +# done without rebuilding the earlier layers of the Docker image. + +COPY docker-config/docker-entrypoint.sh /usr/local/bin/ ENTRYPOINT ["docker-entrypoint.sh"] -EXPOSE 80 +# ================================================================== -WORKDIR $APP_ROOT +# Add enviroment variables to control some things during container startup + +ENV SSL=0 \ + PAPERSIZE=letter \ + SYSTEM_TIMEZONE=UTC \ + ADD_LOCALES=0 \ + ADD_PACKAGES=0 + +# ================================================ CMD ["apache2", "-DFOREGROUND"] diff --git a/docker-compose.yml b/docker-compose.yml index df1c97e7f1..a22c3a3453 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,45 +1,194 @@ -version: '2' +version: '3.5' services: db: - image: mariadb:10.1 + image: mariadb:10.4 volumes: - mysql:/var/lib/mysql + # Set up UTF8MB4 in config file for the container. # Needs to be done BEFORE the database is created. - # - "./docker-config/db/mariadb.cnf:/etc/mysql/conf.d/mariadb.cnf" + - "./docker-config/db/mariadb.cnf:/etc/mysql/conf.d/mariadb.cnf" restart: always environment: - MYSQL_ROOT_PASSWORD: randomepassword + # When the MariaDB container is first started it will set the + # the MYSQL_ROOT_PASSWORD if there is no mysql database in the + # data volume. + MYSQL_ROOT_PASSWORD: sqlRootPasswordSetThisPasswordBEFOREfirstStartingTheDBcontainer + + # When the MariaDB container is first started it will create + # the WW database and WW DB user based on: MYSQL_DATABASE: webwork - MYSQL_USER: webworkWrite - MYSQL_PASSWORD: passwordRW + MYSQL_USER: ${WEBWORK_DB_USER} + MYSQL_PASSWORD: ${WEBWORK_DB_PASSWORD} + app: - build: . image: webwork + + # Select the appropriate "build:" block: + + # For use/building when docker-compose.yml is in the webwork2 directory + build: . + + # For use/building when docker-compose.yml is OUTSIDE the webwork2 directory. + # For example, if multiple hosts use a NFS shared webwork2/ directory, and + # each one needs customized values in docker-compose.yml. + # Under typical use, the Dockerfile should not need to be customized per host, + # but may contain some changes/additions relative to the standard webwork image. + # + #build: + # context: /Path_To/webwork2/ + # dockerfile: /Path_To/Dockerfile + depends_on: - db - r + volumes: - - ".:/opt/webwork/webwork2" - # OLD approach put the courses tree under webwork2/.data/courses - #- "./.data/courses:/opt/webwork/courses" - # NEW appoach puts the courses tree in a separate tree outside of webwork2/ - - "../ww-docker-data/courses:/opt/webwork/courses" + # ====================================================================== + + # If you are using locally modified webwork2 files, then + # either mount them from the webwork2 tree from which you start Docker: + #- ".:/opt/webwork/webwork2" + # OR mount it from a fixed external location + #- "/path_to/webwork2:/opt/webwork/webwork2" + + # Shared main /pg repository - allows local PG development + #- "/path_to_shared/pg:/opt/webwork/pg" + # OR locally modified PG directory + #- "../pg:/opt/webwork/pg" + + # ====================================================================== + + # Sometimes it is helpful to mount certain webwork2/conf files from elsewhere + # so the main contents of webwork2 can be shared by several hosts (ex. NFS) + #- "/per_host_conf_path/conf/authen_LTI.conf:/opt/webwork/webwork2/conf/authen_LTI.conf" + #- "/per_host_conf_path/conf/localOverrides.conf:/opt/webwork/webwork2/conf/localOverrides.conf" + #- "/per_host_conf_path/conf/site.conf:/opt/webwork/webwork2/conf/site.conf" + + # webwork2 misc LOCAL files - mount live (per host) so NOT in the main webwork2 location + #- "/per_host_conf_path/htdocs/my_site_info.txt:/opt/webwork/webwork2/htdocs/my_site_info.txt" + + # webwork2 LOCAL logs and htdocs/tmp directories (per host) + #- "/per_host_data_path/webwork2/logs:/opt/webwork/webwork2/logs" + #- "/per_host_data_path/webwork2/htdocs/tmp:/opt/webwork/webwork2/htdocs/tmp" + + # By default the courses tree in a separate tree outside of webwork2/ as follows: + - "${COURSES_DIRECTORY_ON_HOST}:/opt/webwork/courses" + # OR mount like (here we are assuming that the hosts have different courses on them) + #- "/per_host_data_path/courses/:/opt/webwork/courses/" + + # ====================================================================== + + # By default the OPL is stored in a named Docker storage volume: + - oplVolume:/opt/webwork/libraries/webwork-open-problem-library + # + # as an alternative, you can comment out the prior option and uncomment the line below to use a local directory containing the OPL + #- "/path_to/webwork-open-problem-library:/opt/webwork/libraries/webwork-open-problem-library" + + # ====================================================================== + + # The mounts from ./docker-config/ below are local samples. + # In production, there may be per-host versions of most + # of these files stored in an appropriate place. + # If not - the samples should be edited as needed. + + # Main index.html page with a redirect (you probably need to customize some of these files) + #- "./docker-config/apache/index.html:/var/www/html/index.html" + #- "./docker-config/apache/htaccess:/var/www/html/.htaccess" + + # Apache config (you probably need to customize some of these files) + - "./docker-config/apache/000-default.conf:/etc/apache2/sites-available/000-default.conf" + - "./docker-config/apache/apache2.conf:/etc/apache2/apache2.conf" + - "./docker-config/apache/mpm_prefork.conf:/etc/apache2/mods-enabled/mpm_prefork.conf" + + # Apache logs - to have them persistent (per host) mount directory from outside. + #- "/per_host_data_path/apache2_logs:/var/log/apache2" + + # ====================================================================== + + # SSL certificates (subdirectory with certificate and key) + # (you MUST replace/customize these files, or change the location they are mounded from) + - "./docker-config/ssl/local/:/etc/ssl/local" + + # Apache SSL config (you probably need to customize some of these files) + # (make sure default-ssl.conf points to the certificates where they will be in the container) + - "./docker-config/ssl/ssl.conf:/etc/apache2/mods-available/ssl.conf" + - "./docker-config/ssl/default-ssl.conf:/etc/apache2/sites-available/default-ssl.conf" + + # ====================================================================== + + hostname: myhost.mydomain.edu - # Uncomment the line below to use local OPL for development - #- "../opl:/opt/webwork/libraries/webwork-open-problem-library" - # Uncomment the line below to use local PG for development - - "../pg:/opt/webwork/pg" ports: - - "8080:80" + # For a personal machine + - "${WEBWORK2_HTTP_PORT_ON_HOST}:80" + + # For a production machine + #- "80:80" + #- "443:443" + + # For a production machine + #restart: always + environment: + DEV: 0 + + APACHE_RUN_GROUP: www-data + + # Standard database environment variables needed by WeBWorK: + WEBWORK_DB_HOST: db + WEBWORK_DB_PORT: 3306 + WEBWORK_DB_NAME: webwork + WEBWORK_DB_DSN: DBI:mysql:webwork:db:3306 + # We currently need to put the same data in the WEBWORK_DB_DSN line above + # as we cannot use the following form, as it would be done before the values + # needed are available. + # NO GOOD # WEBWORK_DB_DSN: DBI:mysql${WEBWORK_DB_NAME}:${WEBWORK_DB_HOST}:${WEBWORK_DB_PORT} + + + # These are set in the .env file and import values from there + WEBWORK_DB_PASSWORD: ${WEBWORK_DB_PASSWORD} + WEBWORK_DB_USER: ${WEBWORK_DB_USER} + + # ======================================================= + # Local configuration variables: + + # To turn on SSL in the running container + #SSL: 1 + + # Change to A4 paper + #PAPERSIZE: a4 + + # Use to build additional locales in the running container at startup. Ex: + #ADD_LOCALES: he_IL ISO-8859-8,he_IL.UTF-8 UTF-8 + + # Extra Ubuntu packages to install during startup + #ADD_PACKAGES: mc vim telnet + + # The system timezone for the container can be set using + #SYSTEM_TIMEZONE: zone/city + # where zone/city must be a valid setting. + # "/usr/bin/timedatectl list-timezones" on an Ubuntu system with + # that tool installed will find valid values. + + # ======================================================= + + # If you use https below, make sure to set up the certificate and SSL configuration +# WEBWORK_ROOT_URL: https://myhost.mydomain.edu + +# WEBWORK_SMTP_SERVER: smtp.mydomain.edu +# WEBWORK_SMTP_SENDER: support@mydomain.edu + +# WEBWORK_TIMEZONE: America/New_York + r: image: ubcctlt/rserve - ports: - - "6311:6311" +# # The R server need not be available from outside the local Docker network. +# ports: +# - "6311:6311" volumes: + oplVolume: mysql: - diff --git a/docker-compose.yml.nomb4.dist b/docker-compose.yml.nomb4.dist deleted file mode 100644 index e7133f18d5..0000000000 --- a/docker-compose.yml.nomb4.dist +++ /dev/null @@ -1,45 +0,0 @@ -version: '2' -services: - db: - image: mariadb:10.1 - volumes: - - mysql:/var/lib/mysql - # Set up UTF8MB4 in config file for the container. - # Needs to be done BEFORE the database is created. - - "./docker-config/db/mariadb.cnf:/etc/mysql/conf.d/mariadb.cnf" - restart: always - environment: - MYSQL_ROOT_PASSWORD: randomepassword - MYSQL_DATABASE: webwork - MYSQL_USER: webworkWrite - MYSQL_PASSWORD: passwordRW - app: - build: . - image: webwork - depends_on: - - db - - r - volumes: - - ".:/opt/webwork/webwork2" - - # OLD approach put the courses tree under webwork2/.data/courses - #- "./.data/courses:/opt/webwork/courses" - # NEW appoach puts the courses tree in a separate tree outside of webwork2/ - - "../ww-docker-data/courses:/opt/webwork/courses" - - # Uncomment the line below to use local OPL for development - #- "../opl:/opt/webwork/libraries/webwork-open-problem-library" - # Uncomment the line below to use local PG for development - - "../pg:/opt/webwork/pg" - ports: - - "8080:80" - environment: - DEV: 0 - r: - image: ubcctlt/rserve - ports: - - "6311:6311" - -volumes: - mysql: - diff --git a/docker-compose.yml.utf8_mb4_storage.dist b/docker-compose.yml.utf8_mb4_storage.dist deleted file mode 100644 index 53dc498be0..0000000000 --- a/docker-compose.yml.utf8_mb4_storage.dist +++ /dev/null @@ -1,54 +0,0 @@ -version: '2' -services: - # We have renamed the database service from "db" to "dbMB4", - # changed the name of the data volume to "mysqlMB4" and set - # environment variables to use the "dbMB4" server. All this was needed - # ONLY to allow leaving a version of the "db" container which does not - # use utf8mb4 available until the UTF8MB4 changes become mainstream. - dbMB4: - image: mariadb:10.1 - volumes: - - mysqlMB4:/var/lib/mysql - # Set up UTF8MB4 in config file for the container. - # Needs to be done BEFORE the database is created. - - "./docker-config/db/mariadb.cnf:/etc/mysql/conf.d/mariadb.cnf" - restart: always - environment: - MYSQL_ROOT_PASSWORD: randomepassword - MYSQL_DATABASE: webwork - MYSQL_USER: webworkWrite - MYSQL_PASSWORD: passwordRW - app: - build: . - image: webwork - depends_on: - - dbMB4 - - r - volumes: - - ".:/opt/webwork/webwork2" - - # OLD approach put the courses tree under webwork2/.data/courses - #- "./.data/courses:/opt/webwork/courses" - # NEW appoach puts the courses tree in a separate tree outside of webwork2/ - - "../ww-docker-data/courses:/opt/webwork/courses" - - # Uncomment the line below to use local OPL for development - #- "../opl:/opt/webwork/libraries/webwork-open-problem-library" - # Uncomment the line below to use local PG for development - #- "../pg:/opt/webwork/pg" - ports: - - "8080:80" - environment: - - DEV=0 - - WEBWORK_DB_HOST=dbMB4 - # - WEBWORK_DB_PORT=3306 - # - WEBWORK_DB_NAME=webwork - - WEBWORK_DB_DSN=DBI:mysql:webwork:dbMB4:3306 - r: - image: ubcctlt/rserve - ports: - - "6311:6311" - -volumes: - mysqlMB4: - diff --git a/docker-config/apache/000-default.conf b/docker-config/apache/000-default.conf new file mode 100644 index 0000000000..ab9887a59a --- /dev/null +++ b/docker-config/apache/000-default.conf @@ -0,0 +1,54 @@ + + # This fake virtual host is intented to capture traffic which + # spoofs the "Host:" header value for security reasons. + # It will deny ALL such traffic. + ServerName fake + DocumentRoot "/www/www/html" + + Order deny,allow + deny from all + + + + + ServerName localhost + DocumentRoot /var/www/html + ErrorLog ${APACHE_LOG_DIR}/error.log + CustomLog ${APACHE_LOG_DIR}/access.log combined + + + + # The ServerName directive sets the request scheme, hostname and port that + # the server uses to identify itself. This is used when creating + # redirection URLs. In the context of virtual hosts, the ServerName + # specifies what hostname must appear in the request's Host: header to + # match this virtual host. For the default virtual host (this file) this + # value is not decisive as it is used as a last resort host regardless. + # However, you must set it for any further virtual host explicitly. + + ServerAdmin support@mydomain.edu + ServerName myserver.mydomain.edu + ServerAlias myserver.mydomain.edu + + DocumentRoot /var/www/html + + UseCanonicalName On + + # Available loglevels: trace8, ..., trace1, debug, info, notice, warn, + # error, crit, alert, emerg. + # It is also possible to configure the loglevel for particular + # modules, e.g. + #LogLevel info ssl:warn + + ErrorLog ${APACHE_LOG_DIR}/error.log + CustomLog ${APACHE_LOG_DIR}/access.log combined + + # For most configuration files from conf-available/, which are + # enabled or disabled at a global level, it is possible to + # include a line for only one particular virtual host. For example the + # following line enables the CGI configuration for this host only + # after it has been globally disabled with "a2disconf". + #Include conf-available/serve-cgi-bin.conf + + +# vim: syntax=apache ts=4 sw=4 sts=4 sr noet diff --git a/docker-config/apache/apache2.conf b/docker-config/apache/apache2.conf new file mode 100644 index 0000000000..e9de2b7880 --- /dev/null +++ b/docker-config/apache/apache2.conf @@ -0,0 +1,234 @@ +# This is the main Apache server configuration file. It contains the +# configuration directives that give the server its instructions. +# See http://httpd.apache.org/docs/2.4/ for detailed information about +# the directives and /usr/share/doc/apache2/README.Debian about Debian specific +# hints. +# +# +# Summary of how the Apache 2 configuration works in Debian: +# The Apache 2 web server configuration in Debian is quite different to +# upstream's suggested way to configure the web server. This is because Debian's +# default Apache2 installation attempts to make adding and removing modules, +# virtual hosts, and extra configuration directives as flexible as possible, in +# order to make automating the changes and administering the server as easy as +# possible. + +# It is split into several files forming the configuration hierarchy outlined +# below, all located in the /etc/apache2/ directory: +# +# /etc/apache2/ +# |-- apache2.conf +# | `-- ports.conf +# |-- mods-enabled +# | |-- *.load +# | `-- *.conf +# |-- conf-enabled +# | `-- *.conf +# `-- sites-enabled +# `-- *.conf +# +# +# * apache2.conf is the main configuration file (this file). It puts the pieces +# together by including all remaining configuration files when starting up the +# web server. +# +# * ports.conf is always included from the main configuration file. It is +# supposed to determine listening ports for incoming connections which can be +# customized anytime. +# +# * Configuration files in the mods-enabled/, conf-enabled/ and sites-enabled/ +# directories contain particular configuration snippets which manage modules, +# global configuration fragments, or virtual host configurations, +# respectively. +# +# They are activated by symlinking available configuration files from their +# respective *-available/ counterparts. These should be managed by using our +# helpers a2enmod/a2dismod, a2ensite/a2dissite and a2enconf/a2disconf. See +# their respective man pages for detailed information. +# +# * The binary is called apache2. Due to the use of environment variables, in +# the default configuration, apache2 needs to be started/stopped with +# /etc/init.d/apache2 or apache2ctl. Calling /usr/bin/apache2 directly will not +# work with the default configuration. + + +# Global configuration +# + +ServerName myserver.mydomain.edu +ServerAdmin support@mydomain.edu + +# +# ServerRoot: The top of the directory tree under which the server's +# configuration, error, and log files are kept. +# +# NOTE! If you intend to place this on an NFS (or otherwise network) +# mounted filesystem then please read the Mutex documentation (available +# at ); +# you will save yourself a lot of trouble. +# +# Do NOT add a slash at the end of the directory path. +# +#ServerRoot "/etc/apache2" + +# +# The accept serialization lock file MUST BE STORED ON A LOCAL DISK. +# +#Mutex file:${APACHE_LOCK_DIR} default + +# +# The directory where shm and other runtime files will be stored. +# + +DefaultRuntimeDir ${APACHE_RUN_DIR} + +# +# PidFile: The file in which the server should record its process +# identification number when it starts. +# This needs to be set in /etc/apache2/envvars +# +PidFile ${APACHE_PID_FILE} + +# +# Timeout: The number of seconds before receives and sends time out. +# +Timeout 1200 + +# +# KeepAlive: Whether or not to allow persistent connections (more than +# one request per connection). Set to "Off" to deactivate. +# +KeepAlive On + +# +# MaxKeepAliveRequests: The maximum number of requests to allow +# during a persistent connection. Set to 0 to allow an unlimited amount. +# We recommend you leave this number high, for maximum performance. +# +MaxKeepAliveRequests 100 + +# +# KeepAliveTimeout: Number of seconds to wait for the next request from the +# same client on the same connection. +# +KeepAliveTimeout 5 + + +# These need to be set in /etc/apache2/envvars +User ${APACHE_RUN_USER} +Group ${APACHE_RUN_GROUP} + +# +# HostnameLookups: Log the names of clients or just their IP addresses +# e.g., www.apache.org (on) or 204.62.129.132 (off). +# The default is off because it'd be overall better for the net if people +# had to knowingly turn this feature on, since enabling it means that +# each client request will result in AT LEAST one lookup request to the +# nameserver. +# +HostnameLookups Off + +# ErrorLog: The location of the error log file. +# If you do not specify an ErrorLog directive within a +# container, error messages relating to that virtual host will be +# logged here. If you *do* define an error logfile for a +# container, that host's errors will be logged there and not here. +# +ErrorLog ${APACHE_LOG_DIR}/error.log + +# +# LogLevel: Control the severity of messages logged to the error_log. +# Available values: trace8, ..., trace1, debug, info, notice, warn, +# error, crit, alert, emerg. +# It is also possible to configure the log level for particular modules, e.g. +# "LogLevel info ssl:warn" +# +LogLevel warn + +# Include module configuration: +IncludeOptional mods-enabled/*.load +IncludeOptional mods-enabled/*.conf + +# Include list of ports to listen on +Include ports.conf + + +# Sets the default security model of the Apache2 HTTPD server. It does +# not allow access to the root filesystem outside of /usr/share and /var/www. +# The former is used by web applications packaged in Debian, +# the latter may be used for local directories served by the web server. If +# your system is serving content from a sub-directory in /srv you must allow +# access here, or in any related virtual host. + + Options FollowSymLinks + AllowOverride None + Require all denied + + + + AllowOverride None + Require all granted + + + + Options Indexes FollowSymLinks + AllowOverride None + Require all granted + + + + Options Indexes FollowSymLinks + AllowOverride All + Require all granted + + +# +# Options Indexes FollowSymLinks +# AllowOverride None +# Require all granted +# + + +# AccessFileName: The name of the file to look for in each directory +# for additional configuration directives. See also the AllowOverride +# directive. +# +AccessFileName .htaccess + +# +# The following lines prevent .htaccess and .htpasswd files from being +# viewed by Web clients. +# + + Require all denied + + + +# +# The following directives define some format nicknames for use with +# a CustomLog directive. +# +# These deviate from the Common Log Format definitions in that they use %O +# (the actual bytes sent including headers) instead of %b (the size of the +# requested file), because the latter makes it impossible to detect partial +# requests. +# +# Note that the use of %{X-Forwarded-For}i instead of %h is not recommended. +# Use mod_remoteip instead. +# +LogFormat "%v:%p %h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" vhost_combined +LogFormat "%h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" combined +LogFormat "%h %l %u %t \"%r\" %>s %O" common +LogFormat "%{Referer}i -> %U" referer +LogFormat "%{User-agent}i" agent + +# Include of directories ignores editors' and dpkg's backup files, +# see README.Debian for details. + +# Include generic snippets of statements +IncludeOptional conf-enabled/*.conf + +# Include the virtual host configurations: +IncludeOptional sites-enabled/*.conf + +# vim: syntax=apache ts=4 sw=4 sts=4 sr noet diff --git a/docker-config/apache/htaccess b/docker-config/apache/htaccess new file mode 100644 index 0000000000..0003da531b --- /dev/null +++ b/docker-config/apache/htaccess @@ -0,0 +1 @@ +Redirect /index.html https://myserver.mydomain.edu/webwork2/ diff --git a/docker-config/apache/index.html b/docker-config/apache/index.html new file mode 100644 index 0000000000..dc2ebed7f7 --- /dev/null +++ b/docker-config/apache/index.html @@ -0,0 +1,12 @@ + + + + + WeBWorK site - redirects to main page + + + You probably want to use the + the WeBWorK list of courses page + + + diff --git a/docker-config/apache/mpm_prefork.conf b/docker-config/apache/mpm_prefork.conf new file mode 100644 index 0000000000..1ebb9aba57 --- /dev/null +++ b/docker-config/apache/mpm_prefork.conf @@ -0,0 +1,19 @@ +# prefork MPM +# StartServers: number of server processes to start +# MinSpareServers: minimum number of server processes which are kept spare +# MaxSpareServers: maximum number of server processes which are kept spare +# MaxRequestWorkers: maximum number of server processes allowed to start +# MaxConnectionsPerChild: maximum number of requests a server process serves + + + StartServers 5 + MinSpareServers 5 + MaxSpareServers 15 + MaxRequestWorkers 20 + MaxConnectionsPerChild 50 + + +# Was MaxRequestWorkers 30 +# Was MaxConnectionsPerChild 100 +# +# vim: syntax=apache ts=4 sw=4 sts=4 sr noet diff --git a/docker-config/db/mariadb.cnf b/docker-config/db/mariadb.cnf index 22c4abce0b..88245b35b9 100644 --- a/docker-config/db/mariadb.cnf +++ b/docker-config/db/mariadb.cnf @@ -32,3 +32,13 @@ character_set_server = utf8mb4 collation_server = utf8mb4_general_ci init-connect='SET NAMES utf8mb4' +# Increase max_connections +max_connections = 500 + +# Modify: +# wait_timeout (default usually 28800), +# interactive_timeout (default usually 28800), +# net_read_timeout (default usually 60) +wait_timeout = 28800 +interactive_timeout = 28800 +net_read_timeout = 3600 diff --git a/docker-config/docker-entrypoint.sh b/docker-config/docker-entrypoint.sh new file mode 100755 index 0000000000..31d944aad9 --- /dev/null +++ b/docker-config/docker-entrypoint.sh @@ -0,0 +1,201 @@ +#!/bin/bash +set -eo pipefail + +function wait_for_db { + echo "Waiting for database to become available..." + while ! timeout 1 bash -c "(cat < /dev/null > /dev/tcp/$WEBWORK_DB_HOST/$WEBWORK_DB_PORT) >/dev/null 2>&1"; do \ + echo "waiting..." + sleep 0.5; \ + done +} +# if command starts with an option, prepend apache2 +if [ "${1:0:1}" = '-' ]; then + set -- apache2 "$@" +fi + +# Enable SSL when it is requested by the SSL environment variable +if [ $SSL -eq 1 ]; then + echo "Enabling SSL" + a2enmod ssl && a2ensite default-ssl +fi + +# Build more locales +if [ "$ADD_LOCALES" != "0" ]; then + echo "Rebulding locales - adding: $ADD_LOCALES" + cp -a /etc/locale.gen /etc/locale.gen.orig + /bin/echo -e "en_US ISO-8859-1\nen_US.UTF-8 UTF-8\n$ADD_LOCALES" > /etc/locale.gen.tmp + /usr/bin/tr "," "\n" < /etc/locale.gen.tmp > /etc/locale.gen + rm /etc/locale.gen.orig + /usr/sbin/locale-gen +fi + +# Set system timezone if not the default UTC +if [ "$SYSTEM_TIMEZONE" != "UTC" ]; then + echo "Setting system timezone to $SYSTEM_TIMEZONE" + rm /etc/localtime + rm /etc/timezone + echo "$SYSTEM_TIMEZONE" > /etc/timezone + dpkg-reconfigure -f noninteractive tzdata +fi + +# Modify default papersize based on environment variable PAPERSIZE +echo "Setting libpaper1 papersize to $PAPERSIZE" +echo "libpaper1 libpaper/defaultpaper select $PAPERSIZE\nlibpaper1:amd64 libpaper/defaultpaper select $PAPERSIZE\ndebconf debconf/frontend select Noninteractive" > /tmp/preseed.txt +debconf-set-selections /tmp/preseed.txt +dpkg-reconfigure -f noninteractive libpaper1 + +# Install some extra packages +if [ "$ADD_PACKAGES" != "0" ]; then + apt-get update + apt-get install -y --no-install-recommends --no-install-suggests $ADD_PACKAGES +fi + +# If necessary, install the OPL in the running container, hopefully in persistent storage +if [ ! -d "$APP_ROOT/libraries/webwork-open-problem-library/OpenProblemLibrary" ]; then + echo "Installing the OPL - This takes time - please be patient." + cd $APP_ROOT/libraries/ + /usr/bin/git clone -v --progress --single-branch --branch master https://github.com/openwebwork/webwork-open-problem-library.git + + # FIXME / TO-DO : Download a saved version of the OPL sql table data to be loaded and extract + # it in the appropriate location.This would avoid the need for a length run of OPL-update. + # At present, a distribution point has not been set up for such data. + + # The next line forces the system to run OPL-update or load saved OPL tables below, as we just installed it + touch "$APP_ROOT/libraries/Restore_or_build_OPL_tables" +fi + +if [ "$1" = 'apache2' ]; then + # generate conf files if not exist + for i in site.conf localOverrides.conf; do + if [ ! -f $WEBWORK_ROOT/conf/$i ]; then + echo "Creating a new $WEBWORK_ROOT/conf/$i" + cp $WEBWORK_ROOT/conf/$i.dist $WEBWORK_ROOT/conf/$i + if [ $i == 'site.conf' ]; then + sed -i -e 's/webwork_url = '\''\/webwork2'\''/webwork_url = $ENV{"WEBWORK_URL"}/' \ + -e 's/server_root_url = '\'''\''/server_root_url = $ENV{"WEBWORK_ROOT_URL"}/' \ + -e 's/database_dsn ="dbi:mysql:webwork"/database_dsn =$ENV{"WEBWORK_DB_DSN"}/' \ + -e 's/database_username ="webworkWrite"/database_username =$ENV{"WEBWORK_DB_USER"}/' \ + -e 's/database_password ="passwordRW"/database_password =$ENV{"WEBWORK_DB_PASSWORD"}/' \ + -e 's/mail{smtpServer} = '\'''\''/mail{smtpServer} = $ENV{"WEBWORK_SMTP_SERVER"}/' \ + -e 's/mail{smtpSender} = '\'''\''/mail{smtpSender} = $ENV{"WEBWORK_SMTP_SENDER"}/' \ + -e 's/siteDefaults{timezone} = "America\/New_York"/siteDefaults{timezone} = $ENV{"WEBWORK_TIMEZONE"}/' \ + -e 's/$server_groupID = '\''wwdata'\''/$server_groupID = "www-data"/' \ + $WEBWORK_ROOT/conf/site.conf + fi + fi + done + # create admin course if not existing + if [ ! -d "$APP_ROOT/courses/admin" ]; then + newgrp www-data + umask 2 + cd $APP_ROOT/courses + wait_for_db + $WEBWORK_ROOT/bin/addcourse admin --db-layout=sql_single --users=$WEBWORK_ROOT/courses.dist/adminClasslist.lst --professors=admin + chown www-data:www-data -R $APP_ROOT/courses + echo "Admin course is created." + fi + # modelCourses link if not existing + if [ ! -d "$APP_ROOT/courses/modelCourse" ]; then + echo "create modelCourse subdirectory" + rm -rf $APP_ROOT/courses/modelCourse + cd $WEBWORK_ROOT/courses.dist + cp -R modelCourse $APP_ROOT/courses/ + fi + # create htdocs/tmp directory if not existing + if [ ! -d "$WEBWORK_ROOT/htdocs/tmp" ]; then + echo "Creating htdocs/tmp directory" + mkdir $WEBWORK_ROOT/htdocs/tmp + chown www-data:www-data -R $WEBWORK_ROOT/htdocs/tmp + echo "htdocs/tmp directory created" + fi + + # defaultClasslist.lst and adminClasslist.lst files if not existing + if [ ! -f "$APP_ROOT/courses/defaultClasslist.lst" ]; then + echo "defaultClasslist.lst is being created" + cd $WEBWORK_ROOT/courses.dist + cp *.lst $APP_ROOT/courses/ + fi + if [ ! -f "$APP_ROOT/courses/adminClasslist.lst" ]; then + echo "adminClasslist.lst is being created" + cd $WEBWORK_ROOT/courses.dist + cp *.lst $APP_ROOT/courses/ + fi + # run OPL-update if necessary + if [ ! -f "$WEBWORK_ROOT/htdocs/DATA/tagging-taxonomy.json" ]; then + # The next line forces the system to run OPL-update below, as the + # tagging-taxonomy.json file was found to be missing. + if [ -f "$APP_ROOT/libraries/webwork-open-problem-library/TABLE-DUMP/OPL-tables.sql" ]; then + echo "The tagging-taxonomy.json file is missing in webwork2/htdocs/DATA/." + echo "But the libraries/webwork-open-problem-library/TABLE-DUMP/OPL-tables.sql files was seen" + echo "so the OPL tables and the JSON files will (hopefully) be restored from save versions" + else + echo "We will run OPL-update as the tagging-taxonomy.json file is missing in webwork2/htdocs/DATA/." + echo "Check if you should be mounting webwork2/htdocs/DATA/ from outside the Docker image!" + fi + touch "$APP_ROOT/libraries/Restore_or_build_OPL_tables" + fi + if [ -f "$APP_ROOT/libraries/Restore_or_build_OPL_tables" ]; then + if [ -f "$APP_ROOT/libraries/webwork-open-problem-library/TABLE-DUMP/OPL-tables.sql" ]; then + echo "Restoring OPL tables from the TABLE-DUMP/OPL-tables.sql file" + wait_for_db + $WEBWORK_ROOT/bin/restore-OPL-tables.pl + $WEBWORK_ROOT/bin/load-OPL-global-statistics.pl + if [ -d $APP_ROOT/libraries/webwork-open-problem-library/JSON-SAVED ]; then + # Restore saved JSON files + echo "Restoring JSON files from JSON-SAVED directory" + cp -a $APP_ROOT/libraries/webwork-open-problem-library/JSON-SAVED/*.json $WEBWORK_ROOT/htdocs/DATA/ + else + echo "No webwork-open-problem-library/JSON-SAVED directory was found." + echo "You are missing some of the JSON files including tagging-taxonomy.json" + echo "Some of the library functions will not work properly" + fi + else + echo "About to start OPL-update. This takes a long time - please be patient." + wait_for_db + $WEBWORK_ROOT/bin/OPL-update + # Dump the OPL tables, to allow a quick restore in the future + $WEBWORK_ROOT/bin/dump-OPL-tables.pl + # Save a copy of the generated JSON files + mkdir -p $APP_ROOT/libraries/webwork-open-problem-library/JSON-SAVED + cp -a $WEBWORK_ROOT/htdocs/DATA/*.json $APP_ROOT/libraries/webwork-open-problem-library/JSON-SAVED + fi + rm $APP_ROOT/libraries/Restore_or_build_OPL_tables + fi + # Compile chromatic/color.c if necessary - may be needed for PG directory mounted from outside image + if [ ! -f "$APP_ROOT/pg/lib/chromatic/color" ]; then + cd $APP_ROOT/pg/lib/chromatic + gcc color.c -o color + fi + # generate apache2 reload config if needed + if [ $DEV -eq 1 ]; then + echo "PerlModule Apache2::Reload" >> /etc/apache2/conf-enabled/apache2-reload.conf + echo "PerlInitHandler Apache2::Reload" >> /etc/apache2/conf-enabled/apache2-reload.conf + echo "Running in DEV mode..." + else + if [ $SSL -eq 0 ]; then + rm -f /etc/apache2/conf-enabled/apache2-reload.conf + fi + fi + + # Fix possible permission issues + echo "Fixing ownership and permissions (just in case it is needed)" + cd $WEBWORK_ROOT + # Symbolic links which have no target outside the Docker container + # cause problems duringt the rebuild process on some systems. + # So we delete them. They will be rebuilt automatically when needed again + # at the cost of some speed. + find htdocs/tmp -type l -exec rm -f {} \; + chown -R www-data:www-data logs tmp DATA htdocs/tmp + chmod -R u+w logs tmp DATA ../courses htdocs/tmp + cd $APP_ROOT + # The chown for files/directories under courses is done using find, as + # using a simple "chown -R www-data $APP_ROOT/courses" would sometimes + # cause errors in Docker on Mac OS X when there was a broken symbolic link + # somewhere in the directory tree being processed. + find courses -type f -exec chown www-data:www-data {} \; + find courses -type d -exec chown www-data:www-data {} \; + echo "end fixing ownership and permissions" + +fi + +exec "$@" diff --git a/docker-config/ssl/default-ssl.conf b/docker-config/ssl/default-ssl.conf new file mode 100644 index 0000000000..0bd30d4292 --- /dev/null +++ b/docker-config/ssl/default-ssl.conf @@ -0,0 +1,45 @@ + + + # This fake virtual host is intented to capture traffic which + # spoofs the "Host:" header value for security reasons. + # It will deny ALL such traffic. + ServerName fake + DocumentRoot "/var/www/html/" + SSLEngine on + SSLCertificateFile /etc/ssl/local/my.crt + SSLCertificateKeyFile /etc/ssl/local/my.key + SSLCertificateChainFile /etc/ssl/local/myCA_chain.crt + + Order deny,allow + deny from all + + + + + ServerAdmin support@mydomain.edu + DocumentRoot /var/www/html/ + ServerName myserver.mydomain.edu + ServerAlias myserver.mydomain.edu + + UseCanonicalName On + + ErrorLog ${APACHE_LOG_DIR}/error.log + CustomLog ${APACHE_LOG_DIR}/access.log combined + + SSLEngine on + + SSLCertificateFile /etc/ssl/local/my.crt + SSLCertificateKeyFile /etc/ssl/local/my.key + SSLCertificateChainFile /etc/ssl/local/myCA_chain.crt + + + SSLOptions +StdEnvVars + + + SSLOptions +StdEnvVars + + + + + +# vim: syntax=apache ts=4 sw=4 sts=4 sr noet diff --git a/docker-config/ssl/local/PutYourCertificate_and_key_here.txt b/docker-config/ssl/local/PutYourCertificate_and_key_here.txt new file mode 100644 index 0000000000..a1eb1a947d --- /dev/null +++ b/docker-config/ssl/local/PutYourCertificate_and_key_here.txt @@ -0,0 +1,8 @@ +This directory should have your real SSL key and certificate, and +the Certificate Authority's root certificate or certrificate chain. + +The file names should match those defined in default-ssl.conf, ex: + + SSLCertificateFile /etc/ssl/local/my.crt + SSLCertificateKeyFile /etc/ssl/local/my.key + SSLCertificateChainFile /etc/ssl/local/myCA_chain.crt diff --git a/docker-config/ssl/local/my.crt b/docker-config/ssl/local/my.crt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/docker-config/ssl/local/my.key b/docker-config/ssl/local/my.key new file mode 100644 index 0000000000..e69de29bb2 diff --git a/docker-config/ssl/local/myCA_chain.crt b/docker-config/ssl/local/myCA_chain.crt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/docker-config/ssl/ssl.conf b/docker-config/ssl/ssl.conf new file mode 100644 index 0000000000..7e364639e9 --- /dev/null +++ b/docker-config/ssl/ssl.conf @@ -0,0 +1,85 @@ + + + # Pseudo Random Number Generator (PRNG): + # Configure one or more sources to seed the PRNG of the SSL library. + # The seed data should be of good random quality. + # WARNING! On some platforms /dev/random blocks if not enough entropy + # is available. This means you then cannot use the /dev/random device + # because it would lead to very long connection times (as long as + # it requires to make more entropy available). But usually those + # platforms additionally provide a /dev/urandom device which doesn't + # block. So, if available, use this one instead. Read the mod_ssl User + # Manual for more details. + # + SSLRandomSeed startup builtin + SSLRandomSeed startup file:/dev/urandom 512 + SSLRandomSeed connect builtin + SSLRandomSeed connect file:/dev/urandom 512 + + ## + ## SSL Global Context + ## + ## All SSL configuration in this context applies both to + ## the main server and all SSL-enabled virtual hosts. + ## + + # + # Some MIME-types for downloading Certificates and CRLs + # + AddType application/x-x509-ca-cert .crt + AddType application/x-pkcs7-crl .crl + + # Pass Phrase Dialog: + # Configure the pass phrase gathering process. + # The filtering dialog program (`builtin' is a internal + # terminal dialog) has to provide the pass phrase on stdout. + SSLPassPhraseDialog exec:/usr/share/apache2/ask-for-passphrase + + # Inter-Process Session Cache: + # Configure the SSL Session Cache: First the mechanism + # to use and second the expiring timeout (in seconds). + # (The mechanism dbm has known memory leaks and should not be used). + #SSLSessionCache dbm:${APACHE_RUN_DIR}/ssl_scache + SSLSessionCache shmcb:${APACHE_RUN_DIR}/ssl_scache(512000) + SSLSessionCacheTimeout 300 + + # Semaphore: + # Configure the path to the mutual exclusion semaphore the + # SSL engine uses internally for inter-process synchronization. + # (Disabled by default, the global Mutex directive consolidates by default + # this) + #Mutex file:${APACHE_LOCK_DIR}/ssl_mutex ssl-cache + + + # SSL Cipher Suite: + # List the ciphers that the client is permitted to negotiate. See the + # ciphers(1) man page from the openssl package for list of all available + # options. + # Enable only secure ciphers: + SSLCipherSuite HIGH:!aNULL + + # SSL server cipher order preference: + # Use server priorities for cipher algorithm choice. + # Clients may prefer lower grade encryption. You should enable this + # option if you want to enforce stronger encryption, and can afford + # the CPU cost, and did not override SSLCipherSuite in a way that puts + # insecure ciphers first. + # Default: Off + #SSLHonorCipherOrder on + + # The protocols to enable. + # Available values: all, SSLv3, TLSv1, TLSv1.1, TLSv1.2 + # SSL v2 is no longer supported + SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1 + + # Allow insecure renegotiation with clients which do not yet support the + # secure renegotiation protocol. Default: Off + #SSLInsecureRenegotiation on + + # Whether to forbid non-SNI clients to access name based virtual hosts. + # Default: Off + #SSLStrictSNIVHostCheck On + + + +# vim: syntax=apache ts=4 sw=4 sts=4 sr noet diff --git a/docker-entrypoint.sh b/docker-entrypoint.sh deleted file mode 100755 index 7860cee2f5..0000000000 --- a/docker-entrypoint.sh +++ /dev/null @@ -1,101 +0,0 @@ -#!/bin/bash -set -eo pipefail - -# if command starts with an option, prepend apache2 -if [ "${1:0:1}" = '-' ]; then - set -- apache2 "$@" -fi - - - -if [ "$1" = 'apache2' ]; then - # generate conf files if not exist - for i in site.conf localOverrides.conf; do - if [ ! -f $APP_ROOT/webwork2/conf/$i ]; then - cp $APP_ROOT/webwork2/conf/$i.dist $APP_ROOT/webwork2/conf/$i - if [ $i == 'site.conf' ]; then - sed -i -e 's/webwork_url = '\''\/webwork2'\''/webwork_url = $ENV{"WEBWORK_URL"}/' \ - -e 's/server_root_url = '\'''\''/server_root_url = $ENV{"WEBWORK_ROOT_URL"}/' \ - -e 's/database_dsn ="dbi:mysql:webwork"/database_dsn =$ENV{"WEBWORK_DB_DSN"}/' \ - -e 's/database_username ="webworkWrite"/database_username =$ENV{"WEBWORK_DB_USER"}/' \ - -e 's/database_password ="passwordRW"/database_password =$ENV{"WEBWORK_DB_PASSWORD"}/' \ - -e 's/mail{smtpServer} = '\'''\''/mail{smtpServer} = $ENV{"WEBWORK_SMTP_SERVER"}/' \ - -e 's/mail{smtpSender} = '\'''\''/mail{smtpSender} = $ENV{"WEBWORK_SMTP_SENDER"}/' \ - -e 's/siteDefaults{timezone} = "America\/New_York"/siteDefaults{timezone} = $ENV{"WEBWORK_TIMEZONE"}/' \ - -e 's/$server_groupID = '\''wwdata'\''/$server_groupID = "root"/' \ - $APP_ROOT/webwork2/conf/site.conf - fi - fi - done - # create admin course if not existing - if [ ! -d "$APP_ROOT/courses/admin" ]; then - # wait for db to start up - echo "Waiting for database to start..." - while ! timeout 1 bash -c "(cat < /dev/null > /dev/tcp/$WEBWORK_DB_HOST/$WEBWORK_DB_PORT) >/dev/null 2>&1"; do sleep 0.5; done - newgrp www-data - umask 2 - cd $APP_ROOT/courses - WEBWORK_ROOT=$APP_ROOT/webwork2 $APP_ROOT/webwork2/bin/addcourse admin --db-layout=sql_single --users=$APP_ROOT/webwork2/courses.dist/adminClasslist.lst --professors=admin - chown www-data:root -R $APP_ROOT/courses - echo "Admin course is created." - fi - # modelCourses link if not existing - if [ ! -d "$APP_ROOT/courses/modelCourse" ]; then - echo "create modelCourse subdirectory" - rm -rf $APP_ROOT/courses/modelCourse - cd $APP_ROOT/webwork2/courses.dist - cp -R modelCourse $APP_ROOT/courses/ - fi - # create htdocs/tmp directory if not existing - if [ ! -d "$APP_ROOT/webwork2/htdocs/tmp" ]; then - mkdir $APP_ROOT/webwork2/htdocs/tmp - echo "htdocs/tmp directory created" - fi - chown www-data:root -R $APP_ROOT/webwork2/htdocs/tmp - - # defaultClasslist.lst and adminClasslist.lst files if not existing - if [ ! -f "$APP_ROOT/courses/defaultClasslist.lst" ]; then - echo "defaultClasslist.lst is being created" - cd $APP_ROOT/webwork2/courses.dist - cp *.lst $APP_ROOT/courses/ - fi - if [ ! -f "$APP_ROOT/courses/adminClasslist.lst" ]; then - echo "adminClasslist.lst is being created" - cd $APP_ROOT/webwork2/courses.dist - cp *.lst $APP_ROOT/courses/ - fi - # run OPL-update if necessary - if [ ! -f "$APP_ROOT/webwork2/htdocs/DATA/tagging-taxonomy.json" ]; then - cd $APP_ROOT/webwork2/bin - ./OPL-update - fi - - # generate apache2 reload config if needed - if [ $DEV -eq 1 ]; then - echo "PerlModule Apache2::Reload" > /etc/apache2/conf-enabled/apache2-reload.conf - echo "PerlInitHandler Apache2::Reload" >> /etc/apache2/conf-enabled/apache2-reload.conf - echo "Running in DEV mode..." - else - rm -f /etc/apache2/conf-enabled/apache2-reload.conf - fi - - # Fix possible permission issues - echo "Fixing ownership and permissions (just in case it is needed)" - cd $APP_ROOT/webwork2 - rm -rf htdocs/tmp/* # pointers which which have no target shut down the rebuild process. - # the tmp directory is rebuilt automatically at the cost of some speed. - chown -R www-data logs tmp DATA htdocs/tmp - chmod -R u+w logs tmp DATA ../courses htdocs/tmp - cd $APP_ROOT - find courses -type f -exec chown www-data:root {} \; - find courses -type d -exec chown www-data:root {} \; - - # echo "start cpan install XML::Simple" - # cpan install XML::Simple - # echo "end fixing ownership and permissions" - # OLD: chown www-data -R $APP_ROOT/courses - # but that sometimes caused errors in Docker on Mac OS X when there was a broken symbolic link somewhere in the directory tree being processed - -fi - - exec "$@"