diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..1517dd95524e629801c00c91ef668a485011ec6a
--- /dev/null
+++ b/.github/workflows/release.yaml
@@ -0,0 +1,54 @@
+# This action pushes new amd64 and arm64 docker images to the Docker and GitHub
+# registries on every new release of the project.
+#
+# Cobbled together from these sources:
+# - https://github.com/docker/build-push-action/#usage
+# - https://docs.github.com/en/actions/publishing-packages/publishing-docker-images
+
+name: Release
+
+"on":
+  release:
+    types: [published]
+
+jobs:
+  docker:
+    runs-on: ubuntu-latest
+    steps:
+      - name: Check out the repo
+        uses: actions/checkout@v3
+
+      - name: Set up QEMU
+        uses: docker/setup-qemu-action@v2
+
+      - name: Set up Docker Buildx
+        uses: docker/setup-buildx-action@v2
+
+      - name: Login to Docker Hub
+        uses: docker/login-action@v2
+        with:
+          username: ${{ secrets.DOCKERHUB_USERNAME }}
+          password: ${{ secrets.DOCKERHUB_TOKEN }}
+
+      - name: Login to GitHub Container Registry
+        uses: docker/login-action@v2
+        with:
+          registry: ghcr.io
+          username: mccutchen
+          password: ${{ secrets.GITHUB_TOKEN }}
+
+      - name: Extract metadata for Docker
+        id: meta
+        uses: docker/metadata-action@v4
+        with:
+          images: |
+            mccutchen/go-httpbin
+            ghrc.io/mccutchen/go-httpbin
+
+      - name: Build and push
+        uses: docker/build-push-action@v3
+        with:
+          platforms: linux/amd64,linux/arm64
+          push: true
+          tags: ${{ steps.meta.outputs.tags }}
+          labels: ${{ steps.meta.outputs.labels }}