注:早在学习《云计算》这门课之前就已经知道docker,学习这门课时老师还鼓励我们自己尝试一下;但是直到去年年底才有机会尝试,用过之后感觉确实很好用。最近需要部署几个shiny应用,又回顾了一下,并记录与此。

1. 初识docker


最开始听说docker,就知道可以使用docker来部署应用,相对于之前在主机上直接安装应用所需的运行环境,docker要方便的多。对于我这样时不时被开发环境搞的怀疑人生的半个开发人员,自然会对这样神奇的工具有所关注,只是一直没有找到机会尝试。直到去年年底,为了部署一个Django应用,终于有机会尝试了一下。有以下几点认识:

  1. 与虚拟机相比,docker是操作系统级别的虚拟化,与host共享了很多系统资源。因此docker比虚拟机更轻量级,运行的时候启动速度更快,开销也更小;
  2. 虚拟机可以安装桌面,但是docker部署的应用一般通过"IP+端口"的方式来访问;
  3. docker以image(镜像)为基础,应用程序运行在基于特定image开启的container(容器)上;
  4. 如果多个程序使用同一个image来开启不同的container,这些container共享该image而不需要复制多个;
  5. 一个image可以是一个完整的操作系统(例如Ubuntu的官方镜像,大小为2G左右),也可以只是满足某个应用程序运行的基本环境(例如运行nginx的alpine镜像,只有15.5M);
  6. image是分层的,已有image的层是只读属性的,可以在已有image的基础上添加新的层来覆盖下层的东西,从而构建出新的image.

图1:docker与虚拟机的区别,图片来源:link

由于应用程序运行在container中,而容器又是基于image构建的,因此image就显得非常重要了。image相当于一个刻录好的光盘,里面有预装好的操作系统或应用程序等。docker官方维护了docker hub这个网站,类似于github,可以直接从该网站上pull各种应用程序的官方镜像。这些镜像可以直接使用,也可以在此基础上添加新的层,来构建自己的镜像。

 Docker的安装

windows下需要win10操作系统的特定版本(Windows 10 64bit: Pro, Enterprise or Education (1607 Anniversary Update, Build 14393 or later))才可以安装docker engine。下面是CentOS下安装及启动Docker Community Edition(CE)的官方文档:

  • 下载安装:https://docs.docker.com/install/linux/docker-ce/centos/
  • 基本使用方法:https://docs.docker.com/get-started/

在安装好docker,并启动docker之后,就可以pull官方的image,并在这些image的基础上按照自己的需要创建新的image。

2. Dockerfile文件


创建自己的image只需要一个Dockerfile文件就可以,该文件中保存了构建image的每一步命令。image的每一层可以仅包含一个命令也可以是多个命令,且每一层执行完成后可以缓存起来(下次不用重新执行已构建完成的层中的命令),这样就让可追溯的逐步搭建运行环境成为可能。

Dockerfile中保存的是与基础image对应的操作系统命令,例如以Ubuntu为基础image构建的新的image,该文件中就是Ubuntu系统的shell命令。以下是docker官网对该文件的介绍:

Docker can build images automatically by reading the instructions from a Dockerfile. A Dockerfile is a text document that contains all the commands a user could call on the command line to assemble an image. Using docker build users can create an automated build that executes several command-line instructions in succession.

下面是一个该文件的示例,使用了jupyter的官方镜像datascience-notebook:

 # 指定基础image
FROM jupyter/datascience-notebook:03b897d05f16
MAINTAINER Xin Xiong <xiongxin20008@126.com> # 替换CRAN镜像为国内的镜像,可以更快的安装R packages
ARG CRAN_MIRROR=https://mirrors.tuna.tsinghua.edu.cn/CRAN/ # 由于要安装程序,使用root身份
USER root # install Java
RUN \
apt-get update -qq && \
apt-get install -y openjdk-8-jdk && \
apt-get install -y mlocate && updatedb && \
rm -rf /var/lib/apt/lists/* # 为安装rJava做准备
# need using ln to avoid some errors, such as conftest.c:1:10: fatal error: jni.h: No such file or directory
RUN \
ln -s /usr/lib/jvm/java-8-openjdk-amd64/include/jni.h /opt/conda/include/ && \
ln -s /usr/lib/jvm/java-8-openjdk-amd64/include/linux/jni_md.h /opt/conda/include/ && \
ln -s /usr/lib/jvm/java-8-openjdk-amd64/jre/lib/amd64/server/libjvm.so /usr/lib/ && \
R CMD javareconf # 添加本地文件夹package到镜像中的/src
ADD ./package/ /src/ # link lib
RUN \
ln -s /opt/conda/lib/libpcre.so /usr/lib/ && \
ln -s /opt/conda/lib/liblzma.so /usr/lib/ && \
ln -s /opt/conda/lib/libbz2.so /usr/lib/ && \
ln -s /opt/conda/lib/libz.so /usr/lib/ && \
ln -s /opt/conda/lib/libiconv.so /usr/lib/ && \
ln -s /opt/conda/lib/libicuuc.so /usr/lib/ && \
ln -s /opt/conda/lib/libicui18n.so /usr/lib/ # 安装前面添加到镜像/src文件夹中rpacks.txt文件中的R package
# 且使用国内的镜像地址CRAN_MIRROR
RUN \
cd /src && \
R -e 'install.packages(sub("(.+)\\\\n","\\1", scan("rpacks.txt", "character")), repos="'"${CRAN_MIRROR}"'")' # 安装前面添加到镜像/src文件夹中requirements.txt文件中的Python package
RUN \
cd /src && \
pip --no-cache-dir install -r requirements.txt && \
rm -rf /root/.cache # 直接使用conda安装Python package
RUN conda install -c rdkit rdkit # 切换到默认普通用户
USER jovyan

Jupyter的官方镜像datascience-notebook,包含了Python, R和Julia以及一些数据分析中常用的包。我在该镜像的基础上,安装了Java以及其他一些自己需要的Python和R包。这些包的的名字保存在文件夹package的rpacks.txt和requirements.txt两个文件中,每个包名称一行。在上面的操作中,第28行添加该文件夹中的内容到镜像中的的/src目录下,第42-44行安装了rpacks.txt文件中的R包,第47-50行安装了requirements.txt文件中的Python包。更多关于该镜像的说明可以在官方文档的描述中看到,还有其他的官方镜像可供选择。

2.1 Dockfile中的关键字

如上面的例子所示,Dockfile中包含的最重要的内容是可以在系统命令行中执行的命令,只是每一行命令前加了一些Dockfile特有的关键词。下面是一些常见的关键词:

2.1.1 FROM

FROM <镜像>:<标签>  指定基础镜像为该镜像的一个标签版本,上面例子中的第2行

2.1.2 RUN

运行指定的命令。使用RUN可以运行任何被基础image支持的命令。如果基础image是ubuntu系统,那么软件管理部分只能使用ubuntu的命令

2.1.3 ADD

添加本地文件或目录到container

2.1.4 LABLE

添加一些元数据,格式为LABEL <key>=<value>,例如上面的第3行可以写成LABEL maintainer="Xin Xiong, xiongxin@20008@126.com". MAINTAINER关键词已弃用。

2.1.5 ARG

定义一个变量,如第6行,可以重复使用

更多关键词,可以参考官方文档。此外,"&&"用来连接两条不同的指令,"\" 表示同一条语句换行显示

2.2 Dockerfile的最佳实践

官方文档给出了一些最佳实践指南,比如说不要安装不需要的package,应用解偶联,最小化层数,如何最好的使用"apt-get",COPY和ADD关键词的差别等。

2.3 构建自己的image

有了上面的文件,就可以在Dockerfile这个文件所在的文件夹,使用下面的命令build自己的镜像了:

docker build -t onlybelter/ds-notebook .

这句命令会使用当前目录下的Dockerfile文件,构建一个image,新image的名称为onlybelter/ds-notebook。

3. docker-compose


docker-compose可以用来配置一些在image中没有设置的参数,例如端口号,log日志的目录,容器启动时运行的命令等。此外还可以用来启动、停止容器,打印log,查看容器状态和限制资源使用等功能。

docker-compose的其他介绍及安装可以参考官方文档

3.1 docker-compose的配置文件

docker-compose的配置文件是一个放在与Dockerfile相同目录下,以.yml结尾的文件,示例如下:

 version: '2.2'

 services:
jupyterlab:
image: onlybelter/ds-notebook
command: /bin/bash -c "jupyter lab --no-browser --ip=0.0.0.0 --notebook-dir=/mnt/notebook"
cpus: 16
mem_limit: 8g
volumes:
- /mnt/home/belter/github/jupyter-note:/mnt/notebook
- /etc/localtime:/etc/localtime:ro
environment:
- PYTHONUNBUFFERED=1
ports:
- 8888:8888

第1行,指定了配置文件的版本号,由于v3不支持单机模式下配置资源,因此这里使用了v2.2(如果不适用swarm或其他集群模式,官方推荐使用v2);

第4行是service的名称;

第5行指定了image的名称,就是上面build好的镜像;

第6行设置了容器启动时的命令;

第7-8行限制了资源的使用:16个CPU核,8G内存;

第10行,相当于挂载了一个本地目录到容器,这样容器和外部的host之间就可以交换文件了(内外对应的文件夹里的内容是同步的);

第11行用于同步容器与host的时间;

第13行设置了一个环境变量;

第15行设置了容器内外端口号的对应关系,左边是host的端口号,右边是容器内的端口号。

3.2 启动容器

配置好上面的.yml文件(我的文件为docker-compose.yml)后,就可以启动前面build好的镜像来创建一个容器了。

$ sudo docker-compose up -d

$ sudo docker-compose logs

第1行命令使用当前目录下的docker-compose.yml文件创建容器,并在后台运行;第2行命令打印logs,可以从logs中获得Jupyter Notebook生成的token来登录。

Attaching to jupyterlab_jupyterlab_1
jupyterlab_1 | [I ::06.567 LabApp] Writing notebook server cookie secret to /home/jovyan/.local/share/jupyter/runtime/notebook_cookie_secret
jupyterlab_1 | [I ::06.731 LabApp] JupyterLab beta preview extension loaded from /opt/conda/lib/python3./site-packages/jupyterlab
jupyterlab_1 | [I ::06.731 LabApp] JupyterLab application directory is /opt/conda/share/jupyter/lab
jupyterlab_1 | [W ::06.737 LabApp] JupyterLab server extension not enabled, manually loading...
jupyterlab_1 | [I ::06.737 LabApp] JupyterLab beta preview extension loaded from /opt/conda/lib/python3./site-packages/jupyterlab
jupyterlab_1 | [I ::06.737 LabApp] JupyterLab application directory is /opt/conda/share/jupyter/lab
jupyterlab_1 | [I ::06.744 LabApp] Serving notebooks from local directory: /mnt/notebook
jupyterlab_1 | [I ::06.744 LabApp] active kernels
jupyterlab_1 | [I ::06.744 LabApp] The Jupyter Notebook is running at:
jupyterlab_1 | [I ::06.744 LabApp] http://1c7e68e582c4:8888/?token=3bda623azj07414dbcf58bf977e2c2855158bd052f77afa2
jupyterlab_1 | [I ::06.744 LabApp] Use Control-C to stop this server and shut down all kernels (twice to skip confirmation).

使用该host的ip加端口号8888,输入日志中的token就可以打开Jupyter的界面。我的本地地址为,http://192.168.1.33:8888/lab?

界面如下图所示:

其他docker-compose命令:

$ sudo docker-compose down  # 关闭容器
$ sudo docker-compose ps # 查看容器运行状态

此外使用docker stats <container name>可以查看该容器资源使用情况:

PS: 最近都是忙到每个月最后一天更新博客,要改改啦!

Reference


https://stackoverflow.com/questions/16047306/how-is-docker-different-from-a-virtual-machine

https://www.docker.com/resources/what-container#/package_software

https://blog.csdn.net/weixin_37645838/article/details/83343029

https://docs.docker.com/engine/reference/builder/

使用docker搭建数据分析环境的更多相关文章

  1. mac下通过docker搭建LEMP环境

    在mac下通过docker搭建LEMP环境境 1.安装virtualbox.由于docker是在lxc环境的容器 2.安装boot2docker,用于与docker客户端通讯 > brew up ...

  2. 【Devops】【docker】【CI/CD】1.docker搭建Gitlab环境

    CI/CD[持续化集成/持续化交付] docker搭建Gitlab环境 1.查询并拉取gitlab镜像 docker search gitlab docker pull gitlab/gitlab-c ...

  3. Mac下docker搭建lnmp环境 + redis + elasticsearch

    之前在windows下一直使用vagrant做开发, 团队里面也是各种开发环境,几个人也没有统一环境,各种上线都是人肉,偶尔还会有因为开发.测试.生产环境由于软件版本或者配置不一致产生的问题, 今年准 ...

  4. 【python数据分析】利用Anaconda在window上搭建数据分析环境

    由于在进行数据分析过程中,需要安装一些第三方库,导致python总会报一些错误,现将通过利用Anaconda搭建数据分析环境,已测可用. 1.到官网上下载python:https://www.pyth ...

  5. docker搭建lnmp环境(问题,资料,命令)

    入门参考 http://www.runoob.com/docker/docker-install-nginx.html 十大常用命令玩转docker 1. #从官网拉取镜像 docker pull & ...

  6. Docker搭建disconf环境,三部曲之一:极速搭建disconf

    Docker下的disconf实战全文链接 <Docker搭建disconf环境,三部曲之一:极速搭建disconf>: <Docker搭建disconf环境,三部曲之二:本地快速构 ...

  7. Docker搭建disconf环境,三部曲之二:本地快速构建disconf镜像

    Docker下的disconf实战全文链接 <Docker搭建disconf环境,三部曲之一:极速搭建disconf>: <Docker搭建disconf环境,三部曲之二:本地快速构 ...

  8. Docker搭建disconf环境,三部曲之三:细说搭建过程

    Docker下的disconf实战全文链接 <Docker搭建disconf环境,三部曲之一:极速搭建disconf>: <Docker搭建disconf环境,三部曲之二:本地快速构 ...

  9. 使用Docker搭建apache环境

    Docker搭建apache环境 前言 操作机:ubuntu16 x64 Dockers servion 18.09.7 下载镜像 使用docker pull 拉取最新的 apache镜像 命令:do ...

随机推荐

  1. quartz一次简单应用经历

    项目里使用到每月的第一天需要定时统计上一个月的某种数据,这个时候,我开始第一次知道任务调度这么一个专业词汇.也初次了解quartz这个任务调度框架.网上看了好几篇博文,有种quartz越看越难的感觉, ...

  2. 前后台分离开发时遇到循环引用问题"$ref"

    1. 遇到的问题 { "errMsg": "", "data": { "baseinfo": { "freeT ...

  3. affiliate的使用方式

    什么是affiliate https://www.zhihu.com/question/24262490 通俗的理解就是,我们寻找合作伙伴,让合作伙伴帮忙做宣传,我们会根据他们的宣传力度发放相关的奖励 ...

  4. java+phantomjs实现动态网页抓取

    1.下载地址:http://phantomjs.org/download.html 2.java代码 public void getHtml(String url) { HTML="&quo ...

  5. 整理CSS中display flex(布局利器)

    关于display:flex布局,有人了解颇深,我也是看着别人的东西学习的. display:flex的布局是什么.基本概念之类的我根本就不了解,只会用.每次看到概念之类的东西,我都是扫一眼就过去. ...

  6. TYVJ1424-占卜DIY

    题目有点长,对于样例最好拿张A4纸模拟写一遍. 可以发现程序一定不会死循环,因为每种牌都是4张,而死循环的条件是某种牌有5张然后你拿了又放进去.如果写出来死循环了,那就是写不对了. 有几点可能是需要注 ...

  7. struts2 升级至2.3.32时访问页面报错 File "/struts-tags" not found

    Apache struts是美国阿帕奇(Apache)软件基金会负责维护的一个开源项目,是一套用于创建企业级Java Web 应用的开源MVC框架,主要提供两个版本框架产品: struts 1和str ...

  8. now

  9. JS自定义鼠标右击菜单

    自定义鼠标右击菜单要素: 禁止页面默认右击事件 设置右击菜单的样式以及菜单出现的位置(通过捕获鼠标点击位置来确定菜单的位置) 鼠标在指定控件(区域)上右击时显示菜单(默认菜单隐藏,点击鼠标右键时显示) ...

  10. [转] IPTables for KVM Host

    IPTables for KVM Host January 26, 2012 By Andrew Galdes Use the following IPTables rules “/etc/sysco ...