一般来说我们是不需要自己构建镜像的,这个比较麻烦,初学者直接使用 Docker Hub 上的一些公共的镜像就好了。最简单的工作流程如下:

  • Step 1:在 Docker Hub 检索自己想要的软件或流程(有的软件会有官方 docker 仓库)
  • Step 2:选择排名靠前,注释比较详细的镜像(最好提供 Dockerfile),下载镜像
  • Step 3:根据镜像创建容器
  • Step 4:在容器中进行相应分析

下面我就举一个现成的例子。

方案一:直接下载已有镜像

比如我们分析 16s 数据常用的软件 QIIME2 就提供了官方的 docker 仓库:https://docs.qiime2.org/2020.11/install/virtual/docker/

如何快速构建 Docker 镜像 - 图1

如何快速构建 Docker 镜像 - 图2

我们直接下载官方镜像即可:

  1. docker pull quay.io/qiime2/core:2020.11

使用镜像(创建容器):

docker run -t -i -v $(pwd):/data quay.io/qiime2/core:2020.11 qiime

那要是官方没有提供镜像,或者在 DockerHub 上也找不到镜像呢,我们也可以根据已有的镜像自己创建镜像,下面我们依旧以 QIIME2 这个软件为例。

方案二:根据已有镜像创建镜像

在这一部分中,我们假设 QIIME2 没有提供 Docker 镜像,我们将尝试自己创建 QIIME2 镜像。根据 QIIME2 官网的介绍,我们可以使用 conda 安装:https://docs.qiime2.org/2020.11/install/native/#miniconda

如何快速构建 Docker 镜像 - 图3

所以我就先在 dockerhub 上搜索下有没有 miniconda 的镜像:

如何快速构建 Docker 镜像 - 图4

可以看到排名第一的 miniconda 镜像下载量已经超过 500 万次,一般这种优质镜像都会提供比较详细的 Overview,提供不同的软件版本(Tags),以及镜像构建过程(Dockerfile)。

如何快速构建 Docker 镜像 - 图5

我们就选择这个镜像吧,其实下载量多的一般就比较靠谱,后续我们将基于该镜像构建 QIIME2 镜像。

下载镜像:

docker pull continuumio/miniconda3

根据该镜像创建一个容器:

docker run -it --name docker_tutorial continuumio/miniconda3 /bin/bash

参数说明:

  • -i: 以交互模式运行容器,通常与 -t 同时使用;
  • -t: 为容器重新分配一个伪输入终端,通常与 -i 同时使用;
  • --name: 为容器指定一个名称

进入容器后,根据 QIIME2 的安装指南,我们需要先下载一个 yml 配置文件,再基于此创建 conda 环境。

如何快速构建 Docker 镜像 - 图6

下载 yml 文件:

wget https://data.qiime2.org/distro/core/qiime2-2020.11-py36-linux-conda.yml

创建环境:

conda env create -n qiime2-2020.11 --file qiime2-2020.11-py36-linux-conda.yml

安装完毕后,使用快捷键 Ctrl+P+Q 退出容器(退出容器,但容器不关闭)。

对于上面的容器,我们现在已经对它进行了一些改动(安装了 QIIME2),下一步就可以使用docker commit <container_id> <image_name> 命令,基于已有的容器创建一个新的镜像(这里命名为 zwbao/qiime_tmp):

docker commit docker_tutorial zwbao/qiime_tmp

使用 docker images 命令就能看到刚刚创建好的镜像啦。

最后用完容器后记得停止并删除容器,否则你的容器就会越来越多,先用 docker stop <container-id> 停止容器,再 docker rm <container-id> 删除容器:

docker stop docker_tutorial
docker rm docker_tutorial

方案三:使用 dockerfile 创建镜像

除了上面这种土办法创建镜像外,还有没有更高效率的方法呢,我们可以使用 dockerfile 来创建镜像。Dockerfile就是一个文本文件,里面包含了打包 docker 镜像所需要用到的所有命令,这样,docker 就可以通过读取 Dockerfile 里面的命令来自动化地构建 docker 镜像。 最后,再执行 docker build 就可以启动这样的一个自动化流程。相比于 commit,使用Dockerfile的好处在于其生成镜像的方式更加透明,我们可以一目了然地知道这个镜像是如何一步步生成的,同时构建的镜像也相对较小,文本的形式也方便镜像的管理与复用。

先来复习下,之前我们是如何通过docker commit来生成一个新镜像的:

Step 1:首先,我们需要启动一个容器,当我们运行镜像并生成容器时,会在基础镜像的顶部添加新的可写层(“容器层”);
Step 2:然后,我们会对容器执行一些操作(比如安装软件)。我们对容器所做的所有更改都将写入此可写容器层,每一个操作都会在上面累加一层,每一层都是前一层变化的增量;
Step 3:最后执行 docker commit <container_id> <image_name> 来基于已有的容器创建一个新的镜像。

如何快速构建 Docker 镜像 - 图7

DockerFile其实执行的是相同的步骤。首先,我们需要使用FROM命令指定一个基础镜像生成一个容器,然后用一些「镜像操作指令」对容器做一些修改。最后用docker build命令来生成镜像。

Dockerfile常用指令

类型 命令
基础镜像信息 FROM
维护者信息 MAINTAINER
镜像操作指令 RUN、COPY、ADD、EXPOSE、WORKDIR、ONBUILD、USER、VOLUME等
容器启动时执行指令 CMD、ENTRYPOINT

我把上面的 QIIME2 的例子改写为 Dockerfile 形式就是这样(vi Dockerfile 写入下面的内容):

FROM continuumio/miniconda3
COPY qiime2-2020.11-py36-linux-conda.yml .
RUN conda env create -n qiime2-2020.11 --file qiime2-2020.11-py36-linux-conda.yml \
&& rm qiime2-2020.11-py36-linux-conda.yml \
&& echo "source activate qiime2-2020.11" > ~/.bashrc
ENV PATH /opt/conda/envs/qiime2-2020.11/bin:$PATH

意思就是,先用 FROM 命令从 continuumio/miniconda3 基础镜像创建一个容器,接着用 COPY 命令将宿主机中的 yml 文件拷贝到容器根目录,再使用RUN命令运行 conda,安装分析环境,将激活命令写入 ~/.bashrc,这样启动容器的时候就能自动激活 conda 环境。

创建完 DockerFile,我们就可以使用docker build来创建镜像了。

docker build -t test:v1.0 .

执行命令后,控制台会逐层输出构建内容,直到输出两个 Successfully 即为构建成功。

Successfully built 93a111d8c6e5
Successfully tagged test:v1.0

使用 docker images 命令就能看到刚刚创建好的镜像啦。