Change default JupyterLab working directory

HI, I’m a total noob here so please go easy on me. My goal is to have JupyterHub/JupyterLab running on Docker inside an Azure Container Instance, and have a persistent Azure File Share mounted to the container instance.

Some background. I’m using Docker Desktop (windows) to create the image. Then I push the image to Azure Container Registry, then I build the Azure Container Instance from there. The volume mounts successfully and I can see a user folder being created in the file share.

But for the life of me, I cannot get the working directory of JupyterLab to change from /home/{username} to /home/user/data/{username}. I cannot navigate the tree and therefore, I cannot save a new notebook to the file share. Using the terminal I have verified the /home/user/data/{username} directory is there.

If someone with could please look at my configs and help me fix this, that would be amazing. I have tried many variations both with and without the jupyter_server_config file. I’m not sure what is right and what is wrong at this point.

Thanks,

----------------------------
**Dockerfile:**
FROM jupyterhub/jupyterhub

# Sets user as root
USER root

# Install JupyterHub dependencies
RUN pip3 install --upgrade pip && \
    pip3 install \
	jupyterhub-firstuseauthenticator \
	jupyterhub-ldapauthenticator \
	jupyterlab
	

# Install Python libraries and other dependencies
RUN pip3 install --upgrade pip && \
    pip3 install \
	pandas \
	numpy \
	matplotlib \
	pulp \
	azure-storage-file-share


# Installs various packages
RUN apt-get update && apt-get install -y \
    r-base \
    r-base-dev \
    libzmq3-dev \
    libcurl4-openssl-dev \
    libssl-dev \
	libfontconfig1-dev \
	libharfbuzz-dev \
	libfribidi-dev \
	libfreetype6-dev \
	libpng-dev \
	libtiff5-dev \
	libjpeg-dev \
	git \
	python3.10-venv \
	python3 \
	cifs-utils \
	nano



# Install R kernel and other dependencies
RUN R -e "install.packages(c('repr', 'IRdisplay', 'IRkernel'), repos='http://cran.rstudio.com/')"
RUN R -e "IRkernel::installspec(user = FALSE)"


# Enables widgets
RUN pip3 install ipywidgets && \
    jupyter nbextension enable --py widgetsnbextension --sys-prefix


# Disables JupyterLab Announcements
RUN jupyter labextension disable "@jupyterlab/apputils-extension:announcements"

# Creates 'jupyteradmin' user and grants administrator permissions to this account
RUN useradd -m jupyteradmin && echo "jupyteradmin:password" | chpasswd && adduser jupyteradmin sudo
RUN usermod -aG sudo jupyteradmin


# Installs Conda
RUN apt-get update && \
    apt-get install -y wget && \
    wget --no-check-certificate -q https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O miniconda.sh && \
    bash miniconda.sh -b -p /opt/conda && \
    rm miniconda.sh && \
    /opt/conda/bin/conda clean --all && \
    ln -s /opt/conda/etc/profile.d/conda.sh /etc/profile.d/conda.sh && \
    echo ". /opt/conda/etc/profile.d/conda.sh" >> ~/.bashrc && \
    echo "conda activate base" >> ~/.bashrc
	

# Add Conda to system PATH
ENV PATH /opt/conda/bin:$PATH

# Disable SSL verification in Conda
RUN conda config --set ssl_verify false

# create a new conda environment
RUN conda create --name py38azml

# activate the new environment
SHELL ["conda", "run", "-n", "py38azml", "/bin/bash", "-c"]

# install ipykernel inside the new environment
RUN pip install ipykernel && \
	pip install azureml-core && \
	python -m ipykernel install --user --name py38azml --display-name "Python 3.8 - Azure ML" 	# install the kernel into jupyter kernels directory

# copy the kernel directory from root to shared directory
RUN cp -r /root/.local/share/jupyter/kernels/py38azml /usr/local/share/jupyter/kernels/



# create a new conda environment
RUN conda create --name py310azml-sdkv2

# activate the new environment
SHELL ["conda", "run", "-n", "py310azml-sdkv2", "/bin/bash", "-c"]

# install ipykernel inside the new environment
RUN pip install ipykernel && \
	pip install azure-ai-ml && \
	python -m ipykernel install --user --name py310azml-sdkv2 --display-name "Python 3.10 - SDK v2"	# install the kernel into jupyter kernels directory

# copy the kernel directory from root to shared directory
RUN cp -r /root/.local/share/jupyter/kernels/py310azml-sdkv2 /usr/local/share/jupyter/kernels/



# create a new conda environment
RUN conda create --name py38azml_pttf

# activate the new environment
SHELL ["conda", "run", "-n", "py38azml_pttf", "/bin/bash", "-c"]

# install ipykernel inside the new environment
RUN pip install ipykernel && \
	pip install tensorflow && \
	python -m ipykernel install --user --name py38azml_pttf --display-name "Python 3.8 - Pytorch and Tensorflow"	# install the kernel into jupyter kernels directory

RUN conda install pytorch torchvision -c pytorch

# copy the kernel directory from root to shared directory
RUN cp -r /root/.local/share/jupyter/kernels/py38azml_pttf /usr/local/share/jupyter/kernels/


# Sets environment variables
ENV AZURE_STORAGE_ACCOUNT=accountname
ENV AZURE_STORAGE_ACCESS_KEY=key
ENV NB_UID=1000
ENV NB_GID=1000


# Installs Azure File Share client
RUN pip install azure-storage-file-share


# User permissions
RUN mkdir /mnt/azure && \
    chmod 777 /mnt/azure && \
    mkdir -p /home/user/data && \
    chown -R $NB_UID:$NB_GID /home/user/data && \
    chmod -R 777 /home/user/data

	
# Copies the jupyterhub_config.py file from your local machine to the /srv/jupyterhub/ directory in the Docker image.
COPY jupyterhub_config.py /srv/jupyterhub/jupyterhub_config.py
COPY jupyter_server_config.py /srv/jupyter/jupyter_server_config.py



# Expose the JupyterHub port
EXPOSE 8000


# Start the JupyterHub server
CMD ["jupyterhub", "--ip=0.0.0.0", "--port=8000", "--config=/srv/jupyterhub/jupyterhub_config.py"]

---------------------------------------------------
**jupyterhub_config.py File:**
import subprocess
import os

# Jupyterhub settings
c.JupyterHub.ip = '0.0.0.0'
c.JupyterHub.port = 8000
c.JupyterHub.base_url = '/'

# Authentication Settings
c.JupyterHub.authenticator_class = 'firstuseauthenticator.FirstUseAuthenticator'
c.Authenticator.admin_users = {'jupyteradmin'}


# Spawner settings
c.JupyterHub.spawner_class = 'jupyterhub.spawner.LocalProcessSpawner'
c.LocalProcessSpawner.default_shell_cmd = ['/bin/bash']
c.LocalProcessSpawner.env_keep.append('HOME')
c.LocalProcessSpawner.cmd = ['jupyterhub-singleuser', "--config=/srv/jupyter/jupyter_server_config.py"]



from subprocess import check_call

def pre_spawn_hook(spawner):
    setup_azure_mount(spawner)  # call setup_azure_mount() with argument
    username = spawner.user.name
    try:
        check_call(['useradd', '-ms', '/bin/bash', username])
    except Exception as e:
        print(f'{e}')

    azure_user_path = os.path.join('/mnt/azure', username)
    os.makedirs(azure_user_path, exist_ok=True)

    local_user_path = os.path.join('/home/user/data', username)
    if not os.path.exists(local_user_path):
        os.symlink(azure_user_path, local_user_path)

    spawner.environment['HOME'] = local_user_path  # Set user's HOME environment variable    
    spawner.user_options = {'notebook_dir': local_user_path}
    spawner.args = [arg.format(notebook_dir=local_user_path) for arg in spawner.args]


c.Spawner.pre_spawn_hook = pre_spawn_hook






def setup_azure_mount(spawner):
    subprocess.run(
        [
            "/bin/bash",
            "-c",
            'echo "//containername.file.core.windows.net/test-jupyter /mnt/azure cifs vers=3.0,username=containername,password=password,dir_mode=0777,file_mode=0777" >> /etc/fstab && mkdir -p /mnt/azure && mount -a && chown -R 1000:100 /mnt/azure'
        ]
    )


c.Spawner.mem_limit = '2G'
c.Spawner.cpu_limit = 1

# Needed for additional environments
c.Spawner.env_keep.append('VIRTUAL_ENV')


---------------------------------------------------

**jupyter_server_config.py File:**
# Configuration file for lab.

c = get_config()  #noqa


## The directory to use for notebooks and kernels.
#  Default: ''
import os

c.ServerApp.root_dir = f"/home/user/data/{os.environ.get('JUPYTERHUB_USER')}"