一、Docker镜像
1.1 核心定义
Docker 镜像 是一个只读的模板,它包含了运行一个应用程序所需的所有内容:代码、运行时环境、系统工具、系统库和设置。
1.2 关键特性与原理
1.2.1 分层存储(Layer)
这是 Docker 镜像最核心、最精妙的设计。
-
只读层 :镜像由一系列只读层 叠加而成。每一层代表 Dockerfile 中的一条指令(例如:
COPY、RUN、ADD)。例如:-
第一层:基础操作系统(如
Ubuntu) -
第二层:安装
Python -
第三层:复制项目代码
app.py -
第四层:设置环境变量
-
-
联合文件系统 :当您启动一个容器时,Docker 会在所有只读层之上,添加一个可写的容器层。所有对运行中容器的修改(如写入日志、创建临时文件)都只发生在这个可写层。底层的镜像内容始终保持不变。
-
好处:
-
高效存储 :多个镜像可以共享相同的基础层。例如,如果你有10个基于
Ubuntu的镜像,你的硬盘上只存储一份Ubuntu基础层。 -
快速分发:传输镜像时,只需要传输本地没有的层,大大加快了下载速度。
-
可复用性:可以基于一个镜像轻松创建出新的、功能更丰富的镜像。
-
1.2.2 内容寻址存储
每个镜像和每一层都有一个基于其内容计算出的唯一加密哈希值(ID)。这保证了镜像内容的完整性和一致性。
1.3 镜像的生命周期与操作
1.3.1 创建镜像
-
从 Registry 拉取 :最常用的是从 Docker 官方的公共仓库 Docker Hub 拉取。命令:
docker search nginx(搜索镜像)docker pull nginx:latest(拉取镜像) -
使用 Dockerfile 。Dockerfile 是一个文本文件,里面包含了一条条构建镜像所需的指令。执行**
docker build -t my-app:1.0 .** 命令,Docker 引擎会读取当前目录下的 Dockerfile 并逐步执行指令,最终生成一个新的镜像,镜像名为my-app,镜像标签为1.0。 -
从文件载入 :可以将别人导出的镜像文件加载到本地。命令:
docker load -i my_image.tar -
从容器提交 (不推荐用于生产):对一个运行中的容器进行修改后,可以将其提交为一个新镜像。命令:
docker commit <container_id> my-new-image。这种方式不利于追溯和自动化,通常只用于临时调试。
1.3.2 查看与管理本地镜像
-
docker images:列出本地所有镜像。 -
docker rmi <image_id>:删除本地不需要的镜像。 -
docker image prune:清理未被使用的镜像(悬空镜像)。
1.3.3 分发与共享镜像
-
推送至 Registry :可以将本地构建的镜像推送到 Docker Hub 或私有的镜像仓库(如 Harbor、GitLab Registry)。命令:
docker push my-username/my-app:1.0 -
导出为文件 :可以将镜像保存为一个 tar 归档文件,方便离线分享。命令:
docker save -o my_image.tar my-app:1.0
二、Docker容器
2.1 核心定义
Docker容器 是 Docker镜像的一个运行实例 。你可以把它理解为一个轻量级、隔离的进程沙箱,这个沙箱里运行着由镜像定义好的应用程序及其所有依赖。
2.2 关键特性与原理
2.2.1 从镜像到容器
当你执行 docker run nginx:latest 时,Docker引擎会:
-
检查本地是否存在
nginx:latest镜像,若没有则从仓库拉取。 -
在镜像的只读层 之上,创建一个薄薄的可写层(容器层)。
-
分配一个唯一的容器ID,设置网络、存储等命名空间。
-
执行镜像中定义的启动命令(如
CMD ["nginx", "-g", "daemon off;"]),启动容器进程。
2.2.2 核心特性
- 轻量级:
容器直接共享宿主机的操作系统内核,无需像虚拟机(VM)一样模拟完整的操作系统,因此启动极快(秒级甚至毫秒级)、资源开销极小(只占用进程本身的内存和CPU)。
- 隔离性:
通过 Linux 内核的 Namespaces 技术实现隔离。每个容器拥有独立的:
进程空间(PID):容器内的进程ID从1开始,看不到宿主机或其他容器的进程。
网络空间(Net):容器可以有自己独立的虚拟网卡、IP地址、端口空间。
文件系统挂载点(Mnt) :容器看到的是自己的根目录
/。用户和用户组(User):可以在容器内建立独立的用户体系。
通过 cgroups 技术实现资源限制与核算,可以限制容器使用的CPU、内存、磁盘I/O等资源。
- 可移植性(一致性环境):
容器内包含了应用运行所需的所有库和依赖,确保了 "一次构建,到处运行"。在开发机、测试环境、生产环境,只要使用同一个镜像启动容器,运行行为就是一致的。
- 临时性(无状态/易失):
默认情况下,容器内的文件系统是临时的。容器的生命周期与其内部运行的进程一致,进程结束,容器就停止。对容器可写层的所有修改(如写入的数据、产生的日志),在容器删除后也会消失。这是理解容器存储的关键。
2.3 容器的生命周期与核心操作
容器的生命周期通常围绕以下几个核心命令和状态:
创建(Create) -> 运行(Running) -> 暂停(Paused)/停止(Stopped) -> 删除(Removed)
2.3.1 创建容器:
docker run [OPTIONS] IMAGE [COMMAND]:最核心的命令。它会创建并启动一个新容器。常用选项:
-d:后台运行(守护态)。
-it:交互式运行,分配一个伪终端,通常与/bin/bash结合使用进入容器内部。
--name:为容器指定一个名字。
-p:端口映射(主机端口:容器端口)。
-v:挂载数据卷(主机目录:容器目录)。
2.3.2 管理容器:
-
docker ps:查看正在运行 的容器列表。加-a查看所有容器(包括已停止的)。 -
docker stop <容器名/ID>:优雅地停止运行中的容器(发送 SIGTERM 信号)。 -
docker start <容器名/ID>:启动一个已停止的容器。 -
docker restart <容器名/ID>:重启容器。 -
docker pause/unpause <容器名/ID>:暂停/恢复容器内所有进程。 -
docker exec -it <容器名/ID> /bin/bash:进入一个正在运行的容器内部执行命令,这是调试和排查问题的关键命令。 -
docker rm <容器名/ID>:删除一个已停止 的容器。加-f可以强制删除一个运行中的容器(不推荐)。
2.3.3 查看容器信息与日志:
-
docker logs <容器名/ID>:查看容器的标准输出日志(即应用打印到控制台的信息)。加-f可以实时跟踪。 -
docker inspect <容器名/ID>:获取容器的底层详细信息(配置、状态、网络、数据卷等),以JSON格式返回。 -
docker stats:实时查看容器的资源使用情况(CPU、内存、网络IO等)。
2.4 容器数据持久化
由于容器的临时性,重要数据必须持久化存储,主要有两种方式:
2.4.1 数据卷(Volumes):
由Docker管理、存在于宿主机文件系统(通常在
/var/lib/docker/volumes/下)的存储区域。生命周期独立于容器,即使容器被删除,数据卷依然保留。
用法:
docker run -v my_volume:/app/data nginx
2.4.2 绑定挂载(Bind Mounts):
将宿主机上的一个指定目录或文件直接挂载到容器中。
常用于开发环境,实现主机代码与容器代码的实时同步。
用法:
docker run -v /home/user/project:/app nginx
2.4.3 临时文件系统(tmpfs mount):
将数据存储在宿主机的内存中,速度极快,但容器停止即消失。用于存储非持久化的敏感数据或临时文件。
2.5 容器网络
Docker为容器提供了多种网络模式,实现容器间、容器与外部世界的通信:
bridge(桥接) :默认模式 。容器连接到名为
docker0的虚拟网桥,通过NAT与外部通信。同一桥接网络内的容器可以通过容器名互访。
host:容器直接使用宿主机的网络命名空间,没有隔离。性能最好,但端口冲突风险高。
none:容器没有网络接口,完全隔离。
用户自定义网络:可以创建更复杂的自定义网络,提供更好的容器发现和DNS解析功能。
三、VSCode Dev Container
Dev Container 的核心思想是:将你的开发环境(包括运行时、工具、依赖库、甚至编辑器配置)容器化,并放入一个 Docker 容器中运行。 而你本地的 VSCode 则作为"前端",通过该插件无缝连接到这个容器内部进行开发。简单来说,它让你在 Docker 容器里写代码,但体验和在本机一模一样。使用Dev Container需要包含两个文件:devcontainer.json和Dockerfile,通常我们设计项目结构如下:
your-project/
├── .devcontainer/
│ ├── devcontainer.json # 你提供的配置文件
│ └── Dockerfile # 容器镜像定义文件
├── src/ # 项目源代码
├── CMakeLists.txt # 项目构建文件
└── ... # 其他项目文件
需要准备的软件与插件:
Visual Studio Code
Docker Desktop(Windows)或 Docker Engine (Linux)
VS Code扩展:Dev Containers(ms-vscode-remote.remote-containers)
3.1 核心功能与工作原理
3.1.1 一键构建开发环境:
-
你的项目根目录下包含一个配置文件(
.devcontainer/devcontainer.json),里面定义了需要什么基础镜像、要安装哪些扩展、运行什么命令等。 -
当你用 VSCode 打开这个项目时,插件会读取此配置,自动构建或启动一个 Docker 容器。
-
你无需在本地安装 Python、Node.js、Java、数据库等任何与项目相关的运行时和工具。
3.1.2 无缝连接与集成:
-
容器启动后,VSCode 的整个核心进程(语言服务、调试器、终端等)都会运行在容器内部。
-
你在 VSCode 里打开的终端,是容器内的终端;你运行的代码,使用的是容器内的环境;你安装的扩展,也可以指定安装在容器内部(与本地扩展隔离)。
-
你的项目代码目录,会被"挂载"到容器内,因此文件编辑是双向同步的。
3.1.3 环境完全一致与隔离:
-
一致性:无论你是在 Windows、macOS 还是 Linux 上,只要安装了 Docker 和 VSCode,就能获得完全相同的开发环境。这对团队协作和新成员 onboarding 至关重要。
-
隔离性:每个项目都可以有自己独立的、互不干扰的环境。项目A用 Python 3.8,项目B用 Python 3.11,完全不会冲突。