Docker学习笔记——入门

背景

在运行mythril的时候,第一次接触到了docker,由于当时的重心在于运行并改造Mythril,因此,我与docker的交互只存在于一句run命令。现在在运行Fabric的时候,docker又一次出现在了我的面前,其作用域也不仅仅在一句run命令了。从安装到运行,再到以后我也不知道会发生什么事情的地方,docker所扮演的角色越来越重要。我觉得有必要好好学习一下docker了。

什么是docker

Docker0.1开源与2013年,是一门年轻但是潜力无限的技术。

使用Go开发实现的,基于Linux内核的,对进程进行封装隔离的,属于操作系统层面的虚拟化技术。由于隔离的进程独立于宿主和其他进程,因此称其为容器。但是Docker不是容器。Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的 Linux 机器上。

Docker和传统虚拟化技术

传统虚拟化技术,比如VMware是在虚拟出一套硬件之后,再在上面运行一个OS,然后再在这个OS上运行程序。

Docker没有进行硬件虚拟,进程直接运行在宿主的内核之中。

上图是Docker和虚拟机的比较,可由此推出为什么要用Docker。

三大概念

  • 镜像image

应用的运行需要一个环境,镜像就是来提供这个环境的。比如,一个镜像可以完全包含了Ubuntu操作系统环境。镜像是只读的,包含了文件系统。

镜像的构建不是堆一起的,而是分层构建。上层以下层为基础,逐步搭建起来,每一层都是只读层。

  • 容器container

Docker利用容器来隔离和运行程序,容器从镜像创建的应用运行实例,镜像虽然是只读的,但是在创建容器时会在上面建立一个可写层,镜像依然不变。可以理解为镜像就是我们装系统用的ISO文件,而容器就是我们正在用的系统,已经被我们装上了各种各样的软件。

容器可以被创建、启动、停止、删除和暂停。其实质就是一个进程,只是和宿主的进程不一样,运行在自己的namespace之中,使得自己拥有自己的root文件系统、网络配置、进程空间之类的。

PS:容器的存储层的生命依赖于容器,容器亡则存储亡,因此通常用Volume(数据卷)或者绑定宿主目录直接对宿主发生读写。Volume的生命独立于容器。

  • 仓库repository

仓库用来存放镜像的仓库,有一个Registry(注册服务器),是用来存放多个仓库的。通常一个仓库会包含一个软件的不同版本,标签则对应相应的版本,因此我们用<仓库名>:<标签>来指定哪个版本。

我的理解是,一个公司就是一个注册服务器,它有多少种产品就有多少个仓库,每个仓库都是这个产品的不同版本。

镜像的使用:

  • 获取镜像

命令为:

docker pull [选项] [Docker Registry 地址[:端口号]/]仓库名[:标签]

镜像是由多层存储所构成。下载也是一层层的去下载,并非单一文件。下载过程中给出了每一层的ID的前12位。并且下载结束后,给出该镜像完整的sha256的摘要,以确保下载一致性。由于官方镜像一直在维护,解决BUG,因此隔一段时间之后,在下载内容可能会得到不一样的ID和sha256值。

  • 列出镜像:

docker image ls

列表包含了仓库名、标签、镜像ID、创建时间以及所占用的空间。

  • 镜像体积

Docker Hub中的体积大小是压缩后的值,而我们pull之后的值是解压之后的值。但是这些显示的大小是真的占据我们磁盘空间的大小吗?NO。别忘了我们的镜像是分层的,也就是说,如果两个镜像有相同的某个分层的话,那么这些层是只需要下载一份就可以了。下面的命令可以看到真实大小。

docker system df

  • 删除本地镜像

docker image rm [选项] <镜像1> [<镜像2> ...]

Untagger 和 Deleted

删除镜像实际是删除标签,因为一个镜像可能有多个标签。我们删去了这个标签后,依然可能有其它标签指向这个镜像。此时只有untagged发生。当一个镜像没有标签指着的时候,就可能(注意是可能)会出现deleted。由于镜像是分层结构,所以删除的时候是从上向下删除,但是上层依赖于下层,当有上层依赖于该层时,虽然该层没有标签了,但依然可以存在。还有就是如果这个镜像的容器存在,即使没有启动也无法删除,因为有个读写层存在使得下层不会出现变化。

 

自己造镜像太繁琐了,DockerFile可不是入门级别的东西,放在以后再说吧,下面来谈谈怎么玩容器吧。

容器的使用

  • 启动容器

启动容器有两种方式,1.基于镜像新建一个容器;2.将存在但是停止的容器启动。为什么有俩方式呢?都怪这个Docker太轻量了,把大家惯坏了,现在的人都养成了用完就删的习惯,现用现造,快的过分。新建并启动命令就是:

docker run 指定镜像 命令

其操作如下:

  1. 检查本地有没有指定的镜像,没有就从公有仓库下载
  2. 利用镜像创建一个容器
  3. 分配文件系统,在镜像外面挂一个读写层
  4. 从宿主主机配置的网桥接口中桥接一个虚拟接口到容器中去
  5. 从地址池配置一个ip地址给容器
  6. 执行用户指定的应用程序
  7. 执行完毕后容器被终止

 

  • 启动已终止容器的命令:

docker container start

  • 终止容器:

docker container stop

除了上面的命令,当容器中指定的程序跑完了,该容器也会终止。

终止状态的容器可以用  docker container ls -a  命令看到。

此外, docker container restart  命令会将一个运行态的容器终止,然后再重新启动它。

  • 进入容器

docker exec(推荐)和docker attach

  • 导出容器

docker export 7691a814370e > ubuntu.tar这样将导出容器快照到本地文件。

  • 导入容器

可以使用  docker import  从容器快照文件中再导入为镜像

  • 删除容器

docker container rm

如果这个容器还在运行,可以在后面加 -f。

  • 清理终止状态的容器

docker container prune

 

Docker的数据

前面说了,容器删了,数据就没了,因此用数据卷或者绑定本地目录的方式来保存数据。下面就开始介绍一下这俩。

  • 数据卷(Volumes)

这是一个可以供多个容器使用的目录,读写它不会对镜像产生影响,而且它独立于容器,不会因为容器的删除而删除。

创建数据卷

docker volume create my-vol

查看所有数据卷

docker volume ls

查看数据卷的信息

docker volume inspect my-vol

删除数据卷

docker volume rm my-vol

  • 绑定主机目录(Bind Mount)

--mount 可以指定挂载一个本地主机的目录到容器之中。

docker run -d -P \
--name web \
--mount type=bind,source=/src/webapp,target=/opt/webapp \
training/webapp \
python app.py

挂载的默认权限是读写,可以加readonly来使之只读。

docker run -d -P \
--name web \
--mount type=bind,source=/src/webapp,target=/opt/webapp,readonly \
training/webapp \
python app.py

参考:

http://www.runoob.com/docker/docker-architecture.html

https://www.cnblogs.com/SzeCheng/p/6822905.html

https://blog.csdn.net/bskfnvjtlyzmv867/article/details/81044217

https://www.jianshu.com/p/2c832c1b8fd5

《Docker 入门白皮书》

《Docker——从入门到实践》

猜你喜欢

转载自blog.csdn.net/z695516174/article/details/86560287
今日推荐