diff --git a/.circleci/config.yml b/.circleci/config.yml
index 026ba472ef3f6ba885f55c12e939b5aae1563de1..b4187ba43d276a4162544cefb87cc6840c5cb91a 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -7,15 +7,15 @@ jobs:
       - checkout
       - restore_cache:
           keys:
-            - go-v1-{{ checksum "go.sum" }}
+            - go-v3-{{ checksum "go.sum" }}
             # Fallback to using the latest cache if no exact match is found.
-            - go-v1-
+            - go-v3-
       - run: ./ci/fmt.sh
       - save_cache:
           paths:
-            - /root/go
+            - /root/gopath
             - /root/.cache/go-build
-          key: go-v1-{{ checksum "go.sum" }}
+          key: go-v3-{{ checksum "go.sum" }}
 
   lint:
     docker:
@@ -24,15 +24,15 @@ jobs:
       - checkout
       - restore_cache:
           keys:
-            - go-v1-{{ checksum "go.sum" }}
+            - go-v3-{{ checksum "go.sum" }}
             # Fallback to using the latest cache if no exact match is found.
-            - go-v1-
+            - go-v3-
       - run: ./ci/lint.sh
       - save_cache:
           paths:
-            - /root/go
+            - /root/gopath
             - /root/.cache/go-build
-          key: go-v1-{{ checksum "go.sum" }}
+          key: go-v3-{{ checksum "go.sum" }}
 
   test:
     docker:
@@ -41,18 +41,18 @@ jobs:
       - checkout
       - restore_cache:
           keys:
-            - go-v1-{{ checksum "go.sum" }}
+            - go-v3-{{ checksum "go.sum" }}
             # Fallback to using the latest cache if no exact match is found.
-            - go-v1-
+            - go-v3-
       - run: ./ci/test.sh
       - store_artifacts:
           path: ci/out
           destination: out
       - save_cache:
           paths:
-            - /root/go
+            - /root/gopath
             - /root/.cache/go-build
-          key: go-v1-{{ checksum "go.sum" }}
+          key: go-v3-{{ checksum "go.sum" }}
       - store_test_results:
           path: ci/out
 
@@ -63,18 +63,20 @@ jobs:
       - checkout
       - restore_cache:
           keys:
-            - go-v1-{{ checksum "go.sum" }}
+            - go-v3-{{ checksum "go.sum" }}
             # Fallback to using the latest cache if no exact match is found.
-            - go-v1-
+            - go-v3-
       - run: ./ci/bench.sh
       - store_artifacts:
           path: ci/out
           destination: out
       - save_cache:
           paths:
-            - /root/go
+            - /root/gopath
             - /root/.cache/go-build
-          key: go-v1-{{ checksum "go.sum" }}
+          key: go-v3-{{ checksum "go.sum" }}
+      - store_test_results:
+          path: ci/out
 
 workflows:
   version: 2
diff --git a/ci/bench.sh b/ci/bench.sh
index b4a0d06e30edeaedce4e7f76f1123db256affb08..fa11e325eb6d677196029ecec102f9a3360c098c 100755
--- a/ci/bench.sh
+++ b/ci/bench.sh
@@ -4,7 +4,7 @@ set -euo pipefail
 cd "$(dirname "${0}")"
 cd "$(git rev-parse --show-toplevel)"
 
-mkdir -p ci/out
+mkdir -p ci/out/gobench
 benchArgs=(
   "-vet=off"
   "-run=^$"
@@ -20,7 +20,7 @@ benchArgs=(
 if [[ ${CI-} ]]; then
   # https://circleci.com/docs/2.0/collect-test-data/
   go test "${benchArgs[@]}" | tee /dev/stderr |
-    go run github.com/jstemmer/go-junit-report > ci/out/testReport.xml
+    go run github.com/jstemmer/go-junit-report > ci/out/gobench/report.xml
 else
   go test "${benchArgs[@]}"
 fi
diff --git a/ci/image/Dockerfile b/ci/image/Dockerfile
index bedc571f4abda678f49d2a5ea366250ebb82a758..e87f0e2bd2f5f180a9edb8f58e81b9b14e1a4a44 100644
--- a/ci/image/Dockerfile
+++ b/ci/image/Dockerfile
@@ -1,13 +1,11 @@
-FROM archlinux/base
+FROM golang:1
 
-RUN pacman -Syu --noconfirm
+ENV DEBIAN_FRONTEND=noninteractive
+ENV GOPATH /root/gopath
+ENV GOFLAGS -mod=readonly
 
-RUN pacman -S --noconfirm go git shellcheck tar openssh gzip ca-certificates
-
-RUN pacman -S --noconfirm gcc python2-pip && \
-  pip2 install autobahntestsuite
-
-RUN pacman -S --noconfirm npm && \
+RUN apt-get update && \
+  apt-get install -y shellcheck python-pip npm && \
+  pip2 install autobahntestsuite && \
   npm install -g prettier
 
-ENV GOFLAGS -mod=readonly
\ No newline at end of file
diff --git a/ci/image/push.sh b/ci/image/push.sh
index fdc321d4dd004d84a044481f1e91e8ccdf76d241..1cbae979fd0d492a0889eee69b3a4d605fa1bf30 100755
--- a/ci/image/push.sh
+++ b/ci/image/push.sh
@@ -2,6 +2,7 @@
 
 set -euo pipefail
 cd "$(dirname "${0}")"
+cd "$(git rev-parse --show-toplevel)"
 
-docker build -t nhooyr/websocket-ci .
+docker build -f ./ci/image/Dockerfile -t nhooyr/websocket-ci .
 docker push nhooyr/websocket-ci
diff --git a/ci/test.sh b/ci/test.sh
index 93b9a4f38f6974492839e1b77a6ca6c8957e75b4..988add51bb8d7b741ff6faf9fa35a3778ef1cb79 100755
--- a/ci/test.sh
+++ b/ci/test.sh
@@ -4,17 +4,17 @@ set -euo pipefail
 cd "$(dirname "${0}")"
 cd "$(git rev-parse --show-toplevel)"
 
-mkdir -p ci/out
+mkdir -p ci/out/gotest
 testFlags=(-race "-vet=off" "-coverprofile=ci/out/coverage.prof" "-coverpkg=./...")
 if [[ ${CI-} ]]; then
   # https://circleci.com/docs/2.0/collect-test-data/
   go test "${testFlags[@]}" -v ./... 2>&1 | tee /dev/stderr |
-    go run github.com/jstemmer/go-junit-report > ci/out/testReport.xml
+    go run github.com/jstemmer/go-junit-report > ci/out/gotest/report.xml
 else
   go test "${testFlags[@]}" ./...
 fi
-go tool cover -html=ci/out/coverage.prof -o=ci/out/coverage.html
 
+go tool cover -html=ci/out/coverage.prof -o=ci/out/coverage.html
 if [[ ${CI:-} ]]; then
   bash <(curl -s https://codecov.io/bash) -f ci/out/coverage.prof
 fi