diff --git a/Dockerfile b/Dockerfile
index df2eb966c1d8c11601c9fa31cb153e35fb414662..ebda51956d562e6b3a981c8b2805002c4a917c06 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -32,3 +32,21 @@ RUN echo 'eval "$(rbenv init -)"' >> /home/gdk/.bash_profile
 RUN mkdir /home/gdk/.rbenv/plugins
 RUN git clone https://github.com/sstephenson/ruby-build.git /home/gdk/.rbenv/plugins/ruby-build
 RUN bash -l -c "rbenv install 2.3.3 && rbenv global 2.3.3"
+
+WORKDIR /home/gdk
+
+ENV host=0.0.0.0 port=5000
+
+ADD review-apps/init /review-apps/init
+RUN /review-apps/init
+
+USER root
+RUN apt-get install -y nano vim ed
+USER gdk
+
+ADD review-apps/run /review-apps/run
+COPY support /home/gdk/gitlab-development-kit/support
+COPY Makefile /home/gdk/gitlab-development-kit/Makefile
+
+EXPOSE 5000
+CMD ["/review-apps/run"]
diff --git a/Makefile b/Makefile
index 7a5d78ea89a06b900234a13ee6ba5174b87da5c2..558e44a3415f6db926fa94c6c91a143896e6b28e 100644
--- a/Makefile
+++ b/Makefile
@@ -13,6 +13,7 @@ port = $(shell cat port 2>/dev/null)
 username = $(shell whoami)
 sshd_bin = $(shell which sshd)
 git_bin = $(shell which git)
+docker_repo = "ayufan/gitlab-development-kit"
 
 all: gitlab-setup gitlab-shell-setup gitlab-workhorse-setup support-setup gitaly-setup
 
@@ -91,25 +92,36 @@ update: gitlab-update gitlab-shell-update gitlab-workhorse-update gitaly-update
 gitlab-update: gitlab/.git/pull
 	cd ${gitlab_development_root}/gitlab && \
 		bundle install --without mysql production --jobs 4
+ifeq ($(OFFLINE_UPDATE),)
 	@echo ""
 	@echo "------------------------------------------------------------"
 	@echo "Make sure Postgres is running otherwise db:migrate will fail"
 	@echo "------------------------------------------------------------"
 	@echo ""
 	cd ${gitlab_development_root}/gitlab && \
-		bundle exec rake db:migrate db:test:prepare && \
-		npm prune && \
-		npm install
+		bin/rake db:migrate db:test:prepare
+else
+	support/migrate-rails
+endif
+	cd ${gitlab_development_root}/gitlab && \
+	npm prune && \
+	npm install
 
 gitlab-shell-update: gitlab-shell/.git/pull
 	cd ${gitlab_development_root}/gitlab-shell && \
 		bundle install --without production --jobs 4
 
 gitlab/.git/pull:
+ifeq ($(CI_CHECKOUT_SHA),)
 	cd ${gitlab_development_root}/gitlab && \
 		git checkout -- Gemfile.lock db/schema.rb && \
 		git stash && git checkout master && \
 		git pull --ff-only upstream master
+else
+	cd ${gitlab_development_root}/gitlab && \
+		git fetch origin && \
+		git checkout -f $(CI_CHECKOUT_SHA)
+endif
 
 gitlab-shell/.git/pull:
 	cd ${gitlab_development_root}/gitlab-shell && \
@@ -155,9 +167,9 @@ redis: redis/redis.conf
 redis/redis.conf:
 	sed "s|/home/git|${gitlab_development_root}|" $@.example > $@
 
-postgresql: postgresql/data
+postgresql: postgresql/data/PG_VERSION
 
-postgresql/data:
+postgresql/data/PG_VERSION:
 	${postgres_bin_dir}/initdb --locale=C -E utf-8 postgresql/data
 	support/bootstrap-rails
 
@@ -272,3 +284,13 @@ clean-config:
 	redis/redis.conf \
 	.ruby-version \
 	Procfile \
+
+docker_build:
+	docker build --cache-from=ayufan/gitlab-development-kit -t $(docker_repo) .
+
+docker_build_and_run: docker_build
+	-docker rm -f -v gdk
+	docker run -it --name=gdk --rm $(docker_repo) $(docker_cmd)
+
+docker_build_and_push: docker_build
+	docker push $(docker_repo)
diff --git a/review-apps/init b/review-apps/init
new file mode 100755
index 0000000000000000000000000000000000000000..1cc309885a0cce079e6e1dc4e50b54db258b3641
--- /dev/null
+++ b/review-apps/init
@@ -0,0 +1,8 @@
+#!/bin/bash -l
+
+set -xe
+
+gem install gitlab-development-kit
+gdk init
+cd gitlab-development-kit
+gdk install
diff --git a/review-apps/run b/review-apps/run
new file mode 100755
index 0000000000000000000000000000000000000000..7aa1e23e902effc597fdd903a8eb365b90171ede
--- /dev/null
+++ b/review-apps/run
@@ -0,0 +1,13 @@
+#!/bin/bash -l
+
+set -xe
+
+export ENABLE_SPRING=true
+
+cd gitlab-development-kit
+
+make update \
+  OFFLINE_UPDATE=1 \
+  CI_CHECKOUT_SHA=$CI_CHECKOUT_SHA
+
+gdk run
diff --git a/support/migrate-rails b/support/migrate-rails
new file mode 100755
index 0000000000000000000000000000000000000000..737f3f86f0a4a48d8be68f95dcf8135294d4a6e4
--- /dev/null
+++ b/support/migrate-rails
@@ -0,0 +1,20 @@
+#!/usr/bin/env ruby
+
+success = true
+begin
+  foreman_pid = spawn('./run', 'db')
+  [
+    %W(bin/rake db:migrate),
+    %W(bin/rake db:test:prepare),
+  ].each do |cmd|
+    success &&= system(*cmd, chdir: 'gitlab')
+  end
+ensure
+  Process.kill('TERM', foreman_pid)
+end
+
+Process.wait(foreman_pid)
+
+exit true if success
+
+abort "#$0 failed"