Skip to content

Instantly share code, notes, and snippets.

@manics
Last active November 30, 2023 23:10
Show Gist options
  • Save manics/1de8aa610c319d5c24b07ea73f84f891 to your computer and use it in GitHub Desktop.
Save manics/1de8aa610c319d5c24b07ea73f84f891 to your computer and use it in GitHub Desktop.
JupyterHub Dockerspawner with user-mode (rootless) Podman

Running JupyterHub Dockerspawner with user-mode Podman

Tested with Vagrant box generic/ubuntu2004 (libvirt, 3.2.16)

Install Node, Podman, Python3

echo "deb https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/xUbuntu_20.04/ /" | sudo tee /etc/apt/sources.list.d/devel:kubic:libcontainers:stable.list
curl -L https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/xUbuntu_20.04/Release.key | sudo apt-key add -

sudo apt-get update
sudo apt-get -y install npm podman python3-venv

Configure podman user-mode daemon

Based on the RHEL 8 guide

mkdir -p ~/.config/systemd/user

cat << EOF > ~/.config/systemd/user/podman.socket
[Unit]
Description=Podman API Socket

[Socket]
ListenStream=%h/podman.sock
SocketMode=0660

[Install]
WantedBy=sockets.target
EOF

cat << EOF > ~/.config/systemd/user/podman.service
[Unit]
Description=Podman API Service
Requires=podman.socket
After=podman.socket
StartLimitIntervalSec=0

[Service]
Type=oneshot
Environment=REGISTRIES_CONFIG_PATH=%h/.config/containers/registries.conf
ExecStart=/usr/bin/podman system service unix://%h/podman.sock
TimeoutStopSec=30
KillMode=process

[Install]
WantedBy=multi-user.target
Also=podman.socket
EOF

mkdir -p ~/.config/containers

cat << EOF > ~/.config/containers/storage.conf
[storage]
  driver = "overlay"
  [storage.options]
    mount_program = "/usr/bin/fuse-overlayfs"
EOF

Several registries are configured by default in /etc/containers/registries.conf. You can either copy it and use fully qualified image names, or if you want the default Docker behaviour configure a single registry

ln -s /etc/containers/registries.conf ~/.config/containers/registries.conf
# cat << EOF > ~/.config/containers/registries.conf
# unqualified-search-registries = ["docker.io"]
# EOF

Start the Podman service, and set DOCKER_HOST (for Docker client) and CONTAINER_HOST (for Podman client) to point to the user's podman socket

systemctl --user daemon-reload
systemctl --user enable --now podman.socket

export DOCKER_HOST=unix://$HOME/podman.sock
export CONTAINER_HOST=unix://$HOME/podman.sock

Docker expects there to be a default bridge network.

podman network create bridge

Install JupyterHub

Install configurable-http-proxy without root

mkdir "${HOME}/.npm-packages"
npm config set prefix "${HOME}/.npm-packages"
export PATH="$PATH:${HOME}/.npm-packages/bin"
npm install -g configurable-http-proxy

Install JupyterHub into a virtualenv and create a configuration file

python3 -mvenv ~/jh
. ~/jh/bin/activate
pip install jupyterhub dockerspawner

cat << EOF > jupyterhub_config.py
c.JupyterHub.authenticator_class = "dummy"
c.JupyterHub.spawner_class = "docker"
c.JupyterHub.hub_ip = '0.0.0.0'

# Get external IP https://stackoverflow.com/a/166589
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.connect(("8.8.8.8", 80))
c.JupyterHub.hub_connect_ip = s.getsockname()[0]
s.close()

c.DockerSpawner.image = 'docker.io/jupyter/base-notebook'
c.DockerSpawner.remove = True
EOF

Run JupyterHub

jupyterhub --debug --config=jupyterhub_config.py

Connect to http://<IP>:8000/, login with any username and password

You may get an error the first time the Docker client makes a call to the Podman API. If this happens retry.

@cwseys
Copy link

cwseys commented Apr 6, 2023

Thanks for these hints!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment