working dockerization
This commit is contained in:
parent
cf4b05c0a5
commit
dfe5d2781d
29
Dockerfile
29
Dockerfile
|
@ -19,8 +19,13 @@ FROM phusion/baseimage:0.9.16
|
|||
|
||||
# Dockerfile metadata.
|
||||
MAINTAINER Joshua Tauberer (http://razor.occams.info)
|
||||
EXPOSE 25 53/udp 53/tcp 80 443 587 993
|
||||
VOLUME /data
|
||||
EXPOSE 25 53/udp 53/tcp 80 443 587 993 4190
|
||||
VOLUME /home/user-data
|
||||
|
||||
CMD ["/sbin/my_init"]
|
||||
|
||||
# Create the user-data user, so the start script doesn't have to.
|
||||
RUN useradd -m user-data
|
||||
|
||||
# Docker has a beautiful way to cache images after each step. The next few
|
||||
# steps of installing system packages are very intensive, so we take care
|
||||
|
@ -32,23 +37,17 @@ VOLUME /data
|
|||
RUN apt-get update
|
||||
RUN DEBIAN_FRONTEND=noninteractive apt-get upgrade -y
|
||||
|
||||
# We want to use Ubuntu's stock rsyslog rather than syslog-ng
|
||||
# that the base image provides.
|
||||
RUN DEBIAN_FRONTEND=noninteractive apt-get install -y rsyslog
|
||||
RUN rm -rf /etc/service/syslog-ng
|
||||
|
||||
# Install packages needed by Mail-in-a-Box.
|
||||
ADD containers/docker/apt_package_list.txt /tmp/mailinabox_apt_package_list.txt
|
||||
RUN DEBIAN_FRONTEND=noninteractive apt-get install -y $(cat /tmp/mailinabox_apt_package_list.txt)
|
||||
RUN DEBIAN_FRONTEND=noninteractive apt-get install -y rsyslog
|
||||
RUN rm -f /tmp/mailinabox_apt_package_list.txt
|
||||
RUN apt-get clean
|
||||
|
||||
# Create the user-data user, so the start script doesn't have to.
|
||||
RUN useradd -m user-data
|
||||
|
||||
# Now add Mail-in-a-Box to the system.
|
||||
ADD . /usr/local/mailinabox
|
||||
|
||||
# We can't know things like the IP address where the container will eventually
|
||||
# be deployed until the container is started. We also don't want to create any
|
||||
# private keys during the creation of the image --- that should wait until the
|
||||
# container is started too. So our whole setup process is deferred until the
|
||||
# container is started.
|
||||
RUN mkdir -p /etc/my_init.d
|
||||
RUN ln -s /usr/local/mailinabox/containers/docker/init.sh /etc/my_init.d/20-mailinabox.sh
|
||||
# Cleanup
|
||||
RUN apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
|
||||
|
|
|
@ -17,58 +17,21 @@ if [ ! -t 0 ]; then
|
|||
export NONINTERACTIVE=1
|
||||
fi
|
||||
|
||||
# The phusion/baseimage base image we use for a working Ubuntu
|
||||
# replaces the normal Upstart system service management with
|
||||
# a ligher-weight service management system called runit that
|
||||
# requires a different configuration. We need to create service
|
||||
# run files that do not daemonize.
|
||||
|
||||
# For most of the services, there is a common pattern we can use:
|
||||
# execute the init.d script that the Ubuntu package installs, and
|
||||
# then poll for the termination of the daemon.
|
||||
function make_runit_service {
|
||||
INITD_NAME=$1
|
||||
WAIT_ON_PROCESS_NAME=$2
|
||||
mkdir -p /etc/service/$INITD_NAME
|
||||
cat > /etc/service/$INITD_NAME/run <<EOF;
|
||||
#!/bin/bash
|
||||
source /usr/local/mailinabox/setup/functions.sh
|
||||
hide_output /etc/init.d/$INITD_NAME restart
|
||||
while [ \`ps a -C $WAIT_ON_PROCESS_NAME -o pid= | wc -l\` -gt 0 ]; do
|
||||
sleep 30
|
||||
done
|
||||
echo $WAIT_ON_PROCESS_NAME died.
|
||||
sleep 20
|
||||
EOF
|
||||
chmod +x /etc/service/$INITD_NAME/run
|
||||
}
|
||||
#make_runit_service bind9 named
|
||||
#make_runit_service fail2ban fail2ban
|
||||
#make_runit_service mailinabox mailinabox-daemon
|
||||
#make_runit_service memcached memcached
|
||||
#make_runit_service nginx nginx
|
||||
#make_runit_service nsd nsd
|
||||
#make_runit_service opendkim opendkim
|
||||
#make_runit_service php5-fpm php5-fpm
|
||||
#make_runit_service postfix postfix
|
||||
#make_runit_service postgrey postgrey
|
||||
#make_runit_service spampd spampd
|
||||
|
||||
# Dovecot doesn't provide an init.d script, but it does provide
|
||||
# a way to launch without daemonization. We wrote a script for
|
||||
# that specifically.
|
||||
#
|
||||
# We also want to use Ubuntu's stock rsyslog rather than syslog-ng
|
||||
# that the base image provides. Our Dockerfile installs rsyslog.
|
||||
rm -rf /etc/service/syslog-ng
|
||||
for service in dovecot; do
|
||||
for service in rsyslog dovecot memcached postgrey postfix nginx bind9 fail2ban spampd nsd opendkim opendmarc php5-fpm
|
||||
do
|
||||
# create runit service from source file
|
||||
mkdir -p /etc/service/$service
|
||||
cp /usr/local/mailinabox/containers/docker/runit/$service.sh /etc/service/$service/run
|
||||
chmod +x /etc/service/$service/run
|
||||
done
|
||||
|
||||
# Rsyslog isn't starting automatically but we need it during setup.
|
||||
service rsyslog start
|
||||
# runit -> LSB compatibility
|
||||
# see http://smarden.org/runit/faq.html#lsb
|
||||
if [ -f /etc/init.d/$service ]; then
|
||||
mv /etc/init.d/$service /etc/init.d/$service.lsb
|
||||
chmod -x /etc/init.d/$service.lsb
|
||||
fi
|
||||
ln -s /usr/bin/sv /etc/init.d/$service
|
||||
done
|
||||
|
||||
# Start configuration. Using 'source' means an exit from inside
|
||||
# also exits this script and terminates the container.
|
||||
|
|
|
@ -22,6 +22,10 @@
|
|||
# Build or rebuild the image.
|
||||
# Rebuilds are very fast.
|
||||
|
||||
HOST_HTTP_PORT=${HOST_HTTP_PORT:-80}
|
||||
HOST_HTTPS_PORT=${HOST_HTTPS_PORT:-443}
|
||||
HOST_USERDATA_VOLUME=${HOST_USERDATA_VOLUME:-/home/user-data}
|
||||
|
||||
tput setaf 2
|
||||
echo "Building/updating base image (mailinabox)..."
|
||||
tput setaf 7
|
||||
|
@ -36,8 +40,8 @@ if ! docker ps -a | grep mailinabox-userdata > /dev/null; then
|
|||
|
||||
docker run -d \
|
||||
--name mailinabox-userdata \
|
||||
-v /home/user-data \
|
||||
scratch /bin/does-not-exist-but-thats-ok
|
||||
-v $HOST_USERDATA_VOLUME:/home/user-data \
|
||||
phusion/baseimage:0.9.16
|
||||
else
|
||||
tput setaf 2
|
||||
echo
|
||||
|
@ -63,15 +67,43 @@ echo
|
|||
echo "Starting new container (mailinabox-services)..."
|
||||
tput setaf 7
|
||||
|
||||
# Run the services container detached.
|
||||
# Notes:
|
||||
# * Passing through SKIP_NETWORK_CHECKS makes it easier to do testing
|
||||
# on a residential network.
|
||||
|
||||
# * --privileged flag cause an issue with bind9/named failing to start in this case
|
||||
# see docker/docker#7318
|
||||
docker run \
|
||||
--privileged \
|
||||
-v /dev/urandom:/dev/random \
|
||||
-p 25 -p 53/udp -p 53/tcp -p 80 -p 443 -p 587 -p 993 \
|
||||
-p 25:25 \
|
||||
-p 53:53/udp \
|
||||
-p 53:53/tcp \
|
||||
-p $HOST_HTTP_PORT:80 \
|
||||
-p $HOST_HTTPS_PORT:443 \
|
||||
-p 587:587 \
|
||||
-p 993:993 \
|
||||
-p 4190:4190 \
|
||||
--name mailinabox-services \
|
||||
--volumes-from mailinabox-userdata \
|
||||
-e "SKIP_NETWORK_CHECKS=$SKIP_NETWORK_CHECKS" \
|
||||
-d \
|
||||
-t \
|
||||
mailinabox
|
||||
|
||||
tput setaf 2
|
||||
echo
|
||||
echo "Initializing container (mailinabox-services)..."
|
||||
tput setaf 7
|
||||
|
||||
# run init.sh
|
||||
docker exec \
|
||||
-it \
|
||||
mailinabox-services \
|
||||
/usr/local/mailinabox/containers/docker/init.sh
|
||||
|
||||
tput setaf 2
|
||||
echo
|
||||
echo "Restarting container..."
|
||||
tput setaf 7
|
||||
|
||||
docker restart mailinabox-services
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
#!/bin/bash
|
||||
|
||||
# for a chrooted server: "-u bind -t /var/lib/named"
|
||||
# Don't modify this line, change or create /etc/default/bind9.
|
||||
OPTIONS=""
|
||||
RESOLVCONF=no
|
||||
|
||||
test -f /etc/default/bind9 && . /etc/default/bind9
|
||||
|
||||
# dirs under /var/run can go away on reboots.
|
||||
mkdir -p /var/run/named
|
||||
chmod 775 /var/run/named
|
||||
chown root:bind /var/run/named >/dev/null 2>&1 || true
|
||||
|
||||
exec named -f $OPTIONS 2>&1
|
|
@ -1,3 +1,3 @@
|
|||
#!/bin/bash
|
||||
|
||||
/usr/sbin/dovecot -F -c /etc/dovecot/dovecot.conf &> /var/log/dovecot.log
|
||||
exec /usr/sbin/dovecot -F -c /etc/dovecot/dovecot.conf &> /var/log/dovecot.log
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
#!/bin/bash
|
||||
|
||||
NAME=fail2ban
|
||||
DAEMON=/usr/bin/$NAME-server
|
||||
|
||||
# Ad-hoc way to parse out socket file name
|
||||
SOCKFILE=`grep -h '^[^#]*socket *=' /etc/$NAME/$NAME.conf /etc/$NAME/$NAME.local 2>/dev/null \
|
||||
| tail -n 1 | sed -e 's/.*socket *= *//g' -e 's/ *$//g'`
|
||||
[ -z "$SOCKFILE" ] && SOCKFILE='/tmp/fail2ban.sock'
|
||||
|
||||
# Assure that /var/run/fail2ban exists
|
||||
[ -d /var/run/fail2ban ] || mkdir -p /var/run/fail2ban
|
||||
|
||||
# Run as root by default.
|
||||
FAIL2BAN_USER=root
|
||||
|
||||
# Read configuration variable file if it is present
|
||||
[ -r /etc/default/$NAME ] && . /etc/default/$NAME
|
||||
DAEMON_ARGS="$FAIL2BAN_OPTS"
|
||||
|
||||
exec $DAEMON -f $DAEMON_ARGS 2>&1
|
|
@ -0,0 +1,14 @@
|
|||
#!/bin/bash
|
||||
|
||||
NAME=mailinabox
|
||||
DAEMON=/usr/local/bin/mailinabox-daemon
|
||||
|
||||
export LANGUAGE=en_US.UTF-8
|
||||
export LC_ALL=en_US.UTF-8
|
||||
export LANG=en_US.UTF-8
|
||||
export LC_TYPE=en_US.UTF-8
|
||||
|
||||
# Read configuration variable file if it is present
|
||||
[ -r /etc/default/$NAME ] && . /etc/default/$NAME
|
||||
|
||||
exec $DAEMON 2>&1
|
|
@ -0,0 +1,3 @@
|
|||
#!/bin/sh
|
||||
|
||||
exec /sbin/setuser memcache /usr/bin/memcached >>/var/log/memcached.log 2>&1
|
|
@ -0,0 +1,3 @@
|
|||
#!/bin/bash
|
||||
|
||||
exec /usr/sbin/nginx -c /etc/nginx/nginx.conf -g "daemon off;" 2>&1
|
|
@ -0,0 +1,15 @@
|
|||
#!/bin/bash
|
||||
|
||||
NAME=nsd
|
||||
DAEMON=/usr/sbin/$NAME
|
||||
CONFFILE=/etc/nsd/nsd.conf
|
||||
DAEMON_ARGS="-d -c $CONFFILE"
|
||||
|
||||
# reconfigure since the ip may have changed
|
||||
# if it fails runit will retry anyway, but
|
||||
# don't do this on first start
|
||||
if [ -f /var/lib/mailinabox/api.key ]; then
|
||||
/usr/local/mailinabox/tools/dns_update
|
||||
fi
|
||||
|
||||
exec $DAEMON $DAEMON_ARGS 2>&1
|
|
@ -0,0 +1,25 @@
|
|||
#!/bin/bash
|
||||
|
||||
DAEMON=/usr/sbin/opendkim
|
||||
NAME=opendkim
|
||||
USER=opendkim
|
||||
RUNDIR=/var/run/$NAME
|
||||
SOCKET=local:$RUNDIR/$NAME.sock
|
||||
|
||||
# Include opendkim defaults if available
|
||||
if [ -f /etc/default/opendkim ] ; then
|
||||
. /etc/default/opendkim
|
||||
fi
|
||||
|
||||
if [ -f /etc/opendkim.conf ]; then
|
||||
CONFIG_SOCKET=`awk '$1 == "Socket" { print $2 }' /etc/opendkim.conf`
|
||||
fi
|
||||
|
||||
# This can be set via Socket option in config file, so it's not required
|
||||
if [ -n "$SOCKET" -a -z "$CONFIG_SOCKET" ]; then
|
||||
DAEMON_OPTS="-p $SOCKET $DAEMON_OPTS"
|
||||
fi
|
||||
|
||||
DAEMON_OPTS="-f -x /etc/opendkim.conf -u $USER $DAEMON_OPTS"
|
||||
|
||||
exec $DAEMON $DAEMON_OPTS 2>&1
|
|
@ -0,0 +1,25 @@
|
|||
#!/bin/sh
|
||||
|
||||
DAEMON=/usr/sbin/opendmarc
|
||||
NAME=opendmarc
|
||||
USER=opendmarc
|
||||
RUNDIR=/var/run/$NAME
|
||||
SOCKET=local:$RUNDIR/$NAME.sock
|
||||
|
||||
# Include opendkim defaults if available
|
||||
if [ -f /etc/default/opendmarc ] ; then
|
||||
. /etc/default/opendmarc
|
||||
fi
|
||||
|
||||
if [ -f /etc/opendmarc.conf ]; then
|
||||
CONFIG_SOCKET=`awk '$1 == "Socket" { print $2 }' /etc/opendmarc.conf`
|
||||
fi
|
||||
|
||||
# This can be set via Socket option in config file, so it's not required
|
||||
if [ -n "$SOCKET" -a -z "$CONFIG_SOCKET" ]; then
|
||||
DAEMON_OPTS="-p $SOCKET $DAEMON_OPTS"
|
||||
fi
|
||||
|
||||
DAEMON_OPTS="-f -c /etc/opendmarc.conf -u $USER $DAEMON_OPTS"
|
||||
|
||||
exec $DAEMON $DAEMON_OPTS 2>&1
|
|
@ -0,0 +1,10 @@
|
|||
#!/bin/bash
|
||||
|
||||
NAME=php5-fpm
|
||||
DAEMON=/usr/sbin/$NAME
|
||||
DAEMON_ARGS="--fpm-config /etc/php5/fpm/php-fpm.conf -F"
|
||||
|
||||
# Read configuration variable file if it is present
|
||||
[ -r /etc/default/$NAME ] && . /etc/default/$NAME
|
||||
|
||||
exec $DAEMON $DAEMON_ARGS 2>&1
|
|
@ -0,0 +1,12 @@
|
|||
#!/bin/bash
|
||||
|
||||
exec 1>&2
|
||||
|
||||
test -f /etc/default/postfix && . /etc/default/postfix
|
||||
|
||||
command_directory=`postconf -h command_directory`
|
||||
daemon_directory=`$command_directory/postconf -h daemon_directory`
|
||||
# make consistency check
|
||||
$command_directory/postfix check 2>&1
|
||||
# run Postfix
|
||||
exec $daemon_directory/master 2>&1
|
|
@ -0,0 +1,9 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Read config file if it is present.
|
||||
if [ -r /etc/default/postgrey ]
|
||||
then
|
||||
. /etc/default/postgrey
|
||||
fi
|
||||
|
||||
exec /usr/sbin/postgrey $POSTGREY_OPTS 2>&1
|
|
@ -0,0 +1,3 @@
|
|||
#!/bin/bash
|
||||
|
||||
exec rsyslogd -n 2>&1
|
|
@ -1,3 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
rsyslogd -n
|
|
@ -0,0 +1,60 @@
|
|||
#!/bin/bash
|
||||
|
||||
NAME='spampd'
|
||||
PROGRAM=/usr/sbin/spampd
|
||||
|
||||
if [ -f /etc/default/$NAME ]; then
|
||||
. /etc/default/$NAME
|
||||
fi
|
||||
|
||||
istrue () {
|
||||
ANS=$(echo $1 | tr A-Z a-z)
|
||||
[ "$ANS" = 'yes' -o "$ANS" = 'true' -o "$ANS" = 'enable' -o "$ANS" = '1' ]
|
||||
}
|
||||
|
||||
#
|
||||
# Calculate final commandline
|
||||
#
|
||||
S_TAGALL=''
|
||||
S_AWL=''
|
||||
S_LOCALONLY=''
|
||||
|
||||
istrue "$TAGALL" \
|
||||
&& S_TAGALL='--tagall'
|
||||
|
||||
istrue "$AUTOWHITELIST" \
|
||||
&& S_AWL='--auto-whitelist'
|
||||
|
||||
istrue "$LOCALONLY" \
|
||||
&& S_LOCALONLY='--L'
|
||||
|
||||
istrue "$LOGINET" \
|
||||
&& LOGTARGET="inet" \
|
||||
|| LOGTARGET="unix"
|
||||
|
||||
ARGS="${S_LOCALONLY} ${S_AWL} ${S_TAGALL} "
|
||||
|
||||
[ -n "${LISTENPORT}" ] && ARGS="${ARGS} --port=${LISTENPORT}"
|
||||
|
||||
[ -n "${LISTENHOST}" ] && ARGS="${ARGS} --host=${LISTENHOST}"
|
||||
|
||||
[ -n "${DESTPORT}" ] && ARGS="${ARGS} --relayport=${DESTPORT}"
|
||||
|
||||
[ -n "${DESTHOST}" ] && ARGS="${ARGS} --relayhost=${DESTHOST}"
|
||||
|
||||
[ -n "${PIDFILE}" ] && ARGS="${ARGS} --pid=${PIDFILE}"
|
||||
|
||||
[ -n "${CHILDREN}" ] && ARGS="${ARGS} --children=${CHILDREN}"
|
||||
|
||||
[ -n "${USERID}" ] && ARGS="${ARGS} --user=${USERID}"
|
||||
|
||||
[ -n "${GRPID}" ] && ARGS="${ARGS} --group=${GRPID}"
|
||||
|
||||
[ -n "${LOGTARGET}" ] && ARGS="${ARGS} --logsock=${LOGTARGET}"
|
||||
|
||||
[ -n "${ADDOPTS}" ] && ARGS="${ARGS} ${ADDOPTS}"
|
||||
|
||||
# Don't daemonize
|
||||
ARGS="${ARGS} --nodetach"
|
||||
|
||||
exec $PROGRAM $ARGS 2>&1
|
|
@ -162,6 +162,8 @@ def shell(method, cmd_args, env={}, capture_stderr=False, return_bytes=False, tr
|
|||
|
||||
def create_syslog_handler():
|
||||
import logging.handlers
|
||||
# This requires rsyslog to be started.
|
||||
# Could be enhanced for docker logging with phusion/baseimage.
|
||||
handler = logging.handlers.SysLogHandler(address='/dev/log')
|
||||
handler.setLevel(logging.WARNING)
|
||||
return handler
|
||||
|
|
|
@ -166,17 +166,6 @@ function ufw_allow {
|
|||
|
||||
function restart_service {
|
||||
# Restart a service quietly.
|
||||
|
||||
if [[ ! -z "$IS_DOCKER" && "$1" == "dovecot" ]]; then
|
||||
# In Docker, sysvinit takes care of any services with an init.d
|
||||
# script. The dovecot package provides an Upstart config only,
|
||||
# and so it won't work this way. We make a new script for it
|
||||
# elsewhere. We also cant do `sv restart dovecot` because runit
|
||||
# is not running until after the setup scripts are run. So we
|
||||
# will have to skip starting dovecot for now.
|
||||
return 0
|
||||
fi
|
||||
|
||||
hide_output service $1 restart
|
||||
}
|
||||
|
||||
|
|
|
@ -17,9 +17,22 @@ ln -s `pwd`/management/daemon.py /usr/local/bin/mailinabox-daemon
|
|||
|
||||
# Create an init script to start the management daemon and keep it
|
||||
# running after a reboot.
|
||||
rm -f /etc/init.d/mailinabox
|
||||
ln -s $(pwd)/conf/management-initscript /etc/init.d/mailinabox
|
||||
hide_output update-rc.d mailinabox defaults
|
||||
if [ ! -z "$IS_DOCKER" ]; then
|
||||
# Use runit for docker
|
||||
mkdir -p /etc/service/mailinabox
|
||||
cp /usr/local/mailinabox/containers/docker/runit/mailinabox.sh /etc/service/mailinabox/run
|
||||
chmod +x /etc/service/mailinabox/run
|
||||
|
||||
# runit -> LSB compatibility
|
||||
# see http://smarden.org/runit/faq.html#lsb
|
||||
mv /etc/init.d/mailinabox /etc/init.d/mailinabox.lsb
|
||||
chmod -x /etc/init.d/mailinabox.lsb
|
||||
ln -s /usr/bin/sv /etc/init.d/mailinabox
|
||||
else
|
||||
rm -f /etc/init.d/mailinabox
|
||||
ln -s $(pwd)/conf/management-initscript /etc/init.d/mailinabox
|
||||
hide_output update-rc.d mailinabox defaults
|
||||
fi
|
||||
|
||||
# Perform a daily backup.
|
||||
cat > /etc/cron.daily/mailinabox-backup << EOF;
|
||||
|
|
|
@ -4,6 +4,7 @@ if [ -z "$NONINTERACTIVE" ]; then
|
|||
# e.g. if we piped a bootstrapping install script to bash to get started. In that
|
||||
# case, the nifty '[ -t 0 ]' test won't work. But with Vagrant we must suppress so we
|
||||
# use a shell flag instead. Really supress any output from installing dialog.
|
||||
apt_get_quiet update
|
||||
apt_get_quiet install dialog
|
||||
message_box "Mail-in-a-Box Installation" \
|
||||
"Hello and thanks for deploying a Mail-in-a-Box!
|
||||
|
|
|
@ -39,7 +39,7 @@ fi
|
|||
# Put a start script in a global location. We tell the user to run 'mailinabox'
|
||||
# in the first dialog prompt, so we should do this before that starts.
|
||||
cat > /usr/local/bin/mailinabox << EOF;
|
||||
#!/bin/bash
|
||||
|
||||
cd `pwd`
|
||||
source setup/start.sh
|
||||
EOF
|
||||
|
@ -146,13 +146,6 @@ source setup/owncloud.sh
|
|||
source setup/zpush.sh
|
||||
source setup/management.sh
|
||||
|
||||
# In Docker, sysvinit services are started automatically. Runit services
|
||||
# aren't started until after this setup script finishes. But we need
|
||||
# Dovecot (which is Upstart-only) running in order to create the first
|
||||
# mail user. So start dovecot now.
|
||||
if [ ! -z "$IS_DOCKER" ]; then
|
||||
/usr/sbin/dovecot -c /etc/dovecot/dovecot.conf
|
||||
fi
|
||||
|
||||
# Ping the management daemon to write the DNS and nginx configuration files.
|
||||
while [ ! -f /var/lib/mailinabox/api.key ]; do
|
||||
|
|
Loading…
Reference in New Issue