1.什么是Docker?
Docker是基于Go语言进行开发,基于Linux内核的cgroup,namespace,对进程进行隔离封装,属于操作系统层面的虚拟化技术。由于隔离的进程独立于其他宿主和其他的隔离的进程,所以也被称为容器。
传统虚拟机技术是虚拟出一套硬件后,在其上运行一个完整操作系统,在该系统上再运行所需应用进程;而容器内的应用进程直接运行于宿主的内核,容器内没有自己的内核,而且也没有进行硬件虚拟。
因此容器要比传统虚拟机更为轻便。
2.Docker的优点
-
更高效的利用系统资源
相比传统的虚拟机方式的技术,由于容器不需要进行硬件虚拟以及运行完整操作系统等额外开销,Docker 对系统资源的利用率更高。因此,相比虚拟机技术,一个相同配置的主机,往往可以运行更多数量的应用。 -
更快速的启动时间
传统的虚拟机技术启动应用服务往往需要数分钟,而 Docker 容器应用,由于直接运行于宿主内核,无需启动完整的操作系统,因此可以做到秒级、甚至毫秒级的启动时间。大大的节约了开发、测试、部署的时间。 -
一致的运行环境
开发过程中常见的一个问题就是环境一致性问题,由于开发、测试、生产环境不一致,导致有些bug并未在开发过程中被发现。而Docker的镜像提供了除内核外完整的运行环境,确保了应用的一致性,从而避免了
"这段代码在本地上测试没问题"的情况。 -
持续的交付和部署
对于开发和运维(Devops)来说,最希望的就是一次创建和配置,可以在任意地方正常运行。使用Docker可以通过定制应用镜像来实现持续集成、持续交付、部署。开发人员可以通过Dockerfile来进行镜像构建,
并结合持续集成系统进行集成测试,而运维人员则可以直接在生产环境中快速部署该镜像,甚至结合持续部署系统进行自动部署。 -
更轻松的迁移
由于 Docker 确保了执行环境的一致性,因此用户可以很轻易的将在一个平台上运行的应用,迁移到另一个平台上,而不用担心运行环境的变化导致应用无法正常运行的情况。
首先,先动手下载安装Docker.
3.Docker的基本组成
Docker三大组件:镜像、仓库、容器
1. 镜像
镜像就是一个linux的文件系统(Root FileSystem),这个文件系统包含可以运行在linux内核的程序以及相应的数据。镜像是一个特殊的文件系统,提供容器运行时所需的程序、库、资源、配置等文件,另外还包含了一些为运行时准备的一些配置参数(如匿名卷、环境变量、用户等)。
一般而言, Linux分为两个部分:Linux内核(Linux Kernel)与用户空间,而真正的Linux操作系统,是指Linux内核,我们常用的Ubuntu,Centos等操作系统其实是不同厂商在Linux内核基础上添加自己的软件与工具集(tools)形成的发布版本(Linux Distribution)。
因此,我们也可以把镜像看成是上面所说的用户空间,当Docker通过镜像创建一个容器时,就是将镜像定义好的用户空间作为独立隔离的进程运行在宿主机的Linux内核之上。 另外强调一下镜像的两个特征:
1).镜像是分层(Layer)的:即一个镜像可以多个中间层组成,多个镜像可以共享同一中间层,我们也可以通过在镜像添加多一层来生成一个新的镜像。
2).镜像是只读的(read-only):镜像在构建完成之后,便不可以再修改,而上面我们所说的添加一层构建新的镜像,这中间实际是通过创建一个临时的容器,在容器上增加或删除文件,从而形成新的镜像,因为容器是可以动态改变的。
获取镜像
在安装了Docker之后,我们本地并没有任何镜像,当然我们可以自己构建,不过更方便还是从Docker官方提供的仓库服务Docker Hub上拉取官方或第三方已经构建好的镜像。
要拉取镜像,需要指定Docker Registry的URL和端口号,默认是Docker Hub,另外还需要指定仓库名和标签,仓库名和标签唯一确定一个镜像,而标签是可能省略,如果省略,则默认使用latest作为标签名,而仓库名则由作者名和软件名组成。
拉取镜像如:
$ docker pull centos
这是最简单的官方仓库拉取centos最新镜像的语句
$ docker pull docker.finogeeks.club/swan/kl-account-service:latest
这是从docker.finogeeks.club拉取作者为swan的kl-account-service的最新镜像
查看本地镜像:
$ docker image
镜像的导入与导出:
如果想与别人共享某个镜像,除了从镜像服务仓库中pull镜像和把镜像push到仓库上去之外,其实我们还可以将本地构建好的镜像直接导出并保存为文件发送给别人,如下:
$ docker image save -o /tmp/test_image.tar.gz centos:latest
而当你拿到别人导出的镜像文件,你可以使用docker load命令把镜像加载到本地的Docker镜像列表中,如下:
$ docker load < /tmp/test_image.tar.gz
创建镜像
上面的例子都是直接使用官方提供的镜像,其实,除了从官方仓库或其他镜像仓库拉取别人构建好的镜像外,我们也可以构建自己的镜像,一般有以下两种构建方式。
1).使用docker commit命令,我们可以将修改过的容器重新提交为一个镜像,使用这种方式构建的镜像,我们称为黑箱镜像
2).使用Dockerfile构建镜像,一般推荐编写Dockerfile来构建一种镜像,Docker Hub上的镜像都是采用这种方式构建的
使用Dockerfile构建镜像:
编写一个简单的go程序:
package main
import "fmt"
func main(){
fmt.Println("Hello Go")
}
将Go程序编译为可执行程序,如:
$ go build hello.go
编写Dockerfile文件:
# 从一个空白的镜像开始
FROM stratch
ADD hello /
# 执行
CMD /hello
注:在linux上执行下面语句新建Dockerfile文件,然后打开编辑:
# touch Dockerfile
# sudo vim Dockerfile
编写好Dockerfile文件后,构建镜像,需要使用docker build命令进行构建,docker build命令的格式如下:
$ docker build -t "hello-go:1.0" .
注意最后的点(.)表示当前目录,即Dockerfile所在的目录
2. 容器
容器与镜像的关系,就像面向对象编程里面的对象与类之间的关系。因为容器是基于镜像构建的,必须先有镜像才能构建容器,而生成的容器是一个独立于宿主机的隔离进程,并且有属于容器自己的网络和命名空间。镜像由多个中间层(layer)组成,生成的镜像是只读的,但容器却是可读可写的,这是因为容器是在镜像上面添一层读写层(writer/read layer)来实现的,如下图所示:
启动容器
启动容器有几种不同的方式,最常用的方法是使用docker run命令可以通过镜像创建一个容器,如:
$ docker run -p 80:80 nginx
这个容器是一种提供服务的守护进程,开放端口80供外部访问
也可以为容器指定一个名称,如:
$ docker run -p 80:80 --name webserver nginx
另外一种则是使用docker start命令重新启动已经停止运行的容器,如(container_id表示容器的id):
$ docker start container_id
Docker 通过 run 命令来启动一个新容器。Docker 首先在本机中寻找该镜像,如果没有安装,Docker 在 Docker Hub 上查找该镜像并下载安装到本机,最后 Docker 创建一个新的容器并启动该程序,如图:
但是,当第二次执行 docker run 时,因为 Docker 在本机中已经安装该镜像,所以 Docker 会直接创建一个新的容器并启动该程序:
查看本地容器列表:
$ docker ps
上面的命令只会显示正在运行的容器,如果要显示全部容器,包含退出执行的,可以加参数-a
停止容器:
$ docker stop container_id1,container_id2...
3.仓库
仓库(Repository)是集中存储镜像的地方,公共仓库一般是指Docker Hub,前面我们已经多次介绍如何从Docker Hub获取镜像,除了获取镜像外,我们也可以将自己构建的镜像存放到Docker Hub,这样,别人也可以使用我们构建的镜像。不过要将镜像上传到Docker Hub,必须先在Docker的官方网站上注册一个账号。
私有仓库
有时候自己部门内部有一些镜像要共享时,如果直接导出镜像拿给别人又比较麻烦,使用像Docker Hub这样的公共仓库又不是很方便,这时候我们可以自己搭建属于自己的私有仓库服务,用于存储和分布我们的镜像。
一般公司使用的都是私有仓库,例如搭建Harbor私有仓库使用。