1、目录
docker基本概念入门
1.1、容器是什么?
1.2、容器和虚拟机的区别
1.3、主流容器技术概念
1.4、Docker概念:镜像、容器,仓库,各个组件等
1.5、Docker安装
1.6、Docker运行一个Demo
容器编排技术:docker compose
制作镜像DockerFile
容器本地仓库搭建:registry/Harbor
Docker swarm 容器集群管理工具
k3s搭建(3主3从+内部集成ETCD)
k3s继承kuboard
k3s部署微服务,支持动态扩容节点(actuator+Prometheus)
k3s+springboot+本地仓库+actuator+Prometheus案例
2、容器是什么
定义:容器是操作系统级别的虚拟化技术。它允许你在共享宿主机内核的同时,运行多个相互隔离的用户空间实例。
运维黑话解释:
是一个进程级别的“沙箱”。
不是一个完整的OS,只是一个被“伪装”成独立系统的进程。
类比: 容器就像公寓楼里的单间公寓(共享大楼地基和电梯,但房间内独立装修)。
一句话总结:换句话说,就是运行在宿主系统上、共享宿主系统资源的,进程级别的一个不完整的OS系统。
3、容器与常见虚拟机的区别
比如:VmWare、Proxmox VE(KVM/LXC)等
这几个都是虚拟化技术的落地,认为“都是跑应用的隔离环境”。 但从技术底层看,它们的隔离边界、资源利用率和启动逻辑截然不同。
区别就在于下面几点:
3.1、核心本质:共享内核 vs 独立内核
虚拟机:模拟的是完整的硬件——CPU、内存、硬盘、网卡,甚至主板芯片组。每个虚拟机都包含一个独立的客户操作系统(Guest OS),这个 OS 拥有自己完整的内核。
VMware:Type-2 或 Type-1 混合模型,重点在硬件全虚拟化
PVE(Proxmox VE):基于 KVM(Linux 内核虚拟化模块),同样是硬件级虚拟化
容器:容器没有自己独立的内核。所有容器共享宿主机的内核。每个容器只是一个进程级别的隔离环境,通过 Linux 内核的 Namespace 和 Cgroups 技术实现:
Namespace:让每个容器看到自己独立的进程树、网络栈、文件系统、用户 ID 等(隔离视角)
Cgroups:限制每个容器能使用的 CPU、内存、磁盘 IO 等物理资源(限制用量)
一句话总结:虚拟机虚拟的是硬件,容器虚拟的是操作系统接口(系统调用)。
3.2、启动速度与资源占用:秒级 vs 分钟级
假设你有一个 16 核 32GB 的服务器:
跑 Docker:轻松跑几百个相互隔离的小服务(例如微服务架构)
跑 VMware:跑 10~20 个常规 Linux 虚拟机就比较吃力了
3.3、隔离级别与安全性
虚拟机:硬件级隔离。一个虚拟机里的内核崩溃、恶意驱动、甚至蓝屏,绝对不会影响其他虚拟机或宿主机。这是银行、政务、多租户云主机首选的原因——安全边界非常清晰。
容器:进程级隔离。所有容器共享同一个宿主机内核,如果某个容器内的应用利用内核漏洞提权,理论上可以威胁到宿主机和其他容器。虽然 Docker 有 Capabilities、Seccomp、AppArmor 等加固手段,但隔离强度仍不如虚拟机。
3.4、可移植性与交付方式
Docker 的优势领域:封装应用及其依赖(库、配置文件、环境变量),但不包括内核。一个 Docker 镜像可以在任何支持 Docker 的 Linux 发行版上运行(内核版本兼容即可)。开发环境、测试环境、生产环境一致性极佳。
虚拟机镜像:包含了完整 OS 和应用,体积巨大。跨平台迁移(比如从 VMware 到 KVM)通常需要格式转换(如 OVF/OVA),且可能遇到硬件驱动兼容问题。
虚拟机是“物理计算机的软件模拟”,每个虚拟机自备操作系统内核;容器是“操作系统之上的进程沙盒”,所有容器共享宿主机内核,但彼此看不见。
4、各种容器技术对比
4.1、容器和Docker关系
我们经常说到容器技术,首先想到的就是Docker,那么Docker和容器是对等的吗,他们是什么关系
容器是一种虚拟化的技术,指利用Linux内核的Namespace(隔离视角)和Cgroups(限制资源)实现的进程级隔离环境。这是操作系统自带的能力,不是Docker发明的。
Docker是一个容器管理工具,它把底层容器技术封装成好用的镜像构建、分发、运行体验。
4.2、Docker与其他工具对比(Podman、Containerd)
简单总结:
Docker:功能最全,用户体验最好,适合开发和测试,以及中小规模部署
Podman:无守护进程、支持rootless,安全性更好,红帽系生产环境常见
Containerd:只管跑容器,不管镜像构建和网络等,Kubernetes的标配底层
用一句话记忆:Docker是瑞士军刀,Podman是安全版Docker,Containerd是K8s背后的隐形冠军。
4.3、Docker概念
Docker有很多概念:镜像、容器、Network、Volume
我们以面向对象变成的类-对象的概念,来理解镜像和容器的概念
4.3.1、镜像
可以理解成:类
镜像是一个只读的、静态的文件包,里面包含:
一个精简的操作系统文件系统
应用程序代码
依赖的库、环境变量
启动命令的默认参数
关键特性:
只读,不能修改
分层构建(UnionFS),多个镜像共享底层,节省空间
可以存储在Registry中(如Docker Hub)
类比:镜像就像Java里的
class文件,它是一个定义,不能直接运行。
4.3.2、容器
可以理解成:对象
当你执行docker run时,Docker会:
加载镜像的只读层
在最上面加一个可写层(Container Layer)
通过Namespace和Cgroups隔离成独立进程环境
这个正在运行的、带可写层的实例,就叫容器。
关键特性:
顶层可写,底层镜像只读
有状态(运行中、停止、退出)
删除容器后,可写层数据丢失(除非用卷)
类比:容器就像
new出来的对象,可以运行、修改、销毁。同一个镜像可以创建无数个容器。
4.3.3、Network
容器之间是一个封闭的简易版OS,Network是用来打破容器的网络隔离,换句话说,Network是用来给容器通网的(拥有自己的IP)
外部用户,是无法直接访问容器内部应用的,需要通过Network的不同网络模式进行访问
Network有四种网络模式
overlay
docker network create --subnet=192.160.1.0/24 --gateway=192.160.1.1 wss-cloud-network
--driver
4.3.4、Volume(卷)
容器是一个封闭隔离的简易版OS,我们可以将各种应用,运行在这个封闭的OS上面,那么应用产生的各种数据,都会存储在这个OS中,当我们删除容器,或者容器异常的时候,数据就会丢失。
那么Volume就是用来解决容器数据丢失问题,是Docker管理的、独立于容器生命周期的数据存储区域。
它可以挂载容器的某个目录(如
/var/lib/mysql)容器写入这个目录的数据,实际写到了Volume里
Volume实际存储在宿主机的指定位置(/var/lib/docker/volume)删除容器,Volume还在;重新创建容器,挂载同一个Volume,数据恢复
三种挂载方式对比
docker volume create my-redis-volume
5、Docker安装
我这里采用离线安装的方式(线上大多数都是离线环境,无法直接访问外网)
# wget https://download.docker.com/linux/static/stable/x86_64/docker-20.10.23.tgz
# tar zxvf docker-20.10.23.tgz
# cp docker/* /usr/bin/
# vim /etc/systemd/system/docker.service (创建配置文件)
配置内容如下
[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 --selinux-enabled=false --insecure-registry=127.0.0.1
ExecReload=/bin/kill -s HUP $MAINPID
LimitNOFILE=infinity
LimitNPROC=infinity
LimitCORE=infinity
TimeoutStartSec=0
Delegate=yes
KillMode=process
Restart=on-failure
StartLimitBurst=3
StartLimitInterval=60s
[Install]
WantedBy=multi-user.target
继续执行如下命令:
# chmod +x /etc/systemd/system/docker.service
# systemctl daemon-reload
# systemctl start docker
# systemctl enable docker
# docker --version
Docker version 20.10.23, build 7155243
6、运行一个简单的例子
这里部署一个redis为例
docker run -d --name redis --restart unless-stopped --network my-network -p 16379:6379 -v my-redis-volume:/data --cpus=1 --memory=512m --memory-swap=512m --log-driver json-file --log-opt max-size=10m --log-opt max-file=3 docker.1ms.run/library/redis:7.2 redis-server --requirepass 123456 --bind 0.0.0.0 --protected-mode no
docker run -d --name redis --log-opt max-size=10m --log-opt max-file=3 -m 512m --cpus=2 --restart unless-stopped -p 6379:6379 -v ~/redis/data:/data -v ~/redis/conf/redis.conf:/usr/local/etc/redis/redis.conf:ro 08567fe300e8 redis-server /usr/local/etc/redis/redis.conf --bind 0.0.0.0 --requirepass 123456
也可以自定义配置文件
mkdir -p /opt/redis/conf
cat > /opt/redis/conf/redis.conf << 'EOF'
# 基础配置
requirepass 123456
bind 0.0.0.0
protected-mode no
port 6379
# AOF 持久化配置(你要的 aop -> AOF)
appendonly yes
appendfilename "appendonly.aof"
appendfsync everysec
no-appendfsync-on-rewrite no
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
# RDB 持久化配置(可选,作为补充备份)
save 900 1
save 300 10
save 60 10000
stop-writes-on-bgsave-error yes
rdbcompression yes
rdbchecksum yes
dbfilename dump.rdb
# 数据目录(与 volume 映射对应)
dir /data
# 内存配置(限制 400MB 给 Redis 数据,留 112MB 给系统)
maxmemory 400mb
maxmemory-policy allkeys-lru
# 日志配置
loglevel notice
logfile ""
# 性能优化
tcp-backlog 511
timeout 0
tcp-keepalive 300
databases 16
EOF
docker run -d \
--name redis \
--restart unless-stopped \
--network jm-network \
-p 16379:6379 \
-v my-redis-volume:/data \
-v /opt/redis/conf/redis.conf:/usr/local/etc/redis/redis.conf:ro \
--cpus=1 \
--memory=512m \
--memory-swap=512m \
--log-driver json-file \
--log-opt max-size=10m \
--log-opt max-file=3 \
docker.1ms.run/library/redis:7.2 \
redis-server /usr/local/etc/redis/redis.conf
:ro 只读挂载,防止容器内误修改配置 protected-mode(保护模式) 是 Redis 的一个安全机制,默认是 yes(开启)。
它的设计目的是:防止 Redis 意外暴露在公网上被未授权访问。
当以下 三个条件同时满足 时,保护模式会生效:
条件 说明
protected-mode yes 保护模式开启(默认)
没有配置 bind 指令 Redis 监听所有网络接口(0.0.0.0)
没有配置密码(requirepass) 无需认证即可访问 三个条件缺一不可。 只要配置了 bind 或设置了密码,保护模式不会制造麻烦。