什么是docker?

通过本节您可以了解Docker镜像的使用以及在本平台内关于镜像的基本操作。

Docker的起源

在曾经没有docker的日子里,假设我们正在开发一个“如何把人逗笑”的人工智能项目,这个项目需要的依赖比较多,需要很多的编译库,不同的语言包,以及很多的软件和服务。从头到尾搭建一套环境可能需要一天时间,然后开始写代码,写完代码后,我们要把代码交给另一个伙伴进行测试,这时测试伙伴如果不能使用你的开发环境(你只能给他代码,例如github),他就需要开始从头到尾搭建这套环境,这时由于操作系统差异,系统版本问题,依赖包的版本问题,各种各样的原因,最终导致测试花费大量时间最终没有运行起来代码,或者运行过程中出现大量奇葩问题。这是作为开发者的我们只能弱弱的回一句“明明在人家的环境上可以运行的”。这还仅仅是测试,到了上线,发布产品的时候或者分享给其他人使用时,他们又需要重新再搭建一遍,可想而知,变数还是挺大的。

从整个过程可以看到,不但我们重复搭建了三套环境,非常的浪费时间和效率,聪明的程序员是永远不会满足现状的,因此又到了程序员改变世界的时候了,容器技术应运而生。

Docker是一个用Go语言实现的开源项目,它是一个功能强大的开放软件平台。通过封装软件到Docker镜像(image)中,可以使软件在不同平台与环境下运行。同时人们可以将Docker镜像放在公共(Docker Hub)或私有的Docker仓库(repository)中,互相分享。这些都极大地方便了软件的安装、分享以及运行。

Docker的安装

用户可以通过下面的链接了解Docker的安装,Docker为用户提供了linux / windows / macOS 各个平台的下载安装教程,您可以选择具体的平台查看安装详情。 https://docs.docker.com/engine/install/

Linux ubuntu系统安装Docker示例

以Ubuntu系统安装为例,安装教程可以访问https://docs.docker.com/engine/install/ubuntu/

操作系统最低要求

为了保证docker能够正常运行,您的系统版本需要需要满足一下任意要求

>= Ubuntu Groovy 20.10
>= Ubuntu Focal 20.04 (LTS)
>= Ubuntu Bionic 18.04 (LTS)
>= Ubuntu Xenial 16.04 (LTS)
删除旧版本

较旧的Docker版本称为docker,docker.io或docker-engine。 如果安装了这些,请卸载它们:

sudo apt-get remove docker docker-engine docker.io containerd runc
docker依赖安装

首次安装Docker之前,需要安装Docker仓库。 之后,您可以从Docker仓库中安装和更新Docker。

sudo apt-get update
sudo apt-get install \
    apt-transport-https \
    ca-certificates \
    curl \
    gnupg \
lsb-release

添加Docker的官方GPG密钥,如果失效,请访问 https://docs.docker.com/engine/install/ubuntu/

curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg

设置稳定的镜像源,如果您的系统是x86_64 / amd64,您可以使用下方命令,其他系统请参考上方教程

echo \
  "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \
  $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
Docker安装
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io

要安装特定版本的Docker Engine,请在存储库中列出可用版本,然后选择并安装:

#  列出可用版本
apt-cache madison docker-ce

#  返回结果
#  docker-ce | 5:18.09.1~3-0~ubuntu-xenial | https://download.docker.com/linux/ubuntu  xenial/stable amd64 Packages
#  docker-ce | 5:18.09.0~3-0~ubuntu-xenial | https://download.docker.com/linux/ubuntu  xenial/stable amd64 Packages
#  docker-ce | 18.06.1~ce~3-0~ubuntu       | https://download.docker.com/linux/ubuntu  xenial/stable amd64 Packages
#  docker-ce | 18.06.0~ce~3-0~ubuntu       | https://download.docker.com/linux/ubuntu  xenial/stable amd64 Packages

使用第二列中的版本字符串安装特定版本,例如 5:18.09.1~3-0~ubuntu-xenial

sudo apt-get install docker-ce=<VERSION_STRING> docker-ce-cli=<VERSION_STRING> containerd.io

安装完成后,可以测试是否安装成功:

sudo docker run hello-world

Docker工具的使用

详细的Docker工具参考教程您可以访问https://docs.docker.com/get-started/,我们在此将展示简单的命令演示。

从远程仓库拉基础镜像
# dockr pull 镜像名:版本

# 从远程仓库拉取基础镜像ubuntu:16.04
docker pull ubuntu:16.04

# 从远程仓库拉取安装有R语言的基础镜像r-base:3.6.3
docker pull r-base:3.6.3

# 从远程仓库拉取生物信息分析工具fastaqc,可访问https://biocontainers.pro/registry获取更多生物信息工具镜像
docker pull biocontainers/fastqc:v0.11.9_cv7
查看本地镜像仓库
# 查看本地镜像
docker images

# 返回结果为镜像列表,第一行为列名,包括了仓库名 / 标签 / 镜像ID / 创建时间 / 镜像大小
# REPOSITORY               TAG                 IMAGE ID            CREATED             SIZE
# biocontainers/fastqc    v0.11.9_cv7        e5e3008d2bd1        5 months ago        834MB
# r-base                   3.6.3               cec2502269fb        11 months ago       682MB
# ubuntu                   16.04               dec3202189t1        1 months ago        1.5GB
使用镜像开启一个容器并运行
# 启动r-base:3.6.3镜像,并将服务器下的/data目录与镜像容器内的/data目录相映射,并设置容器名称为DEMO
docker run -it --name DEMO -v /data:/data r-base:3.6.3  /bin/bash

# 如果要退出
exit
查看所有容器列表
docker ps -a
# 返回结果为容器列表,第一行为容器ID / 依赖的镜像名 / 命令 / 创建时间 / 状态 / 端口 / 容器名称

# CONTAINER ID    IMAGE         COMMAND       CREATED          STATUS                        PORTS      NAMES
# 8759b9205aba    r-base:3.6.3  "/bin/bash"   9 seconds ago    Exited (0) 6 seconds ago                 DEMO

# 如果要重启退出的容器 docker start 容器ID
docker start 8759b9205aba
docker ps -a 

# 返回结果为容器列表,第一行为容器ID / 依赖的镜像名 / 命令 / 创建时间 / 状态 / 端口 / 容器名称
# CONTAINER ID    IMAGE         COMMAND       CREATED          STATUS    PORTS      NAMES
# 8759b9205aba    r-base:3.6.3  "/bin/bash"  9 seconds ago   Up 4 seconds         DEMO

# 如果要以命令行模式进入已经启动的容器中 docker exec -it 容器ID /bin/bash
docker exec -it 8759b9205aba /bin/bash
将容器成为新的镜像
# docker commit  容器ID  新的镜像名:设置版本

docker commit  8759b9205aba  new_r:1
docker images

# 新增了一个新的工具镜像

# REPOSITORY               TAG                 IMAGE ID            CREATED             SIZE
# new_r                    1                   1877eedea49d        1 second ago        682MB
# biocontainers/fastqc     v0.11.9_cv7         e5e3008d2bd1        5 months ago        834MB
# r-base                   3.6.3               cec2502269fb        11 months ago       682MB
# ubuntu                   16.04               dec3202189t1           1 months ago        1.5GB
删除容器
# 如果容器正在运行,则先停止运行 docker stop 容器ID
docker stop 8759b9205aba

# 删除容器 docker rm 容器ID
docker rm 8759b9205aba
删除镜像
# 如果有容器依赖要删除的镜像,则需要先将这些容器删除,参考删除容器
# 删除镜像 docker rmi 镜像名:版本
docker rmi new_r:1
基于DockerFile安装镜像

Dockerfile 是一个用来构建镜像的文本文件,文本内容包含了一条条构建镜像所需的指令和说明。由于工具的制作可能不仅依赖一些基础的镜像,我们还需要在这些基础镜像上进一步修改,添加一些程序,以实现工具的正常运行。如果通过在基础镜像中开启一个容器,然后进入容器修改后保存成一个新的镜像,这样的镜像大小会相对较大,不利于传输,我们更建议使用DockerFile制作工具镜像。具体介绍可以访问https://docs.docker.com/develop/develop-images/dockerfile_best-practices/

什么是dockerfile?

Dockerfile是一个包含用于组合映像的命令的文本文档。可以使用在命令行中调用任何命令。 Docker通过读取Dockerfile中的指令自动生成映像。docker build命令用于从Dockerfile构建映像。

用户可以在docker build命令中使用-f标志指向文件系统中任何位置的Dockerfile,-t用来指定docker名字及版本号。例:

# docker build -f /path/to/a/Dockerfile -t fastp:latest

Dockerfile的基本结构

Dockerfile 一般分为四部分:基础镜像信息、维护者信息、镜像操作指令和容器启动时执行指令,#为 Dockerfile 中的注释。

Dockerfile文件说明

Docker以从上到下的顺序运行Dockerfile的指令。为了指定基本映像,第一条指令必须是FROM。一个声明以#字符开头则被视为注释。可以在Docker文件中使用RUN,CMD,FROM,EXPOSE,ENV等指令。在这里列出了一些常用的指令。

FROM说明
FROM:指定基础镜像,必须为第一个命令格式:
例如:FROM <image>  
例如:FROM <image>:<tag>  
例如:FROM <image>@<digest>

示例:  
FROM gatk:4.0
注: tag或digest是可选的,如果不使用这两个值时,会使用latest版本的基础镜像
MAINTAINER说明
MAINTAINER: 维护者信息格式:
MAINTAINER <name>

示例:
MAINTAINER flowhub MAINTAINER flowhub_team@flowhub.com.cn
MAINTAINER flowhub <flowhub_team@flowhub.com.cn>
ADD说明
ADD:将本地文件添加到容器中,tar类型文件会自动解压(网络压缩资源不会被解压),可以访问网络资源,类似wget格式:    
ADD <src>... <dest>
ADD ["<src>",... "<dest>"] 用于支持包含空格的路径

示例:
ADD hom* /mydir/
# 添加所有以"hom"开头的文件    

ADD hom?.txt /mydir/      
# ? 替代一个单字符,例如:"home.txt"    

ADD test relativeDir/     
# 添加 "test" 到 `WORKDIR`/relativeDir/    

ADD test /absoluteDir/ 
# 添加 "test" 到 /absoluteDir/
COPY说明
COPY:功能类似ADD,但是是不会自动解压文件,也不能访问网络资源
RUN说明
RUN:构建镜像时执行的命令RUN用于在镜像容器中执行命令,其有以下两种命令执行方式:
shell执行格式:    
RUN <command>

exec执行格式:
RUN executable param1 param2

示例:
RUN executable param1  param2    
RUN apk update
RUN /etc/execfile arg1 arg1    
注:RUN指令创建的中间镜像会被缓存,并会在下次构建中使用。如果不想使用这些缓存镜像,可以在构建时指定--no-cache参数,如:docker build --no-cache
ENV说明
ENV:设置环境变量格式: 
ENV <key> <value>  
#<key>之后的所有内容均会被视为其<value>的组成部分,因此,一次只能设置一个变量

ENV <key>=<value> ...  
#可以设置多个变量,每个变量为一个"<key>=<value>"的键值对,如果<key>中包含空格,可以使用\来进行转义,也可以通过""来进行标示;另外,反斜线也可以用于续行

示例:  
ENV myName John Doe  
ENV myCat=fluffy

以下是一个基于dockerfile制作pytorch工具镜像的小例子:

# 设置变量后续通过${xxx}可以获取到这个变量
ARG BASE_IMAGE=ubuntu:18.04
ARG PYTHON_VERSION=3.8

# 该镜像以ubuntu:18.04构建
FROM ${BASE_IMAGE} as dev-base

# RUN命令可以理解为直接在终端中执行命令
RUN --mount=type=cache,id=apt-dev,target=/var/cache/apt \
    apt-get update && apt-get install -y --no-install-recommends \
        build-essential \
        ca-certificates \
        ccache \
        cmake \
        curl \
        git \
        libjpeg-dev \
        libpng-dev && \
    rm -rf /var/lib/apt/lists/*
RUN /usr/sbin/update-ccache-symlinks
RUN mkdir /opt/ccache && ccache --set-config=cache_dir=/opt/ccache

# 设置conda环境变量
ENV PATH /opt/conda/bin:$PATH


# 多个 FROM 指令并不是为了生成多根的层关系,最后生成的镜像,仍以最后一条 FROM 为准,之前的 FROM 会被抛弃,那么之前的FROM 又有什么意义呢?
# 每一条 FROM 指令都是一个构建阶段,多条 FROM 就是多阶段构建,虽然最后生成的镜像只能是最后一个阶段的结果,
# 但是,能够将前置阶段中的文件拷贝到后边的阶段中,这就是多阶段构建的最大意义。
# 最大的使用场景是将编译环境和运行环境分离
FROM dev-base as conda
ARG PYTHON_VERSION=3.8
RUN curl -fsSL -v -o ~/miniconda.sh -O  https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh  && \
    chmod +x ~/miniconda.sh && \
    ~/miniconda.sh -b -p /opt/conda && \
    rm ~/miniconda.sh && \
    /opt/conda/bin/conda install -y python=${PYTHON_VERSION} conda-build pyyaml numpy ipython&& \
    /opt/conda/bin/conda clean -ya

FROM dev-base as submodule-update
# 设置当前的工作目录,可以理解为cd /opt/pytorch
WORKDIR /opt/pytorch
# 将当前执行命令的文件复制进docker的build目录
COPY . .
RUN git submodule update --init --recursive

FROM conda as build
WORKDIR /opt/pytorch
COPY --from=conda /opt/conda /opt/conda
COPY --from=submodule-update /opt/pytorch /opt/pytorch
RUN --mount=type=cache,target=/opt/ccache \
    TORCH_CUDA_ARCH_LIST="3.5 5.2 6.0 6.1 7.0+PTX 8.0" TORCH_NVCC_FLAGS="-Xfatbin -compress-all" \
    CMAKE_PREFIX_PATH="$(dirname $(which conda))/../" \
    python setup.py install

FROM conda as conda-installs
ARG PYTHON_VERSION=3.8
ARG CUDA_VERSION=11.1
ARG CUDA_CHANNEL=nvidia
ARG INSTALL_CHANNEL=pytorch-nightly
ENV CONDA_OVERRIDE_CUDA=${CUDA_VERSION}
RUN /opt/conda/bin/conda install -c "${INSTALL_CHANNEL}" -c "${CUDA_CHANNEL}" -y python=${PYTHON_VERSION} pytorch torchvision torchtext "cudatoolkit=${CUDA_VERSION}" && \
    /opt/conda/bin/conda clean -ya
RUN /opt/conda/bin/pip install torchelastic

FROM ${BASE_IMAGE} as official
ARG PYTORCH_VERSION
LABEL com.nvidia.volumes.needed="nvidia_driver"
RUN --mount=type=cache,id=apt-final,target=/var/cache/apt \
    apt-get update && apt-get install -y --no-install-recommends \
        ca-certificates \
        libjpeg-dev \
        libpng-dev && \
    rm -rf /var/lib/apt/lists/*
COPY --from=conda-installs /opt/conda /opt/conda
ENV PATH /opt/conda/bin:$PATH
ENV NVIDIA_VISIBLE_DEVICES all
ENV NVIDIA_DRIVER_CAPABILITIES compute,utility
ENV LD_LIBRARY_PATH /usr/local/nvidia/lib:/usr/local/nvidia/lib64
ENV PYTORCH_VERSION ${PYTORCH_VERSION}
WORKDIR /workspace

FROM official as dev
# Should override the already installed version from the official-image stage
COPY --from=build /opt/conda /opt/conda

results matching ""

    No results matching ""