首页 > 解决方案 > 如果采用 8888,则配置 Docker 以动态选择第一个可用的 Jupyter 端口

问题描述

tl; dr 如果使用端口 8888,我们是否可以配置我们的Dockerfile和/或docker run命令以动态选择 Jupyter 的下一个可用端口?

我们有一个 Docker,用户可以在其中运行 Jupyter 笔记本。但是,当用户已经打开现有的 Jupyter 服务器时,我们会遇到问题。原因是,当他们运行 Docker 时,它默认使用端口 8888。如果另一个本地 Jupyter 服务器具有端口 8888,则生成的 Docker Jupyter 链接docker run将不起作用(它会显示一些令牌身份验证屏幕,但它会显示唯一的令牌accept 是与他们的本地 Jupyter 服务器关联的那个,而不是与我们的 Docker 关联的那个)。

我们尝试将start_docker.sh脚本(用户将运行bash start_docker.sh以启动 Docker)更改为:

# find lowest open port available
PORT=8888

until [[ $(lsof -i -P -n | grep 127.0.0.1:$PORT | wc -l) -eq 0 ]]
  do
    ((PORT=PORT+1))
done

echo $PORT

# run docker and start notebook server
docker run -it \
  -p $PORT:8888 \
  -v ...
  ...

但是,在这种情况下,Jupyter 仍然在端口 8888 上打开,而不是在所需的$PORT计算上打开。

在我们的 Dockerfile 中,我们的 Jupyter 配置设置是:

# jupyter notebook
CMD ["jupyter", "notebook", "--ip=0.0.0.0", "--allow-root"]

我们显然可以尝试添加一个参数--port=8889(或其他一些硬编码端口),但如果用户也有一个使用指定端口的本地进程,这可能会出现问题。

是否可以配置它,或者我们是否必须坚持用户在启动 Docker 时没有使用端口 8888 的任何东西?

标签: dockerjupyter-notebookjupyter

解决方案


如果您docker run -p只使用一个端口号运行,Docker 会选择主机端口。然后,您可以使用docker port它来查找它选择的实际主机端口。

# Start the container.
#
# Start it _in the background_, since we need to probe the dynamically
# assigned port.
#
# If we expect to have arbitrarily many of these containers, we also
# can't assign a fixed --name, so depend on `docker run -d` printing the
# container ID.
#
# Note only one port number `-p 8888` to let Docker pick the host port.
cid=$(docker run -d -i -t -p 8888 ...)

# Print out the port number
echo -n "Listening on "
docker port "$cid" 8888

# Wait for the container to exit on its own
docker wait "$cid"

# Clean up
docker rm "$cid"

请注意,docker port输出包括绑定地址,通常是0.0.0.0. 这不是您可以实际用于访问容器的地址。您需要知道主机的 IP 地址,或者在某些环境中您可能已经在系统前面配置了负载平衡器或其他网关。Docker 不知道这些细节。


推荐阅读