diff --git a/Dockerfile b/Dockerfile
index cb410dab5030a4d70aae6d0443730c11a0dbf57f..41c0d6f8fc56d71063b77747579d4dcaa9b94985 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -27,11 +27,22 @@ FROM alpine:3.13.1
 # experience when this doesn't work out of the box.
 #
 # OpenSSL is required so wget can query HTTPS endpoints for health checking.
+ARG TARGETARCH
+ARG TARGETVARIANT=""
+ARG GOMPLATE_VERSION=v3.9.0
+
 RUN apk add --no-cache --update ca-certificates openssl
+RUN wget -O /usr/local/bin/gomplate \
+  "https://github.com/hairyhenderson/gomplate/releases/download/${GOMPLATE_VERSION}/gomplate_linux-${TARGETARCH:-amd64}${TARGETVARIANT}" \
+  && chmod +x /usr/local/bin/gomplate
 
 RUN mkdir -p /var/dex
 RUN chown -R 1001:1001 /var/dex
 
+RUN mkdir -p /etc/dex
+COPY examples/config-example.tmpl /etc/dex/config.tmpl
+RUN chown -R 1001:1001 /etc/dex
+
 # Copy module files for CVE scanning / dependency analysis.
 COPY --from=builder /usr/local/src/dex/go.mod /usr/local/src/dex/go.sum /usr/local/src/dex/
 COPY --from=builder /usr/local/src/dex/api/v2/go.mod /usr/local/src/dex/api/v2/go.sum /usr/local/src/dex/api/v2/
@@ -46,6 +57,7 @@ COPY --from=builder /usr/local/src/dex/web /web
 
 USER 1001:1001
 
-ENTRYPOINT ["dex"]
+COPY entrypoint.sh /
 
-CMD ["version"]
+ENTRYPOINT ["/entrypoint.sh"]
+CMD ["serve", "/etc/dex/config.tmpl"]
diff --git a/entrypoint.sh b/entrypoint.sh
new file mode 100755
index 0000000000000000000000000000000000000000..3e6a8e271abc4937951cb54be54ee685a4334a5c
--- /dev/null
+++ b/entrypoint.sh
@@ -0,0 +1,13 @@
+#!/bin/sh -e
+
+### Usage: /entrypoint.sh <command> <args>
+set -e
+command=$1
+
+if [ "$command" == "serve" ]; then
+  file="$2"
+  gomplate -f "$file" -o "/etc/dex/config.yaml";
+  exec dex serve "/etc/dex/config.yaml"
+else
+  exec dex $@
+fi
diff --git a/examples/config-example.tmpl b/examples/config-example.tmpl
new file mode 100644
index 0000000000000000000000000000000000000000..acbe90e2f3065927a5c1bf64d360a7f5be5db61f
--- /dev/null
+++ b/examples/config-example.tmpl
@@ -0,0 +1,54 @@
+issuer: {{ getenv "DEX_ISSUER" "http://127.0.0.1:5556/dex" }}
+
+storage:
+  type: sqlite3
+  config:
+    file: {{ getenv "DEX_STORAGE_SQLITE3_CONFIG_FILE" "/etc/dex/dex.db" }}
+
+web:
+{{- if getenv "DEX_WEB_HTTPS" "" }}
+  https: {{ .Env.DEX_WEB_HTTPS }}
+  {{- if getenv "DEX_WEB_TLS_KEY" }}
+  tlsKey: {{ .Env.DEX_WEB_TLS_KEY }}
+  {{- else }}
+{{- fail "$DEX_WEB_TLS_KEY is required" }}
+  {{- end }}
+  {{- if getenv "DEX_WEB_TLS_CERT" "" }}
+  tlsCert: {{ .Env.DEX_WEB_TLS_CERT }}
+  {{- else }}
+{{- fail "$DEX_WEB_TLS_CERT is required" }}
+  {{- end }}
+{{- end }}
+  http: {{ getenv "DEX_WEB_HTTP" "0.0.0.0:5556" }}
+
+{{- if getenv "DEX_TELEMETRY_HTTP" "" }}
+telemetry:
+  http: {{ .Env.DEX_TELEMETRY_HTTP }}
+{{- end }}
+
+expiry:
+  deviceRequests: {{ getenv "DEX_EXPIRY_DEVICE_REQUESTS" "5m" }}
+  signingKeys: {{ getenv "DEX_EXPIRY_SIGNING_KEYS" "6h" }}
+  idTokens: {{ getenv "DEX_EXPIRY_ID_TOKENS" "24h" }}
+  authRequests: {{ getenv "DEX_EXPIRY_AUTH_REQUESTS" "24h" }}
+
+logger:
+  level: {{ getenv "DEX_LOGGER_LEVEL" "info" }}
+  format: {{ getenv "DEX_LOGGER_FORMAT" "text" }}
+
+oauth2:
+  responseTypes: {{ getenv "DEX_OAUTH2_RESPONSE_TYPES" "[code]" }}
+  skipApprovalScreen: {{ getenv "DEX_OAUTH2_SKIP_APPROVAL_SCREEN" "false" }}
+  alwaysShowLoginScreen: {{ getenv "DEX_OAUTH2_ALWAYS_SHOW_LOGIN_SCREEN" "false" }}
+{{- if getenv "DEX_OAUTH2_PASSWORD_CONNECTOR" "" }}
+  passwordConnector: {{ .Env.DEX_OAUTH2_PASSWORD_CONNECTOR }}
+{{- end }}
+
+enablePasswordDB: {{ getenv "DEX_ENABLE_PASSWORD_DB" "true" }}
+
+connectors:
+{{- if getenv "DEX_CONNECTORS_ENABLE_MOCK" "" }}
+- type: mockCallback
+  id: mock
+  name: Example
+{{- end }}
diff --git a/examples/config.tmpl b/examples/config.tmpl
deleted file mode 100644
index 43d12dbc7c90a0342ad83df3293aba7b038f7523..0000000000000000000000000000000000000000
--- a/examples/config.tmpl
+++ /dev/null
@@ -1,44 +0,0 @@
-issuer: {{ default .Env.DEX_ISSUER "http://127.0.0.1:5556/dex" }}
-
-storage:
-  type: sqlite3
-  config:
-    file: {{ default .Env.DEX_STORAGE_SQLITE3_CONFIG_FILE "/etc/dex/dex.db" }}
-
-web:
-{{- if .Env.DEX_WEB_HTTPS }}
-  https: {{ .Env.DEX_WEB_HTTPS }}
-{{- else }}
-  http: {{ default .Env.DEX_WEB_HTTP "0.0.0.0:5556" }}
-{{- end }}
-{{- if .Env.DEX_WEB_TLS_KEY }}
-  tlsKey: {{ .Env.DEX_WEB_TLS_KEY }}
-{{- end }}
-{{- if .Env.DEX_WEB_TLS_CERT }}
-  tlsCert: {{ .Env.DEX_WEB_TLS_CERT }}
-{{- end }}
-
-{{- if .Env.DEX_TELEMETRY_HTTP }}
-telemetry:
-  http: {{ .Env.DEX_TELEMETRY_HTTP }}
-{{- end }}
-
-expiry:
-  deviceRequests: {{ default .Env.DEX_EXPIRY_DEVICE_REQUESTS "5m" }}
-  signingKeys: {{ default .Env.DEX_EXPIRY_SIGNING_KEYS "6h" }}
-  idTokens: {{ default .Env.DEX_EXPIRY_ID_TOKENS "24h" }}
-  authRequests: {{ default .Env.DEX_EXPIRY_AUTH_REQUESTS "24h" }}
-
-logger:
-  level: {{ default .Env.DEX_LOGGER_LEVEL "info" }}
-  format: {{ default .Env.DEX_LOGGER_FORMAT "text" }}
-
-oauth2:
-  responseTypes: {{ default .Env.DEX_OAUTH2_RESPONSE_TYPES "[code]" }}
-  skipApprovalScreen: {{ default .Env.DEX_OAUTH2_SKIP_APPROVAL_SCREEN "false" }}
-  alwaysShowLoginScreen: {{ default .Env.DEX_OAUTH2_ALWAYS_SHOW_LOGIN_SCREEN "false" }}
-{{- if .Env.DEX_OAUTH2_PASSWORD_CONNECTOR }}
-  passwordConnector: {{ .Env.DEX_OAUTH2_PASSWORD_CONNECTOR }}
-{{- end }}
-
-enablePasswordDB: {{ default .Env.DEX_ENABLE_PASSWORD_DB "true" }}