如果使用 8888,配置 Docker 以动态选择第一个可用的 Jupyter 端口
Configure Docker to dynamically choose first available Jupyter port if 8888 is taken
tl;dr 如果 8888 端口被占用,有没有办法配置我们的 Dockerfile
and/or docker run
命令为 Jupyter 动态选择下一个可用端口?
我们有一个 Docker,用户可以在其中 运行 Jupyter 笔记本。但是,当用户已经打开现有的 Jupyter 服务器时,我们会 运行 遇到问题。原因是因为,当他们 运行 Docker 时,它默认为端口 8888。如果另一个本地 Jupyter 服务器具有端口 8888,则 Docker Jupyter link 从 docker run
将不起作用(它会显示一些令牌身份验证屏幕,但它接受的唯一令牌是与其本地 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
计算上。
在我们的 Docker 文件中,我们的 Jupyter 配置设置是:
# jupyter notebook
CMD ["jupyter", "notebook", "--ip=0.0.0.0", "--allow-root"]
我们显然可以尝试添加参数 --port=8889
(或其他一些硬编码端口),但如果用户也有使用指定端口的本地进程,那可能会出现问题。
是否可以配置这个,或者我们是否必须坚持用户在启动我们的 Docker 时没有任何使用端口 8888 的东西?
如果您 运行 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 不知道这些细节。
tl;dr 如果 8888 端口被占用,有没有办法配置我们的 Dockerfile
and/or docker run
命令为 Jupyter 动态选择下一个可用端口?
我们有一个 Docker,用户可以在其中 运行 Jupyter 笔记本。但是,当用户已经打开现有的 Jupyter 服务器时,我们会 运行 遇到问题。原因是因为,当他们 运行 Docker 时,它默认为端口 8888。如果另一个本地 Jupyter 服务器具有端口 8888,则 Docker Jupyter link 从 docker run
将不起作用(它会显示一些令牌身份验证屏幕,但它接受的唯一令牌是与其本地 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
计算上。
在我们的 Docker 文件中,我们的 Jupyter 配置设置是:
# jupyter notebook
CMD ["jupyter", "notebook", "--ip=0.0.0.0", "--allow-root"]
我们显然可以尝试添加参数 --port=8889
(或其他一些硬编码端口),但如果用户也有使用指定端口的本地进程,那可能会出现问题。
是否可以配置这个,或者我们是否必须坚持用户在启动我们的 Docker 时没有任何使用端口 8888 的东西?
如果您 运行 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 不知道这些细节。