本文大部分参考《docekr入门,这一篇就够了》

docekr背景介绍

什么是docekr

Docker是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可抑制的容器中,然后发布到任何流行的Linux机器上,也可以实现虚拟化。容器完全使用沙盒机制,相互之间不会存在任何接口。几乎没有性能开销,可以很容易的在机器和数据中心运行。最重要的是,他们不依赖于任何语言、框架或者包装系统。

小知识:沙盒也叫沙箱(sandbox)。在计算机领域指一种虚拟技术,而且多用于计算机安全技术。安全软件可以让它在沙盒中运行,如果含有恶意行为,则禁止程序的进一步运行,而这不会对系统造成任何危害。
官网https://www.docker.com/

Docker容器技术与虚拟机的区别

Docker 容器技术和虚拟机(VM)都是实现资源隔离和环境一致性的技术,但它们的底层实现和特性有显著区别,主要体现在架构、性能、启动速度等方面。以下是两者的核心区别:

1. 架构原理

  • 虚拟机(VM)
    基于硬件虚拟化,需要在宿主机(Host)上安装Hypervisor(如 VMware、KVM),每个虚拟机都包含完整的操作系统(Guest OS)、应用程序及必要的库。
    虚拟机通过 Hypervisor 模拟硬件资源(CPU、内存、硬盘等),与宿主机完全隔离,相当于一个独立的 “物理机”。

  • Docker 容器
    基于操作系统级虚拟化,不需要 Hypervisor,而是直接使用宿主机的操作系统内核。
    容器仅包含应用程序及其依赖的库(如 Python、Java 环境),共享宿主机的 OS 内核,通过Namespace(隔离进程、网络等)和Cgroups(限制资源)实现隔离。

2. 资源占用

  • 虚拟机
    每个 VM 需要分配独立的 CPU、内存、磁盘等资源,且包含完整 OS,资源占用高(通常 GB 级)。

  • Docker 容器
    共享宿主机内核,仅占用应用程序本身的资源,资源占用极低(通常 MB 级),可在同一台宿主机上运行成百上千个容器。

3. 启动速度

  • 虚拟机
    启动需经历 BIOS、OS 加载等完整流程,通常需要分钟级(如 1-5 分钟)。

  • Docker 容器
    无需启动操作系统,直接运行应用进程,启动速度为秒级甚至毫秒级(如 1-3 秒)。

4. 隔离性

  • 虚拟机
    隔离性极强,VM 之间、VM 与宿主机之间完全独立,一个 VM 的崩溃或安全问题不会影响其他 VM。

  • Docker 容器
    隔离性较弱,共享宿主机内核,若内核存在漏洞,可能影响所有容器。但通过 Namespace 和 Cgroups,可实现进程、网络、文件系统的隔离,满足大部分场景需求。

5. 移植性

  • 虚拟机
    镜像体积大(通常 GB 级),移植和分发较慢,且受 Hypervisor 类型限制(如 VMware 镜像无法直接在 KVM 上运行)。

  • Docker 容器
    镜像体积小(通常 MB 级),移植性极强,“一次构建,到处运行”,只要宿主机安装 Docker,即可运行相同的容器(不受底层 OS 发行版影响,如 Ubuntu 和 CentOS 上可运行同一容器)。

6. 适用场景

  • 虚拟机
    • 需运行不同操作系统(如 Windows 和 Linux 同时运行)。
    • 对隔离性和安全性要求极高(如金融、医疗等领域)。
    • 运行需要完整 OS 支持的复杂应用。
  • Docker 容器
    • 微服务架构(将应用拆分为多个独立容器)。
    • 持续集成 / 持续部署(CI/CD),快速构建、测试、部署。
    • 资源密集型场景(如高并发 Web 服务),高效利用硬件资源。

总结对比表

特性 虚拟机(VM) Docker 容器
核心技术 硬件虚拟化(Hypervisor) 操作系统级虚拟化(Namespace/Cgroups)
资源占用 高(GB 级) 低(MB 级)
启动速度 分钟级 秒级 / 毫秒级
隔离性 极强 较强(共享内核)
镜像体积
移植性 较差(受 Hypervisor 限制) 极强(跨平台兼容)
适用场景 强隔离需求、多 OS 运行 微服务、CI/CD、高效资源利用

docker相较于VM的优点

  1. 比VM小、快,Docker容器的尺寸减小相比于整个虚拟机大大简化了分布到云和分发时间的开销。Docker启动一个容器实例时间仅仅需要几秒钟。
  2. Docker是一个开放的平台,构建、发布和运行分布式应用程序。
  3. 开发人员不需要关系具体是哪个Linux操作系统
  4. Google、微软(azure)、亚马逊、IBM等都支持docker。
  5. Docker支持Unix/Linux操作系统,也支持Windows和Mac。

Docker局限性

Docker用于应用程序时是最有用的,但并不包含数据、日志、数据库等通常放在Docker容器外。一个容器的镜像通常都很小,不用和存储大量数据,存储可以通过外部挂载等方式使用,比如:NFS、ipsan、MFS等 ,或者docker命令 ,-v映射磁盘分区
总之,docker只用于计算,存储交给别人。

通过docker架构图初步了解docker


工作流程:

  1. 启动docker
  2. 下载镜像到本地
  3. 启动docker容器实例

==Docker核心技术:==

  1. Namespace —> 实现Container的进程、网络、消息、文件系统和主机名的隔离。
  2. Cgroup —> 实现对资源的配额和调度。
    注意:Cgroup的配额,可以指定实例使用的CPU个数,内存大小等。

Docker特性

文件系统隔离:每个进程容器运行在一个完全独立的根文件系统里。
资源隔离:系统资源,像CPU和内存等可以分配到不同的容器中,使用cgroup。
网络隔离:每个进程容器运行在自己的网路空间,虚拟接口和IP地址。
日志记录:Docker将收集到和记录的每个进程容器的标准流(stdout/stderr/stdin),用于实时检索或者批量检索
变更管理:容器文件系统的变更可以提交到新的镜像中,并可重复使用以创建更多的容器。无需使用模板或者手动配置。
交互式shell:Docker可以分配一个虚拟终端并且关联到任何容器的标准输出上,例如运行一个一次性交互shell。

Docker的安装

docekr安装背景

docker安装的三种方式,基于CentOS

1
2
3
4
5
6
yum -y install docker

yum -y install docker-engine

yum -y install docker-ce

因为Docker最早的版本名是docker和docker-engin,现在的名字是docker-ce和docker-ee。
官方安装文档https://docs.docker.com/engine/install/centos/

2017年初,docker公司将原先的docker开源项目改名为moby。
moby是集成了原先的docker项目,是社区维护的开源项目,谁都可以在moby的基础打造自己的容器产品。
docker-ce 是docker公司维护的开源项目,是一个基于moby项目的免费容器产品。
docker-ee 是docker公司维护的闭源产品,是docker公司的商业昌平。
注:moby是源代码,docker-ce 和docker-ee 是产品容器,rpm包。

安装docker依赖环境

1
yum install -y yum-utils device-mapper-persistent-data lvm2

配置国内docker-ce的yum源(这里采用的是阿里云)

1
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

yum-config-manager命令作用是添加yum源。
敲完命令之后大家执行一下命令去看一下有没有配置成功。

1
2
cd /etc/yum.repos.d
ls

安装docker

1
yum -y install docker-ce doker-ce-cli containerd.io

安装速度可能会比较慢,请耐心等待。
docker-ce:docker程序
docker-ce-cli:
如果不知道包名的作用,可以使用yum info 程序 命令查看

开启网络转发功能

默认会自动开启。
路径 :==/proc/sys/net/ipv4/ip_forward==
手动开启:

1
2
3
4
5
vim /etc/sysctl.conf   #插入以下内容
net.ipv4.forward =1
-------------------------
sysctl -p #生效
cat /proc/sys/net/ipv4/ip_forward #查看结果,为1开启成功。

如果没有开启网络转发,我们启动实例的时候就会报错!!!

关闭防火墙:

1
2
3
4
5
6
7
8
iptables -nL #查看一下iptable规则,关闭防火墙后会自动插入新规则

systemctl stop firewalld && systemctl disable firewalld #关闭防火墙

sysctlrem restart docker # 关闭防火墙要把docker重启一下,不然docker
的ip包转发功能无法使用。即便防火墙关闭了,docker依旧会调用内核模块netfilter增加规则,所以会新增iptables规则

iptables -nL #再查看一下iptable规则,会发现多出很多规则

iptables -nL

启动服务

1
systemctl start docker && systemctl enable docker

启动完成后会该网络参数,这个是ip转发会改成1。默认0

1
cat /proc/sys/net/ipv4/ip_forward

执行以上指令会显示1

查看docekr版本

1
docekr version


这里我们很清晰的可以看到docker是一个C/S架构的模式。客户端是我们的命令行操作,服务端是一个守护进程。

查看docekr信息

1
docker info

我们可以通过==docker info==看到机器存放docker镜像得地址,也可以看到docker仓库的地址。

docker入门命令

搜索镜像

docker search

1
docker search centos #从docker hub中搜索docker名为centos的镜像


name:代表此镜像的名称
description:此镜像的描述
stars:下载次数
official:是否由官方提供(官方提供可放心下载,可以基于此镜像做自己的镜像)

拉取镜像

==docker pull== ,默认是拉去docker hub上搜索到的最新版本(第一个)。

1
docker pull centos

注意,如果这里报错,TLS handshake timeout,那就是网络原因导致超时,尝试多pull几次。下面介绍配置镜像加速
==使用阿里云docker镜像加速器。==

地址:https://cr.console.aliyun.com的控制台,使用支付宝账号登录,左侧加速器帮助页面会为你显示独立的加速地址,这个加速地址每个人的都不同。


可以通过修改daemon配置文件/etc/docker/daemon.json来使用加速器。
把自己的专属加速地址放到下面的地址改一下,写入文件就可以了。

1
2
3
4
5
6
{
"registry-mirrors": ["https://eu5rxjvf.mirror.aliyuncs.com"]
}

systemctl daemon-reload #启动配置
systemctl restart docker #重启docker服务

查看镜像

1
docker images  #查看已下载镜像。

压缩包tar镜像导入镜像

1
docker load -i /root/docker-centos-httpd.tar

docker命令小结

帮助命令

1
2
3
docker version     #显示docker详细信息
docker info #显示docker的系统信息,包括镜像和容器的数量
docker --help #docker帮助命令手册

镜像命令

1
2
3
4
5
6
7
8
9
10
11
12
docker images  #查看所有本地主机的镜像
docker search 镜像名 #搜索镜像
docker pull 镜像名 [标签] #下载镜像(如果不写tag,默认是latest)
docker rmi 镜像名 [标签] #删除镜像 docker rmi -f $(docker images -aq) 删除全部镜像
docker tag 镜像名:版本 新镜像名:版本 #复制镜像并且修改名称
docker commit -a "xxx" -c "xxx" 镜像ID 名字:版本 #提交镜像
-a :提交的镜像作者;
-c :使用Dockerfile指令来创建镜像;
-m :提交时的说明文字;

docker load -i /xxx/xxx.tar #导入镜像
docker save -o /xxx/xxx.tar #保存一个镜像为一个tar包

容器命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
docker run [可选参数] image 命令 #启动容器(无镜像会先下载镜像)
#参数说明
--name = "Name" 容器名字
-c 后面跟待完成的命令
-d 以后台方式运行并且返回ID,启动守护进程式容器
-i 使用交互方式运行容器,通常与t同时使用
-t 为容器重新分配一个伪输入终端。也即启动交互式容器
-p 指定容器端口 -p 容器端口:物理机端口 映射端口
-P 随机指定端口
-v 给容器挂载存储卷

docker build #创建镜像 -f:指定dockerfile文件路径 -t:镜像名字以及标签
docker logs 容器实例的ID #查看容器日志
docker rename 旧名字 新名字 # 给容器重新命名
docker top 容器实例的ID #查看容器内进程
docker ps -a #列出所有容器(不加-a就是在运行的)
docker rm 容器实例的ID #删除容器(正在运行容器不能删除,除非加-f选项)
docker kill 容器实例的ID #杀掉容器
docker history 容器实例的ID #查看docker镜像的变更历史
docker start 容器实例的ID #启动容器
docker restart 容器实例的ID #重启容器
docker stop 容器实例的ID #停止正在运行的容器
docker attach /docker exec 容器实例的ID #同为进入容器命令,不同的是attach连接终止会让容器退出后台运行,而exec不会。并且,docker attach是进入正在执行的终端,不会情动新的进程,而docker exec则会开启一个新的终端,可以在里面操作。
docker image inspect 容器名称:容器标签 #查看容器内源数据
docker cp 容器id:容器内路径 目的主机路径 #从容器内拷贝文件到主机(常用)或者从主机拷贝到容器(一般用挂载)
exit #直接退出容器
crlt + P + Q #退出容器但是不终止运行

Docker容器数据卷

容器数据卷介绍。

docker容器在产生数据的时候,如果不通过docker commit生成新的镜像,使得数据作为镜像的一部分保存下来,那么当容器删除之后,数据自然而然的也会消失。为了能保存数据,容器中引用了数据卷的概念。

作用以及特点

卷就是目录或者文件,存在一个或者多个容器之中,由docker挂载到容器,但是不属于联合文件系统,因此能够绕过Union File System提供一些用于持续存储或者共享数据的特性。

卷的设计目的就是数据的持久化完全独立于容器的生存周期,因此docker不会再容器删除时删除其挂载的数据卷。

它还存在以下几种特点:

  1. 数据卷可在容器之间共享或者重用数据。
  2. 卷中的更改可以直接生效。
  3. 数据卷中的更改不会包含在镜像的更新中。
  4. 数据卷的生命周期一直持续到没有容器使用它为止。

使用数据卷

直接使用命令来挂载 , -v

1
docker run -it -v 主机目录:容器目录 /bin/bash

我们在创建容器之前,先看看挂载路径上有没有test01这个目录,可以看到,是没有的。执行命令之后进入到容器内,我们ls看一下容器的home目录,是空的。

1
docker run -it -v /home/test01:/home centos /bin/bash


另外打开一个终端,cd /home目录,这下我们发现多出来了一个test01目录,这个test01目录,就是我们刚刚启动的容器内部的home目录,并且,此时这两个目录是同步的状态,我们在home目录中写入任何新的文件,都会同步到主机home目录下的test01目录。
|500

测试,进入容器内部,echo进去一个a.txt文件

然后来到宿主机上,看一眼是不是test01目录下也出现了a.txt。(双向绑定)

docker inspect 容器ID查看是否挂载成功,找到这个==Mounts==,它代表着挂载,type是类型(绑定),source是源(/home/test01),也就是把什么挂载到哪里。destination(home)就是挂载的目标路径了。

docekr的匿名挂载和具名挂载

匿名挂载(Anonymous Volume)

  • 特点:只指定容器内的挂载路径,不指定宿主机的路径或卷名,Docker 会自动生成一个随机的卷名。
  • 作用:临时或简单场景下使用,无需关心数据在宿主机的具体存储位置,由 Docker 自动管理。
  • 示例
    1
    2
    # 格式:docker run -v 容器内路径 ...
    docker run -d -v /app/data --name mycontainer nginx
    此时 Docker 会创建一个随机名称的卷(如abcd1234...),并将容器内的/app/data目录与该卷关联。

具名挂载(Named Volume)

  • 特点:为数据卷指定一个自定义名称,便于管理和复用,同样不需要指定宿主机的具体路径(路径由 Docker 管理)。
  • 作用:需要多次使用同一数据卷(如多个容器共享数据),或需要显式管理卷(如备份、删除)时使用。
  • 示例
    1
    2
    # 格式:docker run -v 卷名:容器内路径 ...
    docker run -d -v mydata:/app/data --name mycontainer nginx
    这里创建了名为mydata的卷,容器内/app/data的数据会存储在该卷中,后续其他容器也可通过mydata卷共享数据。

两者的共同点与区别

特性 匿名挂载 具名挂载
卷标识 随机生成的 ID 自定义名称
管理难度 较难(需记住随机 ID) 简单(通过名称操作)
适用场景 临时数据、一次性使用 长期复用、多容器共享
查看卷信息 docker volume ls 可见 docker volume ls 可见

补充说明

  • 无论是匿名还是具名挂载,数据卷的实际存储路径都由 Docker 管理(通常在/var/lib/docker/volumes/目录下)。
  • 若需要指定宿主机的具体路径进行挂载(绑定挂载),格式为-v 宿主机路径:容器内路径,这与上述两种方式不同。

通过这两种挂载方式,可有效实现容器数据的持久化和共享,避免容器删除后数据丢失。

Docker网络

本机网络理解

我们使用ifconfig可以看到三组网络。
首先是docker0,这是我们本节的重点,docker的网络。之后是eth0,本机的外网地址。lo口,本地环回地址,可以代表localhost

关于docker0呢,其实就是一个叫docker0的虚拟网桥。我们使用brctl命令来查看一下。(没有这个命令的下载yum -y install bridge-utils

veth-pair技术

什么是veth-pair技术?要理解它,我们首先来启动两个tomcat容器。

1
2
3
docker run -d -P --name=tomcat01 tomcat:7
docker run -d -P --name=tomcat02 tomcat:7
提示:选择tomcat7是因为这个镜像包含了ip addr 等常用命令!

启动机器之后,我们查看容器ip,通过容器的ip 去ping宿主机ip,发现是通的

1
docker exec -it tomcat01 ip addr

1
ping 172.17.0.3


理解:我们每启动一个docker容器,docker就会给docker容器分配一个ip,安装docker之后,会产生一个叫docker0的网卡,这里使用的就是veth-pair技术

使用ip addr命令,查看我们的网卡。

我们发现多出来了两个网卡,到了这里,你已经知道这两张网卡是那里来的了吧。没错,是启动容器之后产生的!我们回过头来查看我们在启动的容器IP,就会很清晰的发现,这个网卡是成对存在的!容器内的64对应着宿主机的65,容器内的66对应宿主机的67。

什么是==veth-pair?==
veth-pair 就是一堆的虚拟设备接口,他们都是成对出现的,一端连接着协议,一端连接着彼此。使得它充当了一个桥梁的作用。

docker网络详解


不难看出,tomcat01和tomcat02是共用的同一个路由器,即docker0。所有的容器在不指定我网络的情况下,都是docker0路由的,docekr会给我们的容器分配一个默认IP。
docker网络就是下面这个网络模型所描述的。(docker所有的网络接口都是虚拟的,虚拟的转发效率高)

docker网络模式

docker网络模式有以下几种

1
2
3
4
5
6
7
8
Host:容器不会虚拟出自己的网卡,配置主机的IP等,而是使用宿主机的IP和端口

Container: 创建的容器不会创建自己的网卡,配置自己的IP,而是和一个指定的容器共享IP。(一般不用)

None: 该模式关闭了容器的网络功能。(一般不用)

Bridge:默认为该模式(桥接,自己创建也是用它),此模式会为每一个容器分配,设置IP等,并将容器连接到一个docker0 的虚拟网桥,通过docker 0 网桥以及iptables nat 表配置与宿主机通信。

1
docker network ls   #列出docker网卡

创建自定义网络的容器

1
2
3
4
我们直接启动命令, --net bridge,就是docker0(默认)
docker run -d -P --name=tomcat01 --net bridge tomcat

docker0特点:默认,域名不能访问,--link不建议使用

下面我们自己来创建一个bridge。

1
2
3
docker network create --driver bridge --subnet 192.168.0.0/24 --gateway 192.168.0.1 testnet

docekr network ls

查看网卡详情信息

1
docker network inspect 网卡名字  #查看网卡详细信息

发布两个在自己创建的网络里的容器

1
2
docker run -d -P --name=tomcat01-net --net=testnet tomcat:7
docker run -d -P --name=tomcat02-net --net testnet tomcat:7

然后使用docker network inspect testnet,就可以看到刚才创建的这两个容器的IP了。

还记得我们前面说的docker0的缺点之一,不能通过域名访问吗?而我们自定义的网络,就修复了这个功能!

1
2
3
4
docker exec -it tomcat01-net ping -c 3 IP
docker exec -it tomcat01-net ping -c 3 tomcat02-net

提示,ping -c可以自定义ping的次数