In #1266 I suggest the use of configmap's to customize jupyterhub jinja templates for its looks. Perhaps this is something we want to do for our jupyterhub_config.py file etc. as well that is currently residing in our Dockerfile.
We've been experimenting with mounting etc/jupyter as a volume in mybinder.org-deploy and it's been really nice. I think we should try to explore a similar approach to allowing arbitrary config and files in e.g. /etc/jupyterhub from values.yaml, and others using the helm files api.
Ah! mounting /etc/jupyter as a volume from a ConfigMap! Nice!
Min your comment inspired me to inject templates and images into the hub pod, as well as configuration files into the singleuser pods.
These are the files I inject, through four ConfigMaps.

WARNING: I decided to override the images folder of the hub, residing in
/usr/local/share/jupyterhub/static/with the one I provide. So while doing that I also decided to copy the files I found in this folder to the folder I inject.
NOTE: This configmap was provided in a meta-chart that has a
requirements.yamlfile with a dependency on the Z2JH Helm chart. This is why I'm able to use Helm templating.
apiVersion: v1
kind: ConfigMap
metadata:
name: hub-templates
data:
{{- (.Files.Glob "files/etc/jupyterhub/templates/*").AsConfig | nindent 2 }}
---
apiVersion: v1
kind: ConfigMap
metadata:
name: hub-images
# NOTE: Because '.AsConfig' and '.AsSecret' only work on string files, we rely on 'binaryData'
# to perform a base64 decoding before mount, and we base64 our image files first.
binaryData:
{{- $root := . }}
{{- range $path, $bytes := .Files.Glob "files/static/images/*" }}
{{ base $path }}: '{{ $root.Files.Get $path | b64enc }}'
{{- end }}
---
apiVersion: v1
kind: ConfigMap
metadata:
name: user-bash-bashrc
data:
{{- (.Files.Glob "files/etc/bash.bashrc").AsConfig | nindent 2 }}
---
apiVersion: v1
kind: ConfigMap
metadata:
name: user-jupyter-notebook-config
data:
{{- (.Files.Glob "files/etc/jupyter/*").AsConfig | nindent 2 }}
NOTE: These was provided to a meta-chart that has a
requirements.yamlfile with a dependency on the Z2JH Helm chart. This is why I'm nesting my configuration underjupyterhub.
# extract from my provided helm template values in config.yaml
jupyterhub:
hub:
extraConfig:
templates: |
c.JupyterHub.template_paths.insert(0, "/etc/jupyterhub/templates")
extraVolumes:
- name: hub-templates
configMap:
name: hub-templates
- name: hub-images
configMap:
name: hub-images
extraVolumeMounts:
- mountPath: /etc/jupyterhub/templates
name: hub-templates
- mountPath: /usr/local/share/jupyterhub/static/images
name: hub-images
singleuser:
storage:
extraVolumes:
- name: user-bash-bashrc
configMap:
name: user-bash-bashrc
- name: user-jupyter-notebook-config
configMap:
name: user-jupyter-notebook-config
extraVolumeMounts:
# NOTE: using 'subPath' we can mount a single file, and by specifying a filename in the mountPath
# we will mount this single file into a file instead of a directory.
# See: https://stackoverflow.com/questions/44325048/kubernetes-configmap-only-one-file
- mountPath: /etc/bash.bashrc
subPath: bash.bashrc
name: user-bash-bashrc
- mountPath: /etc/jupyter/jupyter_notebook_config.py
subPath: jupyter_notebook_config.py
name: user-jupyter-notebook-config
We have extracted jupyterhub_config.py from being built into our Dockerfile in https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/1407.
Most helpful comment
We've been experimenting with mounting etc/jupyter as a volume in mybinder.org-deploy and it's been really nice. I think we should try to explore a similar approach to allowing arbitrary config and files in e.g. /etc/jupyterhub from values.yaml, and others using the helm files api.