1)旧版本的卸载,由于现在linux系统都默认安装docker,且都是旧版本,以防万一,所以应当先卸载。
$ sudo apt-get remove docker docker.io docker-engine
2)准备工作
添加https传输包和2ca证书。
$ sudo apt-get update
$ sudo apt-get install \
apt-transport-https \
ca-certificates \
curl \
software-properties-common
为了确认所下载软件包的合法性,需要添加软件源的 GPG
密钥。
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
向 source.list
中添加 Docker 软件源
$ sudo add-apt-repository \
"deb [arch=amd64] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) \
stable"
这里需要注意的是,如果软件源添加错误,会报错 "the list of sources could not be read" ,这时我们需要在管理员权限下进入 /etc/apt/source.list 文件里,将我们上面添加的代码改正即可。
3)安装docker
$ sudo apt-get update
$ sudo apt-get install docker-c
我们都知道,操作系统分为内核和用户空间。对于 Linux 而言,内核启动后,会挂载 root
文件系统为其提供用户空间支持。而 Docker 镜像(Image),就相当于是一个 root
文件系统。比如官方镜像 ubuntu:16.04
就包含了完整的一套 Ubuntu 16.04 最小系统的 root
文件系统。
Docker 镜像是一个特殊的文件系统,除了提供容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数(如匿名卷、环境变量、用户等)。镜像不包含任何动态数据,其内容在构建之后也不会被改变
1)docker镜像的分层存储。
因为镜像包含操作系统完整的 root
文件系统,其体积往往是庞大的,因此在 Docker 设计时,就充分利用 Union FS 的技术,将其设计为分层存储的架构。所以严格来说,镜像并非是像一个 ISO 那样的打包文件,镜像只是一个虚拟的概念,其实际体现并非由一个文件组成,而是由一组文件系统组成,或者说,由多层文件系统联合组成。
镜像构建时,会一层层构建,前一层是后一层的基础。每一层构建完就不会再发生改变,后一层上的任何改变只发生在自己这一层。比如,删除前一层文件的操作,实际不是真的删除前一层的文件,而是仅在当前层标记为该文件已删除。在最终容器运行的时候,虽然不会看到这个文件,但是实际上该文件会一直跟随镜像。因此,在构建镜像的时候,需要额外小心,每一层尽量只包含该层需要添加的东西,任何额外的东西应该在该层构建结束前清理掉。
分层存储的特征还使得镜像的复用、定制变的更为容易。甚至可以用之前构建好的镜像作为基础层,然后进一步添加新的层,以定制自己所需的内容,构建新的镜像。
2)获取镜像。
标准的获取命令如下
$ sudo docker pull [选项] [Docker Registry 地址[:端口号]/]仓库名[:标签]
而对于学习来说,可以直接使用默认的官方仓库获取,就可以得到我们所需要的,例如获取ubuntu:16.04的镜像。
$ sudo docker pull ubuntu:16.04
使用命令查看获取的镜像
$ sudo docker image ls
可以看到和下面类似的内容
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx v3 7403d95c9c1c About an hour ago 109MB
ubuntu 16.04 7aa3602ab41e 5 days ago 115MB
nginx latest c82521676580 7 days ago 109MB
hello-world latest 2cb0d9787c4d 3 weeks ago 1.85kB
sdhibit/rpi-raspbian latest 07410247bde8 3 years ago 121MB
3)删除镜像。
$ sudo docker rmi <镜像名或id>
4)生成自己的镜像。
多数情况下,官方的标准镜像并不符合我们实际学习和开发需求,这时我们需要自己定制一些镜像。
定制镜像有两种方法。
i)使用commit生成镜像。
$ sudo docker pull jsurf/rpi-raspbian
拉去镜像jsurf/rpi-raspbian。这是一个linux操作系统的镜像。
$ sudo docker run -it jsurf/rpi-raspbian /bin/bash
这里参数 -it 其实是两个参数。-i 和 -t,分别是指交互式运行的终端运行。后面/bin/bash指明应用程序。
然后在终端里安装vim
apt-get install vim
安装完成后直接 exit 退出终端。
执行命令
$ sudo docker commit -author "作者名" -message "add vim" jsurf/rpi-raspbian my/raspbian:v2
在该命令里注意-message、-author 标签,-message 后面是备注,-author 后面是提交的作者。jsurf/rpi-raspbian是要从那个镜像提交,my是新的名字,v2是标签。
然后输入
$ sudo docker image ls
就可以看到自己的镜像啦。
ii)使用 Dockerfile 定制镜像
Dockerfile 是一个文本文件,其内包含了一条条的指令(Instruction),每一条指令构建一层,因此每一条指令的内容,就是描述该层应当如何构建。
以上面定制镜像为例。
首先需要创建一个目录和Dockerfile文件。
$ sudo mkdir raspbian
$ sudo touch Dockerfile
$ vim Dockerfile
在文件中写入以下内容。
# This is a comment
FROM fsurf/rpi-raspbian
RUN apt-get install vim
FROM 表示从那个镜像仓库
然后执行脚本。
$ sudo docker build -t my/raspbian:v3 .
-t 表示是新镜像用户,raspbian是基于那个镜像,v3 对新镜像打个 tag,点(.)表示 Dockerfile 是当前目录。
使用 docker commit
命令虽然可以比较直观的帮助理解镜像分层存储的概念,但是实际环境中并不会这样使用。
首先,如果仔细观察之前的 docker diff webserver
的结果,你会发现除了真正想要修改的 /usr/share/nginx/html/index.html
文件外,由于命令的执行,还有很多文件被改动或添加了。这还仅仅是最简单的操作,如果是安装软件包、编译构建,那会有大量的无关内容被添加进来,如果不小心清理,将会导致镜像极为臃肿。
此外,使用 docker commit
意味着所有对镜像的操作都是黑箱操作,生成的镜像也被称为黑箱镜像,换句话说,就是除了制作镜像的人知道执行过什么命令、怎么生成的镜像,别人根本无从得知。而且,即使是这个制作镜像的人,过一段时间后也无法记清具体在操作的。虽然 docker diff
或许可以告诉得到一些线索,但是远远不到可以确保生成一致镜像的地步。这种黑箱镜像的维护工作是非常痛苦的。
而且,回顾之前提及的镜像所使用的分层存储的概念,除当前层外,之前的每一层都是不会发生改变的,换句话说,任何修改的结果仅仅是在当前层进行标记、添加、修改,而不会改动上一层。如果使用 docker commit
制作镜像,以及后期修改的话,每一次修改都会让镜像更加臃肿一次,所删除的上一层的东西并不会丢失,会一直如影随形的跟着这个镜像,即使根本无法访问到。这会让镜像更加臃肿。
5)删除镜像。
如果要删除本地的镜像,可以使用 docker image rm
命令,其格式为:
$ docker image rm [选项] <镜像1> [<镜像2> ...]
参考书籍:《Docker从入门到实践》