docker/docker-基础.md
2025-04-04 17:31:23 +08:00

18 KiB
Raw Blame History

Docker


一:容器

1. 容器介绍

容器(container)其实是一种沙盒技术。顾名思义,沙盒就是能够像一个集装箱一样,把你的应用"装"起来的技术。这样,应用与应用之间,就因为有了边界而不至于相互干扰;而被装进集装箱的应用,也可以被方便地搬来搬去,这其实是 PaaS 最理想的状态。

2. Docker VS 传统

部署方式

  • 传统的部署模式: 安装(包管理工具或者源码包编译)->配置->运行
  • Docker部署模式 复制->运行

容器和虚拟机

  1. 容器提供了基于进程的隔离,而虚拟机提供了资源的完全隔离。

  2. 虚拟机可能需要一分钟来启动,而容器只需要一秒钟或更短。

  3. 容器使用宿主操作系统的内核,而虚拟机使用独立的内核

  4. 容器只是一个进程,而虚拟机不是

容器是应用程序层的抽象,将代码和依赖项打包在一起。多个容器可以在同一台计算机上运行,并与其他容器共享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的隔离性主要是通过内核的命名空间来实现 的,有pidnetipcmntuts命令空间,将容器的进程、网络、消息、文件系统和主机名进行隔离。
  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) 组成。

每一个镜像都可能依赖于由一个或多个下层的组成的另一个镜像,下层那个镜像是上层镜像的父镜像。

镜像名称:

registry/repo:tag

基础镜像

一个没有任何父镜像的镜像,谓之基础镜像

镜像ID

所有镜像都是通过一个 64 位十六进制字符串 (内部是一个 256 bit 的值)来标识的。 为简化使用,前 12 个字符可以组成一个短ID可以在命令行中使用。短ID还是有一定的碰撞机率所以服务器总是返回长ID。

镜像名称

镜像是Docker最核心的技术之一,也是应用发布的标准格式。无论你是用docker pull image,或者是在Dockerfile里面写FROM image,下载镜像应该是Docker操作里面最频繁的动作之一。

下面是在本地机器运行docker images的输出结果:

[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镜像其实不是一个镜像名称,而是代表了一个名为centosRepository,同时在这个Repository下面有一系列打了tagImageImage的标记是一个GUID,为了方便也可以通过Repository:tag来引用。

那么Registry又是什么呢?Registry存储镜像数据,并且提供拉取和上传镜像的功能。

Registry中镜像是通过Repository来组织的,而每个Repository又包含了若干个Image

  • Registry包含一个或多个Repository
  • Repository包含一个或多个Image
  • ImageGUID表示,有一个或多个Tag与之关联

注意:

当一个镜像的名称不足以分辨这个镜像所代表的含义时你可以通过tag将版本信息添加到run命令中,以执行特定版本的镜像。

docker run ubuntu:14.04

2.3 Docker 容器

Docker 容器和文件夹很类似一个Docker容器包含了所有的某个应用运行所需要的环境。

每一个 Docker 容器都是从 Docker 镜像创建的。Docker 容器可以运行、开始、停止、移动和删除。

每一个 Docker 容器都是独立和安全的应用平台Docker 容器是 Docker 的运行部分。

Docker容器可以使用命令创建

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输出到文件中,方便后续脚本操作
--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") 名字空间允许每个容器拥有独立的 hostnamedomain name,使其在网络上可以被视作一个独立的节点而非主机上的一个进程。

  6. user命名空间

    每个容器可以有不同的用户和组id,也就是说可以在容器内用容器内部的用户执行程序而非主机上的用户。

Docker 安装

1. Docker 版本

  • **Docker-ce**是docker公司维护的开源项目是一个基于moby项目的免费的容器产品
  • **Docker-ee**是docker公司维护的闭源产品是docker公司的商业产品。

2. Docker 安装

[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

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

配置加速器

[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. 启动服务

[root@docker ~]# systemctl start docker
[root@docker ~]# systemctl enable docker

5. Docker 查看

查看安装版本

[root@docker ~]# docker -v
Docker version 26.1.4, build 5650f9b

查看docker运行状态

[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