Skip to content

Docker-基础

Docker 是一个开源的应用容器引擎,基于 Go 语言开发。它允许开发者将应用及其依赖打包到一个轻量级、可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。

核心概念

容器是轻量级的独立运行环境,镜像如同“模具”,容器则是“糕点”,共享宿主机内核,比虚拟机更高效。

  1. 镜像(Image)
    • 容器的模板(类比:模具)
    • 分层存储结构
    • 包含应用代码+运行环境
  2. 容器(Container)
    • 独立的软件运行环境
    • 共享宿主机系统内核(与虚拟机本质区别)
    • 轻量级、启动快(秒级)
  3. 仓库(Repository)
    • Docker Hub:官方镜像仓库
    • 镜像命名规范:[registry]/[namespace]/[image]:[tag]
    • 常用镜像站解决网络问题

容器与VM区别

用容器化技术给应用程序封装独立的运行环境。 每个运行环境就是一个容器,运行容器的计算机被称为宿主机。Docker容器与虚拟机的最大区别是,Docker容器之间共用同一个系统内核, 而每个虚拟机都包含一个操作系统的完整内核, 所以Docker容器比虚拟机更轻、更小,启动速度更快。

VM

tex
+-------------------+-------------------+-------------------+
|      App 1        |      App 2        |      App 3        |
+-------------------+-------------------+-------------------+
|     Guest OS      |     Guest OS      |     Guest OS      |
+-----------------------------------------------------------+
|                Hypervisor (虚拟机监视器)                   |
+-----------------------------------------------------------+
|                     Host Operating System                  |
+-----------------------------------------------------------+
|                       Hardware                            |
+-----------------------------------------------------------+

利用 Hypervisor 虚拟化技术来模拟CPU、内存等硬件资源,这样就可以在宿主机上建立一个CentOS ,这是常说的安装一个虚拟机。每一个虚拟机都有一个独立的内核,比如 Ubuntu、CentOS 甚至是 Windows 等,在这样的虚拟机之下,每个应用都是相互独立的,VM 可以提供一个更好的隔离效果。但这样的隔离效果需要付出一定的代价,因为需要把一部分的计算资源交给虚拟化,这样就很难充分利用现有的计算资源,并且每个虚拟机都需要占用大量的磁盘空间,比如 Windows 操作系统的安装需要 10~30G 的磁盘空间,Ubuntu 也需要 5~6G,同时这样的方式启动很慢。正是因为虚拟机技术的缺点,催生出了容器技术。

容器

tex
+-------------------+-------------------+-------------------+
|  Container 1      |  Container 2      |  Container 3      |
|  (App + Deps)     |  (App + Deps)     |  (App + Deps)     |
+-----------------------------------------------------------+
|                Container Runtime (如Docker)                |
+-----------------------------------------------------------+
|                     Host Operating System                  |
+-----------------------------------------------------------+
|                       Hardware                            |
+-----------------------------------------------------------+

是针对于进程而言的,因此无需虚拟机 ,只需要一个独立的文件系统提供其所需要文件集合即可。所有的文件隔离都是进程级别的,因此启动时间快于 VM,并且所需的磁盘空间也小于 VM。当然了,进程级别的隔离并没有想象中的那么好,隔离效果相比 VM 要差很多。

主要区别对比

特性容器 (Docker等)虚拟机 (VMware, VirtualBox等)
虚拟化级别操作系统级虚拟化硬件级虚拟化
隔离性进程级别隔离(较弱)完全隔离(更强)
启动速度秒级(非常快)分钟级(较慢)
性能接近原生性能有性能损耗(约5-15%)
资源占用非常小(共享主机内核)较大(每个VM需要完整OS)
镜像大小通常为MB级别通常为GB级别
可移植性高(跨平台需相同OS内核)高(完全独立)
安全性较弱(共享内核)强(完全隔离)
部署密度高(可部署更多实例)低(资源占用大)
典型用途微服务、CI/CD、云原生应用传统应用、需要完全隔离的环境
  1. 虚拟化方式不同
    • 虚拟机: 虚拟化硬件,每个VM运行完整的操作系统
    • 容器: 虚拟化操作系统,共享主机内核
  2. 资源利用率
    • 容器共享主机内核,无需为每个实例加载完整OS,资源利用率高
    • 虚拟机需要为每个实例分配完整OS资源,开销大
  3. 启动时间
    • 容器启动只需启动进程,非常快速
    • 虚拟机需要启动完整操作系统,较慢
  4. 隔离性
    • 虚拟机提供完全的硬件级隔离,安全性更高
    • 容器是进程级隔离,共享内核,存在潜在安全风险
  5. 可移植性
    • 容器镜像更小,更易于迁移
    • 虚拟机镜像包含完整OS,体积大

Docker的隔离原理

Docker主要就是借助 Linux 内核技术Namespace来做到隔离的,Linux Namespaces机制提供一种资源隔离方案。PID,IPC,Network等系统资源不再是全局性的,而是属于某个特定的Namespace。每个namespace下的资源对于其他namespace下的资源都是透明,不可见的。因此在操作系统层面上看,就会出现多个相同pid的进程。系统中可以同时存在两个进程号为0,1,2的进程,由于属于不同的namespace,所以它们之间并不冲突。而在用户层面上只能看到属于用户自己namespace下的资源,例如使用ps命令只能列出自己namespace下的进程。这样每个namespace看上去就像一个单独的Linux系统。

namespace命令空间的隔离

命名空间类型系统调用参数隔离内容备注
UTSCLONE_NEWUTS主机名和域名 (hostnamedomainname)允许容器拥有独立的主机标识
IPCCLONE_NEWIPC进程间通信资源:信号量(Semaphore)、消息队列(Message Queue)、共享内存(Shared Memory)防止跨命名空间的进程通信
PIDCLONE_NEWPID进程编号(PID),容器内进程从1开始编号容器内只能看到自己的进程树
NetworkCLONE_NEWNET网络设备、网络协议栈、端口、路由表、防火墙规则等容器拥有独立的网络环境(需配合虚拟网卡)
MountCLONE_NEWNS文件系统挂载点(Mount Points)NS 表示"Namespace",是历史上第一个实现的命名空间
UserCLONE_NEWUSER用户和用户组ID映射(UID/GID)允许容器内用户以非root身份映射到宿主机的非root用户
CgroupCLONE_NEWCGROUP控制组(Cgroup)资源限制Linux 4.6+ 引入,隔离资源限制视图
TimeCLONE_NEWTIME系统时钟(Boot Time和Monotonic Time)Linux 5.6+ 引入,允许容器修改系统时间

资源限制(cgroup)

  • 资源限制:限制任务使用的资源总额,并在超过这个 配额 时发出提示
  • 优先级分配:分配CPU时间片数量及磁盘IO带宽大小、控制任务运行的优先级
  • 资源统计:统计系统资源使用量,如CPU使用时长、内存用量等
  • 任务控制:对任务执行挂起、恢复等操作
  • 容器与镜像的关系类似于面向对象编程中的对象与类。

Docker-部署

yum安装

卸载旧版本

若您安装过docker,需要先删掉,之后再安装依赖:

bash
sudo yum -y remove docker docker-common docker-selinux docker-engine
sudo yum -y install yum-utils device-mapper-persistent-data lvm2

安装 Docker

openEuler源

bash
# 注册openEuler
dnf config-manager --add-repo https://repo.openeuler.openatom.cn/openEuler-24.03-LTS/update/x86_64/

# 安装
dnf -y install docker docker-compose-plugin

huaweicloud源

bash
# 下载repo文件(也可选注册repo方式)
wget -O /etc/yum.repos.d/docker-ce.repo https://mirrors.huaweicloud.com/docker-ce/linux/centos/docker-ce.repo
# 注册华为repo
dnf config-manager --add-repo=https://repo.huaweicloud.com/docker-ce/linux/centos/docker-ce.repo

# 软件仓库地址替换
sudo sed -i 's+download.docker.com+mirrors.huaweicloud.com/docker-ce+' /etc/yum.repos.d/docker-ce.repo
# 替换centos识别版本号
sed -i 's+$releasever+9+' /etc/yum.repos.d/docker-ce.repo

# 安装docker-ce和依赖
dnf -y install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

aliyun源

bash
# 安装必要的一些系统工具(Cent系列需要安装)
yum install -y yum-utils

# 添加软件源信息
yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

# 替换centos识别版本号
sed -i 's+$releasever+9+' /etc/yum.repos.d/docker-ce.repo

# 安装Docker
dnf -y install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

# Step 4: 开启Docker服务
systemctl start docker

# 注意:
# 官方软件源默认启用了最新的软件,您可以通过编辑软件源的方式获取各个版本的软件包。例如官方并没有将测试版本的软件源置为可用,您可以通过以下方式开启。同理可以开启各种测试版本等。
# vim /etc/yum.repos.d/docker-ce.repo
#   将[docker-ce-test]下方的enabled=0修改为enabled=1
#
# 安装指定版本的Docker-CE:
# Step 1: 查找Docker-CE的版本:
# yum list docker-ce.x86_64 --showduplicates | sort -r
#   Loading mirror speeds from cached hostfile
#   Loaded plugins: branch, fastestmirror, langpacks
#   docker-ce.x86_64            17.03.1.ce-1.el7.centos            docker-ce-stable
#   docker-ce.x86_64            17.03.1.ce-1.el7.centos            @docker-ce-stable
#   docker-ce.x86_64            17.03.0.ce-1.el7.centos            docker-ce-stable
#   Available Packages
# Step2: 安装指定版本的Docker-CE: (VERSION例如上面的17.03.0.ce.1-1.el7.centos)
# sudo yum -y install docker-ce-[VERSION]

启动

bash
systemctl daemon-reload 
systemctl enable docker --now

离线部署Docker

下载离线包

bash
wget https://download.docker.com/linux/static/stable/x86_64/docker-28.2.2.tgz
# 解压缩
tar -zxvf docker-28.2.2.tgz -C /usr/local
# 移动文件
cp /usr/local/docker/* /usr/bin/

注册daemon

bash
cat >> /etc/systemd/system/docker.service << EOF
[Unit]
Description=Docker Application Container Engine
Documentation=https://docs.docker.com
After=network-online.target firewalld.service
Wants=network-online.target
 
[Service]
Type=notify
ExecStart=/usr/bin/dockerd
ExecReload=/bin/kill -s HUP $MAINPID
LimitNOFILE=infinity
LimitNPROC=infinity
TimeoutStartSec=0
Delegate=yes
KillMode=process
Restart=on-failure
StartLimitBurst=3
StartLimitInterval=60s
 
[Install]
WantedBy=multi-user.target
EOF

赋权启动

bash
chmod +x /etc/systemd/system/docker.service
systemctl daemon-reload 
systemctl enable docker --now

官方shell脚本

bash
# 打不开情况下需要科学上网方式
curl -fsSL https://get.docker.com -o install-docker.sh
sh install-docker.sh --dry-run

Docker-配置文件

bash
vi /etc/docker/daemon.json
{
	# 定义dockers工作目录
    "data-root":"/data/docker",
    # 存储驱动的模式
    "storage-driver":"overlay2",
    # 限制日志格式和大小
    "log-driver": "json-file",
    "log-opts": {
        "max-size": "10m",
        "max-file": "5"
    },
    # 国内的镜像加速源
    "registry-mirrors":[
        "https://docker.m.daocloud.io",
        "https://noohub.ru",
        "https://huecker.io",
        "https://dockerhub.timeweb.cloud"
    ],
    # ulimits 优化
    "default-ulimits": {
      "nofile": {
        "Name": "nofile",
        "Hard": 65535,
        "Soft": 32768
      },
      "nproc": {
        "Name": "nproc",
        "Hard": 4096,
        "Soft": 2048
      }
    },
    # 指定docker的IP要区别于主机,记得加子网掩码
    "bip":"172.18.0.1/16",
    # 禁用 Docker 自带的 iptables 规则(Kubernetes 场景适用)
    "iptables": false,
    "ip-masq": false,
    # 启动时候的额外的参数
    "exec-opts":["native.cgroupdriver=systemd"],
    # docker引擎死掉了,用docker引擎起来的容器可以继续活着
    "live-restore":true,
    # 设置默认容器资源限制(如文件描述符数)
    "default-ulimits": { "nofile": { "Hard": 65536, "Soft": 65536 } },
    # DNS
    "dns": ["223.5.5.5", "114.114.114.114"],
    # IPv6
    "ipv6": false
}


# 创建docker工作目录
mkdir /data/docker -p
# 启动dockers
systemctl start docker