Skip to content

Commit

Permalink
Add better Docker development and prod support
Browse files Browse the repository at this point in the history
  • Loading branch information
FWest98 committed Nov 26, 2020
1 parent e0462af commit fcf2c24
Show file tree
Hide file tree
Showing 27 changed files with 1,453 additions and 66 deletions.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

server {
listen 80 default;
listen 443 ssl;
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
6 changes: 0 additions & 6 deletions .docker/node/Dockerfile

This file was deleted.

48 changes: 48 additions & 0 deletions .docker/release/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# Inspired by the original Rainloop dockerfile from youtous on GitLab
FROM php:7.3-fpm-buster

ARG FILES_ZIP
LABEL org.label-schema.description="SnappyMail webmail client image using nginx, php-fpm based on Debian Buster"

ENV UID=991 GID=991 UPLOAD_MAX_SIZE=50M LOG_TO_STDERR=true MEMORY_LIMIT=128M SECURE_COOKIES=true
ENV fpm.pool.clear_env=false

# Install dependencies such as nginx
RUN mkdir -p /usr/share/man/man1/ /usr/share/man/man3/ /usr/share/man/man7/ && \
apt-get update -q --fix-missing && \
apt-get -y upgrade && \
apt-get install --no-install-recommends -y \
apt-transport-https gnupg openssl wget curl ca-certificates nginx supervisor sudo \
unzip libzip-dev libxml2-dev libldb-dev libldap2-dev \
sqlite3 libsqlite3-dev libsqlite3-0 libpq-dev postgresql-client mariadb-client logrotate \
zip mlocate libmcrypt-dev libpcre3-dev libicu-dev \
build-essential chrpath libssl-dev \
libxft-dev libfreetype6 libfreetype6-dev \
libpng-dev libjpeg62-turbo-dev \
libfontconfig1 libfontconfig1-dev \
&& \
rm -rf /var/lib/apt/lists/*

# Install PHP extensions
RUN php -m && \
docker-php-ext-configure ldap --with-libdir=lib/x86_64-linux-gnu/ && \
docker-php-ext-configure intl && \
docker-php-ext-configure gd --with-freetype-dir=/usr/include --with-jpeg-dir=/usr/include/ && \
docker-php-ext-install ldap opcache pdo_mysql pdo_pgsql zip intl gd && \
php -m

# Install snappymail
WORKDIR /tmp
COPY ${FILES_ZIP} .
RUN mkdir /snappymail && \
unzip -q ${FILES_ZIP} -d /snappymail && \
find /snappymail -type d -exec chmod 755 {} \; && \
find /snappymail -type f -exec chmod 644 {} \; && \
rm -rf ${FILES_ZIP}

# Install other content
COPY files /
RUN chmod +x /entrypoint.sh && chmod +x /logrotate-loop.sh
VOLUME /snappymail/data
EXPOSE 8888
CMD ["/entrypoint.sh"]
77 changes: 77 additions & 0 deletions .docker/release/files/entrypoint.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
#!/bin/sh

# Create not root user
groupadd --gid "$GID" php-cli -f
adduser --uid "$UID" --disabled-password --gid "$GID" --shell /bin/bash --home /home/php-cli php-cli --force --gecos ""


# Set attachment size limit
sed -i "s/<UPLOAD_MAX_SIZE>/$UPLOAD_MAX_SIZE/g" /usr/local/etc/php-fpm.d/php-fpm.conf /etc/nginx/nginx.conf
sed -i "s/<MEMORY_LIMIT>/$MEMORY_LIMIT/g" /usr/local/etc/php-fpm.d/php-fpm.conf

# Remove postfixadmin-change-password plugin if exist
if [ -d "/snappymail/data/_data_/_default_/plugins/postfixadmin-change-password" ]; then
rm -rf /snappymail/data/_data_/_default_/plugins/postfixadmin-change-password
fi

# Set log output to STDERR if wanted (LOG_TO_STDERR=true)
if [ "$LOG_TO_STDERR" = true ]; then
echo "[INFO] Logging to stderr activated"
sed -i "s/.*error_log.*$/error_log \/dev\/stderr warn;/" /etc/nginx/nginx.conf
sed -i "s/.*error_log.*$/php_admin_value[error_log] = \/dev\/stderr/" /usr/local/etc/php-fpm.d/php-fpm.conf
fi

# Secure cookies
if [ "${SECURE_COOKIES}" = true ]; then
echo "[INFO] Secure cookies activated"
{
echo 'session.cookie_httponly = On';
echo 'session.cookie_secure = On';
echo 'session.use_only_cookies = On';
} > /usr/local/etc/php/conf.d/cookies.ini;
fi

# Add postfixadmin-change-password plugin
mkdir -p /snappymail/data/_data_/_default_/plugins/
cp -r /usr/local/include/postfixadmin-change-password /snappymail/data/_data_/_default_/plugins/

# Copy snappymail default config if absent
SNAPPYMAIL_CONFIG_FILE=/snappymail/data/_data_/_default_/configs/application.ini
if [ ! -f "$SNAPPYMAIL_CONFIG_FILE" ]; then
echo "[INFO] Creating default Snappymail configuration"
mkdir -p $(dirname $SNAPPYMAIL_CONFIG_FILE)
cp /usr/local/include/application.ini $SNAPPYMAIL_CONFIG_FILE
fi

# Enable output of snappymail logs
if [ "${LOG_TO_STDERR}" = true ]; then
sed -z 's/\; Enable logging\nenable = Off/\; Enable logging\nenable = On/' -i $SNAPPYMAIL_CONFIG_FILE
sed 's/^filename = .*/filename = "errors.log"/' -i $SNAPPYMAIL_CONFIG_FILE
sed 's/^write_on_error_only = .*/write_on_error_only = Off/' -i $SNAPPYMAIL_CONFIG_FILE
sed 's/^write_on_php_error_only = .*/write_on_php_error_only = On/' -i $SNAPPYMAIL_CONFIG_FILE
else
sed -z 's/\; Enable logging\nenable = On/\; Enable logging\nenable = Off/' -i $SNAPPYMAIL_CONFIG_FILE
fi
# Always enable snappymail Auth logging
sed 's/^auth_logging = .*/auth_logging = On/' -i $SNAPPYMAIL_CONFIG_FILE
sed 's/^auth_logging_filename = .*/auth_logging_filename = "auth.log"/' -i $SNAPPYMAIL_CONFIG_FILE
sed 's/^auth_logging_format = .*/auth_logging_format = "[{date:Y-m-d H:i:s}] Auth failed: ip={request:ip} user={imap:login} host={imap:host} port={imap:port}"/' -i $SNAPPYMAIL_CONFIG_FILE
# Redirect snappymail logs to stderr /stdout
mkdir -p /snappymail/data/_data_/_default_/logs/
# empty logs
cp /dev/null /snappymail/data/_data_/_default_/logs/errors.log
cp /dev/null /snappymail/data/_data_/_default_/logs/auth.log
chown -R php-cli:php-cli /snappymail/data/

# Fix permissions
chown -R $UID:$GID /snappymail/data /var/log /var/lib/nginx
chmod o+w /dev/stdout
chmod o+w /dev/stderr


# Touch supervisord PID file in order to fix permissions
touch /run/supervisord.pid
chown php-cli:php-cli /run/supervisord.pid

# RUN !
exec sudo -u php-cli -g php-cli /usr/bin/supervisord -c '/supervisor.conf' --pidfile '/run/supervisord.pid'
5 changes: 5 additions & 0 deletions .docker/release/files/etc/logrotate.d/snappymail
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/snappymail/data/_data_/_default_/logs/* {
size 10M
rotate 0
missingok
}
106 changes: 106 additions & 0 deletions .docker/release/files/etc/nginx/nginx.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
worker_processes auto;
pid /tmp/nginx.pid;

events {
worker_connections 1024;
use epoll;
}

http {
include /etc/nginx/mime.types;
default_type application/octet-stream;

access_log off;
error_log /tmp/ngx_error.log error;

sendfile on;
keepalive_timeout 15;
keepalive_disable msie6;
keepalive_requests 100;
tcp_nopush on;
tcp_nodelay on;
server_tokens off;

fastcgi_temp_path /tmp/fastcgi 1 2;
client_body_temp_path /tmp/client_body 1 2;
proxy_temp_path /tmp/proxy 1 2;
uwsgi_temp_path /tmp/uwsgi 1 2;
scgi_temp_path /tmp/scgi 1 2;

gzip on;
gzip_comp_level 5;
gzip_min_length 512;
gzip_buffers 4 8k;
gzip_proxied any;
gzip_vary on;
gzip_disable "msie6";
gzip_types
text/css
text/javascript
text/xml
text/plain
text/x-component
application/javascript
application/x-javascript
application/json
application/xml
application/rss+xml
application/vnd.ms-fontobject
font/truetype
font/opentype
image/svg+xml;

server {
listen 8888;
root /snappymail;
index index.php;
charset utf-8;

client_max_body_size <UPLOAD_MAX_SIZE>;

location ^~ /data {
deny all;
}

location / {
try_files $uri $uri/ index.php;
}

# Assets cache control
# --------------------------------------
location ~* \.(?:html|xml|json)$ {
expires -1;
}

location ~* \.(?:css|js)$ {
expires 7d;
add_header Pragma public;
add_header Cache-Control "public";
}

location ~* \.(?:gif|jpe?g|png|ico|otf|eot|svg|ttf|woff|woff2)$ {
expires 30d;
log_not_found off;
add_header Pragma public;
add_header Cache-Control "public";
}

# PHP Backend
# --------------------------------------
location ~* \.php$ {
try_files $uri =404;
include fastcgi_params;
fastcgi_split_path_info ^(.+\.php)(/.*)$;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_param HTTP_PROXY "";
fastcgi_index index.php;
fastcgi_pass unix:/tmp/php-fpm.sock;
fastcgi_intercept_errors on;
fastcgi_request_buffering off;
fastcgi_param REMOTE_ADDR $http_x_real_ip;
}

}

}
23 changes: 23 additions & 0 deletions .docker/release/files/listener.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php
$stdIn = STDIN;
$stdOut = STDOUT;

fwrite($stdOut, "READY\n");

while(true) {
if (false == $line = trim(fgets($stdIn))) {
continue;
}

$match = null;
if (preg_match('/eventname:(.*?) /', $line, $match)) {
if (in_array($match[1], ['PROCESS_STATE_EXITED', 'PROCESS_STATE_STOPPED', 'PROCESS_STATE_FATAL'])) {
exec('kill -15 '.file_get_contents('/run/supervisord.pid'));
}
}

fwrite($stdOut, "RESULT 2\nOK");

sleep(1);
fwrite($stdOut, "READY\n");
}
113 changes: 113 additions & 0 deletions .docker/release/files/logrotate-loop.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
#!/bin/bash
# ----------------------------------------------------------------------
# Simple script to invoke logrotate at regular intervals
# ----------------------------------------------------------------------

# from https://github.com/misho-kr/docker-appliances/blob/master/nginx-nodejs/logrotate-loop.sh

LOGROTATE_BIN="logrotate"

STATE="$HOME/logrotate.state"
CONF="/etc/logrotate.d/snappymail"

export LOGROTATE_BIN STATE CONF

RUN_INTERVAL="3600" # every hour

# helper functions for logging
export FMT="%a %b %d %Y %H:%M:%S GMT%z (%Z)"

function log_date() {
echo "$(date +"$FMT"): $*"
}

# ----------------------------------------------------------------------
# Main loop of the logrotate service:
#
# while True:
# sleep N seconds
# run logrotate
#
# ----------------------------------------------------------------------

function logrotate_loop() {

trap on_terminate TERM INT

local interval="${1}"

log_date "===================================================="
log_date
log_date "logrotate service starting (pid=$$)"
log_date "logrotate process will run every ${interval} seconds"

while true; do

current_time=$(date "+%s")
next_run_time=$(( current_time + interval ))

while (( current_time < next_run_time ))
do
logrotate_sleep $(( next_run_time - current_time ))
current_time=$(date "+%s")
done

logrotate_run
done
}

# helper function to execute logrotate and pass it the right parameters
function logrotate_run() {

log_date "logrotate will run now"
${LOGROTATE_BIN} -s ${STATE} ${CONF}
}

# ----------------------------------------------------------------------
# Procedure to idle the execution for a number of seconds
#
# There are two requirements:
#
# - export the PID of the sleep command so that it can be terminated
# in case the logrotate service is being shutdown
# - keep this (bash) process responsive to SIGTERM while in sleep
# mode (normally the signal will be masked and will not be delivered
# until the subprocess completes)
# ----------------------------------------------------------------------

proc_sleep_pid=""

function logrotate_sleep() {

local sleep_interval=${1}

log_date "logrotate will sleep for ${sleep_interval} seconds"

( exec -a "logrotate: sleep" sleep ${sleep_interval} )&

proc_sleep_pid=$!
wait ${proc_sleep_pid}
}

# ----------------------------------------------------------------------
# Signal handler for logrotate service to make sure the process exits:
#
# - properly by terminating the sleep process that is used to idle
# the service
# - gracefully by writing a message in the log
# ----------------------------------------------------------------------

function on_terminate() {

log_date "logrotate will terminate"
log_date

kill -TERM ${proc_sleep_pid}
exit 0
}

# ----------------------------------------------------------------------
# main
# ----------------------------------------------------------------------

logrotate_loop ${1:-RUN_INTERVAL}
Loading

0 comments on commit fcf2c24

Please sign in to comment.