Docker

------ ## 一:容器 ### 1. 容器介绍 ![](accents\image-202503310001.png) ​ 容器(container)其实是一种沙盒技术。顾名思义,沙盒就是能够像一个集装箱一样,把你的应用"装"起来的技术。这样,应用与应用之间,就因为有了边界而不至于相互干扰;而被装进集装箱的应用,也可以被方便地搬来搬去,这其实是 PaaS 最理想的状态。 ### 2. Docker VS 传统 **部署方式** - 传统的部署模式: 安装(包管理工具或者源码包编译)->配置->运行 - Docker部署模式: 复制->运行 **容器和虚拟机** 1. 容器提供了基于进程的隔离,而虚拟机提供了资源的完全隔离。 2. 虚拟机可能需要一分钟来启动,而容器只需要一秒钟或更短。 3. 容器使用宿主操作系统的内核,而虚拟机使用独立的内核 4. 容器只是一个进程,而虚拟机不是 ![](C:\Users\wxin\Desktop\docker\accents\image-202503310002.png) ​ 容器是应用程序层的抽象,将代码和依赖项打包在一起。多个容器可以在同一台计算机上运行,并与其他容器共享`OS`内核,每个容器在用户空间中作为隔离的进程运行。容器占用的空间少于`VM`,可以处理更多的应用程序,并且需要的`VM`和操作系统更少。 **Docker对服务器端开发/部署带来的变化:** - 实现更轻量级的虚拟化,方便快速部署 - 对于部署来说可以极大的减少部署的时间成本和人力成本 ​ `Docker`支持将应用打包进一个可以移植的容器中,重新定义了应用开发,测试,部署上线的过程,核心理念就是 Build once, Run anywhere 1. 标准化应用发布,`docker`容器包含了运行环境和可执行程序,可以跨平台和主机使用; 2. 节约时间,快速部署和启动,`VM`启动一般是分钟级,`docker`容器启动是秒级; 3. 方便构建基于`SOA`架构或微服务架构的系统,通过服务编排,更好的松耦合; 4. 节约成本,以前一个虚拟机至少需要几个`G`的磁盘空间,`docker`容器可以减少到`MB`级; 5. 方便持续集成,通过与代码进行关联使持续集成非常方便; 6. 可以作为集群系统的轻量主机或节点,在`IaaS`平台上,已经出现了`CaaS`,通过容器替代原来的主机。 ### 3. 云计算服务类型 - 基础设施即服务`IaaS` - 平台即服务`PaaS` - 软件即服务`SaaS` **注意:** **IAAS:**指把IT基础设施作为一种服务通过网络对外提供,并根据用户对资源的实际使用量或占用量进行计费的一种服务模式。 **PaaS:**为开发人员提供了一个框架,使他们可以基于它创建自定义应用程序。所有服务器,存储和网络都可以由企业或第三方提供商进行管理,而开发人员可以负责应用程序的管理。 **SaaS:**提供商为企业搭建信息化所需要的所有网络基础设施及软件、硬件运作平台,并负责所有前期的实施、后期的维护等一系列服务,企业无需购买软硬件、建设机房、招聘IT人员,即可通过互联网使用信息系统。就像打开自来水龙头就能用水一样,企业根据实际需要,向`SaaS`提供商租赁软件服务。 ### 4. Docker 的优势 **交付物标准化** ​ `Docker`是软件工程领域的"标准化"交付组件,最恰到好处的类比是"集装箱";集装箱将零散、不易搬运的大量物品封装成一个整体,集装箱更重要的意义在于它提供了一种通用的封装货物的标准,卡车、火车、货轮、桥吊等运输或搬运工具采用此标准,隧道、桥梁等也采用此标准。以集装箱为中心的标准化设计大大提高了物流体系的运行效率。 注意: ​ 传统的软件交付物包括:应用程序、依赖软件安装包、配置说明文档、安装文档、上线文档等非标准化组件。 ​ `Docker`的标准化交付物称为"镜像",它包含了应用程序及其所依赖的运行环境,大大简化了应用交付的模式。 **一次构建,多次交付** ​ 类似于集装箱的"一次装箱,多次运输",`Docker`镜像可以做到"一次构建,多次交付"。当涉及到应用程序多副本部署或者应用程序迁移时,更能体现`Docker`的价值。 **应用隔离** ​ 集装箱可以有效做到货物之间的隔离,使化学物品和食品可以堆砌在一起运输。`Docker`可以隔离不同应用程序之间的相互影响,但是比虚拟机开销更小。 ​ 总之,容器技术部署速度快,开发、测试更敏捷;提高系统利用率,降低资源成本。 ### 5. Docker 的度量 ​ `Docker`是利用容器来实现的一种轻量级的虚拟技术,从而在保证隔离性的同时达到节省资源的目的。`Docker`的可移植性可以让它一次建立,到处运行。`Docker`的度量可以从以下四个方面进行: 1. **隔离性** - `Docker`采用`libcontainer`作为默认容器,代替了以前的`LXC`。libcontainer的隔离性主要是通过内核的命名空间来实现 的,有`pid`、`net`、`ipc`、`mnt`、`uts`命令空间,将容器的进程、网络、消息、文件系统和主机名进行隔离。 2. **可度量性** - `Docker`主要通过`cgroups`控制组来控制资源的度量和分配。 3. **移植性** - `Docker`利用`AUFS`来实现对容器的快速更新。 - `AUFS`是一种支持将不同目录挂载到同一个虚拟文件系统下的文件系统,支持对每个目录的读写权限管理。`AUFS`具有层的概念,每一次修改都是在已有的只写层进行增量修改,修改的内容将形成新的文件层,不影响原有的层。 4. **安全性** - 安全性可以分为容器内部之间的安全性;容器与托管主机之间的安全性。 - 容器内部之间的安全性主要是通过命名空间和`cgroups`来保证的。 - 容器与托管主机之间的安全性主要是通过内核能力机制的控制,可以防止`Docker`非法入侵托管主机。 **Docker容器使用AUFS作为文件系统,有如下优势** 1. **节省存储空间:**多个容器可以共享同一个基础镜像存储。 2. **快速部署:**如果部署多个来自同一个基础镜像的容器时,可以避免多次复制操作。 3. **升级方便:**升级一个基础镜像即可影响到所有基于它的容器。 4. **增量修改:**可以在不改变基础镜像的同时修改其目录的文件,所有的更高都发生在最上层的写操作层,增加了基础镜像的可共享内容。 ## 二:Docker 核心概念 ### 1. Docker 系统 `Docker`系统有两个程序:`docker`服务端和`docker`客户端 - `Docker`服务端:是一个服务进程,管理着所有的容器 - `Docker`客户端:是`docker`服务端的远程控制器,可以用来控制`docker`的服务端进程 ### 2. Docker 核心组件 - Docker 镜像 - Docker images - Docker 仓库 - Docker registeries - Docker 容器 - Docker containers **容器组成要素** - 命名空间 namespace - 资源限制 cgroups - 文件系统 overlay2(UnionFS) #### 2.1 Docker 仓库 ​ 用来保存镜像,可以理解为代码控制中的代码仓库。同样的,Docker 仓库也有公有和私有的概念。 ​ 公有的 Docker 仓库名字是 Docker Hub **库:registry** - 公有库:Docker-hub Daocloud ali 网易蜂巢 - 私有库:公司内部使用(自己部署) **分类:** - 操作系统名称 centos ubuntu - 应用名称 nginx tomcat mysql **Tag:** - 表示镜像版本 #### 2.2 Docker 镜像 ​ Docker 镜像是 Docker 容器运行时的只读模板,每一个镜像由一系列的层 (layers) 组成。 ​ 每一个镜像都可能依赖于由一个或多个下层的组成的另一个镜像,下层那个镜像是上层镜像的父镜像。 **镜像名称:** ```shell registry/repo:tag ``` **基础镜像** ​ 一个没有任何父镜像的镜像,谓之基础镜像 **镜像ID** ​ 所有镜像都是通过一个 64 位十六进制字符串 (内部是一个 256 bit 的值)来标识的。 为简化使用,前 12 个字符可以组成一个短ID,可以在命令行中使用。短ID还是有一定的碰撞机率,所以服务器总是返回长ID。 **镜像名称** ​ 镜像是`Docker`最核心的技术之一,也是应用发布的标准格式。无论你是用`docker pull image`,或者是在`Dockerfile`里面写`FROM image`,下载镜像应该是`Docker`操作里面最频繁的动作之一。 下面是在本地机器运行`docker images`的输出结果: ```bash [root@docker ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE wxin/centos v1 fe13d78ff413 34 minutes ago 231MB mysql 5.7 5107333e08a8 15 months ago 501MB centos latest 5d0da3dc9764 3 years ago 231MB centos v7 5d0da3dc9764 3 years ago 231MB ``` ​ 常说的`centos`镜像其实不是一个镜像名称,而是代表了一个名为`centos`的`Repository`,同时在这个`Repository`下面有一系列打了`tag`的`Image`,`Image`的标记是一个`GUID`,为了方便也可以通过`Repository:tag`来引用。 ​ 那么`Registry`又是什么呢?`Registry`存储镜像数据,并且提供拉取和上传镜像的功能。 ​ `Registry`中镜像是通过`Repository`来组织的,而每个`Repository`又包含了若干个`Image`。 - `Registry`包含一个或多个`Repository` - `Repository`包含一个或多个`Image` - `Image`用`GUID`表示,有一个或多个`Tag`与之关联 **注意:** ​ 当一个镜像的名称不足以分辨这个镜像所代表的含义时,你可以通过tag将版本信息添加到`run`命令中,以执行特定版本的镜像。 ```bash docker run ubuntu:14.04 ``` #### 2.3 Docker 容器 ​ Docker 容器和文件夹很类似,一个Docker容器包含了所有的某个应用运行所需要的环境。 ​ 每一个 Docker 容器都是从 Docker 镜像创建的。Docker 容器可以运行、开始、停止、移动和删除。 ​ 每一个 Docker 容器都是独立和安全的应用平台,Docker 容器是 Docker 的运行部分。 Docker容器可以使用命令创建: ```bash docker run imagename ``` ​ 它会在所有的镜像层之上增加一个可写层。这个可写层有运行在CPU上的进程,而且有两个不同的状态: - 运行态(Running) - 退出态 (Exited) ​ 这就是Docker容器。当我们使用docker run启动容器,Docker容器就进入运行态,当我们停止Docker容器时,它就进入退出态。当我们有一个正在运行的Docker容器时,从运行态到停止态,我们对它所做的一切变更都会永久地写到容器的文件系统中。要切记,对容器的变更是写入到容器的文件系统的,而不是写入到Docker镜像中的。我们可以用同一个镜像启动多个Docker容器,这些容器启动后都是活动的,彼此还是相互隔离的。我们对其中一个容器所做的变更只会局限于那个容器本身。如果对容器的底层镜像进行修改,那么当前正在运行的容器是不受影响的,不会发生自动更新现象。 ​ 64字符的十六进制的字符串来定义容器ID,它是容器的唯一标识符。容器之间的交互是依靠容器ID识别的,由于容器ID的字符太长,我们通常只需键入容器ID的前4个字符即可。当然,我们还可以使用容器名。 **容器名称** ​ --name= Assign a name to the container ​ --为容器分配一个名字,如果没有指定,会自动分配一个随机名称 ​ --docker run子命令的参数 **容器命名方式** ​ 使用`UUID`长命名`("f78375b1c487e03c9438c729345e54db9d20cfa2ac1fc3494b6eb60872e74778")` ​ 使用`UUID`短命令`("f78375b1c487")` ​ 使用`Name("centos") ` **注意:** - 这个`UUID`标识是由`Docker deamon`生成的 - 如果你在执行`docker run`时没有指定`--name`,那么`deamon`会自动生成一个随机字符串`UUID` - 但是对于一个容器来说有个`name`会非常方便,当你需要连接其它容器时或者类似需要区分其它容器时,使用容器名称可以简化操作。无论容器运行在前台或者后台,这个名字都是有效的 - 如果在使用`Docker`时有自动化的需求,你可以将`containerID`输出到指定的文件中`(PIDfile)`类似于某些应用程序将自身`ID`输出到文件中,方便后续脚本操作 ```bash --cidfile="": Write the container ID to the file ``` ### 3. 命名空间 ​ 命名空间是 Linux 内核一个强大的特性。每个容器都有自己单独的命名空间,运行在其中的应用都像是在独立的操作系统中运行一样。命名空间保证了容器之间彼此互不影响。 1. **`pid`命名空间** 不同用户的进程就是通过`pid`名字空间隔离开的,且不同名字空间中可以有相同`pid`。所有的`LXC`进程在`Docker`中的父进程为`Docker`进程,每个 `LXC`进程具有不同的名字空间。同时由于允许嵌套,因此可以很方便的实现嵌套的`Docker`容器。 2. **`net`命名空间** 有 了`pid`名字空间, 每个名字空间中的`pid`能够相互隔离,但是网络端口还是共享`host`的端口。网络隔离是通过`net`名字空间实现的,每个`net` 名字空间有独立的 网络设备,`IP`地址, 路由表,`/proc/net`目录。这样每个容器的网络就能隔离开来。`Docker`默认采用`veth`的方式,将容器中的虚拟网卡同`host`上的一 个`Docker`网桥`docker0`连接在一起。 3. **`ipc`命名空间** 容器中进程交互还是采用了`Linux`常见的进程间交互方法(`interprocess communication - IPC`),包括信号量、消息队列和共享内存、`socket`、管道等。然而同`VM`不同的是,容器的进程间交互实际上还是`host`上具有相同`pid`名字空间中的进程间交互,因此需要在`IPC`资源申请时加入名字空间信息,每个`IPC`资源有一个唯一的 32 位`id`。 4. **`mnt`命名空间** 类似`change root`,将一个进程放到一个特定的目录执行。`mnt`名字空间允许不同名字空间的进程看到的文件结构不同,这样每个名字空间 中的进程所看到的文件目录就被隔离开了。同`chroot`不同,每个名字空间中的容器在`/proc/mounts`的信息只包含所在名字空间的`mount point`。 5. **`uts`命名空间** `UTS`("UNIX Time-sharing System") 名字空间允许每个容器拥有独立的 `hostname`和`domain name`,使其在网络上可以被视作一个独立的节点而非主机上的一个进程。 6. **`user`命名空间** 每个容器可以有不同的用户和组`id`,也就是说可以在容器内用容器内部的用户执行程序而非主机上的用户。 ## 三:Docker 安装 ### 1. Docker 版本 - **Docker-ce:**是docker公司维护的开源项目,是一个基于moby项目的免费的容器产品 - **Docker-ee:**是docker公司维护的闭源产品,是docker公司的商业产品。 ### 2. Docker 安装 ```bash [root@docker ~]# yum install -y yum-utils [root@docker ~]# yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo [root@docker ~]# yum -y install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin ``` ### 3. 配置docker加速器 **配置DNS** ```bash vim /etc/resolv.conf ; generated by /usr/sbin/dhclient-script nameserver 114.114.114.114. nameserver 8.8.8.8 options edns0 trust-ad search localdomain ``` **配置加速器** ```bash [root@docker ~]# vim /etc/docker/daemon.json { "max-concurrent-downloads": 10, "max-concurrent-uploads": 5, "default-shm-size": "1G", "debug": true, "experimental": false, "registry-mirrors":[ "https://x9r52uz5.mirror.aliyuncs.com", "https://dockerhub.icu", "https://docker.chenby.cn", "https://docker.1panel.live", "https://docker.awsl9527.cn", "https://docker.anyhub.us.kg", "https://dhub.kubesre.xyz" ] } [root@docker ~]# systemctl daemon-reload ``` ### 4. 启动服务 ```bash [root@docker ~]# systemctl start docker [root@docker ~]# systemctl enable docker ``` ### 5. Docker 查看 **查看安装版本** ```bash [root@docker ~]# docker -v Docker version 26.1.4, build 5650f9b ``` **查看docker运行状态** ```bash [root@docker ~]# docker info Client: Docker Engine - Community Version: 26.1.4 Context: default Debug Mode: false Plugins: buildx: Docker Buildx (Docker Inc.) Version: v0.14.1 Path: /usr/libexec/docker/cli-plugins/docker-buildx compose: Docker Compose (Docker Inc.) Version: v2.27.1 Path: /usr/libexec/docker/cli-plugins/docker-compose Server: Containers: 0 Running: 0 Paused: 0 Stopped: 0 Images: 0 Server Version: 26.1.4 Storage Driver: overlay2 Backing Filesystem: xfs Supports d_type: true Using metacopy: false Native Overlay Diff: true userxattr: false Logging Driver: json-file Cgroup Driver: cgroupfs Cgroup Version: 1 Plugins: Volume: local Network: bridge host ipvlan macvlan null overlay Log: awslogs fluentd gcplogs gelf journald json-file local splunk syslog Swarm: inactive Runtimes: io.containerd.runc.v2 runc Default Runtime: runc Init Binary: docker-init containerd version: d2d58213f83a351ca8f528a95fbd145f5654e957 runc version: v1.1.12-0-g51d5e94 init version: de40ad0 Security Options: seccomp Profile: builtin Kernel Version: 3.10.0-1160.el7.x86_64 Operating System: CentOS Linux 7 (Core) OSType: linux Architecture: x86_64 CPUs: 4 Total Memory: 1.934GiB Name: docker ID: 8d6f9241-c1b7-4371-bc14-eaf68f0c3760 Docker Root Dir: /var/lib/docker Debug Mode: true File Descriptors: 25 Goroutines: 43 System Time: 2025-03-31T18:15:55.298009462+08:00 EventsListeners: 0 Experimental: false Insecure Registries: 127.0.0.0/8 Registry Mirrors: https://x9r52uz5.mirror.aliyuncs.com/ https://dockerhub.icu/ https://docker.chenby.cn/ https://docker.1panel.live/ https://docker.awsl9527.cn/ https://docker.anyhub.us.kg/ https://dhub.kubesre.xyz/ Live Restore Enabled: false ```