diff --git a/.gitignore b/.gitignore index 67b22fe..377c213 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,16 @@ html/* perldoc-browser.conf perldoc-browser.sqlite* hypnotoad.pid + +#Project Files +.project + +#Container Runtime Content +.bash_history +.cpanm +.cpanm/* +perl5 +perl5/* + +#Local Docker-Compose Configuration +docker-compose.yml diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..fac0779 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,26 @@ +FROM debian:buster +RUN apt-get update &&\ + apt-get -y install apt-utils gcc make openssl &&\ + apt-get -y install cpanminus perl-modules perl-doc liblocal-lib-perl &&\ + apt-get -y install libdbi-perl libfile-pushd-perl libipc-run3-perl libmodule-runtime-perl libsort-versions-perl libdevel-patchperl-perl libmodule-build-tiny-perl libmodule-pluggable-perl\ + libsyntax-keyword-try-perl libcapture-tiny-perl libhttp-tinyish-perl libnet-ssleay-perl\ + liburl-encode-perl libextutils-config-perl libextutils-helpers-perl libextutils-installpaths-perl\ + libclone-choose-perl libhash-merge-perl libtest-deep-perl liburi-nested-perl\ + libsql-abstract-perl liburi-db-perl libdbd-sqlite3-perl +RUN mkdir -p /usr/share/perldoc-browser/log +COPY cpanfile cpanfile-cpandoc /usr/share/perldoc-browser/ +RUN cd /usr/share/perldoc-browser/\ + && date +"%s" > log/cpanm_install_$(date +"%F").log\ + ; cpanm -vn --installdeps --with-feature=sqlite . 2>&1 >> log/cpanm_install_$(date +"%F").log\ + ; date +"%s" >> log/cpanm_install_$(date +"%F").log +COPY etc/docker/entrypoint.sh /usr/local/bin/ +RUN chmod a+x /usr/local/bin/entrypoint.sh\ + && ln -s /usr/local/bin/entrypoint.sh /entrypoint.sh # backwards compat +RUN groupadd web &&\ + useradd per1_web -g web -md /home/perldoc-browser -s /sbin/nologin &&\ + chmod a+rx /home/perldoc-browser +VOLUME /home/perldoc-browser +USER per1_web +WORKDIR /home/perldoc-browser +ENTRYPOINT ["entrypoint.sh"] +CMD ["perldoc-browser.pl", "prefork"] diff --git a/docker-compose.yml.example b/docker-compose.yml.example new file mode 100644 index 0000000..e871fa0 --- /dev/null +++ b/docker-compose.yml.example @@ -0,0 +1,12 @@ +version: '3' +services: + web: + container_name: 'perldoc_web' + image: perldoc_web + build: . + ports: + - "3000:3000" + volumes: + - /absolute/path/to/project:/home/perldoc-browser:Z + environment: + - COMPONENT=perldoc_web diff --git a/etc/docker/README.pod b/etc/docker/README.pod new file mode 100644 index 0000000..909798c --- /dev/null +++ b/etc/docker/README.pod @@ -0,0 +1,116 @@ +=head1 NAME + +Perldoc Browser - Docker Deployment + +=head1 DESCRIPTION + +The Objective of the C is to be able to run the C Command in +a seperate Docker Container. +It can be useful to run C Test Suites. + +=head1 REQUIREMENTS + +To build and run the Docker Container the Minimum Requirement is to have the C Service installed. +Additionally the C Command can provide a nice enhancement to ease the Operation +of the Docker Container. + +=head1 INSTALLATION + +=over + +=item docker-compose + +To run the Docker Container with the C Command the C Package should +be installed first. The C Package is provided by most Linux Distributions. + +=item Docker Engine + +Next the C Service has to be installed locally. +if you want to use C it is recommended to do this step first because +the C installation can break your Docker Engine installation. +To install the Docker Engine it is recommended to follow the guides of the Official Documentation +L + +=back + +=head1 IMAGE BUILD + +=over 4 + +=item Preconditions + +=over 2 + +=item * The Docker Service must be running + +=item * Build User must have access to the Docker Service (perhaps C access is required) + +=item * Current Working Directory must be the Project Root Directory + +=item * The C Build requires a F file which can be created + from the F file + +=back + +=item Build with Docker + +The Container Image for the C Web Service was called "I" to difference it +from the Backend Container Image. +So the command to build the docker image is: + + docker build -t perldoc_web . + +=item Build with C + +To build the Container Image with C a F file is required. +It can be created from the F file by copying it. +Within the F file the entry C must be configured to +contain the absolute path to the Project Root Directory on the system. +The F file contains instructions to expose the C Web Service +on Port C<3000> which seems to be the default behaviour for the Application. +If the Application was configured to listen on a different port the file entry C +must be adjusted accordingly. +So the command to build the docker image and launch it is: + + docker-compose up --build + +=back + +=head1 IMAGE INITIALISATION + +=over + +=item C Installation + +As discussed in the task issue L the +installation of the I Modules for the SQLite Backend from the F was executed at Image Build Time. +So on updates of the F it is recommendable to rebuild the Container Image as described above +under B. + +The used F can be found in F within the Docker Image. +Also the C Installation Log is found inside the Image in F. + +To inspect the Docker Image run the command: + + docker run -it -v /absolute/path/to/project:/home/perldoc-browser:Z perldoc_web bash + +This will give a C shell and the file system can be inspected. + +Still the Start-Up Script will detect a different backend configuration or the +C Command and check whether key dependencies are met and run the +C Installation accordingly + +=item populating the search backend + +The new built Container Image contains an empty C Installation +To run correctly the Search Backend needs to be populated. +So the command to populate the Search Backend is: + + docker run -it -v /absolute/path/to/project:/home/perldoc-browser:Z perldoc_web perldoc-browser.pl index all + +This will execute command C in the project directory. +The results will be stored persistently in the project directory for further container launches. + +=back + +=cut diff --git a/etc/docker/entrypoint.sh b/etc/docker/entrypoint.sh new file mode 100644 index 0000000..b679a69 --- /dev/null +++ b/etc/docker/entrypoint.sh @@ -0,0 +1,196 @@ +#!/bin/sh + + + +set -e + +SERVER=`cat /etc/hostname` + +MDNM=`basename $0` + +echo "Container '${SERVER}.${COMPONENT}': '$MDNM' go ..." + +echo "Container '${SERVER}.${COMPONENT}' - Network:" + +echo `cat -A /etc/hosts` + + +if [ "$1" = "perldoc-browser.pl" ]; then + sfeatures="" + sfeatoptions="" + icpanm=0 + + echo "Command: '$@'" + + echo "Configuring Local Installation ..." + perl -Mlocal::lib ; + eval $(perl -I ~/perl5/lib/perl5/ -Mlocal::lib) ; + + echo -n "Mojolicious Version: " + + perl -MMojolicious -e 'print $Mojolicious::VERSION; ' 2>/dev/null 1>log/perl_mojolicious.log ||\ + iresult=$? + + if [ -z "$iresult" ]; then + iresult=0 + fi + + mojolicious=`cat log/perl_mojolicious.log` + + if [ -n "$mojolicious" ]; then + echo "$mojolicious [Code: '$iresult']" + else + echo "NONE [Code: '$iresult']" + + #Trigger cpanm Installation + icpanm=1 + fi #if [ -n "$mojolicious" ]; then + + echo -n "Search Backend: " + + cat perldoc-browser.conf 2>/dev/null | grep -i search_backend | cut -d"=" -f2 | cut -d"'" -f2 >log/web_backend.log ||\ + iresult=$? + + backend=`cat log/web_backend.log` + + if [ -z "$backend" ]; then + echo "not recognized [Code: '$iresult']!" + echo "Falling back to SQLite Backend ..." + backend="sqlite" + else + echo "$backend" + fi #if [ -z "$backend" ]; then + + if [ -n "$backend" ]; then + sfeatures="${sfeatures}${backend}" + fi + + case "$backend" in + sqlite) + #Checking Dependencies for SQLite Backend + + echo -n "Mojo::SQLite Version: " + + perl -MMojo::SQLite -e 'print $Mojo::SQLite::VERSION; ' 2>/dev/null 1>log/mojo_sqlite.log ||\ + iresult=$? + + if [ -z "$iresult" ]; then + iresult=0 + fi + + iversion=`cat log/mojo_sqlite.log` + + if [ -n "$iversion" ]; then + echo "$iversion [Code: '$iresult']" + else + echo "NONE [Code: '$iresult']" + + #Trigger cpanm Installation + icpanm=1 + fi #if [ -n "$iversion" ]; then + ;; + + pg) + #Checking Dependencies for PostgreSQL Backend + + echo -n "Mojo::Pg Version: " + + perl -MMojo::Pg -e 'print $Mojo::Pg::VERSION; ' 2>/dev/null 1>log/mojo_postgres.log ||\ + iresult=$? + + if [ -z "$iresult" ]; then + iresult=0 + fi + + iversion=`cat log/mojo_postgres.log` + + if [ -n "$iversion" ]; then + echo "$iversion [Code: '$iresult']" + else + echo "NONE [Code: '$iresult']" + + #Trigger cpanm Installation + icpanm=1 + fi #if [ -n "$iversion" ]; then + ;; + + es) + #Checking Dependencies for Elasticsearch Backend + + echo -n "Search::Elasticsearch Version: " + + perl -MSearch::Elasticsearch -e 'print $Search::Elasticsearch::VERSION; ' 2>/dev/null 1>log/perl_elasticsearch.log ||\ + iresult=$? + + if [ -z "$iresult" ]; then + iresult=0 + fi + + iversion=`cat log/perl_elasticsearch.log` + + if [ -n "$iversion" ]; then + echo "$iversion [Code: '$iresult']" + else + echo "NONE [Code: '$iresult']" + + #Trigger cpanm Installation + icpanm=1 + fi #if [ -n "$iversion" ]; then + ;; + + esac #case "$backend" in + + if [ "$2" = "install" ]; then + #Checking Dependencies for Perl Versions Installation + + #Enabling cpanm Feature + sfeatures="$sfeatures install" + + echo -n "Perl::Build Version: " + + perl -MPerl::Build -e 'print $Perl::Build::VERSION; ' 2>/dev/null 1>log/perl_build.log ||\ + iresult=$? + + if [ -z "$iresult" ]; then + iresult=0 + fi + + iversion=`cat log/perl_build.log` + + if [ -n "$iversion" ]; then + echo "$iversion [Code: '$iresult']" + else + echo "NONE [Code: '$iresult']" + + #Trigger cpanm Installation + icpanm=1 + fi #if [ -n "$iversion" ]; then + fi #if [ "$1" = "install" ]; then + + if [ $icpanm -eq 1 ]; then + #Run cpanm Installation + echo "Installing Dependencies with cpanm ..." + + for feat in "$sfeatures"; do + sfeatoptions="$sfeatoptions --with-feature=$feat" + done + + date +"%s" > log/cpanm_install_$(date +"%F").log + cpanm -vn --installdeps$sfeatoptions . 2>&1 >> log/cpanm_install_$(date +"%F").log + cpanmrs=$? + date +"%s" >> log/cpanm_install_$(date +"%F").log + + echo "Installation finished with [$cpanmrs]" + fi #if [ $icpanm -eq 1 ]; then + + + echo "Service '$1': Launching ..." + + #Executing the Mojolicious Application + exec ./$@ + +fi #if [ "$1" = "perldoc-browser.pl" ]; then + + +#Launching any other Command +exec $@