Docker中Jupyter Notebook信任状态不一致问题排查
Docker中Jupyter Notebook信任状态异常问题
背景信息
我有一个Docker镜像,内置两个.ipynb笔记本,启动容器时会运行这两个笔记本。
Dockerfile中复制并信任笔记本的步骤:
USER root RUN mkdir -p $NOTEBOOK_DIR COPY /PATH/TO/NOTEBOOK/NB1.ipynb $NOTEBOOK_DIR COPY /PATH/TO/NOTEBOOK/NB2.ipynb $NOTEBOOK_DIR RUN chown -R $NB_USER:$NB_GID $NOTEBOOK_DIR USER $NB_UID WORKDIR $HOME RUN jupyter trust $NOTEBOOK_DIR/NB1.ipynb RUN jupyter trust $NOTEBOOK_DIR/NB2.ipynb
启动脚本start-notebooks.sh内容:
#!/bin/bash set -e NB_PASS=$(echo ${SOME_ID} | python3.8 -c 'from notebook.auth import passwd;print(passwd(input()))') # Run notebooks jupyter trust $NOTEBOOK_DIR/NB1.ipynb jupyter trust $NOTEBOOK_DIR/NB2.ipynb jupyter-notebook --no-browser --ip 0.0.0.0 --port 8888 --NotebookApp.allow_origin='*' \ --NotebookApp.allow_remote_access=True --NotebookApp.quit_button=False --NotebookApp.terminals_enabled=False \ --NotebookApp.trust_xheaders=True --NotebookApp.open_browser=False --NotebookApp.notebook_dir=$NOTEBOOK_DIR \ --NotebookApp.password=${NB_PASS}
容器启动后输出:
my_user@my_host:~$ docker run -it --rm -p 8888:8888 --expose 8888 -v /efs/PATH/TO/NOTEBOOK_FILES:/efs/PATH/TO/NOTEBOOK_FILES -e BASE_PATH=/efs/PATH/TO/BASE_PATH -e SOME_ID=fd283b38-3e4a-11eb-a205-7085c2c5e519 notebooks-image:latest **Notebook already signed: /home/nb_user/notebooks/NB1.ipynb** /home/nb_user/.local/lib/python3.8/site-packages/nbformat/__init__.py:92: MissingIDFieldWarning: Code cell is missing an id field, this will become a hard error in future nbformat versions. You may want to use `normalize()` on your notebooks before validations (available since nbformat 5.1.4). Previous versions of nbformat are fixing this issue transparently, and will stop doing so in the future. validate(nb) **Signing notebook: /home/nb_user/notebooks/NB2.ipynb** [I 11:40:10.051 NotebookApp] Writing notebook server cookie secret to /home/nb_user/.local/share/jupyter/runtime/notebook_cookie_secret [I 11:40:10.303 NotebookApp] [jupyter_nbextensions_configurator] enabled 0.6.1 [I 2022-12-11 11:40:10.507 LabApp] JupyterLab extension loaded from /home/nb_user/.local/lib/python3.8/site-packages/jupyterlab [I 2022-12-11 11:40:10.507 LabApp] JupyterLab application directory is /home/nb_user/.local/share/jupyter/lab [I 11:40:10.513 NotebookApp] Serving notebooks from local directory: /home/nb_user/notebooks [I 11:40:10.513 NotebookApp] Jupyter Notebook 6.5.2 is running at: [I 11:40:10.513 NotebookApp] http://my_host:8888/ [I 11:40:10.513 NotebookApp] Use Control-C to stop this server and shut down all kernels (twice to skip confirmation). [I 11:59:33.290 NotebookApp] 302 GET / (192.168.x.x) 1.300000ms [W 11:59:33.303 NotebookApp] Clearing invalid/expired login cookie username-my_host-8888 [I 11:59:33.304 NotebookApp] 302 GET /tree? (192.168.x.x) 2.570000ms [W 11:59:43.120 NotebookApp] Not allowing login redirect to '/tree?' [I 11:59:43.120 NotebookApp] 302 POST /login?next=%2Ftree%3F (192.168.x.x) 63.300000ms [I 11:59:43.191 NotebookApp] 302 GET / (192.168.x.x) 1.130000ms /home/nb_user/.local/lib/python3.8/site-packages/nbformat/__init__.py:92: MissingIDFieldWarning: Code cell is missing an id field, this will become a hard error in future nbformat versions. You may want to use `normalize()` on your notebooks before validations (available since nbformat 5.1.4). Previous versions of nbformat are fixing this issue transparently, and will stop doing so in the future. validate(nb) [W 11:59:47.222 NotebookApp] **Notebook NB2.ipynb is not trusted**
现象
在Jupyter Notebook GUI中打开NB1时,它已处于信任状态可直接使用;但打开NB2时,会弹出“Notebook not trusted”提示。已知容器中两个笔记本的所有权与权限完全相同。
问题
- 当前的操作流程是否存在问题?
- 若流程无问题,为何NB1可信而NB2不可信?
解答
问题1:流程存在冗余且潜在风险
当前流程有两处明显问题:
- 重复执行
jupyter trust:Dockerfile构建阶段已经以$NB_UID用户身份执行了信任操作,启动脚本中再次执行属于冗余操作。更关键的是,如果容器启动时笔记本文件被挂载卷覆盖(比如你的命令中挂载了/efs/PATH/TO/NOTEBOOK_FILES),构建阶段的信任签名会失效,因为文件内容或元数据已变化。 - 挂载卷可能覆盖镜像内文件:你的
docker run命令挂载了外部卷,若卷内存在同名的NB2.ipynb,会直接覆盖镜像中已经签名的版本,导致启动时虽然执行了jupyter trust,但可能因为文件权限、签名时机或文件内容差异出现信任失败。
问题2:NB1可信而NB2不可信的核心原因
从容器输出看,启动时NB1显示“Notebook already signed”,说明镜像内的NB1没有被挂载卷覆盖,保留了构建阶段的签名;而NB2显示“Signing notebook”,但之后仍提示不信任,大概率是以下情况之一:
- 挂载卷覆盖了NB2:外部卷中的NB2.ipynb没有签名,启动时执行
jupyter trust可能因为文件所有者问题(比如卷内文件属主是root,而容器内以$NB_UID用户执行签名时权限不足,签名未成功写入)。 - NB2本身的格式问题:容器输出中NB2触发了
MissingIDFieldWarning,说明笔记本缺少代码cell的ID字段。Jupyter的信任机制依赖笔记本的结构完整性,格式异常可能导致签名无法被正确识别。 - 签名时机差异:启动脚本中执行
jupyter trust后立刻启动Notebook服务,可能存在文件缓存问题,NB2的签名还未写入磁盘就被服务读取,导致服务未识别到签名。
修复建议
- 移除Dockerfile或启动脚本中的重复信任操作:推荐只在启动脚本中执行
jupyter trust,确保操作针对的是容器内最终的笔记本文件。 - 确保挂载卷文件权限正确:执行
chown -R $NB_USER:$NB_GID $NOTEBOOK_DIR在启动脚本中(在jupyter trust之前),避免卷内文件属主不匹配导致签名失败。 - 修复笔记本格式:对NB2.ipynb执行
jupyter nbformat --normalize NB2.ipynb,补全缺失的cell ID字段,解决格式警告问题。 - 增加签名后的延迟或文件同步:在启动脚本中
jupyter trust之后添加sync命令,确保签名写入磁盘后再启动Notebook服务。
内容的提问来源于stack exchange,提问作者pugi
相关产品推荐
相关产品推荐

