作者 | 天元浪子
来源 | CSDN博客
想要真正理解Docker,就不得不从虚拟化技术的发展历程说起。普遍认为虚拟化技术经历了物理机时代、虚拟机时代,目前已经进入到了容器化时代。可以说,Docker是虚拟化技术不断发展的必然结果。
那么,什么是容器呢?容器和虚拟机有什么不同?Docker和容器又是什么关系呢?搞明白这几个问题,Docker的概念就清晰了。
11 虚拟机和容器
借助于VMWare等软件,可以在一台计算机上创建多个虚拟机,每个虚拟机都拥有独立的 *** 作系统,可以各自独立的运行程序。这种分身术虽然隔离度高( *** 作系统级),使用方便(类似物理机),但占用存储资源多(GB级)、启动速度慢(分钟级)的缺点也是显而易见的。
相较于虚拟机,容器(Container)是一种轻量型的虚拟化技术,它虚拟的是最简运行环境(类似于沙盒)而非 *** 作系统,启动速度快(秒级)、占用存储资源少(KB级或MB级),容器间隔离度为进程级。在一台计算机上可以运行上千个容器,这是容器技术对虚拟机的碾压式优势。
12 容器、镜像和Docker
Docker是一个开源的应用容器引擎,可以创建容器以及基于容器运行的程序。Docker可以让开发者打包他们的应用和依赖包到一个轻量级、可移植的容器中,然后发布到任何流行的Linux机器上,也可以实现虚拟化。
听起来很简单,但是在Docker和容器之间,还隐藏着一个镜像的概念,令初学者颇感困惑。本质上,Docker镜像是一个特殊的文件系统,它提供容器运行时所需的程序、库、资源、配置等文件。Docker镜像类似于一个py文件,它需要Docker的运行时(类似于Python解释器)运行。镜像被运行时,即创建了一个镜像的实例,一个实例就是一个容器。
13 Docker 和 k8s
作为容器引擎,Docker为容器化的应用程序提供了开放的标准,使得开发者可以用管理应用程序的方式来管理基础架构,实现快速交付、测试和部署代码。随着容器的大量使用,又产生了如何协调、调度和管理容器的问题,Docker的容器编排应运而生。
k8s是Google开源的一个容器编排引擎,它支持自动化部署、大规模可伸缩、应用容器化管理,是一个开源的,用于管理云平台中多个主机上的容器化的应用,k8s的目标是让部署容器化的应用简单并且高效,k8s提供了应用部署、规划、更新、维护的一种机制。
Docker和k8sr都是以containerd(容器化标准)作为运行时,因此使用Docker创建的镜像完全可以在k8s中无障碍的使用。
21 在ubuntu中安装
在linux系统中安装Docker非常简单,官方为我们提供了一键安装脚本。这个方法也适用于Debian或CentOS等发行版。
安装过程如果出现超时,不要灰心,多试几次,总会成功的。安装完成后,Docker只能被root用户使用,可以使用下面的命令取消权限限制:
然后,重启docker服务:
最后,关闭当前的命令行,重新打开新的命令行就可以了。
顺便提一下,如果在CentOS下安装,可能会出现一堆类似于下面的错误:
这是由于docker和Podman冲突造成的,需要先卸载Podman:
22 在Win10中安装
Docker的运行,依赖linux的环境,官方提供了Docker Desktop for Windows,但是它需要安装Hyper-V,Hyper-V是微软开发的虚拟机,类似于 VMWare 或 VirtualBox,仅适用于 Windows 10。这个虚拟机一旦启用,QEMU、VirtualBox 或 VMWare Workstation 15 及以下版本将无法使用!如果你必须在电脑上使用其他虚拟机(例如开发 Android 应用必须使用的模拟器),请不要使用 Hyper-V!
我的电脑是win10家庭版,不能直接安装hyper-v,需要将下面的命令保存到cmd文件中:
然后在cmd文件上点击右键,选择使用管理员运行。执行完毕后会重启,在重启的过程中进行安装。
23 Hello world
docker服务启动的情况下,运行下面的命令:
此命令的含义是:
第一次运行时,因为本地没有ubuntu:2004镜像,docker会自动从镜像服务器下载。下载过程可能需要多试几次,只要成功一次,以后执行就不再需要下载了。
docker官方还提供了一个hello-world镜像,可以直接运行:
此命令省略了镜像版本和运行参数,docker使用latest作为版本,即最新版本。
从hello world的例子中,也可以体验到,docker实例的运行是非常快的。
docker官方的镜像库比较慢,在进行镜像 *** 作之前,需要将镜像源设置为国内的站点。
新建文件/etc/docker/daemonjson,输入如下内容:
然后重启docker的服务:
31 列出本地所有镜像
执行命令 docker images 可以查看
当前我本地只有刚才安装的两个镜像。
32 从镜像库中查找镜像
执行命令 docker search 镜像名称可以从docker镜像库中查找镜像。
最好选择官方(OFFICIAL)的镜像,这样的镜像最稳定一些。
33 下载新的镜像
执行命令docker pull 镜像名称:版本号即可下载新的镜像。
镜像下载后,就可以使用镜像来创建容器了。
41 启动容器
执行命令docker run即可启动容器,也就是创建某个镜像的实例。docker run命令非常复杂,可以先执行一个docker run --help来查看帮助:
比如我们要执行python的shell,需要添加-it参数,即:docker run -it python:38
42 将宿主机的文件挂载到容器
docker容器与宿主机是隔离的,要想让容器内的程序能访问宿主机上的文件,需要通过-v参数将宿主机的文件挂载到容器中。
比如我们在宿主机上有一个hellopy,可以打印hello,想要在python容器中执行,就需要进行挂载。-v后还需要接两个参数,分别是宿主机的目录和容器内的目录,两者使用:分隔,路径必须都是绝对路径。
我的hellopy保存在主目录的/docker_test目录中,将这个目录挂载到容器的/docker_test目录,然后在容器内执行python /docker_test/hellopy:
43 容器的端口映射
我们修改一下hellopy,创建一个socket服务端,并监听5000端口,当有客户端连接时,打印客户端的地址,先客户端发送hello,然后关闭连接:
在容器内执行:
接下来,尝试用telnet命令连接,结果却是失败的。原因是,127001是宿主机的ip地址,5000是容器的端口,这与我们的习惯稍微有些不同。事实上,docker的容器是非常轻量的,它并没有自己的网络,要想访问容器的端口,需要进行端口映射,将容器的某端口映射到宿主机的端口,客户端连接时,只要与宿主机的端口进行连接就可以了。
需要注意的是,上面的代码创建的服务器,无论如何也不可能被客户端连接,因为代码中绑定了127001的ip,在容器中运行时,需要绑定所有ip,即0000。
然后,再使用-p参数,-p还需要三个参数,即宿主机的ip地址、宿主机的端口、容器的端口,三者之间使用:分隔。一般的,可以将宿主机的ip地址省略,只写宿主机的端口:容器的端口即可。
这样,就将容器的5000端口映射到了宿主机的5001端口,使用:
即可与容器中的服务器进行连接。
44 容器管理
上面的服务运行之后,可以使用docker ps命令,查看运行中的容器:
显示的内容有下面几列:
要想结束容器,可以使用docker kill 容器ID命令。
一般而言,当我们的程序开发完成后,会连同程序文件与运行环境一起制作成一个新的镜像。
要制作镜像,需要编写Dockerfile。DockeFile由多个命令组成,常用的命令有:
注意,Docker镜像中有一个层的概念,每执行一个RUN命令,就会创建一个层,层过多会导致镜像文件体积增大。尽量在RUN命令中使用&&连接多条shell命令,减少RUN命令的个数,可以有效减小镜像文件的体积。
51 自制显示文本文件内容镜像
编写catpy,接收一个文件名,由python读取文件并显示文件的内容:
这个例子比较简单,缩写Dockerfile如下:
这个Dockerfile的含义是:
需要说明的是,ENTRYPOINT有两种写法:
这里采用第二种写法,是因为我们要在外部给容器传递参数。执行命令编译Docker镜像:
这个命令中,-t的含义是目标,即生成的镜像名为hello,版本号为10,别忘了最后那个,这叫到上下文路径,是指 docker 在构建镜像,有时候想要使用到本机的文件(比如复制),docker build 命令得知这个路径后,会将路径下的所有内容打包。
这样,我们的第一个镜像就制作完成了,使用下面的命令执行它:
即可看到~/docker_test/cat/files/testtxt的内容。
52 自制web服务器镜像
我们使用tornado开发一个网站,而python的官方镜像是没有tornado库的,这就需要在制作镜像时进行安装。
测试的wspy如下:
编写Dockerfile文件如下:
在此我们验证一下CMD与ENTRYPOINT的区别。在Dockerfile所在有目录下执行如下命令:
执行完成后,再使用docker images使用就可以看到生成的镜像了,然后使用下面的命令运行:
在浏览器中输入宿主机的ip和8000端口,就可以看到页面了。
在这个例子中,我使用的运行命令是CMD,如果在docker run中指定的其他的命令,此命令就不会被执行,如:
此时,容器中被执行的是python命令,而不是我们的服务。在更多情况下,我们希望在docker run命令中为我们的服务传参,而不是覆盖执行命令,那么,我们应该使用ENTRYPOINT而不是CMD:
上面这种写法,是不支持传递参数的,ENTRYPOINT和CMD还支持另一种写法:
使用这种写法,docker run命令中的参数才可以传递给hellopy:
这个命令中,--port=9000被作为参数传递到hellopy中,因此容器内的端口就成了9000。
在生产环境中运行时,不会使用-it选项,而是使用-d选项,让容器在后台运行:
这种方式下,即使当前的控制台被关闭,该容器也不会停止。
53 自制apscheduler服务镜像
接下来,制作一个使用apscheduler编写的服务镜像,代码如下:
Dockerfile也是信手拈来:
生成镜像:
应该可以运行了,文件复制需要两个目录,在运行时,可以使用两次-v来挂载不同的目录:
前面用到的官方python镜像大小足足882MB,在这个基础上,再安装用到的第三方库,添加项目需要的等资源,大小很容易就超过1个G,这么大的镜像,网络传给客户非常的不方便,因此,减小镜像的体积是非常必要的工作。
docker hub上有个一python:38-alpine镜像,大小只有445MB。之所以小,是因为alpine是一个采用了busybox架构的 *** 作系统,一般用于嵌入式应用。我尝试使用这个镜像,发现安装一般的库还好,但如果想安装numpy等就会困难重重,甚至网上都找不到解决方案。
还是很回到基本的路线上来,主流的 *** 作系统镜像,ubuntu的大小为729MB,centos的大小为209MB——这也算是我更喜欢使用ubuntu的一个重要原因吧!使用ubuntu作为基础镜像,安装python后的大小为139MB,再安装pip后的大小一下子上升到了407MB,要是再安装点其他东西,很容易就赶上或超过python官方镜像的大小了。
看来,寻常路线是很难压缩镜像文件体积了。幸好,还有一条曲线救国的路可走,这就是多阶段构建法。
多阶段构建的思想其实很简单,先构建一个大而全的镜像,然后只把镜像中有用的部分拿出来,放在一个新的镜像里。在我们的场景下,pip只在构建镜像的过程中需要,而对运行我们的程序却一点用处也没有。我们只需要安装pip,再用pip安装第三方库,然后将第三方库从这个镜像中复制到一个只有python,没有pip的镜像中,这样,pip占用的268MB空间就可以被节省出来了。
1、在ubuntu镜像的基础上安装python:
然后运行:
这样,就生成了python:38-ubuntu镜像。
2、在python:38-ubuntu的基础上安装pip:
然后运行:
这样,就生成了python:38-ubuntu-pip镜像。
3、多阶段构建目标镜像:
这个dockerfile需要解释一下了,因为它有两个FROM命令。
第一个是以python:38-ubuntu-pip镜像为基础,安装numpy,当然,在实际应用中,把所有用到的第三方库出写在这里。
第二个FROM是以FROM python:38-ubuntu镜像为基础,将第三方库统统复制过来,COPY命令后的–from=0的意思是从第0阶段进行复制。实际应用中再从上下文中复制程序代码,添加需要的ENTRYPOINT等。
最后,再运行:
这然,用于我们项目的镜像就做好了。比使用官方python镜像构建的版本,小了大约750MB。
到此,我们的镜像已经制作好了,可是,镜像文件在哪,如何在生产环境下运行呢?
刚才使用docker images命令时,已经看到了生成的镜像:
我们可以使用docker save命令将镜像保存到指定的文件中,保存的文件是一个tar格式的压缩文件:
将hellotar复制到生产环境的机器上,然后执行导入命令:
就可以使用了。
回答之前,先反问一个问题:为什么不用Docker呢?
Docker出现之前,有现在还在用的VMWare虚拟机,有Ghost,部分解决了服务器安装配置的琐碎工作,但是没有解决运行环境的问题。比如常见的环境不一致的问题:开发环境能运行,测试生产环境有bug?还有就是每次新服务器、新环境搭建时无穷无尽的问题。
那么Docker出现后,整个环境被打包起来,也就是将所有安装配置代码化自动化了,结合资源编排和云服务,可以秒启一个集群化的web服务系统,如果没有容器技术是做不到的。Docker是使用最普遍的容器技术,事实上的容器技术标准。
推荐看一个Docker秒启Web服务的视频:>
下载镜像,安装环境 我们先执行如下命令,启动虚拟机: $ boot2docker start 2014/08/18 21:22:41 Waiting for VM to be started 2014/08/18 21:23:21 Started 2014/08/18 21:23:21 Docker client does not run on Windows for
Docker 提供了一个可以运行你的应用程序的封套(envelope),或者说容器。它原本是 dotCloud 启动的一个业余项目,并在前些时候开源了。它吸引了大量的关注和讨论,导致 dotCloud 把它重命名到 Docker Inc。它最初是用 Go 语言编写的,它就相当于是加在 LXC(LinuX Containers,linux 容器)上的管道,允许开发者在更高层次的概念上工作。
Docker 扩展了 Linux 容器(Linux Containers),或着说 LXC,通过一个高层次的 API 为进程单独提供了一个轻量级的虚拟环境。Docker 利用了 LXC, cgroups 和 Linux 自己的内核。和传统的虚拟机不同的是,一个 Docker 容器并不包含一个单独的 *** 作系统,而是基于已有的基础设施中 *** 作系统提供的功能来运行的。这里有一个 Stackoverflow 的答案,里面非常详细清晰地描述了所有 Docker 不同于纯粹的 LXC 的功能特性
Docker 会像一个可移植的容器引擎那样工作。它把应用程序及所有程序的依赖环境打包到一个虚拟容器中,这个虚拟容器可以运行在任何一种 Linux 服务器上。这大大地提高了程序运行的灵活性和可移植性,无论需不需要许可、是在公共云还是私密云、是不是裸机环境等等。
Docker 由下面这些组成:
1 Docker 服务器守护程序(server daemon),用于管理所有的容器。
2 Docker 命令行客户端,用于控制服务器守护程序。
3 Docker 镜像:查找和浏览 docker 容器镜像。
软件开发最大的麻烦事之一,就是环境配置。举例来说,安装一个 Python 应用,计算机必须有 Python 引擎,还必须有各种依赖,可能还要配置环境变量。而且换一台机器,就要重来一次。Docker可以解决这个问题
Docker 属于 Linux 容器的一种封装,提供简单易用的容器使用接口。它是目前最流行的 Linux 容器解决方案。容器是进程级别的,相比虚拟机有很多优势:(1)启动快;(2)资源占用少(3)体积小。
Docker 将应用程序与该程序的依赖,打包在一个文件里面。运行这个文件,就会生成一个虚拟容器。程序在这个虚拟容器里运行,就好像在真实的物理机上运行一样。有了 Docker,就不用担心环境问题。
本小节介绍如何制作 image 文件,以及 docker 的一些高级用法
主要是编写 Dockerfile 文件,此外用dockerignore文件排除不想打包的文件。Dockerfile 文件它是一个文本文件,用来配置 image。Docker 根据 该文件生成二进制的 image 文件。
然后执行 docker image build -t 容器名称 即可构建一个 image
微服务很适合用 Docker 容器实现,每个容器承载一个服务。一台计算机同时运行多个容器,从而就能很轻松地模拟出复杂的微服务架构。如何管理这多个容器呢,即一行命令同时启动或关闭多个容器。Docker Compose可以做到。你需要定义一个 YAML 格式的配置文件 docker-composeyml ,写好多个容器之间的调用关系。
docker-compose up // 启动
docker-compose stop // 关闭以后,这两个容器文件还是存在的,写在里面的数据不会丢失。下次启动的时候,还可以复用。
docker-compose rm // 把这两个容器文件删除
以下两种玩儿发都需要配置国内镜像代理,否则速度极慢,代理配置参考注 >
以上就是关于超值一篇分享,Docker:从入门到实战过程全记录全部的内容,包括:超值一篇分享,Docker:从入门到实战过程全记录、项目为什么用docker、如何将docker image 打包等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)