Docker 学习笔记 I

越来越无法忍受目前用的几台服务器各种软件配置都不一致,无法做到随时无障碍切换,于是决定学点Docker。

什么是docker

Docker 在容器的基础上,进行了进一步的封装,从文件系统、网络互联到进程隔离等等,极大的简化了容器的创建和维护

  • 传统虚拟化
Docker 学习笔记 I_第1张图片
img

虚拟出一套硬件后,在其上运行一个完整操作系统,在该系统上再运行所需应用进程

  • docker
Docker 学习笔记 I_第2张图片
img

容器内的应用进程直接运行于宿主的内核,容器内没有自己的内核,而且也没有进行硬件虚拟

Docker 的优势

  • 解决一致性问题
    • 开发过程中一个常见的问题是环境一致性问题。由于开发环境、测试环境、生产环境不一致,导致有些 bug 并未在开发过程中被发现。
    • 而 Docker 的镜像提供了除内核外完整的运行时环境,确保了应用运行环境一致性,从而不会再出现 「这段代码在我机器上没问题啊」 这类问题。
  • 维护和扩展
  • 迁移方便
  • 快速启动

理解Docker

镜像

  • 操作系统分为内核和用户空间
  • 对于 Linux 而言,内核启动后,会挂载 root 文件系统为其提供用户空间支持
  • Docker 镜像(Image),就相当于是一个 root 文件系统
  • 除了提供容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数(如匿名卷、环境变量、用户等)
  • 镜像不包含任何动态数据,其内容在构建之后也不会被改变

分层存储

  • 因为镜像包含操作系统完整的 root 文件系统,其体积往往是庞大的,因此在 Docker 设计时,就充分利用 Union FS 的技术,将其设计为分层存储的架构
  • 镜像并非是像一个 ISO 那样的打包文件,镜像只是一个虚拟的概念,其实际体现并非由一个文件组成,而是由一组文件系统组成,或者说,由多层文件系统联合组成
  • 镜像构建时,会一层层构建,前一层是后一层的基础。每一层构建完就不会再发生改变,后一层上的任何改变只发生在自己这一层
  • 删除前一层文件的操作,实际不是真的删除前一层的文件,而是仅在当前层标记为该文件已删除

Docker 容器

  • 镜像(Image)和容器(Container)的关系,就像是面向对象程序设计中的类和实例一样,镜像是静态的定义,容器是镜像运行时的实体。
  • 每一个容器运行时,是以镜像为基础层,在其上创建一个当前容器的存储层,我们可以称这个为容器运行时读写而准备的存储层为容器存储层。
  • 容器存储层的生存周期和容器一样,容器消亡时,容器存储层也随之消亡。因此,任何保存于容器存储层的信息都会随容器删除而丢失。
  • 容器不应该向其存储层内写入任何数据,容器存储层要保持无状态化。所有的文件写入操作,都应该使用 数据卷(Volume)、或者绑定宿主目录,在这些位置的读写会跳过容器存储层,直接对宿主(或网络存储)发生读写,其性能和稳定性更高。
  • 数据卷的生存周期独立于容器,容器消亡,数据卷不会消亡。因此,使用数据卷后,容器可以随意删除、重新 run,数据却不会丢失。

仓库 Docker Registry

  • 一个 Docker Registry 中可以包含多个仓库(Repository);每个仓库可以包含多个标签(Tag);每个标签对应一个镜像。
  • 通常,一个仓库会包含同一个软件不同版本的镜像,而标签就常用于对应该软件的各个版本。我们可以通过 <仓库名>:<标签> 的格式来指定具体是这个软件哪个版本的镜像。如果不给出标签,将以 latest 作为默认标签。
  • 仓库名经常以 两段式路径 形式出现,比如 jwilder/nginx-proxy,前者往往意味着 Docker Registry 多用户环境下的用户名,后者则往往是对应的软件名。

在虚拟机上安装Docker

虚拟机版本

  • uname -r : 4.10.0-30-generic
  • sudo lsb_release -a : Description:Ubuntu 17.04

安装Docker

  • sudo apt install docker. io

  • service docker start

  • sudo docker run hello-world

  • 出现如下内容

Docker 学习笔记 I_第3张图片
img

查看docker版本号

  • docker -v:Docker version 1.12.6, build 78d1802

镜像加速器(被坑以后才发现的问题)

在国内下载很多镜像往往会有龟速现象发生,这里使用官方提供的加速器 registry mirror。

  • The URL of the registry mirror for China is registry.docker-cn.com
  • 将此镜像设置为默认
    • 新建文件/etc/docker/daemon.json
    • 输入内容{ "registry-mirrors": ["[https://registry.docker-cn.com](https://registry.docker-cn.com/)"] }

使用Docker安装第一个软件

从 Docker Registry 获取镜像的命令是 docker pull

  • 命令格式 docker pull [选项] [Docker Registry地址]<仓库名>:<标签>
  • 地址格式:<域名/IP>[:端口号] 默认地址是 Docker Hub
  • 仓库名:两段式名称,既<用户名>/<软件名>

具体事例:sudo docker pull biocontainers/blast

  • 用户名是biocontainers 。如果这里没有用户名,会从官方library中进行下载

  • 出现如下的界面

Docker 学习笔记 I_第4张图片
img

从下载过程中可以看到我们之前提及的分层存储的概念,镜像是由多层存储所构成。下载也是一层层的去下载,并非单一文件。

下载过程中给出了每一层的 ID 的前 12 位。并且下载结束后,给出该镜像完整的 sha256 的摘要,以确保下载一致性。

下载完成时显示的内容

Docker 学习笔记 I_第5张图片
img

运行第一个docker程序

  • 镜像安装成功后,以这个镜像为基础启动一个容器来运行
  • docker run 是运行容器的命令
  • 默认情况下,为了排障需求,退出的容器并不会立即删除,除非手动 docker rm。我们这里只是随便执行个命令,看看结果,不需要排障和保留结果,因此使用 --rm 可以避免浪费空间。
  • sudo docker run biocontainers/blast blastp -help
  • 删除容器 docker rm

列出镜像

  • 命令 docker images
img
  • 列表包含了仓库名、标签、镜像 ID、创建时间以及所占用的空间

  • 之前安装的biocontainers/blast 占用了接近2个G的空间

删除本地镜像

  • docker rmi [选项] <镜像1> [<镜像2> ...]

    • <镜像> 可以是 镜像短 ID、镜像长 ID、镜像名 或者 镜像摘要
    • docker images 默认列出的就已经是短 ID
  • 实例 sudo docker rmi b2b

报错Error response from daemon: conflict: unable to delete b2b81d1fe174 (must be forced) - image is being used by stopped container 9bf4b361545d

原因是没有删除容器,所以无法删除镜像

  • 首先查看运行的容器有哪些:
    sudo docker ps -a -q

  • 然后删除相关的容器:
    sudo docker rm

  • 最后再删除镜像

    sudo dokcker rmi

删除流程如下图所示

Docker 学习笔记 I_第6张图片
img
  • 镜像的唯一标识是其 ID 和摘要,而一个镜像可以有多个标签
  • 删除镜像的时候,实际上是在要求删除某个标签的镜像。所以首先需要做的是将满足我们要求的所有镜像标签都取消(untagged)
  • 并非所有的 docker rmi都会产生删除镜像的行为,有可能仅仅是取消了某个标签而已。
  • 当该镜像所有的标签都被取消了,该镜像很可能会失去了存在的意义,因此会触发删除行为。
  • 镜像是多层存储结构,因此在删除的时候也是从上层向基础层方向依次进行判断删除。镜像的多层结构让镜像复用变动非常容易,因此很有可能某个其它镜像正依赖于当前镜像的某一层。这种情况,依旧不会触发删除该层的行为。

用户权限设置

  • 默认情况下,Docker命令的运行需要根用户权限。一个解决办法是把用户加入docker用户组
  • Docker能够将/run/docker.sock的文件权限设为660、用户组设为docker。当把用户加入到docker用户组后,就无需使用sudo命令切换获取根用户权限。
sudo groupadd docker
sudo gpasswd -a ${USER} docker
sudo service docker restart
newgrp - docker # 切换用户组
newgrp - `groups ${USER} | cut -d' ' -f1`

参考资料

  • https://yeasy.gitbooks.io/docker_practice/
  • http://www.runoob.com/docker/docker-hello-world.html

加入靠谱熊基地,和大家一起交流

你可能感兴趣的:(Docker 学习笔记 I)