Docker 学习笔记 I
越来越无法忍受目前用的几台服务器各种软件配置都不一致,无法做到随时无障碍切换,于是决定学点Docker。
什么是docker
Docker 在容器的基础上,进行了进一步的封装,从文件系统、网络互联到进程隔离等等,极大的简化了容器的创建和维护
- 传统虚拟化
虚拟出一套硬件后,在其上运行一个完整操作系统,在该系统上再运行所需应用进程
- docker
容器内的应用进程直接运行于宿主的内核,容器内没有自己的内核,而且也没有进行硬件虚拟
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版本号
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中进行下载
-
出现如下的界面
从下载过程中可以看到我们之前提及的分层存储的概念,镜像是由多层存储所构成。下载也是一层层的去下载,并非单一文件。
下载过程中给出了每一层的 ID 的前 12 位。并且下载结束后,给出该镜像完整的 sha256 的摘要,以确保下载一致性。
下载完成时显示的内容
img运行第一个docker程序
- 镜像安装成功后,以这个镜像为基础启动一个容器来运行
-
docker run
是运行容器的命令 - 默认情况下,为了排障需求,退出的容器并不会立即删除,除非手动 docker rm。我们这里只是随便执行个命令,看看结果,不需要排障和保留结果,因此使用 --rm 可以避免浪费空间。
sudo docker run biocontainers/blast blastp -help
- 删除容器
docker rm
列出镜像
- 命令
docker images
-
列表包含了仓库名、标签、镜像 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
删除流程如下图所示
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`
参考资料
加入靠谱熊基地,和大家一起交流