Docker 容器化技术
AI 文章 第一阶段 预科
1 Docker的历史和作用
1.1 Docker简介
Docker 是一种运行于 Linux 和 Windows 上的软件,用于创建、管理和编排容器。Docker 是在 GitHub 上开发的 Moby 开源项目的一部分。Docker 公司,位于旧金山,是整个 Moby 开源项目的维护者。
Docker 公司位于旧金山,由法裔美籍开发者和企业家 Solumon Hykes 创立,其标志如下图所示。

有意思的是,Docker 公司起初是一家名为 dotCloud 的平台即服务(Platform-as-a-Service, PaaS)提供商。底层技术上,dotCloud 平台利用了 Linux 容器技术。为了方便创建和管理这些容器,dotCloud 开发了一套内部工具,之后被命名为“Docker”。Docker就是这样诞生的!
2013年,dotCloud 的 PaaS 业务并不景气,公司需要寻求新的突破。于是他们聘请了 Ben Golub 作为新的 CEO,将公司重命名为“Docker”,放弃dotCloud PaaS 平台,怀揣着“将 Docker 和容器技术推向全世界”的使命,开启了一段新的征程。如今 Docker 公司被普遍认为是一家创新型科技公司,据说其市场价值约为 10 亿美元。Docker 公司已经通过多轮融资,吸纳了来自硅谷的几家风投公司的累计超过 2.4 亿美元的投资。
1.2 Docker是什么
“Docker”一词来自英国口语,意为码头工人(Dock Worker),即从船上装卸货物的人。多数技术人员在谈到 Docker 时,主要是指 Docker 引擎,Docker 引擎是用于运行和编排容器的基础设施工具,他有类似于Vmware的虚拟化核心但是更加小更加轻便。
Docker 这件“小玩意儿”最早诞生在一家叫 dotCloud 的创业公司里这个我们已经知道了。那时候他们做的是 PaaS 平台,天天为客户部署应用,机器配来配去特麻烦,于是工程师索性把 Linux 里已有的隔离技术(namespaces、cgroups)包了个“盒子”,让程序和依赖一起塞进去——这就是 Docker 的雏形。2013 年,团队干脆把公司名字改成 Docker Inc. 并把代码开源,结果一石激起千层浪:开发者第一次发现“原来装环境可以秒开、还不用担心‘我电脑能跑你电脑死机’的尴尬”。
在传统 IT 架构里,最常见的隔离手段是 虚拟机。它会在硬件与操作系统之间插入一层 “Hypervisor”(例如 VMware ESXi、KVM),给每个业务分配一整套独立的“虚拟硬件”——CPU、内存、硬盘、网卡、BIOS 都要各来一份,然后在其之上再装一套完整的客体操作系统。Docker 所属的 容器技术 则采取了另一条路线:直接共享宿主机内核,只在进程级别做沙箱隔离。两者各有长处,但在开发交付场景下,容器往往显出更轻盈的一面。
一、结构体量与启动速度 虚拟机像给每个应用发一辆“重卡”——要先点火(BIOS→Bootloader→Guest OS),才能跑业务;冷启动动辄几十秒到几分钟。容器更像“共享单车”——宿主机内核早已就位,拉起一个新容器只需复制文件系统、分配命名空间,秒级即可就绪。因此,同一台物理机往往能跑几十甚至上百个容器,而虚拟机数量受内存和磁盘开销强烈限制。
二、资源占用与密度 虚拟机每台都要打包一套 Guest OS,文件系统少则数 GB,多则十几 GB,还得维持系统级守护进程的常驻内存;容器只携带应用二进制和必要依赖,镜像可小到几十 MB。对企业来说,这意味着更高的实例密度、更低的硬件与能耗成本。容器还能利用分层镜像,把公共基础层(如 Ubuntu 根文件系统)多份容器共享,进一步节省磁盘。
三、跨环境一致性与交付链 虚拟机镜像往往与云平台、底层硬件强耦合,迁移时需要转换格式或重新适配驱动;Docker 镜像则遵循 OCI 标准,只描述“文件 + 元数据 + 运行命令”,无论在笔记本、测试机还是云服务器,上下“一条 docker run”即复现同一环境。开发写好 Dockerfile 后,流水线能自动构建镜像、推送仓库、上线生产;若版本有误,拉回上一个镜像便能回滚。这样的交付模型把“软件跑不跑”从系统工程降维成镜像管理,大幅削减了“在我机子好好的”式扯皮。
Docker 引擎可以从 Docker 网站下载,也可以基于 GitHub 上的源码进行构建。无论是开源版本还是商业版本,都有 Linux 和 Windows 版本。Docker 引擎主要有两个版本:企业版(EE)和社区版(CE)。
每个季度,企业版和社区版都会发布一个稳定版本。社区版本会提供 4 个月的支持,而企业版本会提供 12 个月的支持。从 2017 年第一季度开始,Docker 版本号遵循 YY.MM-xx 格式,类似于 Ubuntu 等项目。例如,2018 年 6 月第一次发布的社区版本为 18.06.0-ce。
1.3 什么是容器化技术
容器共享主机内核,轻量、隔离且高效,不像虚拟机需要完整的操作系统,下图展示了 Docker 容器的基本架构:
上层 是多个容器(App A~F),每个容器独立运行一个应用。
中间层 是 Docker,负责管理这些容器。
底层 是主机操作系统(Host OS)和基础设施,为容器提供硬件和系统支持。

1、传统应用部署的痛点
在传统的应用部署中,我们经常遇到以下问题:
环境不一致:应用在开发环境运行正常,但在测试或生产环境出现问题
依赖管理复杂:不同应用需要不同版本的运行时、库文件等
资源利用率低:传统虚拟机需要完整的操作系统,占用大量资源
部署复杂:需要手动配置环境、安装依赖,容易出错
2、容器化技术的解决方案
容器化技术通过以下方式解决了这些问题:
环境标准化:将应用及其依赖打包在一起,确保在任何环境中都能一致运行
轻量级:容器共享宿主机的操作系统内核,比虚拟机更轻量
快速部署:容器可以在几秒内启动,大大提高了部署效率
可移植性:一次构建,到处运行
3、容器化的核心理念
容器化遵循"不可变基础设施"的理念:
应用和环境被打包成不可变的镜像
每次部署都使用相同的镜像
配置通过环境变量或配置文件注入
问题修复通过重新构建镜像而非修改运行中的容器

1.4 Docker 核心概念
镜像 (Image):镜像是一个只读的模板,包含了运行应用所需的所有内容:代码、运行时、库文件、环境变量和配置文件。镜像就像是一个安装程序或者模板,它定义了应用运行所需的一切,但本身不能直接运行。如果当你想要创建一个软件,那么这个镜像通过复用创建容器就可以释放。
容器 (Container):容器是镜像的运行实例,是一个轻量级、可移植的执行环境。每个容器都有自己的文件系统、网络和进程空间;容器可以被创建、启动、停止、删除;如果镜像是类,那么容器就是对象实例。一个镜像可以创建多个容器,就像一个类可以创建多个对象。
仓库 (Repository):仓库是存储和分发镜像的地方,可以包含一个镜像的多个版本。 公共仓库:如 Docker Hub,任何人都可以使用 私有仓库:企业内部搭建,用于存储私有镜像 官方仓库:由软件官方维护的镜像仓库
架构组件:

想像你在厨房做饭:手机里有菜谱(镜像),冰箱里存着半成品(Registry),灶台上正在咕嘟咕嘟的锅就是正在运行的菜(容器)。Docker 的整体架构几乎就是把这一日常流程数字化——只不过“菜谱”被写成 Dockerfile,“冰箱”换成远程镜像仓库,而“灶台”是一台安装了 Docker 引擎的服务器。
Client(客户端,执行命令的窗口)。这其实就是你在终端里敲的 docker build / pull / run 命令。它好比大厨的语音指令:告诉厨房“去拿菜谱、下单采购、开火做菜”。Client 本身不干粗活,它把指令递给后厨总管——Docker daemon。所以图上你看到一条虚线从 Client 指向 daemon。
Docker daemon 住在 DOCKER_HOST 里,可以是一台实体机,也可以是你的 Windows 或 Mac 上的 WSL2。daemon 接到指令后会做两件事:第一,处理镜像仓库的“订货单”;第二,负责开炉灶、端菜,也就是创建和维护容器。它就像餐厅后厨的大总管,既要和仓库沟通进货,也要调度厨师翻锅。
daemon 管的第一块地盘叫 Images。镜像就像菜谱+半成品,把程序和依赖封成一包。它可以来自两条渠道:要么本地 docker build 现做,要么 docker pull 从远程 Registry 拉取。Registry 在图的最右侧,标着 Ubuntu、Redis、Nginx 等标签——那是公共冰箱,存放着别人已经做好的镜像。daemon 一旦收到镜像,就把它放进本地主机的“镜像仓库”一栏,等着调用。
在镜像准备就绪后,大总管会执行 docker run。这一步把镜像复制出来,附上一层隔离的文件系统、网络、进程空间,点火启动,成了 Containers。容器是一份正在翻炒的菜,它消耗宿主的 CPU、内存,却彼此隔离,互不串味。图里三个竖排的盒子代表同时在线的三个容器——可能同一份镜像做出来的多份菜,也可能来自不同镜像。
整条黑色虚线就是数据流:Client 下指令 → daemon 去 Registry 取镜像 → 镜像落地 → run 成容器 → 容器运行完毕再被垃圾回收。
2 安装docker
2.1 windows 安装 docker
Windows 版 Docker 需要运行在一个安装了 64 位 Windows 10,windows11 操作系统的计算机上,通过启动一个独立的引擎来提供 Docker 环境。在以前windows并不支持Dokcer,在2019年的一次补丁更新中加入了对应的补丁加上了HypeV模块,带来了WLS模块。
所以,检查你的电脑系统版本 LTSC 的企业稳定版不支持,并且 win10 1903 版本以下的系统无法使用Docker需要你升级系统,如果你是 21Hxx 22Hxx 全部都在 1903版本以上不用担心,并且Windows 必须是 64 位的版本,CPU 是Arm 还是 x86 的都无所谓。
本质上来说windows兼容Docker的基本是本身windows虚拟化了一个Linux,在内部虚拟化的Linux系统(WSL)中跑docker的核心容器,并且提供了一个简单部署和管理的软件功能,使其管理和使用更加方便;
第一步 按键盘 win + Q 在搜索框中搜索 启用或关闭 Windows 功能;确认
Hyper-V、容器、适用于Linux的Windows子系统复选框已经被勾选,并单击确定按钮。



有些同学可能没有找到 Hype-V 或者容器 或者 适用于Linux的Windows子系统的选项,说明你使用的是windows家庭版并不是专业版,家庭版这些功能是默认开启的,如果你尝试还是安装后报错无法打开那么你可以试试在Vmware中创建Linux虚拟机,教程见2.2
当你点击确定后会提示正在升级和安装内容,要求必须重新启动才可以生效,在重启后就可以开始安装Docker了。这边建议在观望安装最新版,或者安装老师预留的安装包。
访问 Docker 的下载(https://www.docker.com/products/docker-desktop)页面,并单击其中的 Download for Windows AMD64 按钮
访问 Docker 的下载(https://www.docker.com/products/docker-desktop)页面,并单击其中的 Download for Windows AMD64 按钮。

找到上一步下载的安装包并运行即可。以管理员身份运行安装向导,并按照提示一步一步完成整个安装过程。安装完成后 Docker 会作为系统服务自动启动,并且在 Windows 的通知栏看到 Docker 的大鲸鱼图标。
恭喜!到目前为止已经成功完成 Windows 版 Docker 的安装,当我们遇到了要文明登录注册的提示的时候我们是可以全部跳过的,他通常显示在弹出窗口的下面不是很显眼。
但是这个时候我们的Docker启动是不成功的,我们可能没法下载到windows提供的WSL2在线安装服务导致服务出现问题,我们可以安装 003 software 中老师留的 wsl_update_x64.msi 软件进行安装;这相当于离线的安装WSL2软件 在线下载
下载完之后点击安装,安装过程非常傻瓜化,没有多余选项,一步下来即可完成


在windows图标位置右键 选择终端管理员 出现带有 管理员字样的 cmd 窗口。 输入
wsl --set-default-version 2这是wsl 为默认的版本 输入wsl -v返回版本信息就对了
》注意 WSL 功能 或者 HypeV功能会在你安装安卓模拟器的时候冲突甚至关闭使用,会导致docker损坏,请你尽可能不用或者使用 mumu 模拟器此时你退出(在任务托盘或者任务管理器里面彻底关掉)docker 再重新启动就好了,你在cmd窗口输入 docker version 命令也应该不会有问题。
配置下载源 国内屏蔽docker官方仓库,我们需要的镜像和软件都无法拉取或者拉取过慢,就需要我们修改配置源给默认的地址改成国内可以加速和代理的地址。在软件设置中找到 Docker Engine ,删除之前的内容 输入下面的内容
{
"registry-mirrors": [
"https://docker.1panel.live",
"https://docker.1ms.run"
]
}
我们之前默认安装的WSL2的位置是C盘,如果我们的容器运行时间长了或者装的多了会大量占用我们C盘的空间,那么我们就需要修改位置。
先彻底关闭Docker软件,之后还是打开 管理员终端 的 cmd 窗口,输入
wsl --list --verbose这会输出你当前的所有wsl2系统,通常情况下会有一个名为 docker-desktop 的系统,我们用这个来举例子,如果你的不叫这个名字我们还是安装下面步骤同理修改即可。# 这一步在关闭 wsl wsl --shutdown # 检查发行版系统 wsl --list --verbose # NAME STATE VERSION #* docker-desktop Stopped 2 # 创建一个目录 作为 WSL存放目录 mkdir D:\WSL\backup # 导出docker-desktop系统为docker-data.tar wsl --export docker-desktop D:\WSL\backup\docker-desktop.tar # 先注销之前的 docker-desktop wsl --unregister docker-desktop # 解压并且恢复导出的tar包 wsl --import docker-desktop D:\WSL\docker-data D:\WSL\backup\docker-desktop.tar --version 2
之后我们启动docker就正常了,我们释放了WSL到C盘以外的其他位置了。
注意,下面的代码会有 “\” 符号 或者“`” 这些表示的是换行符,在Linux下请使用“\” windows 下请使用 “`” ,并且请不要拿普通cmd 运行,一定得是管理员身份运行。这个符号本身还是命令没有完成的换行,但是windows规范下的cmd不认识也没有转义符 通常只能在管理员权限下的cmd才可以识别。
2.2 Linux 安装Docker的方法
Docker支持64位版本的CentOS 7.9和CentOS 8及更高版本,它要求Linux内核版本不低于3.10。
[ ~]$ uname -r
3.10.0-1160.45.1.el7.x86_64
可以看到,当前Linux内核版本满足Docker的需要。
https://www.alibabacloud.com/help/zh/ecs/use-cases/install-and-use-docker#4787944e3bwid 不同操作系统安装教程(阿里云)
手动安装: 手动安装Docker分三步:卸载、设置仓库、安装。
卸载历史版本。这一步是可选的,如果之前安装过旧版本的Docker,可以使用如下命令进行卸载:
yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-selinux \
docker-engine-selinux \
docker-engine \
docker-ce安装
# 如果你没有修改yum源 按照提示一直回车即可
bash <(curl -sSL https://linuxmirrors.cn/main.sh)
# 安装前置软件
sudo yum install -y yum-utils device-mapper-persistent-data lvm2 wget
#添加Docker软件包源
sudo wget -O /etc/yum.repos.d/docker-ce.repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
sudo sed -i 's|https://mirrors.aliyun.com|https://mirrors.aliyun.com|g' /etc/yum.repos.d/docker-ce.repo
#安装Docker社区版本,容器运行时containerd.io,以及Docker构建和Compose插件
sudo yum -y install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
#启动Docker
sudo systemctl start docker
#设置Docker守护进程在系统启动时自动启动
sudo systemctl enable docker
# 安装 docker compose
sudo yum -y install docker-compose-plugin
sudo docker compose version补充 Docker下载换源:
# 创建一个名为 /etc/docker/daemon.json 的文件
vi /etc/docker/daemon.json
# 在文件中添加国内镜像源地址(以下为示例):
{
"registry-mirrors": [
"https://docker.1panel.live",
"https://docker.1ms.run"
]
}
# 重新加载配置并重启服务:
sudo systemctl daemon-reload
sudo systemctl restart docker
# 执行以下命令检查镜像源是否已生效:
docker info | grep -A 10 -i registry
# 输出中应包含配置的镜像源地址,
# Registry Mirrors:
# https://docker.1panel.live
# https://docker.1ms.run/3 Docker 基础操作
3.1 第一条镜像拉取命令
在学习 Docker 的旅程中,第一步往往是让自己的机器上真正“看到”Docker 能够运行的东西。docker run hello-world 是官方推荐的起点,它不仅验证了 Docker Engine 的安装是否成功,还向你展示了镜像、容器以及生命周期之间的基本关系。
当它执行时,Docker 客户端会先询问守护进程:本地有没有叫做 hello-world 的镜像。假如从未使用过 Docker,守护进程会自动访问默认 Registry,拉取那张只有数十 KB 的镜像文件。
镜像下载完毕后被解压到宿主机的镜像缓存区,再被复制一份生成“容器实例”。此刻,镜像是静态模板,容器是动态进程。容器启动后在标准输出写下一句“Hello from Docker”,随后优雅退出,生命周期随即终止。屏幕能否出现那行文字,是 Docker 工作链路是否完整的最直观验证。
理解这一流程,我们就能区分三个概念:镜像存储在磁盘,容器运行于内存,客户端只是指令的发起者。以后每当键入 docker run,我们可以迅速勾勒出镜像落地、容器生成、进程启动、标准输出反馈的四步。
这个例子中的容器只跑一次就退出,正好演示了 “创建 → 启动 → 运行 → 停止” 的完整周期。
实操:打开cmd 输入 docker run hello-world 等待运行并且创建实例,返回HelloWorld内容

3.2 常用控制命令:ps stop rm logs exec
当你熟悉了 docker run 的基本流程后,下一步是学会管理已运行的容器。Docker 提供了一系列命令来查看、停止、删除以及与容器交互。当容器不再是一次性的“Hello”,而是长时间运行的 Nginx 服务时,我们需要学会与它互动。
查看正在运行的容器:
docker ps 显示所有当前活跃的容器,包括它们的 ID、镜像名、启动时间和映射端口等信息。你可以用 -a 参数把已经退出但未被清理的容器也列出来。
停止与删除
停止:
docker stop <container-id>给容器发送 SIGTERM,默认等待 10 秒后强制终止。删除:
docker rm <container-id>把已停止或未运行的容器从宿主机上彻底移除。查看执行日志
docker logs <container-id>能让你看到容器里进程输出的标准输出和错误流,尤其在调试时非常有用。加-f可以持续跟踪最新日志。进入容器内部执行命令
我们创建完这个容器之后我们是可以操作他的,他可以当做一个正常的系统或者操作环境来操作(常规情况下都是Linux)最常见的方式是
docker exec -it <container-id> /bin/bash它会打开一个交互式 shell,让你像登录本地机器一样操作容器。你可以在这个 shell 中运行
apt-get update、安装软件包或直接编辑文件。
如何退出容器? 正常使用 Ctrl+C 是无法关闭的 ,这里我们直接使用 exit 输入 然后回车就可以直接关闭连接。
练手任务:
用
docker run -d --name nginx-server nginx启动一个 Nginx 容器并让它后台跑。通过
docker ps确认容器正在运行。使用
docker exec -it nginx-server /bin/bash进入容器,打开/usr/share/nginx/html/index.html并把内容改为 “Hello Docker”。用
docker logs nginx-server检查 Nginx 是否正常启动。最后使用
docker stop nginx-server停止并用docker rm nginx-server删除。
3.3 镜像拉取与版本标签 pull、tag、rmi
镜像是 Docker 的核心资产,理解如何管理镜像的不同版本对日后的项目维护至关重要。Docker Hub 上几乎每个官方镜像都有多个 tag,代表了同一软件在不同环境下的构建结果。
拉取指定版本或者特征标签的镜像:docker pull redis:6.2 会拉取 Redis 6.2 的镜像;如果你省略标签,默认会拉取 latest(最新版)。 小技巧:使用 docker image ls 查看本地已有的镜像列表,避免重复下载。
给下载镜像打新标签:有时你想给同一镜像添加自己的业务标签,例如把 Redis 6.2 标记为 “my-redis”。执行 docker tag redis:6.2 my-redis:latest。这样,你可以用更直观的名字来引用镜像,而不必每次都写完整路径。
删除无用镜像:当磁盘空间紧张时,docker rmi <image-id> 可以帮助你删除不再需要的镜像。记住在删除的时候要保证我们没有实例化的容器用了这个镜像,如果有请先删除,否则会报错。
练手任务:
拉取
redis:5、redis:6与redis:7三个版本。用
docker image ls比较三者的大小(注意redis:7通常比 6 略大)。给其中一个镜像打上自定义标签,例如
my-redis:v1。删除掉你不再需要的旧版本,并确认空间已释放。
3.4 端口映射与环境变量:-p -e
服务要对外提供接口,就必须突破容器与宿主机之间的网络边界。以 MySQL 为例,先执行:
docker run -d `
--name my-mysql `
-e MYSQL_ROOT_PASSWORD=mysecret `
-p 13306:3306 `
mysql:8.0-e 选项把环境变量注入容器,让初始化脚本自动为 root 账户设置密码;-p 宿主端口:容器端口 则把宿主机 13306 端口映射到容器的 3306。我们此时可在自己的 IDE 里配置连接字符串 localhost:13306,像连本机数据库一样访问 MySQL。 如果想再开一台只读副本,只需换个容器名和映射端口即可。通过实践,他们会认识到 Docker 网络模式的默认桥接行为,并能灵活使用环境变量完成一键配置。
想要添加多个端口映射?多写一行 -p 就可以了; Docker 会按顺序解析,每组映射一对端口。-e 根据实际Docker镜像源的要求可以选择加和不加(这个参数不是我们能决定的,是开发者规定的一部分,通常会在文档中体现出来或者解码 docker file 源文件)
3.5 数据卷初体验:-v Bind Mount
在前面实验中,你们可能注意到,删除容器后所有数据随之蒸发。为了持久化数据或实现热更新,需要引入卷(Volume)。最直观的方式是 Bind Mount,把宿主机的目录直接挂进容器文件系统。 假设本地有一个 D:\webroot,里面放着正在开发的静态网页。运行:
docker run -d --name web-demo -p 8080:80 `
-v D:\webroot:/usr/share/nginx/html:ro `
nginx浏览器打开 http://localhost:8080,即可看到宿主机目录里的网页。此时在 VS Code 改动 index.html,保存后刷新浏览器马上生效,因为 Nginx 直接读取了宿主机文件。加上 :ro 只读标志,可以避免容器进程误写源文件。 通过这一步,我们学会三件事:数据卷让容器与宿主机共享文件;卷路径既可只读也可读写;热更新开发体验完全不输本地跑服务。更重要的是,他们理解了“把修改放在宿主机”与“让容器保持无状态”之间的设计理念——这正是后续持续集成、持续交付的基石。
4 网络与存储管理
4.1 Docker 网络模式
在宿主机上安装 Docker 之后,系统会默认生成一张叫 bridge 的虚拟网桥,任何新建容器都会掉进这张网里。
当你在单台机器上跑多个容器时,默认的 bridge 网络已经足够用来实现内部通信。它会为每个容器分配一个私有 IP,并且所有桥接网络上的容器都能互相 ping、访问。
它的作用有点像宿舍楼里的集线器:所有同学连在一起,却又不会直接暴露在校园网外部。除默认网桥外,Docker 还提供 host 和 none 两种模式。 host 让容器直接借用宿主机网络栈,端口映射不再生效、性能更高,直通网络分配IP; none 则彻底隔绝网络,仅保留本地 loopback ,常用于安全隔离或自定义网络实验。
实战练习:创建一个显得网络并且查看默认的 bridge 模式带来的效果
创建一个新的网络和两个容器,随后进入 box1 后执行 ping box2,DNS 会自动解析出 box2 的容器 IP 并成功连通。我们此时能直观看到:把容器丢进同一张自定义网,就像把两台电脑插到同一交换机里,彼此之间天然能通信,且不会污染系统默认网络空间。
操作路径代码:
# 创建一个名为 study-net 的网络
docker network create study-net
# 创建一个名为box1的容器
docker run -dit --name box1 --network study-net busybox
# 创建一个名为box2的容器
docker run -dit --name box2 --network study-net busybox
# 进入box1
docker exec -it box1 sh
# ping box2
ping box2
# 退出
exit;进入 box1 的命令是
docker exec -it box1 shBusyBox 是一个极度精简的 Linux 工具集,旨在提供最小化、轻量级的容器镜像。它默认只包含 sh 而不包括完整的 Bash,使用docker exec -it box1 /bin/bash时,Docker 无法找到/bin/bash可执行文件,自然报错这个要注意
网络的查看、修改与清理
Docker 把“增删改查”都收进了 docker network 子命令:
docker network ls能列出宿主机的全部网络,默认能看到 bridge、host、none,再加你刚才的 study-net。docker network inspect study-net可查看这张网桥分到的子网、网关以及已经加入的容器列表。如果容器正跑在默认网桥,也可以随后接入新网络:
docker network connect study-net box1。同理,退出某条网络用docker network disconnect。这一点对运行中的服务尤其有用——不用重启就能把它拉进另一张“局域网”。当一张自定义网桥不再需要,先把里头的容器都 disconnect,再执行
docker network rm study-net彻底删除。若想一键清掉所有无用网络,可使用docker network prune,不过要牢记它会删除所有“未使用”的自定义网络,操作前最好确认没有遗漏连接。
小心常见误区
host 模式并不会给容器分配新 IP,而是让容器与宿主共享同一个网络命名空间。此时
-p端口映射不生效,因为根本不存在 NAT;一旦容器里的服务监听 80 端口,就直接占用了宿主的 80。none 模式下即便
docker exec进入容器,也只有 127.0.0.1 能用;一切外部访问都被切断。如果你发现容器连自己都 ping 不通,十有八九是起错了网络模式。BusyBox 没有 bash,要进入 BusyBox 容器请用
sh;否则会报 “No such file or directory”。这一点在调试网络时很容易踩坑。
网络配置在创建容器的时候可以设置,而不是一整个网络都是这个配置,这大大提升了灵活度和可玩性,当然你也可以手动修改单个容器的网络类型,下面是创建的一个容器 从一个网络转移到另一个网络,然后修改他的类型为host 的例子
1️⃣在创建容器的时候就确定容器的网络
docker run -dit --name box1 --network study-net busybox2️⃣在运行的时候切换到另一个网络 先把 box1 从之前的网络脱离
docker network disconnect study-net box1然后加入新的网络docker network connect bridge box13️⃣修改host模式
host网络直接复用宿主机网络栈,Docker 本身不允许把一个正在运行的容器强行“升级”为 host。因此最安全做法是关停并重建:docker stop box1 docker rm box1 docker run -dit --name playground --network host box1
4.2 容器 DNS 与别名
当容器数量增长,手记 IP 既枯燥又容易出错。Docker 在自定义网络里自带 DNS 服务,每个容器名字都会注册成可解析的主机名。用上一节已有的 Redis 镜像做实验:
# 创建一个名为myredis的容器 网络来自 study-net
docker run -d --name myredis --network study-net redis
# 创建一个名为myredis的容器 网络来自 study-net
docker run -it --rm --network study-net busybox sh在 busybox 里执行 redis-cli -h myredis ping,可以直接看到 PONG。此时我们可以理解到什么是“容器名即地址”。曾经的 --link 选项也能实现类似效果,不过它依赖旧版桥接脚本,官方早已标记为过时。对新项目来说,自定义网络 + 自动 DNS 才是推荐方式。
如果想给同一容器起多个别名,可在 docker run 时追加 --network-alias,例如把 myredis 同时注册成 cache:
# 创建一个名为myredis的容器并且起DNS名为cache redis
docker run -d --name myredis --network study-net --network-alias cache redis之后 redis-cli -h cache ping 同样奏效。我们可以把不同环境写进一份 compose,通过别名自由切换后端,不再硬编码 IP。
4.3 卷的进阶用法
上一阶段已经体验过 Bind Mount,把宿主目录硬塞进容器。接下来要让你们认识“匿名卷与具名卷”这两种更 Docker 式的持久化方案。匿名卷没有显式名字,只在容器删除时自动回收;具名卷则像随身 U 盘,即便容器销毁,数据仍在。
创建具名卷并保存 MySQL 数据的完整流程如下:
docker volume create mysqldata
docker run -d `
--name db `
-e MYSQL_ROOT_PASSWORD=pwd123456 `
-v mysqldata:/var/lib/mysql `
mysql:8.0此时 docker volume inspect mysqldata 能看到实际存放路径。 停掉并删掉容器:docker stop db && docker rm db
再次 docker run 同样挂载 mysqldata,MySQL 会立刻认出之前写入的表。我们亲手验证“数据不丢”后,会理解具名卷对业务连续性的意义。为了迁移数据,只需:
备份压缩我们之前创建的内容然后在合适的地方释放即可,还用之前的内容创建容器即可,我们此时再连接数据库我们可以看到我们创建的数据库内容并没有消失。
实际操作步骤:
# ① 创建名为 mysqldata 的卷
docker volume create mysqldata
# ② 以后台方式启动 MySQL,并将 mysqldata 挂载到 /var/lib/mysql(MySQL 默认数据目录)
docker run -d `
--name db `
-e MYSQL_ROOT_PASSWORD=pwd123456 `
-v mysqldata:/var/lib/mysql `
mysql:8.0
# 等待30秒 等mysql初始化完成 使用mysql远程连接器尝试访问 或者直接运行下面代码 直接通过代码链接并且注入命令
docker exec -it db mysql -uroot -pmysecret -e "CREATE DATABASE demo; USE demo; CREATE TABLE t1(id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(20)); INSERT INTO t1(name) VALUES('Alice'),('Bob'); SELECT * FROM t1;"
# ⑤ 停止容器
docker stop db
# ⑥ 删除容器(不删除卷)
docker rm db
# ⑦ 使用相同的卷再次创建容器 如果你要迁移给之前你挂载的
docker run -d `
--name db2 `
-e MYSQL_ROOT_PASSWORD=mysecret `
-v mysqldata:/var/lib/mysql `
mysql:8.0Windows中一般不使用docker中的这个功能,因为默认放在C盘而且不够灵活
4.4 日志与资源限制
当服务跑久了,就要关注“日志去哪”“资源吃多少”这样更贴近运维的问题。Docker 默认把容器标准输出写进 json-file 日志驱动,可用 docker logs -f 容器名 在线追踪。若希望日志进入宿主机的 syslog 或直接输出到外部日志系统,可以通过 --log-driver、--log-opt 在 run 时指定。课堂上不必深入配置,只要演示 docker logs -f nginx,我们见到实时滚动的访问记录即可。
资源限制更能引发直观冲击。安装 progrium/stress 镜像,运行一个刻意占内存的进程:
docker run --rm `
--name stress `
--memory 100m `
--memory-swap 100m `
--cpus 0.5 `
alpine sh -c "apk add --no-cache stress-ng && stress-ng --vm 2 --vm-bytes 600M --vm-keep --timeout 30s"
# 创建一个临时容器 内存 100mb 并且不带交换分区 cpu 50% 运行一个容器,这个容器运行一个测试 会启动两个线程 每个线程占用200Mb 持续30s因为 --memory 100m,容器在尝试申请 150 MB 时会触发内核 OOM,日志里能看到 kill 记录;同时 --cpus 0.5 把使用率锁死在 50 %。可以感受到 Docker 能像电闸一样给容器设上保险丝,不至于整个系统被误操作拖死。
现在Docker的最新策略会做掉配,你现在应该用这个命令看不到 Kill 的记录了 但是你依然可以看到内存被严格控制在200m
5 docker-compose 和 容器封装
5.1 docker-compose
曾经我们在终端里一条一条地 docker run,先起数据库,再起后端,最后映射端口给前端。三条命令改版本时得三处同步,换台电脑还得把所有参数重敲一次。docker-compose 的出现正是为了解决这种“动手过多带来的出错机会”。
它把命令行里的长串选项写进一份 compose.yml,把“怎么启动”变成一份声明。阅读文件就等于阅读部署文档,执行 docker-compose up -d 便等于把文档落成现实。
下面是一份极小的示例。你在仓库根目录新建 compose.yml,内容只有短短几十行,却囊括了端口映射、环境变量、卷挂载、容器间网络四件事:
services:
web:
image: nginx:latest
ports:
- "8080:80"
db:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: secret
volumes:
- dbdata:/var/lib/mysql
volumes:
dbdata:打开cmd 运行 docker-compose up -d 时,Compose 读取 services 区域,发现需要两个镜像,便自动拉取;它看见 ports 字段,就替你写好 iptables 规则;它发现两台服务都没有显式 network,于是自动生成一张私有网桥,并把 web 与 db 的主机名注册为内置 DNS。所有动作都在后台静默完成,终端只留一句“Creating … done”。停掉整个应用也只需 docker-compose down,卷仍然保留,数据不丢。如此一来,版本号或者镜像仓库地址的变更只需改文本,再次 up 即可复现同样部署。
保存之后 docker-compose up -d --force-recreate,浏览器改访问 http://localhost:8080/,页面依旧出现,这一刻他们会直观体会到“配置即部署”的力量。
5.2 docker 镜像封装
我们前面的学习都是在使用别人的镜像包,那么我们怎么封装一个Docker镜像呢?
首先 你最好有一个 Vscode 软件 下载链接:https://code.visualstudio.com/ 然后创建一个空文件夹 例如 docker-demo,拖入Vscode软件中打开
hello.sh
#!/bin/sh
echo "Hello, $(uname -o) inside container! Time: $(date)"
# 这个代码就是一个简单的输出,类似于给你说了一句HelloWorldDockerfile
# 选用极简的 Debian-slim 作为基础层
FROM debian:stable-slim
# 把脚本复制进镜像
COPY hello.sh /usr/local/bin/hello.sh
# 授权可执行
RUN chmod +x /usr/local/bin/hello.sh
# 容器启动时默认执行脚本
CMD ["/usr/local/bin/hello.sh"]脚本内容很朴素:打印一句问候,加上操作系统标识和时间,便于看见“这是容器内部时钟”。
Dockerfile文件是用于构建镜像的关键文件,我们在执行创建镜像的指令时,docker会自动寻找指定目录下的Dockerfile文件,并读取和执行相关指令。
一般情况下我们的项目都是从一个最基础的模板环境开始的,可以是一个Linux如上面所示,也可以是一个negix等等的软件,当然他们底层肯定也是基于Linux环境封装的。 有了基础环境我们把需要用的的文件从我们的项目中拷贝到容器里面,使用 RUN 可以在内部注入操作,最后CMD表示的是在启动的时候执行什么操作(这些代码的灵活使用和组合就可以构建起很复杂的一个系统)
在 docker-demo 目录打开终端:docker build -t hello-image:v1 . -t 给镜像打上名字 hello-image 与标签 v1。 . 表示 Dockerfile 位于当前目录。
构建完成后,docker images | grep hello-image 能看到几十兆大小的镜像文件。 运行:docker run --rm --name hello-run hello-image:v1 终端应打印类似:Hello, GNU/Linux inside container! Time: Mon Aug 29 13:45:02 UTC 2025 再次执行,会看到时间更新,证明脚本确实在容器启动时被运行。
如果你想要迭代第二版本,你可以直接修改前面的代码,然后重新编写Dockerfile,或者复用修改Dockerfile。打包,运行,在名字的选择上可以使用 hello-image:v2
好的,到目前为止这个可爱的小鲸鱼(docker)已经被你掌握了,后面很多的软件和程序都可以使用docker进行安装,甚至在Linux中可以模块化的管理和使用,说到这个这边大家可以在Linux中安装 1panel 这个是Linux运维面板可以更简单直接的管理软件和内部的资源,本身也是由Docker驱动。(不建议在后面学习大数据的虚拟机中安装这个,大家资源不够会拖慢Linux执行效率和运行速度)
- 感谢你赐予我前进的力量

