#!/bin/sh
# Create lightweight, portable, self-sufficient containers.
# chkconfig: - 95 5
# description:
#  Docker is an open-source project to easily create lightweight, portable,
#  self-sufficient containers from any application. The same container that a
#  developer builds and tests on a laptop can run at scale, in production, on
#  VMs, bare metal, OpenStack clusters, public clouds and more.

### BEGIN INIT INFO
# Provides:           docker
# Required-Start:
# Required-Stop:
# Should-Start:       cgconfig
# Should-Stop:        cgconfig
# Default-Start:      2 3 4 5
# Default-Stop:       0 1 6
# Short-Description:  Create lightweight, portable, self-sufficient containers.
# Description:
#  Docker is an open-source project to easily create lightweight, portable,
#  self-sufficient containers from any application. The same container that a
#  developer builds and tests on a laptop can run at scale, in production, on
#  VMs, bare metal, OpenStack clusters, public clouds and more.
### END INIT INFO

export PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin

BASE=docker

# modify these in /etc/default/$BASE (/etc/default/docker)
DOCKERD=/usr/bin/dockerd
# This is the pid file managed by docker itself
DOCKER_PIDFILE=/var/run/$BASE.pid
# This is the pid file created/managed by start-stop-daemon
DOCKER_SSD_PIDFILE=/var/run/$BASE.pid
DOCKER_OPTS=
DOCKER_DESC="Docker"

# Source function library.
. /etc/rc.d/init.d/functions

if [ -f /etc/sysconfig/$BASE ]; then
	. /etc/sysconfig/$BASE
fi

# Check docker is present
if [ ! -x $DOCKERD ]; then
	echo "$DOCKERD not present or not executable"
	exit 1
fi

fail_unless_root() {
	if [ "$(id -u)" != '0' ]; then
		echo "$DOCKER_DESC must be run as root"
		exit 1
	fi
}

cgroupfs_mount() {
	# see also https://github.com/tianon/cgroupfs-mount/blob/master/cgroupfs-mount
	if grep -v '^#' /etc/fstab | grep -q cgroup \
		|| [ ! -e /proc/cgroups ] \
		|| [ ! -d /sys/fs/cgroup ]; then
		return
	fi
	if ! mountpoint -q /sys/fs/cgroup; then
		mount -t tmpfs -o uid=0,gid=0,mode=0755 cgroup /sys/fs/cgroup
	fi
	(
		cd /sys/fs/cgroup
		for sys in $(awk '!/^#/ { if ($4 == 1) print $1 }' /proc/cgroups); do
			mkdir -p $sys
			if ! mountpoint -q $sys; then
				if ! mount -n -t cgroup -o $sys cgroup $sys; then
					rmdir $sys || true
				fi
			fi
		done
	)
}

case "$1" in
	start)
		fail_unless_root

		cgroupfs_mount

		ulimit -n 1048576

		# Having non-zero limits causes performance problems due to accounting overhead
		# in the kernel. We recommend using cgroups to do container-local accounting.
		if [ "$BASH" ]; then
			ulimit -u unlimited
		else
			ulimit -p unlimited
		fi

		echo -n $"Starting $BASE:"
		$DOCKERD \
				-p "$DOCKER_PIDFILE" \
				$DOCKER_OPTS \
				2>&1 | /usr/bin/logger -t dockerd -p daemon.notice &
		sleep 1
		if [ -s $DOCKER_PIDFILE ]; then
			disown
			touch /var/lock/subsys/docker
			success
		else
			failure
		fi
		echo
		;;

	stop)
		fail_unless_root
		if [ -f "$DOCKER_SSD_PIDFILE" ]; then
			DOCKER_CONTAINERS=$(/usr/bin/docker ps -q)
			if [ "x$DOCKER_CONTAINERS" != "x" ]; then
				echo -n $"Stopping Docker containers:"
				/usr/bin/docker stop -t 60 $DOCKER_CONTAINERS
				DOCKER_CONTAINERS=$(/usr/bin/docker ps -q)
				if [ "x$DOCKER_CONTAINERS" = "x" ]; then
					success
				else
					failure
				fi
				echo
			fi
			echo -n $"Stopping $BASE:"
			DOCKERD_PID=$(cat $DOCKER_SSD_PIDFILE 2>/dev/null)
			kill $DOCKERD_PID
			CNT=0;
			while [ -f "$DOCKER_SSD_PIDFILE" -a $CNT -lt 60 ]; do
				sleep 1
				CNT=$((CNT++))
			done
			if [ ! -f "$DOCKER_SSD_PIDFILE" ]; then
				success
			else
				failure
			fi
		else
			echo -n "Docker already stopped - file $DOCKER_SSD_PIDFILE not found."
		fi
		echo
		rm -f /var/lock/subsys/docker
		;;

	restart)
		fail_unless_root
		DOCKERD_PID=$(cat $DOCKER_SSD_PIDFILE 2>/dev/null)
		[ -n "$DOCKERD_PID" ] \
			&& ps -p $docker_pid > /dev/null 2>&1 \
			&& $0 stop
		$0 start
		;;

	force-reload)
		fail_unless_root
		$0 restart
		;;

	status)
		status -p $DOCKER_SSD_PIDFILE docker
		;;

	*)
		echo "Usage: service docker {start|stop|restart|status}"
		exit 1
		;;
esac
