From 507f72deed520d81264ac6000c25bcc5224742a4 Mon Sep 17 00:00:00 2001 From: Programster Date: Sun, 19 Feb 2017 13:02:20 +0000 Subject: [PATCH 1/5] implemented docker integration. Use the README file within the new docker folder to find out how to deploy through docker. --- docker/.dockerignore | 1 + docker/.gitignore | 1 + docker/Dockerfile | 103 +++++++++++++++++++++++++++++++++ docker/README.md | 6 ++ docker/apache-config.conf | 25 ++++++++ docker/build.sh | 42 ++++++++++++++ docker/crons.conf | 6 ++ docker/deploy.sh | 41 +++++++++++++ docker/docker_settings.sh.tmpl | 22 +++++++ docker/startup.sh | 16 +++++ docker/supervisord.conf | 11 ++++ php/Modules/Database.php | 19 ++++-- 12 files changed, 288 insertions(+), 5 deletions(-) create mode 100755 docker/.dockerignore create mode 100644 docker/.gitignore create mode 100755 docker/Dockerfile create mode 100755 docker/README.md create mode 100755 docker/apache-config.conf create mode 100755 docker/build.sh create mode 100755 docker/crons.conf create mode 100755 docker/deploy.sh create mode 100644 docker/docker_settings.sh.tmpl create mode 100755 docker/startup.sh create mode 100755 docker/supervisord.conf diff --git a/docker/.dockerignore b/docker/.dockerignore new file mode 100755 index 0000000..191381e --- /dev/null +++ b/docker/.dockerignore @@ -0,0 +1 @@ +.git \ No newline at end of file diff --git a/docker/.gitignore b/docker/.gitignore new file mode 100644 index 0000000..74e4471 --- /dev/null +++ b/docker/.gitignore @@ -0,0 +1 @@ +docker_settings.sh diff --git a/docker/Dockerfile b/docker/Dockerfile new file mode 100755 index 0000000..33727f4 --- /dev/null +++ b/docker/Dockerfile @@ -0,0 +1,103 @@ +# Due to layout of this project, the dockerfile will be moved up two directories and run during +# the build. Thus when performing any ADD commands, remember that this is "where you are" +# The layout is this way so that the settings file sits one level above the project (trunk) so that +# each dev can have their own settings and they do not get merged into the trunk. + +FROM debian:jessie + +RUN apt-get update +RUN apt-get dist-upgrade -y + + +# Install the relevant packages +RUN apt-get install vim apache2 libapache2-mod-php5 php5-cli php5-mysqlnd curl php5-curl php5-mcrypt -y + + +# Install yui-compressor for js (and possibly css) minification later. +RUN apt-get install yui-compressor -y + +# Install supervisor (through PIP) +RUN apt-get install python-pip python-dev build-essential -y +RUN pip install --upgrade pip +RUN pip install supervisor + +# Enable the php mod we just installed +RUN a2enmod php5 + + +# expose port 80 and 443 for the web requests +EXPOSE 80 + + +###### Update the php INI settings ######### + +# Increase php's max allowed memory size if you need to +#RUN sed -i 's;memory_limit = .*;memory_limit = -1;' /etc/php5/apache2/php.ini +#RUN sed -i 's;memory_limit = .*;memory_limit = -1;' /etc/php5/cli/php.ini + +RUN sed -i 's;display_errors = .*;display_errors = Off;' /etc/php5/apache2/php.ini +RUN sed -i 's;display_errors = .*;display_errors = On;' /etc/php5/cli/php.ini + +# Change apache php to allow larger uploads/POSTs +RUN sed -i 's;post_max_size = .*;post_max_size = 4000M;' /etc/php5/apache2/php.ini +RUN sed -i 's;upload_max_filesize = .*;upload_max_filesize = 2000M;' /etc/php5/apache2/php.ini + +# Set the max execution time if you want to +#RUN sed -i 's;max_execution_time = .*;max_execution_time = 300;' /etc/php5/apache2/php.ini +#RUN sed -i 's;max_execution_time = .*;max_execution_time = 300;' /etc/php5/cli/php.ini + +# This is also needed for execution time +#RUN sed -i 's;max_input_time = .*;max_input_time = 300;' /etc/php5/apache2/php.ini + + +####### END of updating php INI ######## +######################################## + +# Manually set the apache environment variables in order to get apache to work immediately. +ENV APACHE_RUN_USER www-data +ENV APACHE_RUN_GROUP www-data +ENV APACHE_LOG_DIR /var/log/apache2 + +# It appears that the new apache requires these env vars as well +ENV APACHE_LOCK_DIR /var/lock/apache2 +ENV APACHE_PID_FILE /var/run/apache2/apache2.pid + +# Set up url rewrite ability +RUN a2enmod rewrite +RUN php5enmod mcrypt + +# Install the cron service +RUN apt-get install cron -y + + + +# Add our websites files to the default apache directory (/var/www) +COPY Lychee /var/www/lychee + +# Update our apache sites available with the config we created +RUN cp /var/www/lychee/docker/apache-config.conf /etc/apache2/sites-enabled/000-default.conf + +# Add our supervisor config to the container +RUN cp /var/www/lychee/docker/supervisord.conf /etc/supervisord.conf + + +# Use the crontab file. +# The crontab file was already added when we added "project" +RUN crontab /var/www/lychee/docker/crons.conf + +# Set the base permissions for the site. +RUN chown root:www-data -R /var/www +RUN chmod 750 -R /var/www/lychee + +# Set up the uploads and data directories to be volumes that are writeable. +RUN chmod 770 -R /var/www/lychee/uploads/ +RUN chmod 770 -R /var/www/lychee/data/ + +RUN ln -s /var/www/lychee/uploads uploads +RUN ln -s /var/www/lychee/data data +VOLUME /uploads +VOLUME /data + +# Execute the containers startup script which will start many processes/services +# The startup file was already added when we added "project" +CMD ["/bin/bash", "/var/www/lychee/docker/startup.sh"] diff --git a/docker/README.md b/docker/README.md new file mode 100755 index 0000000..a46567e --- /dev/null +++ b/docker/README.md @@ -0,0 +1,6 @@ +This area is for building and deploying Lychee through docker. + +## Steps +* Copy the docker_settings.sh.tmpl file to docker_settings.sh and fill in the settings appropriately +* Run the command `bash build.sh` +* Deploy your container with bash deploy.sh \ No newline at end of file diff --git a/docker/apache-config.conf b/docker/apache-config.conf new file mode 100755 index 0000000..743abd9 --- /dev/null +++ b/docker/apache-config.conf @@ -0,0 +1,25 @@ +# This is the apache config as it will appear for the deployed container. Bear in mind that this +# does not overwrite anything on the host that the container is deployed to so everything is "safe" +# +# This will need to match up with how files are added to the container from the Dockerfile + + ServerAdmin webmaster@localhost + + DocumentRoot /var/www/lychee + + Options Indexes FollowSymLinks + AllowOverride All + Order allow,deny + allow from all + Require all granted + + + ErrorLog ${APACHE_LOG_DIR}/error.log + + # Possible values include: debug, info, notice, warn, error, crit, + # alert, emerg. + LogLevel warn + + CustomLog ${APACHE_LOG_DIR}/access.log combined + + diff --git a/docker/build.sh b/docker/build.sh new file mode 100755 index 0000000..98ff92a --- /dev/null +++ b/docker/build.sh @@ -0,0 +1,42 @@ +#!/bin/bash + +# ensure running bash +if ! [ -n "$BASH_VERSION" ];then + echo "this is not bash, calling self with bash...."; + SCRIPT=$(readlink -f "$0") + /bin/bash $SCRIPT + exit; +fi + +# Get the path to script just in case executed from elsewhere. +SCRIPT=$(readlink -f "$0") +SCRIPTPATH=$(dirname "$SCRIPT") +cd $SCRIPTPATH + +# Load the variables from settings file. +source docker_settings.sh + +# Copy the docker file up and run it in order to build the container. +# We need to move the dockerfile up so that it can easily add everything to the container. +cp -f Dockerfile ../../. +cp -f .dockerignore ../../. +cd ../../. + +# Ask the user if they want to use the docker cache +read -p "Do you want to use a cached build (y/n)? " -n 1 -r +echo "" # (optional) move to a new line +if [[ $REPLY =~ ^[Yy]$ ]] +then + docker build --pull --tag $REGISTRY/$PROJECT_NAME . +else + docker build --no-cache --pull --tag $REGISTRY/$PROJECT_NAME . +fi + +# Remove the duplicated Dockerfile after the build. +rm $SCRIPTPATH/../../Dockerfile +rm $SCRIPTPATH/../../.dockerignore + +docker push $REGISTRY/$PROJECT_NAME + +echo "Run the container with the following command:" +echo "bash deploy.sh" diff --git a/docker/crons.conf b/docker/crons.conf new file mode 100755 index 0000000..e247561 --- /dev/null +++ b/docker/crons.conf @@ -0,0 +1,6 @@ +# This will become the crontab file. Place any crons that need performing in here. +# This needs to "link up" with how files are added to the conainer from the dockerfile. + +# Add any crons below. +# * * * * * /usr/bin/php /var/www/lychee/path/to/script + diff --git a/docker/deploy.sh b/docker/deploy.sh new file mode 100755 index 0000000..dfadc04 --- /dev/null +++ b/docker/deploy.sh @@ -0,0 +1,41 @@ +#!/bin/bash + +# ensure running bash +if ! [ -n "$BASH_VERSION" ];then + echo "this is not bash, calling self with bash...."; + SCRIPT=$(readlink -f "$0") + /bin/bash $SCRIPT + exit; +fi + +SCRIPT=$(readlink -f "$0") +SCRIPTPATH=$(dirname "$SCRIPT") +cd $SCRIPTPATH + +# load the variables +source $SCRIPTPATH/docker_settings.sh + +CONTAINER_IMAGE="`echo $REGISTRY`/`echo $PROJECT_NAME`" + +echo $PROJECT_NAME +echo "============" + +docker kill $PROJECT_NAME +docker rm $PROJECT_NAME + +# Create the volumes if they dont exist already. +mkdir -p $VOLUME_DIR/uploads +mkdir -p $VOLUME_DIR/data + +docker run -d \ +-p 80:80 \ +-e MYSQL_HOST="$MYSQL_HOST" \ +-e MYSQL_DB_NAME="$MYSQL_DB_NAME" \ +-e MYSQL_USER="$MYSQL_USER" \ +-e MYSQL_PASSWORD="$MYSQL_PASSWORD" \ +-e MYSQL_PORT="$MYSQL_PORT" \ +-v $VOLUME_DIR/uploads:/uploads \ +-v $VOLUME_DIR/data:/data \ +--restart=always \ +--name="$PROJECT_NAME" \ +$CONTAINER_IMAGE diff --git a/docker/docker_settings.sh.tmpl b/docker/docker_settings.sh.tmpl new file mode 100644 index 0000000..1cdeeda --- /dev/null +++ b/docker/docker_settings.sh.tmpl @@ -0,0 +1,22 @@ +# If you want to have the image pushed to your private registry, put it here. +#REGISTRY="docker-registry.mydomain.org:5000" + +# If you want to hav the image be pushed to your public dockerhub, just use your username instead +#REGISTRY="myUsername" + +# If you don't uncomment one of the REGISTRY options above, then the image just won't get pushed. + +# Set the name for this in your registry. You probably want to leave this as lychee +PROJECT_NAME="lychee" + + +# Specify where you want your volume data. +VOLUME_DIR="$HOME/lychee-volume" + + +# Specify the database details. +MYSQL_HOST="lychee.mydomain.com" +MYSQL_DB_NAME="lychee" +MYSQL_USER="lychee" +MYSQL_PASSWORD="myPassword" +MYSQL_PORT=3306 \ No newline at end of file diff --git a/docker/startup.sh b/docker/startup.sh new file mode 100755 index 0000000..7c28cb2 --- /dev/null +++ b/docker/startup.sh @@ -0,0 +1,16 @@ +# Please do not manually call this file! + +# Have supervisor manage the apache process instead +service apache2 stop + +# Make sure I have permissions to the volumes +chown root:www-data -R /var/www/lychee/data +chown root:www-data -R /var/www/lychee/uploads +chmod 770 /var/www/lychee/uploads +chmod 770 /var/www/lychee/data + +# Here is a good point to run database migrations (before the webserver is started up by supervisord) +#/usr/bin/php /var/www/lychee/scripts/migrate.php + +# Start supervisord to manage all processes and tye up the FG process for the docker container. +/usr/local/bin/supervisord \ No newline at end of file diff --git a/docker/supervisord.conf b/docker/supervisord.conf new file mode 100755 index 0000000..6ddd6e3 --- /dev/null +++ b/docker/supervisord.conf @@ -0,0 +1,11 @@ +[supervisord] +nodaemon=true + +[program:apache2] +command=/bin/bash -c "source /etc/apache2/envvars && exec /usr/sbin/apache2 -DFOREGROUND" +autorestart=true + +# Add your own scripts to be executed by supervisor by uncommenting and editing the following lines. +#[program:MyScriptOfAwesomeness] +#command=/usr/bin/php /var/www/lychee/project/scripts/MyScriptOfAwesomeness.php +#autorestart=true \ No newline at end of file diff --git a/php/Modules/Database.php b/php/Modules/Database.php index 11924b5..23243a5 100755 --- a/php/Modules/Database.php +++ b/php/Modules/Database.php @@ -80,10 +80,16 @@ final class Database { * @return object|false Returns the connection when successful. */ public static function connect($host = 'localhost', $user, $password) { - - // Open a new connection to the MySQL server - $connection = @new Mysqli($host, $user, $password); - + + // Load the database settings from the environment variables passed to the docker container + $host = getenv('MYSQL_HOST'); + $dbname = getenv('MYSQL_DB_NAME'); + $user = getenv('MYSQL_USER'); + $password = getenv('MYSQL_PASSWORD'); + $port = getenv('MYSQL_PORT'); + + $connection = @new \mysqli($host, $user, $password, $dbname, $port); + // Check if the connection was successful if ($connection->connect_errno) return false; @@ -125,7 +131,10 @@ final class Database { * @return boolean Returns true when successful. */ public static function createDatabase($connection, $name = 'lychee') { - + + // Override whatever the user fills in with whatever is in the settings file. + $name = getenv('MYSQL_DB_NAME'); + // Check dependencies Validator::required(isset($connection), __METHOD__); From 3a2013c8e9227523a56be847cecb173786f23368 Mon Sep 17 00:00:00 2001 From: Programster Date: Sun, 19 Feb 2017 14:02:23 +0000 Subject: [PATCH 2/5] Using a relative path for the define.php file --- php/define.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php/define.php b/php/define.php index d7bebb7..73d3f3b 100644 --- a/php/define.php +++ b/php/define.php @@ -1,7 +1,7 @@ Date: Sun, 19 Feb 2017 14:02:58 +0000 Subject: [PATCH 3/5] Installing some more packages that were needed. --- docker/Dockerfile | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index 33727f4..ed223f0 100755 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -10,11 +10,10 @@ RUN apt-get dist-upgrade -y # Install the relevant packages -RUN apt-get install vim apache2 libapache2-mod-php5 php5-cli php5-mysqlnd curl php5-curl php5-mcrypt -y - - -# Install yui-compressor for js (and possibly css) minification later. -RUN apt-get install yui-compressor -y +RUN apt-get install vim apache2 libapache2-mod-php5 php5-cli php5-mysqlnd php5-mcrypt \ +unzip php5-common php5-json php5-cli php5-gd php5-imagick php5-json php5-mcrypt php5-readline \ +php-pear libgd-tools \ +-y # Install supervisor (through PIP) RUN apt-get install python-pip python-dev build-essential -y From 4e7f0eae6f57e6ba8241209d50ab2a1adadcaeb2 Mon Sep 17 00:00:00 2001 From: Programster Date: Sun, 19 Feb 2017 14:03:43 +0000 Subject: [PATCH 4/5] Supporting cases where the user does not wish to define the REGISTRY variable to have the container pushed anywhere. --- docker/build.sh | 18 ++++++++++++++---- docker/deploy.sh | 10 ++++++---- 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/docker/build.sh b/docker/build.sh index 98ff92a..e78ba56 100755 --- a/docker/build.sh +++ b/docker/build.sh @@ -22,21 +22,31 @@ cp -f Dockerfile ../../. cp -f .dockerignore ../../. cd ../../. +if [[ $REGISTRY ]]; then + TAG="`echo $REGISTRY`/`echo $PROJECT_NAME`" +else + TAG=$PROJECT_NAME +fi + + # Ask the user if they want to use the docker cache read -p "Do you want to use a cached build (y/n)? " -n 1 -r echo "" # (optional) move to a new line if [[ $REPLY =~ ^[Yy]$ ]] then - docker build --pull --tag $REGISTRY/$PROJECT_NAME . + docker build --pull --tag $TAG . else - docker build --no-cache --pull --tag $REGISTRY/$PROJECT_NAME . + docker build --no-cache --pull --tag $TAG . fi # Remove the duplicated Dockerfile after the build. rm $SCRIPTPATH/../../Dockerfile rm $SCRIPTPATH/../../.dockerignore -docker push $REGISTRY/$PROJECT_NAME +if [[ $REGISTRY ]]; then + docker push $TAG +fi + echo "Run the container with the following command:" -echo "bash deploy.sh" +echo "bash deploy.sh" \ No newline at end of file diff --git a/docker/deploy.sh b/docker/deploy.sh index dfadc04..1814325 100755 --- a/docker/deploy.sh +++ b/docker/deploy.sh @@ -15,10 +15,12 @@ cd $SCRIPTPATH # load the variables source $SCRIPTPATH/docker_settings.sh -CONTAINER_IMAGE="`echo $REGISTRY`/`echo $PROJECT_NAME`" +if [[ $REGISTRY ]]; then + CONTAINER_IMAGE="`echo $REGISTRY`/`echo $PROJECT_NAME`" +else + CONTAINER_IMAGE="`echo $PROJECT_NAME`" +fi -echo $PROJECT_NAME -echo "============" docker kill $PROJECT_NAME docker rm $PROJECT_NAME @@ -38,4 +40,4 @@ docker run -d \ -v $VOLUME_DIR/data:/data \ --restart=always \ --name="$PROJECT_NAME" \ -$CONTAINER_IMAGE +$CONTAINER_IMAGE \ No newline at end of file From 17b0b623cae94bf9abed2649a9520fae2b54bba0 Mon Sep 17 00:00:00 2001 From: Programster Date: Sun, 19 Feb 2017 14:04:08 +0000 Subject: [PATCH 5/5] Need to ensure volume subdirectories get created with necessary permissions. --- docker/startup.sh | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/docker/startup.sh b/docker/startup.sh index 7c28cb2..e535774 100755 --- a/docker/startup.sh +++ b/docker/startup.sh @@ -3,11 +3,15 @@ # Have supervisor manage the apache process instead service apache2 stop -# Make sure I have permissions to the volumes +# Make sure I have permissions to the volumes and the necessary folders exist. +mkdir -p /uploads/big +mkdir -p /uploads/import +mkdir -p /uploads/medium +mkdir -p /uploads/thumb chown root:www-data -R /var/www/lychee/data chown root:www-data -R /var/www/lychee/uploads -chmod 770 /var/www/lychee/uploads -chmod 770 /var/www/lychee/data +chmod 770 -R /var/www/lychee/uploads +chmod 770 -R /var/www/lychee/data # Here is a good point to run database migrations (before the webserver is started up by supervisord) #/usr/bin/php /var/www/lychee/scripts/migrate.php