diff --git a/.gitignore b/.gitignore index a3c121f5b..c1b47c1e0 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,6 @@ .vagrant .DS_Store stack.tgz +build +tmp +*.deb diff --git a/Makefile b/Makefile index 59c3b5fb1..2d85dd334 100644 --- a/Makefile +++ b/Makefile @@ -17,12 +17,25 @@ endif .PHONY: all install copyfiles version plugins dependencies sshcommand pluginhook docker aufs stack count dokku-installer vagrant-acl-add vagrant-dokku include tests.mk +include deb.mk all: # Type "make install" to install. install: dependencies stack copyfiles plugin-dependencies plugins version +release: deb-all package_cloud packer + +package_cloud: + package_cloud push dokku/dokku/ubuntu/trusty buildstep*.deb + package_cloud push dokku/dokku/ubuntu/trusty sshcommand*.deb + package_cloud push dokku/dokku/ubuntu/trusty pluginhook*.deb + package_cloud push dokku/dokku/ubuntu/trusty rubygem*.deb + package_cloud push dokku/dokku/ubuntu/trusty dokku*.deb + +packer: + packer build contrib/packer.json + copyfiles: cp dokku /usr/local/bin/dokku mkdir -p ${PLUGINS_PATH} diff --git a/README.md b/README.md index 1fd30eb9d..60c254ded 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Dokku [![Build Status](https://circleci.com/gh/progrium/dokku/tree/master.svg?style=svg&circle-token=eec5b442dda53a4d229911dd97d4214853acc262 "Build Status")](https://circleci.com/gh/progrium/dokku/tree/master) +# Dokku [![Build Status](https://circleci.com/gh/progrium/dokku/tree/master.svg?style=svg&circle-token=eec5b442dda53a4d229911dd97d4214853acc262 "Build Status")](https://circleci.com/gh/progrium/dokku/tree/master) [![Ubuntu Package](https://img.shields.io/badge/package-ubuntu-brightgreen.svg?style=flat-square "Ubuntu Package")](https://packagecloud.io/dokku/dokku) Docker powered mini-Heroku. The smallest PaaS implementation you've ever seen. Sponsored by our friends at [Deis](http://deis.io/). diff --git a/Vagrantfile b/Vagrantfile index 749494ef7..2d310a943 100644 --- a/Vagrantfile +++ b/Vagrantfile @@ -7,6 +7,7 @@ BOX_MEMORY = ENV["BOX_MEMORY"] || "1024" DOKKU_DOMAIN = ENV["DOKKU_DOMAIN"] || "dokku.me" DOKKU_IP = ENV["DOKKU_IP"] || "10.0.0.2" PREBUILT_STACK_URL = File.exist?("#{File.dirname(__FILE__)}/stack.tgz") ? 'file:///root/dokku/stack.tgz' : nil +PUBLIC_KEY_PATH = "#{Dir.home}/.ssh/id_rsa.pub" make_cmd = "make install" if PREBUILT_STACK_URL @@ -14,12 +15,11 @@ if PREBUILT_STACK_URL end Vagrant::configure("2") do |config| + config.ssh.forward_agent = true + config.vm.box = BOX_NAME config.vm.box_url = BOX_URI config.vm.synced_folder File.dirname(__FILE__), "/root/dokku" - config.vm.network :forwarded_port, guest: 80, host: 8080 - config.vm.hostname = "#{DOKKU_DOMAIN}" - config.vm.network :private_network, ip: DOKKU_IP config.vm.provider :virtualbox do |vb| vb.customize ["modifyvm", :id, "--natdnshostresolver1", "on"] @@ -29,6 +29,29 @@ Vagrant::configure("2") do |config| vb.customize ["modifyvm", :id, "--memory", BOX_MEMORY] end - config.vm.provision :shell, :inline => "apt-get -qq -y install git > /dev/null && cd /root/dokku && #{make_cmd}" - config.vm.provision :shell, :inline => "cd /root/dokku && make dokku-installer" + config.vm.define "empty", autostart: false + + config.vm.define "dokku", primary: true do |vm| + vm.vm.network :forwarded_port, guest: 80, host: 8080 + vm.vm.hostname = "#{DOKKU_DOMAIN}" + vm.vm.network :private_network, ip: DOKKU_IP + vm.vm.provision :shell, :inline => "apt-get -qq -y install git > /dev/null && cd /root/dokku && #{make_cmd}" + vm.vm.provision :shell, :inline => "cd /root/dokku && make dokku-installer" + end + + config.vm.define "dokku-deb", autostart: false do |vm| + vm.vm.network :forwarded_port, guest: 80, host: 8080 + vm.vm.hostname = "#{DOKKU_DOMAIN}" + vm.vm.network :private_network, ip: DOKKU_IP + vm.vm.provision :shell, :inline => "cd /root/dokku && make install-from-deb" + end + + config.vm.define "build", autostart: false do |vm| + vm.vm.provision :shell, :inline => "cd /root/dokku && make deb-all" + end + + if Pathname.new(PUBLIC_KEY_PATH).exist? + config.vm.provision :file, source: PUBLIC_KEY_PATH, destination: '/tmp/id_rsa.pub' + config.vm.provision :shell, :inline => "rm /root/.ssh/authorized_keys && mv /tmp/id_rsa.pub /root/.ssh/authorized_keys" + end end diff --git a/contrib/dokku-installer.rb b/contrib/dokku-installer.rb index ef09ab40d..85a95c155 100755 --- a/contrib/dokku-installer.rb +++ b/contrib/dokku-installer.rb @@ -16,7 +16,7 @@ if ARGV[0] == "onboot" f.puts " }" f.puts "}" end - `rm /etc/nginx/sites-enabled/*` + `rm -f /etc/nginx/sites-enabled/*` puts "Installed Upstart service and default Nginx virtualhost for installer to run on boot." exit end diff --git a/contrib/packer.json b/contrib/packer.json new file mode 100644 index 000000000..f293592ee --- /dev/null +++ b/contrib/packer.json @@ -0,0 +1,32 @@ +{ + "builders": [ + { + "type": "digitalocean", + "region": "nyc3", + "image": "ubuntu-14-04-x64" + } + ], + "provisioners": [ + { + "type": "file", + "source": "deb.mk", + "destination": "/tmp/Makefile" + }, + { + "type": "shell", + "inline": [ + "echo '--> Waiting 30 seconds for core services to be available'", + "sleep 30", + + "echo '--> Updating apt repositories'", + "sudo apt-get update > /dev/null", + + "echo '--> Installing make requirement'", + "sudo apt-get -qq -y install build-essential", + + "cd /tmp && make install-from-deb", + "rm /root/.ssh/authorized_keys" + ] + } + ] +} diff --git a/deb.mk b/deb.mk new file mode 100644 index 000000000..13357eef6 --- /dev/null +++ b/deb.mk @@ -0,0 +1,159 @@ +BUILDSTEP_DESCRIPTION = 'Buildstep uses Docker and Buildpacks to build applications like Heroku' +BUILDSTEP_REPO_NAME ?= progrium/buildstep +BUILDSTEP_VERSION ?= 0.0.1 +BUILDSTEP_ARCHITECTURE = amd64 +BUILDSTEP_PACKAGE_NAME = buildstep_$(BUILDSTEP_VERSION)_$(BUILDSTEP_ARCHITECTURE).deb + +DOKKU_DESCRIPTION = 'Docker powered mini-Heroku in around 100 lines of Bash' +DOKKU_REPO_NAME ?= progrium/dokku +DOKKU_ARCHITECTURE = amd64 + +PLUGINHOOK_DESCRIPTION = 'Simple dispatcher and protocol for shell-based plugins, an improvement to hook scripts' +PLUGINHOOK_REPO_NAME ?= progrium/pluginhook +PLUGINHOOK_VERSION ?= 0.0.1 +PLUGINHOOK_ARCHITECTURE = amd64 +PLUGINHOOK_PACKAGE_NAME = pluginhook_$(PLUGINHOOK_VERSION)_$(PLUGINHOOK_ARCHITECTURE).deb + +SSHCOMMAND_DESCRIPTION = 'Turn SSH into a thin client specifically for your app' +SSHCOMMAND_REPO_NAME ?= progrium/sshcommand +SSHCOMMAND_VERSION ?= 0.0.1 +SSHCOMMAND_ARCHITECTURE = amd64 +SSHCOMMAND_PACKAGE_NAME = sshcommand_$(SSHCOMMAND_VERSION)_$(SSHCOMMAND_ARCHITECTURE).deb + +GEM_ARCHITECTURE = amd64 + +GOROOT = /usr/lib/go +GOBIN = /usr/bin/go +GOPATH = /home/vagrant/gocode + +.PHONY: install-from-deb deb-all deb-buildstep deb-dokku deb-gems deb-pluginhook deb-setup deb-sshcommand + +install-from-deb: + echo "--> Installing docker gpg key" + curl --silent https://get.docker.io/gpg 2> /dev/null | apt-key add - 2>&1 >/dev/null + + echo "--> Installing dokku gpg key" + curl --silent https://packagecloud.io/gpg.key 2> /dev/null | apt-key add - 2>&1 >/dev/null + + echo "--> Setting up apt repositories" + echo "deb http://get.docker.io/ubuntu docker main" > /etc/apt/sources.list.d/docker.list + echo "deb https://packagecloud.io/dokku/dokku/ubuntu/ trusty main" > /etc/apt/sources.list.d/dokku.list + + echo "--> Running apt-get update" + sudo apt-get update > /dev/null + + echo "--> Installing pre-requisites" + sudo apt-get install -y linux-image-extra-`uname -r` apt-transport-https + + echo "--> Installing dokku" + sudo apt-get install -y dokku + + echo "--> Done!" + +deb-all: deb-buildstep deb-dokku deb-gems deb-pluginhook deb-sshcommand + mv /tmp/*.deb . + echo "Done" + +deb-setup: + echo "-> Updating deb repository and installing build requirements" + sudo apt-get update > /dev/null + sudo apt-get install -qq -y git ruby1.9.1-dev 2>&1 > /dev/null + command -v fpm > /dev/null || sudo gem install fpm --no-ri --no-rdoc + ssh -o StrictHostKeyChecking=no git@github.com || true + +deb-buildstep: deb-setup + rm -rf /tmp/tmp /tmp/build $(BUILDSTEP_PACKAGE_NAME) + mkdir -p /tmp/tmp /tmp/build + + echo "-> Creating deb files" + echo "#!/usr/bin/env bash" >> /tmp/tmp/post-install + echo "sleep 5" >> /tmp/tmp/post-install + echo "count=\`sudo docker images | grep progrium/buildstep | wc -l\`" >> /tmp/tmp/post-install + echo 'if [ "$$count" -ne 0 ]; then' >> /tmp/tmp/post-install + echo " echo 'Removing old buildstep image'" >> /tmp/tmp/post-install + echo " sudo docker rmi progrium/buildstep" >> /tmp/tmp/post-install + echo "fi" >> /tmp/tmp/post-install + echo "echo 'Importing buildstep into docker (around 5 minutes)'" >> /tmp/tmp/post-install + echo "sudo docker build -t progrium/buildstep /var/lib/buildstep 1> /dev/null" >> /tmp/tmp/post-install + + echo "-> Cloning repository" + git clone -q "git@github.com:$(BUILDSTEP_REPO_NAME).git" /tmp/tmp/buildstep > /dev/null + rm -rf /tmp/tmp/buildstep/.git /tmp/tmp/buildstep/.gitignore + + echo "-> Copying files into place" + mkdir -p "/tmp/build/var/lib" + cp -rf /tmp/tmp/buildstep /tmp/build/var/lib/buildstep + + echo "-> Creating $(BUILDSTEP_PACKAGE_NAME)" + sudo fpm -t deb -s dir -C /tmp/build -n buildstep -v $(BUILDSTEP_VERSION) -a $(BUILDSTEP_ARCHITECTURE) -p $(BUILDSTEP_PACKAGE_NAME) --deb-pre-depends 'lxc-docker >= 1.4.0' --after-install /tmp/tmp/post-install --url "https://github.com/$(BUILDSTEP_REPO_NAME)" --description $(BUILDSTEP_DESCRIPTION) --license 'MIT License' . + mv *.deb /tmp + +deb-dokku: deb-setup + rm -rf /tmp/tmp /tmp/build dokku_*_$(DOKKU_ARCHITECTURE).deb + mkdir -p /tmp/tmp /tmp/build + + cp -r debian /tmp/build/DEBIAN + mkdir -p /tmp/build/usr/local/bin + mkdir -p /tmp/build/var/lib/dokku + mkdir -p /tmp/build/usr/local/share/man/man1 + mkdir -p /tmp/build/usr/local/share/dokku/contrib + + cp dokku /tmp/build/usr/local/bin + cp -r plugins /tmp/build/var/lib/dokku + find plugins/ -mindepth 1 -maxdepth 1 -type d -printf '%f\n' | while read plugin; do touch /tmp/build/var/lib/dokku/plugins/$$plugin/.core; done + cp dokku.1 /tmp/build/usr/local/share/man/man1/dokku.1 + cp contrib/dokku-installer.rb /tmp/build/usr/local/share/dokku/contrib + git describe --tags > /tmp/build/var/lib/dokku/VERSION + cat /tmp/build/var/lib/dokku/VERSION | cut -d '-' -f 1 | cut -d 'v' -f 2 > /tmp/build/var/lib/dokku/STABLE_VERSION + git rev-parse HEAD > /tmp/build/var/lib/dokku/GIT_REV + sed -i "s/^Version: .*/Version: `cat /tmp/build/var/lib/dokku/STABLE_VERSION`/g" /tmp/build/DEBIAN/control + dpkg-deb --build /tmp/build "/vagrant/dokku_`cat /tmp/build/var/lib/dokku/STABLE_VERSION`_$(DOKKU_ARCHITECTURE).deb" + mv *.deb /tmp + +deb-gems: deb-setup + rm -rf /tmp/tmp /tmp/build rubygem-*.deb + mkdir -p /tmp/tmp /tmp/build + + gem install --quiet --no-verbose --no-ri --no-rdoc --install-dir /tmp/tmp rack -v 1.5.2 > /dev/null + gem install --quiet --no-verbose --no-ri --no-rdoc --install-dir /tmp/tmp rack-protection -v 1.5.3 > /dev/null + gem install --quiet --no-verbose --no-ri --no-rdoc --install-dir /tmp/tmp sinatra -v 1.4.5 > /dev/null + gem install --quiet --no-verbose --no-ri --no-rdoc --install-dir /tmp/tmp tilt -v 1.4.1 > /dev/null + + find /tmp/tmp/cache -name '*.gem' | xargs -rn1 fpm -d ruby -d ruby --prefix /var/lib/gems/1.9.1 -s gem -t deb -a $(GEM_ARCHITECTURE) + mv *.deb /tmp + +deb-pluginhook: deb-setup + rm -rf /tmp/tmp /tmp/build $(PLUGINHOOK_PACKAGE_NAME) + mkdir -p /tmp/tmp /tmp/build + + echo "-> Cloning repository" + git clone -q "git@github.com:$(PLUGINHOOK_REPO_NAME).git" /tmp/tmp/pluginhook > /dev/null + rm -rf /tmp/tmp/pluginhook/.git /tmp/tmp/pluginhook/.gitignore + + echo "-> Copying files into place" + mkdir -p /tmp/build/usr/local/bin $(GOPATH) + sudo apt-get install -qq -y git golang mercurial 2>&1 > /dev/null + export PATH=$(PATH):$(GOROOT)/bin:$(GOPATH)/bin && export GOROOT=$(GOROOT) && export GOPATH=$(GOPATH) && go get "code.google.com/p/go.crypto/ssh/terminal" + export PATH=$(PATH):$(GOROOT)/bin:$(GOPATH)/bin && export GOROOT=$(GOROOT) && export GOPATH=$(GOPATH) && cd /tmp/tmp/pluginhook && go build -o pluginhook + mv /tmp/tmp/pluginhook/pluginhook /tmp/build/usr/local/bin/pluginhook + + echo "-> Creating $(PLUGINHOOK_PACKAGE_NAME)" + sudo fpm -t deb -s dir -C /tmp/build -n pluginhook -v $(PLUGINHOOK_VERSION) -a $(PLUGINHOOK_ARCHITECTURE) -p $(PLUGINHOOK_PACKAGE_NAME) --url "https://github.com/$(PLUGINHOOK_REPO_NAME)" --description $(PLUGINHOOK_DESCRIPTION) --license 'MIT License' . + mv *.deb /tmp + +deb-sshcommand: deb-setup + rm -rf /tmp/tmp /tmp/build $(SSHCOMMAND_PACKAGE_NAME) + mkdir -p /tmp/tmp /tmp/build + + echo "-> Cloning repository" + git clone -q "git@github.com:$(SSHCOMMAND_REPO_NAME).git" /tmp/tmp/sshcommand > /dev/null + rm -rf /tmp/tmp/sshcommand/.git /tmp/tmp/sshcommand/.gitignore + + echo "-> Copying files into place" + mkdir -p "/tmp/build/usr/local/bin" + cp /tmp/tmp/sshcommand/sshcommand /tmp/build/usr/local/bin/sshcommand + chmod +x /tmp/build/usr/local/bin/sshcommand + + echo "-> Creating $(SSHCOMMAND_PACKAGE_NAME)" + sudo fpm -t deb -s dir -C /tmp/build -n sshcommand -v $(SSHCOMMAND_VERSION) -a $(SSHCOMMAND_ARCHITECTURE) -p $(SSHCOMMAND_PACKAGE_NAME) --url "https://github.com/$(SSHCOMMAND_REPO_NAME)" --description $(SSHCOMMAND_DESCRIPTION) --license 'MIT License' . + mv *.deb /tmp diff --git a/debian/conffiles b/debian/conffiles new file mode 100644 index 000000000..e69de29bb diff --git a/debian/control b/debian/control new file mode 100644 index 000000000..5b3437970 --- /dev/null +++ b/debian/control @@ -0,0 +1,10 @@ +Package: dokku +Version: 0.3.12 +Section: base +Priority: optional +Architecture: amd64 +Depends: locales, git, make, curl, software-properties-common, lxc-docker (>= 1.4.0), gcc, python-software-properties, man-db, buildstep, sshcommand, pluginhook +Pre-Depends: nginx, dnsutils, ruby, ruby-dev, rubygem-rack, rubygem-rack-protection, rubygem-sinatra, rubygem-tilt +Provides: dokku +Maintainer: Jose Diaz-Gonzalez +Description: Docker powered mini-Heroku in around 100 lines of Bash diff --git a/debian/postinst b/debian/postinst new file mode 100755 index 000000000..25965e1dd --- /dev/null +++ b/debian/postinst @@ -0,0 +1,28 @@ +#!/bin/sh +set -e + +case "$1" in + abort-upgrade|abort-remove|abort-deconfigure) + ;; + + configure) + mandb + [ ! -x /usr/bin/docker.io ] || ln -sf /usr/bin/docker.io /usr/local/bin/docker + modprobe aufs || echo "WARNING: Restart server to finish installing dokku!" + sshcommand create dokku /usr/local/bin/dokku + egrep -i "^docker" /etc/group || groupadd docker + usermod -aG docker dokku + dokku plugins-install + + if [ -f /etc/init/dokku-installer.conf ] && service dokku-installer status 2> /dev/null | grep waiting; then + sudo service dokku-installer start + fi + ;; + + *) + echo "postinst called with unknown argument \`$1'" >&2 + exit 1 + ;; +esac + +exit 0 diff --git a/debian/preinst b/debian/preinst new file mode 100755 index 000000000..a7a5c7a54 --- /dev/null +++ b/debian/preinst @@ -0,0 +1,37 @@ +#!/bin/sh +set -e + +case "$1" in + install) + INIT_CONF="/etc/init/dokku-installer.conf" + NGINX_CONF="/etc/nginx/conf.d/dokku-installer.conf" + + rm -f $INIT_CONF + touch $INIT_CONF + echo 'start on runlevel [2345]' >> $INIT_CONF + echo 'exec /usr/local/share/dokku/contrib/dokku-installer.rb selfdestruct' >> $INIT_CONF + + rm -f $NGINX_CONF + touch $NGINX_CONF + echo 'upstream dokku-installer { server 127.0.0.1:2000; }' >> $NGINX_CONF + echo 'server {' >> $NGINX_CONF + echo ' listen 80;' >> $NGINX_CONF + echo ' location / {' >> $NGINX_CONF + echo ' proxy_pass http://dokku-installer;' >> $NGINX_CONF + echo ' }' >> $NGINX_CONF + echo '}' >> $NGINX_CONF + + rm -f /etc/nginx/sites-enabled/* + service nginx reload + ;; + + abort-upgrade) + ;; + + *) + echo "preinst called with unknown argument \`$1'" >&2 + exit 1 + ;; +esac + +exit 0