对Docker的一些理解

什么是容器?

其实相比“容器”,翻译成“集装箱”会更加贴切,类比一下,如果把容器看作集装箱,那内部运行的进程 / 应用就应该是集装箱里的物品了。
现实里我们如果有一个集装箱的模具和原材料,很容易就能批量生产出多个规格相同的集装箱。从功能角度看,集装箱可以用来打包和隔离物品。不同类型的物品放在不同的集装箱里,这样东西就不会混在一起。
而且,集装箱里的物品在运输过程中不易损坏,具体说就是不管集装箱里装了什么东西,被送到哪里,只要集装箱没破坏,再次开箱时放在里面的东西就是完好无损的。

因此,我们可以这样来理解,容器是这样一种工作模式:轻量、拥有一个模具(镜像),既可以规模生产出多个相同集装箱(运行实例),又可以和外部环境(宿主机)隔离,最终实现对“内容”的打包隔离,方便其运输传送

一句话说明容器是什么:
容器就是提供了一个特殊的隔离环境,它能够让进程只看到这个环境里的有限信息,不能对外界环境施加影响。

更简单粗暴的说就是:容器就是被隔离的进程

容器的好处:
1、隔离进程保证系统安全
对于 Linux 操作系统来说,一个不受任何限制的应用程序是十分危险的。这个进程能够看到系统里所有的文件、所有的进程、所有的网络流量,访问内存里的任何数据,那么恶意程序很容易就会把系统搞瘫痪,正常程序也可能会因为无意的 Bug 导致信息泄漏或者其他安全事故。虽然 Linux 提供了用户权限控制,能够限制进程只访问某些资源,但这个机制还是比较薄弱的,和真正的“隔离”需求相差得很远。
而现在,使用容器技术,我们就可以让应用程序运行在一个有严密防护的“沙盒”(Sandbox)环境之内,就好像是把进程请进了“隔离酒店”,它可以在这个环境里自由活动,但绝不允许“越界”,从而保证了容器外系统的安全。

2、节约资源
容器技术的另一个本领就是为应用程序加上资源隔离,在系统里切分出一部分资源,让它只能使用指定的配额,比如只能使用一个 CPU,只能使用 1GB 内存等等,就好像在隔离酒店里保证一日三餐,但想要吃山珍海味那是不行的。这样就可以避免容器内进程的过度系统消耗,充分利用计算机硬件,让有限的资源能够提供稳定可靠的服务。

所以,虽然进程被“关”在了容器里,损失了一些自由,但却保证了整个系统的安全。而且只要进程遵守隔离规定,不做什么出格的事情,也完全是可以正常运行的。

容器 vs 虚拟机

首先,容器和虚拟机的目的都是隔离资源,保证系统安全,尽量提高资源的利用率。所以说二者的目的是一样的

区别在于二者虚拟的程度不一样,或者说一个重一些,一个轻量级一些,具体如下:

  • 虚拟机是在宿主机系统里完整虚拟化出一套计算机硬件,在里面还能够安装任意的操作系统,这内外两个系统也同样是完全隔离,互不干扰。
    从实现的角度来看,虚拟机虚拟化出来的是硬件,需要在上面再安装一个操作系统后才能够运行应用程序,而硬件虚拟化和操作系统都比较“重”,会消耗大量的 CPU、内存、硬盘等系统资源,但这些消耗其实并没有带来什么价值,属于“重复劳动”和“无用功”,不过好处就是隔离程度非常高,每个虚拟机之间可以做到完全无干扰。

  • 至于容器,它直接利用了下层的计算机硬件和操作系统,因为比虚拟机少了一层,所以自然就会节约 CPU 和内存,显得非常轻量级,能够更高效地利用硬件资源。不过,因为多个容器共用操作系统内核,应用程序的隔离程度就没有虚拟机那么高了。

容器相比于虚拟机最大的优势就是运行效率更高
一个普通的 Ubuntu 虚拟机安装完成之后,体积都是 GB 级别的,启动的时间通常需要几分钟,我们的电脑上同时运行十来个虚拟机可能就是极限了。而一个 Ubuntu 镜像大小则只有几十 MB,启动基本上不超过一秒钟,同时跑上百个容器也毫无问题。
在这里插入图片描述

容器的实现原理

我们知道虚拟机使用的是 Hypervisor(KVM、Xen 等),那么,容器是怎么实现和下层计算机硬件和操作系统交互的呢?为什么它会具有高效轻便的隔离特性呢?

其实奥秘就在于 Linux 操作系统内核之中,为资源隔离提供了三种技术:namespace、cgroup、chroot
虽然这三种技术的初衷并不是为了实现容器,但它们三个结合在一起就会发生奇妙的“化学反应”。

namespace 是 2002 年从 Linux 2.4.19 开始出现的,和编程语言里的 namespace 有点类似,它可以创建出独立的文件系统、主机名、进程号、网络等资源空间,相当于给进程盖了一间小板房,这样就实现了系统全局资源和进程局部资源的隔离。

cgroup 是 2008 年从 Linux 2.6.24 开始出现的,它的全称是 Linux Control Group,用来实现对进程的 CPU、内存等资源的优先级和配额限制,相当于给进程的小板房加了一个天花板。

chroot 的历史则要比前面的 namespace、cgroup 要古老得多,早在 1979 年的 UNIX V7 就已经出现了,它可以更改进程的根目录,也就是限制访问文件系统,相当于给进程的小板房铺上了地砖。

综合运用这三种技术,一个四四方方、具有完善的隔离特性的容器就此出现了,进程就可以搬进这个小房间里隔离生活了

镜像

我们知道,运行一个容器需要先拉取一个“镜像”(image),再从这个“镜像”来启动容器

那么,这个“镜像”到底是什么东西呢?它又和“容器”有什么关系呢?

其实我们在其他场合中也曾经见到过“镜像”这个词,比如最常见的光盘镜像,重装电脑时使用的硬盘镜像,还有虚拟机系统镜像。这些“镜像”都有一些相同点:只读,不允许修改,以标准格式存储了一系列的文件,然后在需要的时候再从中提取出数据运行起来。

容器技术里的镜像也是同样的道理。因为容器是由操作系统动态创建的,那么必然就可以用一种办法把它的初始环境给固化下来,保存成一个静态的文件,相当于是把容器给“拍扁”了,这样就可以非常方便地存放、传输、版本化管理了。
在这里插入图片描述
如果还拿之前的“小板房”来做比喻的话,那么镜像就可以说是一个“样板间”,把运行进程所需要的文件系统、依赖库、环境变量、启动参数等所有信息打包整合到了一起。之后镜像文件无论放在哪里,操作系统都能根据这个“样板间”快速重建容器,应用程序看到的就会是一致的运行环境了。

从功能上来看,镜像和常见的 tar、rpm、deb 等安装包一样,都打包了应用程序,但最大的不同点在于它里面不仅有基本的可执行文件,还有应用运行时的整个系统环境。这就让镜像具有了非常好的跨平台便携性和兼容性,能够让开发者在一个系统上开发(例如 Ubuntu),然后打包成镜像,再去另一个系统上运行(例如 CentOS),完全不需要考虑环境依赖的问题,是一种更高级的应用打包方式。

理解了上面的内容,我们再来看下面的docker命令

docker pull busybox  //获取一个打包了 busybox 应用的镜像,里面固化了 busybox 程序和它所需的完整运行环境。  
docker run busybox echo hello world //提取镜像里的各种信息,运用 namespace、cgroup、chroot 技术创建出隔离环境,然后再运行 busybox 的 echo 命令,输出 hello world 的字符串。

这两个步骤,由于是基于标准的 Linux 系统调用和只读的镜像文件,所以,无论是在哪种操作系统上,或者是使用哪种容器实现技术,都会得到完全一致的结果。

推而广之,任何应用都能够用这种形式打包再分发后运行,这也是无数开发者梦寐以求的“一次编写,到处运行”的至高境界。
所以,所谓的“容器化的应用”,就是指应用程序不再直接和操作系统打交道,而是封装成镜像,再交给容器环境去运行。

容器、镜像、仓库

如下图所示,容器是由镜像实例化而来,这和我们学习的面向对象的概念十分相似,我们可以把镜像看作类把容器看作类实例化后的对象

也可以说镜像是文件, 容器是进程。 即容器中的进程依赖于镜像中的文件, 这里的文件包括进程运行所需要的可执行文件, 依赖软件, 库文件, 配置文件等等…

在这里插入图片描述

Docker 的优点

一致的运行环境:Docker 的镜像提供了除内核外完整的运行时环境,确保了应用运行环境一致性,从而不会再出现“这段代码在我机器上没问题啊”这类问题。

更快速的启动时间:可以做到秒级、甚至毫秒级的启动时间。大大的节约了开发、测试、部署的时间。

隔离性:避免公用的服务器,资源会容易受到其他用户的影响。

弹性伸缩,快速扩展:善于处理集中爆发的服务器使用压力。

迁移方便:可以很轻易的将在一个平台上运行的应用,迁移到另一个平台上,而不用担心运行环境的变化导致应用无法正常运行的情况。

持续交付和部署:使用Docker可以通过定制应用镜像来实现持续集成、持续交付、部署

Docker 的应用场景

不同的公司应用场景不同,大部分公司主要是用于下两个方面:

  • 快速部署
    尤其是集群服务,把各个服务及依赖的环境都打包成一个个镜像,上传镜像到私有仓库中,集群各个节点从私有仓库下拉镜像然后运行即可,不需要再给每个服务器安装 JDK、Nginx 等环境。

  • 同步开发环境和生产环境
    大家都经常遇到过:程序在自己的电脑运行正常,放到服务器上就报错了,这是运行环境不同造成的。
    通过 Docker在本机配置好 Dockerfile 文件后创建镜像,上传镜像库,再从镜像库下载到生产服务器,直接运行,这样就保证了开发和生产环境的一致。

docker基本命令

Docker 关键字:
镜像:images
镜像名:image_name
镜像 id:image_id
容器:container
容器名:con_name
容器 id:con_id

重要命令:

#运行docker服务
service docker start

#查看版本
docker -v

拉取镜像
docker pull mysql:5.7(镜像名:tag)
运行镜像
docker run mysql:5.7
   
 #查看镜像
 docker images

#删除镜像,删除前要关闭镜像运行的容器
docker rmi 镜像名称
删除容器
docker rm 容器名
#强制删除需要加-f,不加-f不能删除正在运行中的容器,非常危险,最好不用
   

查看正在运行的容器
docker ps
 #查看所有容器
 docker ps -a
#启动一个容器
docker run --name con_name images_name  
--name  #设置容器名,基于创建好的容器自定义docker镜像
关闭容器
docker stop 容器名/id
使用 docker start 启动一个已停止的容器

#创建一个容器的同时进入这个容器
docker run -it --name con_name images_name
进入容器
docker exec -it containerName /bin/bash
#-t: 在新容器内指定一个伪终端或终端。
#-i: 允许你对容器内的标准输入 (STDIN) 进行交互。

后台运行
在大部分的场景下,我们希望 docker 的服务是在后台运行的,我们可以过 -d 指定容器的运行模式
docker run -d
后台运行不会进入容器,此时想要进入容器,可以通过以下指令进入:
1、docker attach
2、docker exec:推荐使用,因为此退出容器终端,不会导致容器的停止,而attach会导致容器的停止。


退出容器
    exit
ubantu安装docker
apt install docker-io

   #重新加载配置
    sudo systemctl daemon-reload
    
    #重启docker服务
    sudo systemctl restart docker
    
    #导出镜像
    docker save -o image_name.tar image_name
    
    
把物理机 80 端口映射到容器的80端口
    docker run -d -p 81:80 image_name
    
看容器的端口映射情况
    docker port con_id
    
   
动态查看容器日志
    docker logs -f con_name

   
查看 Docker 网络
docker network ls

创建一个 Docker 网络 mydocker
    docker network create -d bridge \
    --subnet=192.168.0.0/24 \
    --gateway=192.168.0.100 \
    --ip-range=192.168.0.0/24 \
    mydocker


利用刚才创建的网络启动一个容器
    #docker run --network=mydocker --ip=192.168.0.5 -itd --name=con_name -h lb01 image_name

    --network   #指定容器网络
    --ip        #设定容器ip地址
    -h          #给容器设置主机名

查看容器 pid
    docker top con_name
    
运行 Dockerfile 并给 Dockerfile 创建的镜像建立名字
    docker build -t mysql:3.6.34 `pwd`
    
MariaDB 容器启动前需先设置密码方法
    docker run -d -P -e MYSQL_ROOT_PASSWORD=password  img_id
    
Docker 修改镜像名
    docker tag imageid name:tag
    
进入 Docker 容器脚本
cat nsenter.sh 
 
# 导出和导入容器
导出容器
如果要导出本地某个容器,可以使用 docker export 命令。
$ docker export 1e560fca3906 > ubuntu.tar(ubuntu.tar为本地文件)

Docker 与 Kubernetes(K8S)

K8S:是一个用于管理集群环境中的容器化应用程序的开源系统。以正确的方式使用 Kubernetes 可帮助 DevOps 即服务团队自动扩展应用程序并以零停机时间进行更新。

学习 K8S,可以让你管理更复杂更大的容器集群,可以有更多的场景来选择应对复杂的业务逻辑。

参考资料:
极客时间

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值