前置了解:
操作系统:
LXC(LinuX Containers)是一种操作系统层虚拟化技术,为 Linux 内核容器功能的一个用户空间接口。
尽管 LXC 极大地简化了容器技术的使用,但比起直接通过内核调用来使用容器技术,其复杂程度其实并没有多大降低,因为我们必须要学会 LXC 的一组命令工具,且由于内核的创建都是通过命令来实现的,通过批量命令实现数据迁移并不容易。
其隔离性也没有虚拟机那么强大。后来就出现了 Docker,所以从一定程度上来说,Docker 就是 LXC 的增强版。
Ubuntu 上安装 LXC,如下:
检查及卸载(如需)
systemctl status lxc
lxc-stop -n xxx # 停止所有运行的容器
lxc-destroy -n xxx # 删除所有容器
apt-get purge --auto-remove lxc lxc-templates
systemctl status lxc # 确保服务已卸载
安装 LXC
sudo apt install lxc lxc-templates bridge-utils -y
systemctl status lxc # 检查服务是否正常
LXC的常用命令说明如下:
① 检查系统支持性:lxc-checkconfig
② 创建指定模板容器:lxc-create -n NAME -t TEMPLATE_NAME [--template-options]
③ 启动容器:lxc-start -n NAME -d
④ 列出容器:lxc-ls -f
(-f 参数显示容器得详细信息)
⑤ 查看容器信息:lxc-info -n NAME
⑥ 进入容器:lxc-attach --name=NAME [--COMMAND]
⑦ 停止容器:lxc-stop -n NAME
⑧ 删除容器:lxc-destroy -n NAME
实战如下:
# 1. 检查运行状态
root@VM-8-10-ubuntu:~$ systemctl status lxc
● lxc.service - LXC Container Initialization and Autoboot Code
Loaded: loaded (/lib/systemd/system/lxc.service; enabled; vendor preset: enabled)
Active: active (exited) since Fri 2025-07-11 15:28:38 CST; 3min 34s ago
Docs: man:lxc-autostart
man:lxc
Process: 2423230 ExecStartPre=/usr/lib/x86_64-linux-gnu/lxc/lxc-apparmor-load (code=exited, status=0/SUCCESS)
Process: 2423235 ExecStart=/usr/lib/x86_64-linux-gnu/lxc/lxc-containers start (code=exited, status=0/SUCCESS)
Main PID: 2423235 (code=exited, status=0/SUCCESS)
CPU: 24ms
# 2. 查看可用模板
root@VM-8-10-ubuntu:/home/lighthouse# ls /usr/share/lxc/templates/
lxc-alpine lxc-centos lxc-fedora lxc-oci lxc-plamo lxc-sparclinux lxc-voidlinux
lxc-altlinux lxc-cirros lxc-fedora-legacy lxc-openmandriva lxc-pld lxc-sshd
lxc-archlinux lxc-debian lxc-gentoo lxc-opensuse lxc-sabayon lxc-ubuntu
lxc-busybox lxc-download lxc-local lxc-oracle lxc-slackware lxc-ubuntu-cloud
# 3. 创建容器
lxc-create -n lxchost1 -t ubuntu -- -r xenial -a amd64 # Ubuntu上创建Ubuntu容器
lxc-create -n centos7 --template=download -- --dist=centos --release=7 --arch=amd64 # Ubuntu上创建CentOS容器
# 4. 查看创建结果
root@VM-8-10-ubuntu:/home/lighthouse# lxc-ls -f
NAME STATE AUTOSTART GROUPS IPV4 IPV6 UNPRIVILEGED
lxchost1 STOPPED 0 - - - false
# 5. 启动容器
root@VM-8-10-ubuntu:/home/lighthouse# lxc-start -n lxchost1 -d
root@VM-8-10-ubuntu:/home/lighthouse# lxc-info -n lxchost1
Name: lxchost1
State: RUNNING
PID: 2455869
Link: vethNx0mnE
TX bytes: 726 bytes
RX bytes: 1.41 KiB
Total bytes: 2.12 KiB
# 6. 使用 ssh 进入容器
root@VM-8-10-ubuntu:/home/lighthouse# ssh ubuntu@ip
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
ubuntu@1.12.51.69's password: # 密码是当前 系统密码
# 7. 在容器中执行常用命令
ip addr # 查看网络信息
df -h # 查看磁盘挂载情况
ps -ef # 查看进程信息
ubuntu@VM-8-10-ubuntu:~$ df -h
Filesystem Size Used Avail Use% Mounted on
tmpfs 340M 1.1M 339M 1% /run
/dev/vda2 69G 23G 44G 35% /
tmpfs 1.7G 24K 1.7G 1% /dev/shm
tmpfs 5.0M 0 5.0M 0% /run/lock
tmpfs 340M 4.0K 340M 1% /run/user/1002
tmpfs 340M 4.0K 340M 1% /run/user/1001
tmpfs 1.7G 0 1.7G 0% /run/qemu
tmpfs 340M 4.0K 340M 1% /run/user/1000
# 8. 从宿主机向容器中发送命令
root@VM-8-10-ubuntu:/home/lighthouse# lxc-attach -n lxchost1 --clear-env -- echo "Hello LXC"
Hello LXC
# 9. 停止 & 删除容器
root@VM-8-10-ubuntu:/home/lighthouse# lxc-stop -n lxchost1
root@VM-8-10-ubuntu:/home/lighthouse# lxc-destroy -n lxchost1
libcontainer
,而如今大部分Docker使用的都是libcontainer
而非LXC。Docker 本质其实是 LXC 之类的增强版,它本身不是容器,而是容器的易用工具。
早期 Docker 利用 LXC 做容器管理引擎,但在创建容器时,不再使用 模板 去安装生成,而是通过 镜像技术(把一个操作系统用户空间所需要使用到的组件事先编排好,并整体打包成一个文件,image 文件),镜像文件集中放在一个仓库中。
当需要创建容器时,Docker 调用 LXC 的工具 lxc-create
,但不再通过 lxc 的模板去安装,而是连接到镜像服务器上下载匹配的镜像文件,而后基于镜像启动容器。
所以,Docker 极大地简化了容器的使用难度。以后我们创建启动容器,只需要一个命令,docker-run,docker-stop 就可以启动停止一个容器了。
虚拟机:在硬件层之上,在操作系统层就开始进行隔离。虚拟机通过伪造一个硬件的抽象接口,把操作系统嫁接到硬件上。
容器:也是一种虚拟化的实现技术,它在操作系统之上进行环境隔离,每个容器可以有自己的一套工具和库,但是它们共享操作系统的内核!
特性 | 虚拟机 | Docker |
---|---|---|
磁盘占用 | 几个 GB 到几十个 GB | 几十 MB 到 几百 MB |
CPU 内存占用 | 虚拟操作系统非常占用 CPU 和内存,需要通过虚拟层调用占用率高 | Docker 引擎占用资源极低,直接作用于硬件资源占用少 |
虚拟化层级 | 硬件层之上,模拟完整操作系统 | 操作系统层之上,隔离进程环境 |
安装管理 | 需要专门的运维技术 | 安装、管理方便 |
内核共享 | 不共享,每个 VM 有自己的 OS 内核 | 共享宿主机的内核 |
启动速度 | 较慢(需要启动完整的操作系统) | 极快(秒级甚至毫秒级) |
资源消耗 | 高(每个 VM 占用内存和磁盘空间大) | 低(轻量级,共享资源) |
隔离性 | 强(完全隔离,安全性高,系统级别) | 相对弱(依赖于命名空间和控制组,进程级别) |
可移植性 | 一般(镜像体积大,迁移复杂) | 高(容器镜像小,便于部署) |
适用场景 | 多租户、安全要求高的环境 | 快速部署、微服务、CI/CD |
docker 不需要虚拟内核,所以启动可以更快,相当于 windows 的开机时间省去了
🎮 游戏厅 vs 手机游戏
🏗️ 建房子 vs 搭积木
┌───────────────┬──────────────────────────────┐ ┌───────────────┬──────────────────────────────┐
│ 层级 │ 虚拟机 (VM) │ │ 层级 │ 容器 (Docker) │
├───────────────┼──────────────────────────────┤ ├───────────────┼──────────────────────────────┤
│ 应用程序 │ 各自独立的应用 │ │ 应用程序 │ 各自独立的应用 │
│ 操作系统 │ 各自独立的操作系统 │ │ 容器引擎 │ Docker Engine │
│ Hypervisor │ 虚拟化层(监控器) │ │ 操作系统 │ 共享同一个 Linux 内核 │
│ 物理硬件 │ 物理服务器 │ │ 物理硬件 │ 物理服务器 │
└───────────────┴──────────────────────────────┘ └───────────────┴──────────────────────────────┘
Docker 为什么比虚拟机资源 利用率高,启动快,耦合低
Docker 和 JVM 虚拟化的区别
特性 | JVM | Docker 容器 |
---|---|---|
性能 | Jvm 需要占用一定的 CPU 和内存 | 基本没有损失 |
虚拟层面 | 基于 JVM 虚拟机,更加上层 | 基于操作系统,更加通用 |
代码无关性 | 一个特定代码的执行平台,它是运行时才存在的,只能支撑特定代码的执行,并且必须是在 jvm 进程内 | 模拟了一整个操作系统,它是静态存在的,可以支撑任何代码,相同平台的应用程序 |
主机隔离性 | jvm 不隔离主机 | 通过命名空间实现隔离 |
Docker 发展过程中衍生了以下版本,目前我们学习和使用提到的版本是 docker-ce。
类比理解:上面概念比较难以理解,我们列举个生活中的案例,以一家人去旅游入住酒店为例。
我们来考虑 2 个问题,Docker 为什么要设计镜像,然后又搭建个 Docker Hub,搞个镜像仓库呢?我们来看下现在的时代发生了什么。
1. 数据量疯狂增长:
PB =
TB =
GB =
MB =
KB
随着物联网、边缘计算等智能终端设备不断普及,受到来自物联网设备信号、元数据、娱乐相关数据、云计算和边缘计算的数据增长的驱动,全球数据量呈现加速增长。根据 IDC 分布的《数据时代 2025》预测,全球数据量将从 2018 年的 33ZB 增至 2025 年的 175ZB,增长超过 5 倍;中国平均增速快于全球 3%,预计到 2025 年将增至 48.6ZB,占全球数据圈的比例由 23.4%提升至 27.8%。其中,中国企业级数据量将从 2015 年占中国数据量的 49%增长到 2025 年的 69%。
2. 处理能力快速增加:
3. 软件需求爆发式增长:
Docker 解决方案:云时代需要我们针对这些诉求有一套针对性的解决方案。
思考一:我们要处理海量的数据,如何处理呢?
思考二:软件设计好以后,怎么快速安装启动,有问题回滚呢?
思考三:不同的开发环境怎么搭建呢,一会 java,一会 c++?
下面我们来快速安装一下 Docker,对 Docker 有个初步的认识和了解。
① 确定 CPU 版本以及操作系统版本,如下:
root@VM-8-10-ubuntu:/home/lighthouse# uname -a # CPU 架构
Linux VM-8-10-ubuntu 5.15.0-126-generic #136-Ubuntu SMP Wed Nov 6 10:38:22 UTC 2024 x86_64 x86_64 x86_64 GNU/Linux
root@VM-8-10-ubuntu:/home/lighthouse# cat /etc/*release* # OS 版本
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=22.04
DISTRIB_CODENAME=jammy
DISTRIB_DESCRIPTION="Ubuntu 22.04 LTS"
PRETTY_NAME="Ubuntu 22.04 LTS"
NAME="Ubuntu"
VERSION_ID="22.04"
VERSION="22.04 (Jammy Jellyfish)"
VERSION_CODENAME=jammy
ID=ubuntu
ID_LIKE=debian
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
UBUNTU_CODENAME=jammy
② 卸载之前版本,如果是新购买的云服务器是没有的,比如输入 docker 显示没有这个命令,就无需卸载
# 卸载旧版本
sudo apt-get remove docker docker-engine docker.io containerd runc
# 卸载历史版本
# 卸载软件
sudo apt-get purge docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin docker-ce-rootless-extras -y
# 删除目录
sudo rm -rf /var/lib/docker
sudo rm -rf /var/lib/containerd
③ 准备条件
sudo apt update # 更新软件包索引
# curl 命令安装 -- 以便能够通过HTTPS使用APT
sudo apt install apt-transport-https ca-certificates curl gnupg lsb-release -y
root@VM-8-10-ubuntu:/home/lighthouse# curl www.baidu.com # 测试
# 创建 gpg key 目录 --
sudo mkdir -m 0755 -p /etc/apt/keyrings
# 下载并添加GPG密钥
#添加 Docker 官方 GPG key (可能国内现在访问会存在问题)
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
# 阿里源(推荐使用阿里的gpg KEY)
curl -fsSL https://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
#添加 apt 源:
#Docker官方源
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
#阿里apt源
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://mirrors.aliyun.com/docker-ce/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
#更新源
sudo apt update
sudo apt-get update
④ 安装
sudo apt install docker-ce docker-ce-cli containerd.io # 安装 Docker Engine
# 查看Docker版本
sudo docker version
root@VM-8-10-ubuntu:/home/lighthouse# docker version
Client: Docker Engine - Community
Version: 28.3.2
API version: 1.51
Go version: go1.24.5
Git commit: 578ccf6
Built: Wed Jul 9 16:13:42 2025
OS/Arch: linux/amd64
Context: default
Server: Docker Engine - Community
Engine:
Version: 28.3.2
API version: 1.51 (minimum version 1.24)
Go version: go1.24.5
Git commit: e77ff99
Built: Wed Jul 9 16:13:42 2025
OS/Arch: linux/amd64
Experimental: false
containerd:
Version: 1.7.27
GitCommit: 05044ec0a9a75232cad458027ca83437aae3f4da
runc:
Version: 1.2.5
GitCommit: v1.2.5-0-g59923ef
docker-init:
Version: 0.19.0
GitCommit: de40ad0
⑤ 自启动配置
#配置加载
sudo systemctl daemon-reload
#启动服务
sudo systemctl start docker
#开启启动
sudo systemctl enable docker
#查看服务状态
sudo systemctl status docker
如果出现了如下报错:
root@VM-8-10-ubuntu:/home/lighthouse# docker run hello-world
Unable to find image 'hello-world:latest' locally
docker: Error response from daemon: Get "https://registry-1.docker.io/v2/": net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)
Run 'docker run --help' for more information
原因:因为最近国内无法访问到Docker的,首先在安装的时候,我们选择的是国内阿里的源,因此就需要在docker daemon 配置文件中增加国的可用的 docker hub mirror ,找到你的daemon.json 文件,解决办法如下:
root@VM-8-10-ubuntu:/etc/docker# vim /etc/docker/daemon.json
vi /etc/docker/daemon.json
{
"registry-mirrors": [
"https://docker.m.daocloud.io",
"https://dockerhub.timeweb.cloud",
"https://huecker.io"
]
}
# 通常来讲如果没有其它的配置,那么daemon.json完整的文件内容就是如上
# 文件内容输入后
root@VM-8-10-ubuntu:/etc/docker# sudo systemctl daemon-reload
root@VM-8-10-ubuntu:/etc/docker# sudo systemctl restart docker
# 此时就可以正常输出了
root@VM-8-10-ubuntu:/home/lighthouse# docker run hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
e6590344b1a5: Pull complete
Digest: sha256:ec153840d1e635ac434fab5e377081f17e0e15afab27beb3f726c3265039cfff
Status: Downloaded newer image for hello-world:latest
Hello from Docker!
This message shows that your installation appears to be working correctly.
To generate this message, Docker took the following steps:
1. The Docker client contacted the Docker daemon.
2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
(amd64)
3. The Docker daemon created a new container from that image which runs the
executable that produces the output you are currently reading.
4. The Docker daemon streamed that output to the Docker client, which sent it
to your terminal.
To try something more ambitious, you can run an Ubuntu container with:
$ docker run -it ubuntu bash
Share images, automate workflows, and more with a free Docker ID:
https://hub.docker.com/
For more examples and ideas, visit:
https://docs.docker.com/get-started/
# 查看所有容器
root@VM-8-10-ubuntu:/home/lighthouse# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a856f33f502f hello-world "/hello" 7 minutes ago Exited (0) 7 minutes ago affectionate_leavitt
当我们安装好了Docker之后,有两种方式来执行docker 命令
sudo docker ps
是不是可以让当前用户在不切root,或者不加sudo 的情况下正常使用 docker 命令呢?答案是有的,如下:
# 1.添加docker用户组
root@VM-8-10-ubuntu:/home/lighthouse# sudo groupadd d
# 2.将当前用户添加到用户组
root@VM-8-10-ubuntu:/home/lighthouse# sudo usermod -aG docker lighthouse
# 3.使权限生效
lighthouse@VM-8-10-ubuntu:~$ newgrp docker
lighthouse@VM-8-10-ubuntu:~$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a856f33f502f hello-world "/hello" 10 minutes ago Exited (0) 10 minutes ago affectionate_leavitt
但是此时我们会发现,当每次打开新的终端,都必须先执行一次 newgrp docker
命令,否则当前用户还是不可以执行docker命令,那我们该怎么解决呢,更新.bashrc文件:我们需要编辑 ~/.bashrc文件,并在文件末尾增加 如下一行:
groupadd -f docker