我的Docker之路(一):初识Docker
Docker的热度应该不用多做介绍,已经上升到当代IT人士的必备技能了吧,不了解一点Docker的话就去面试总有点瑟瑟发抖。那就让我们放下浮躁的情绪,好好学习下Docker。本文撰写时Docker已更新到19.03版本。首先,Docker是什么呢,没错Docker是一条可爱的鲸鱼,前戏就到这下面开始正文(严肃脸)。本系列文章主要是针对Docker基础知识及其通过Docker容器化ASP.NET Core程序进行学习与整理。
如果你对Docker还是完全陌生的话,这篇文章可以作为一个很好的入门读物。
Docker是一个开源的应用容器引擎,是基于当下也是比较热门的Go语言实现的,诞生于2013年。
Docker分为CE(Community Edition)版和EE(Enterprise Edition)版,个人用户的话使用CE版完全足够了。
Docker说白了就是一个关于容器的技术。其主要功能是让开发人员可以把应用依赖的环境与应用一起打包到一个轻量级且可移植的容器中,从而解决一直困扰我们的环境问题,开发人员再也不用对测试说那句熟悉的“在我电脑上好好的怎么在你那就不行了呢”。
因为打包的 Docker 应用程序可在任何支持的 Docker 环境上执行。Docker为我们提供了在隔离的容器中打包和运行应用程序的能力,因为各个容器之间是相互隔离的,所以我们可以同时在一台主机上同时运行多个容器。由于这些容器是直接运行在我们主机内核上而不需要额外的虚拟机作负载。如下图展示了使用虚拟机和容器(Container)的区别,虚拟机的模式中,在操作系统之上是一个虚拟机的监控程序(Hypervisor),Hypervisor会为我们虚拟化出硬件资源如CPU、内存等,像是在主机上虚拟出一台台迷你机,随后虚拟机中的系统和软件都跑在这些虚拟的硬件设备上,在这些迷你机中的程序是相互隔离的。而容器模式中,主机的操作系统上运行容器的守护进程来管理和分配容器资源,在容器中包含我们的应用和所需的依赖,而不需要一整个操纵系统的软硬件资源,所以容器是轻量级的。
这是因为这样,和以前使用虚拟机相比,使用Docker可以在一台主机上运行更多的容器。还有一个好处就是,使用容器后我们可以在不同的操作系统下进行更加便捷的部署,开发人员只需进行少量修改甚至无需修改便可以将一套服务部署到不同的环境上。
Docker结构
在学习使用Docker之前要先了解一下它的基本结构和一些专用名词。Docker引擎(Docker Engine)是一个CS结构的应用,下面这张图来自官文。可以看到CS中的S是一个long-running的守护进程(daemon),CS中的C是一个命令行(CLI)工具通过一个REST API接口可以与docker daemon进程来进行通信来控制其工作,来创建和管理其“容器(container)”、“镜像(image)”、“卷(volumes)”和“网络(network)”。
- 镜像(Image):创建容器要用到的所有依赖项和信息的包,容器是由镜像为基础建立的。在网上看的一个类比是这样说的,镜像可以看成一个类,容器就看成由这个类创建出的一个实例,镜像中包含了启动容器的所有内容,或者你可以将镜像看成容器的一个模板。通常一个镜像也是基于其他镜像创建的,这些基础映像都是只读的并且是堆叠在一起,通过“统一文件系统(union files system)”技术将这些多层的结构整合成一个统一的文件系统,这样在外界看来一个容器内只有一个文件系统。
- Dockerfile:就是用来创建镜像的文件。它是Docker镜像的一个描述文件,有点像Windows中的一个批处理脚本文件,通过一条条命令来指定Docker镜像构建的每一个步骤。
- 容器(Container):一个镜像的可运行的实例,可以简单理解为能够独立运行的一组应用。通过Docker客户端CLI,我们就可以创建、运行、停止、移除容器。
- 卷(Volums):因为镜像中的层都是只读的,大部分程序如果要写数据到文件系统里的话容器内得需要一个能保存数据的地方。这便是Volume的作用,Volume通常也叫数据Volume,里面可以存放各种数据,Volume在容器映像顶部添加了一个可写层,这样程序就可以写入数据了。卷位于主机系统中的,如果是使用Windows系统那它就可能保存在某个盘的某个文件夹下,由 Docker 管理。Volume是被持久化的,容器和镜像的删除不会影响Volume的数据。
- 注册中心(Registry):用来管理镜像集合,其实和我们的代码仓库(如GitHub)用来存放我们项目源代码有点像。镜像仓库也分为公有仓库和私有仓库。公有的就如Docker Hub,基本所有官方的标准镜像都可以在Docker Hub上获取到,很便捷。
在了解一些基本概念后应该容易理解官文上关于Docker结构的这张图了。
Windows安装Docker
Docker服务端虽然说是只能在Linux系统下运行,针对Windows系统Docker官方也提供了相应的版本,其解决方案就是利用虚拟机。Windows下官方提供了Docker Desktop供用户使用,无脑安装上就行了。但是是需要Windows10系统的,应该是因为Win10自带了Hyper-V的原因吧。Docker Desktop安装好之后你的电脑就等于安装好了Docker Engine、Docker CLI客户端和Kubernetes在内的全家桶,贴心。运行Docker Desktop之后,在任务栏里会多出一个Docker吉祥物的图标。
在运行控制台输入“docker version”命令,可以看到docker客户端和服务端的对应版本,顺便可以看到服务端是运行在Linux虚拟机中的。
这个Linux虚拟机是运行在Windows10Hyper-V中的,我们打开Hyper-V管理器,便可以看到这个虚拟机已经存在并运行了。
接下来可以运行一个官方提供的测试容器来验证安装的正确性。使用命令行执行“docker run hello-world”,表示根据hello-world这个镜像生成容器并运行,docker发现本地没有便会去Docker Hub上拉取镜像,随后再去生成和运行。当能看到hello-world的输出后表示您的安装已经完全ojbk了。
Docker的一些基本常用命令,可以一一试验下。
命令 | 说明 |
docker --version | 参看docker版本 |
docker search %镜像名% | 搜索镜像 |
docker pull %镜像名% | 从Hub上拉取或者更新镜像 |
docker run %镜像名% | 运行容器,如果本地无指定镜像则会先拉取再生成容器,最后运行容器 |
docker run -d %镜像名% | d : detached, 表示在后台运行容器 |
docker run -i -t %镜像名% | i: interactive, 表示以“交互模式”运行容器,t:tty,为创建容器构件一个伪tty终端 |
docker image ls | 列出从Docker Hub上拉取的镜像信息 |
docker images | 列出本地所有镜像信息 |
docker rmi %参数% docker image rm %参数% |
删除镜像,参数可以是“%镜像名:Tag%”或者“%镜像的ID%” |
docker ps docker container ls |
列出所有正在运行的容器信息 |
docker ps -all docker container ls -all |
列出所有容器信息 |
docker stop %容器名% | 停止运行中的容器 |
docker start %容器名% | 重新开始运行容器 |
docker rm %容器名% | 移除容器 |
docker --help | 获取帮助信息 |
举个例子,使用docker来小试一下Ubuntu系统。先从hub上拉取一个Ubuntu系统的镜像并且运行一个终端。
> docker run -i -t ubuntu bash Unable to find image 'ubuntu:latest' locally latest: Pulling from library/ubuntu d51af753c3d3: Pull complete fc878cd0a91c: Pull complete 6154df8ff988: Pull complete fee5db0ff82f: Pull complete Digest: sha256:747d2dbbaaee995098c9792d99bd333c6783ce56150d1b11e333bbceed5c54d7 Status: Downloaded newer image for ubuntu:latest root@65083fdecd04:/#
接着检查一下主机名,其实这里的主机名被分配成了容器的Id。
root@65083fdecd04:/# hostname 65083fdecd04
使用exit命令退出shell并停止容器的运行。
root@65083fdecd04:/# exit
exit
现在再检查下当前本地的所有容器,就可以看到我们刚刚pull的Ubuntu。
> docker container ls -all CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 65083fdecd04 ubuntu "bash" 9 minutes ago Exited (0) About a minute ago sad_keldysh
初试.NET Core程序
接下来使用巨硬官方提供的.net core示例镜像来尝试下再docker中容器化.net core应用。
通过输入下面的命令来运行官方提供的.net core console程序。
> docker run --rm mcr.microsoft.com/dotnet/core/samples
其中“--rm”表示在容器退出是清理容器的文件系统。在拉取完镜像“mcr.microsoft.com/dotnet/core/samples”后容器被创建并运行起来,在控制台中输出了一个很大的logo。
通过输入以下命令可以在容器中启动示例的ASP.NET Core Web应用程序。
> docker run -it --rm -p 8000:80 --name aspnetcore_sample mcr.microsoft.com/dotnet/core/samples:aspnetapp
其中“-p 8000:80”表示指定端口映射,表示将本机的8000端口映射到容器的80端口。“--name”是为容器指定自定义的名称。在拉取完镜像“mcr.microsoft.com/dotnet/core/samples:aspnetapp”后容器被创建并运行起来,随后由于在本机上映射的端口是8000,那么在浏览器打开“http://localhost:8000”便可以看到在容器中启动的ASP.NET Core项目的网页了。
总结下,本次对Docker的概念和功能有了初步的了解,后续将会对其的具体使用以及在Linux下操作进行一一记录。
参考文献:
[1] 官方文档:https://docs.docker.com/get-started/overview/
[2] 官方文档:https://docs.docker.com/docker-for-windows/
[3] Microsoft关于容器的介绍:https://docs.microsoft.com/en-us/dotnet/architecture/microservices/container-docker-introduction/
[4] Docker Hub:https://hub.docker.com/_/microsoft-dotnet-core-samples
[5] Docker简介:https://juejin.im/post/5b260ec26fb9a00e8e4b031a