Back ground
之前一直在local做数据分析,模型训练.然后发现我在运行training的task的时候机器比较卡,索性将这些计算量比较大的任务放到server上去.于是申请了公司的Cloud上面的VM,启动一个docker container去完成这些事情.这篇文章主要记录了完成构建这个小的运行于docker container的jupyter server的过程. 项目的github地址是:jupyterimage 镜像存储的dockerhub地址是jupyterimage
Prepare docker image
构建image的基础镜像是最新版的centos7. 为了环境搭建方便,使用anaconda3版本为5.2.0 内置的python是3.6以上,目前tensorflow已经支持3.6了,所以使用了一个比较新的anaconda3版本. 因为anaconda的版本较低的话其内置的jupyter版本也可能比较低,导致不支持远程访问jupyter notebook server.完整的dockerfile如下:
# jupyter notebook image
FROM centos
MAINTAINER allocator
# version control
ENV DL_BASE_VERSION_CTL 5/12/2018 11:10:00
# set env
ENV ANACONDA_HOME /usr/local/anaconda3
# install basic software vim
RUN yum install -y vim
# install anaconda3 py3.6.x
RUN yum install -y wget
RUN yum install -y bzip2
RUN mkdir -p /home/download
RUN cd /home/download
RUN wget https://repo.continuum.io/archive/Anaconda3-5.2.0-Linux-x86_64.sh
RUN chmod 755 ./Anaconda3-5.2.0-Linux-x86_64.sh
RUN ./Anaconda3-5.2.0-Linux-x86_64.sh -b -p /usr/local/anaconda3
RUN rm -rf /home/download/*
# set system env
ENV PATH $ANACONDA_HOME/bin:$PATH
# create link
RUN ln -s $ANACONDA_HOME/bin/pip /usr/bin/pip3
# install tensorflow with cpu
RUN pip3 install --upgrade --ignore-installed tensorflow
# install keras
RUN conda install -y keras
# start the jupyter-notebook
ENTRYPOINT ["/usr/local/anaconda3/bin/jupyter-notebook"]
# open the default jupyter listen port
EXPOSE 8888
这个镜像我设置的默认启动程序(ENTRYPOINT)就是jupyter-notebook(注意linux下的jupyter notebook启动指令中间有横线这一点与windows不同), 开放的端口是磨人的jupyter notebook server 的8888端口
Start the container
本身这个镜像比较简单,启动container我索性就运行脚本去启动,没有使用docker compose
,启动的脚本如下:
echo 'start the jupyterimage container'
docker run \
-it \
--name=jpcontainer \
-h jpcontainer \
-v /home/jpdir:/home/jpdir \
-p 8888:8888 \
allocator/jpimage \
--no-browser \
--ip 0.0.0.0 \
--notebook-dir /home/jpdir \
--allow-root
有几个关键的点需要说明一下:1.挂载卷(-v) 一般做模型training的时候还是将数据放在宿主机器上面(cloud vm), container只是提供一个运行环境而已,所以我将容器中的运行目录与宿主机器上面实际存放数据的目录通过挂载卷关联(比较习惯在启动容器的时候动态进行卷挂载,因为卷挂载如果写入dockerfile有两个不妥的地方,第一更改挂载目录后需要重新编译生成镜像;第二,可能存在目录访问受限的问题) 2.容器内的jupyter server 监听的ip地址问题(–ip) 这个地方设置为0.0.0.0 一切操作从简,容器本身的IP地址我们是不需要知道的,只要保证任何一个ip地址能够访问到jupyter notebook server即可. 运行这个shell脚本, 获取到token就能够通过PC的browser访问到Cloud vm 上面的jupyter notebook server了.
About token
jupyter notebook 本身支持远程使用密码访问,或者免密码访问(参考官方文档jupyternotebook). 但是这些配置不太容易和容器技术结合(我不太喜欢启动一个容器然后在里面做修改配置后提交成为新的image这种做法), 感觉不能够单纯的通过编写dockerfile实现. 使用过程中如果container重启了会导致token也变了,使用原来的token可能无法访问远程的jupyter notebook. 不过这个问题比较简单,登录Cloud vm, 进入到container(使用docker attach containername命令), 运行ctrl+c
会提示是否关闭jupyter notebook server,同时也会提供新的token,当然选择不关闭server,在浏览器中使用这个新的token即可顺利访问server