diff --git a/.gitignore b/.gitignore
index e493dd6ee0f8cfed2ba5acf04a0914db8504fc14..db3eaf3e3a6b0c62e1796105ed695ff226c8784a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,3 @@
 bin
 dist
+_output
diff --git a/.travis.yml b/.travis.yml
index cd20f70e0c6ad327d48c112c67d21e27c6d15775..c9dd7d63cf4d9c74c5ee20d41d8eac26cac63815 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,7 +1,7 @@
 language: go
 
 go:
-  - 1.7
+  - 1.7.1
 
 services:
   - postgresql
diff --git a/Dockerfile b/Dockerfile
index 51094255d4bb646bf0003b559061e1b754f1df2e..9f1b277b00955c42b323ca075e17633efa508624 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,11 +1,11 @@
-FROM alpine:latest
+FROM alpine:3.4
 
 MAINTAINER Eric Chiang <eric.chiang@coreos.com>
 
 RUN apk add --update ca-certificates 
 
-COPY bin/dex /dex
+COPY _output/bin/dex /usr/local/bin/dex
 
-ENTRYPOINT ["/dex"]
+ENTRYPOINT ["/usr/local/bin/dex"]
 
 CMD ["version"]
diff --git a/Documentation/dev-releases.md b/Documentation/dev-releases.md
new file mode 100644
index 0000000000000000000000000000000000000000..3182afa5e7c0b2af348bfe298917f0f882b2ec73
--- /dev/null
+++ b/Documentation/dev-releases.md
@@ -0,0 +1,80 @@
+# Releases
+
+Making a dex release involves:
+
+* Tagging a git commit and pushing the tag to GitHub.
+* Building and pushing a Docker image.
+* Building, signing, and hosting an ACI.
+
+This requires the following tools.
+
+* rkt
+* Docker
+* [docker2aci](https://github.com/appc/docker2aci)
+* [acbuild](https://github.com/containers/build) (must be in your sudo user's PATH)
+
+And the following permissions.
+
+* Push access to the github.com/coreos/dex git repo.
+* Push access to the quay.io/coreos/dex Docker repo.
+* Access to the CoreOS application signing key.
+
+## Tagging the release
+
+Make sure you've [uploaded your GPG key](https://github.com/settings/keys) and
+configured git to [use that signing key](
+https://git-scm.com/book/en/v2/Git-Tools-Signing-Your-Work) either globally or
+for the Dex repo. Note that the email the key is issued for must be the email
+you use for git.
+
+```
+git config [--global] user.signingkey "{{ GPG key ID }}"
+git config [--global] user.email "{{ Email associated with key }}"
+```
+
+Create a signed tag at the commit you wish to release. This action will prompt
+you to enter a tag message, which can just be the release version.
+
+```
+git tag -s v2.1.0-alpha ea4c04fde83bd6c48f4d43862c406deb4ea9dba2
+```
+
+Push that tag to the CoreOS repo.
+
+```
+git push git@github.com:coreos/dex.git v2.1.0-alpha
+```
+
+Draft releases on GitHub and summarize the changes since the last release. See
+previous releases for the expected format.
+
+https://github.com/coreos/dex/releases
+
+## Building the Docker image
+
+Build the Docker image and push to Quay.
+
+```bash
+# checkout the tag
+git checkout tags/v2.1.0-alpha
+# rkt doesn't play nice with SELinux, see https://github.com/coreos/rkt/issues/1727
+sudo setenforce Permissive
+# will prompt for sudo password
+make docker-image
+sudo docker push quay.io/coreos/dex:v2.1.0-alpha
+```
+
+## Building the ACI
+
+```bash
+# checkout the tag
+git checkout tags/v2.1.0-alpha
+# rkt doesn't play nice with SELinux, see https://github.com/coreos/rkt/issues/1727
+sudo setenforce Permissive
+# will prompt for sudo password
+make aci
+# aci will be built at _output/image/dex.aci
+```
+
+Sign the ACI using the CoreOS application signing key. Upload the ACI and
+signature to the GitHub release.
diff --git a/Makefile b/Makefile
index 9e884c0c1317c9775e7a00566fcd174c3610a8c3..0205b6df540c102d82b086c0c9774307a5ad2b3e 100644
--- a/Makefile
+++ b/Makefile
@@ -5,10 +5,15 @@ export PATH := $(PWD)/bin:$(PATH)
 
 VERSION=$(shell ./scripts/git-version)
 
-DOCKER_REPO=quay.io/ericchiang/dex
+DOCKER_REPO=quay.io/coreos/dex
 DOCKER_IMAGE=$(DOCKER_REPO):$(VERSION)
 
 $( shell mkdir -p bin )
+$( shell mkdir -p _output/images )
+$( shell mkdir -p _output/bin )
+
+user=$(shell id -u -n)
+group=$(shell id -g -n)
 
 export GOBIN=$(PWD)/bin
 # Prefer ./bin instead of system packages for things like protoc, where we want
@@ -51,15 +56,28 @@ lint:
 server/templates_default.go: $(wildcard web/templates/**)
 	@go run server/templates_default_gen.go
 
-.PHONY: docker-build
-docker-build: bin/dex
-	@docker build -t $(DOCKER_IMAGE) .
+_output/bin/dex:
+	# Using rkt to build the dex binary.
+	@./scripts/rkt-build
+	@sudo chown $(user):$(group) _output/bin/dex
+
+_output/images/library-alpine-3.4.aci:
+	@mkdir -p _output/images
+	# Using docker2aci to get a base ACI to build from.
+	@docker2aci docker://alpine:3.4
+	@mv library-alpine-3.4.aci _output/images/library-alpine-3.4.aci
 
-.PHONY: docker-push
-docker-push: docker-build
-	@docker tag $(DOCKER_IMAGE) $(DOCKER_REPO):latest
-	@docker push $(DOCKER_IMAGE)
-	@docker push $(DOCKER_REPO):latest
+_output/images/dex.aci: _output/bin/dex _output/images/library-alpine-3.4.aci
+	# Using acbuild to build a application container image.
+	@sudo ./scripts/build-aci ./_output/images/library-alpine-3.4.aci
+	@sudo chown $(user):$(group) _output/images/dex.aci
+
+.PHONY: aci
+aci: _output/images/dex.aci
+
+.PHONY: docker-image
+docker-image: _output/bin/dex
+	@docker build -t $(DOCKER_IMAGE) .
 
 .PHONY: grpc
 grpc: api/api.pb.go
@@ -74,7 +92,8 @@ bin/protoc-gen-go:
 	@go install -v $(REPO_PATH)/vendor/github.com/golang/protobuf/protoc-gen-go
 
 clean:
-	@rm bin/*
+	@rm -rf bin/
+	@rm -rf _output/
 
 testall: testrace vet fmt lint
 
diff --git a/scripts/build-aci b/scripts/build-aci
new file mode 100755
index 0000000000000000000000000000000000000000..03f232a788e09799ecbe373b667de41ff46fa964
--- /dev/null
+++ b/scripts/build-aci
@@ -0,0 +1,30 @@
+#!/usr/bin/env bash
+
+set -e
+
+if [ "$EUID" -ne 0 ]; then
+    echo "This script uses functionality which requires root privileges"
+    exit 1
+fi
+
+# Start the build with an empty ACI
+acbuild --debug begin $1
+
+# In the event of the script exiting, end the build
+trap "{ export EXT=$?; sudo acbuild --debug end && exit $EXT; }" EXIT
+
+# Name the ACI
+acbuild --debug set-name coreos.com/dex
+
+# Add a version label
+acbuild --debug label add version $( ./scripts/git-version )
+
+acbuild --debug run -- apk add --update ca-certificates 
+
+acbuild --debug copy _output/bin/dex /usr/local/bin/dex
+
+acbuild --debug port add www tcp 5556
+acbuild --debug port add grcp tpc 5557
+
+acbuild --debug set-exec -- /usr/local/bin/dex
+acbuild --debug write --overwrite _output/images/dex.aci
diff --git a/scripts/rkt-build b/scripts/rkt-build
new file mode 100755
index 0000000000000000000000000000000000000000..55afb5131066d98034b39291cfa5d472b5095304
--- /dev/null
+++ b/scripts/rkt-build
@@ -0,0 +1,13 @@
+#!/bin/bash
+
+mkdir -p _output/bin
+
+sudo rkt run \
+    --volume dex,kind=host,source=$PWD \
+    --mount volume=dex,target=/go/src/github.com/coreos/dex \
+    --dns=8.8.8.8 \
+    --net=host \
+    --insecure-options=image \
+    docker://golang:1.7.1-alpine \
+    --exec=/bin/sh -- -x -c \
+	'apk add --no-cache --update alpine-sdk && go install -v github.com/coreos/dex/cmd/dex && cp /go/bin/dex /go/src/github.com/coreos/dex/_output/bin'