docker 基础知识
Docker 是一个开源的应用容器引擎。它允许开发者将应用及其所有依赖(如库、环境变量、配置文件等)打包到一个标准化的单元中,这个单元就称为容器。
你可以把它想象成一个非常轻量级的虚拟机,但它不像虚拟机那样模拟整个操作系统,而是共享主机系统的内核,从而实现了极高的效率和资源利用率。
镜像是一个只读的模板或快照。它包含了运行某个软件所需的一切:代码、运行时环境、系统工具、系统库和设置。
容器是镜像的一个运行时的实例。当你运行一个镜像时,Docker 会创建一个可写的容器层,你的应用就在这个隔离的环境中运行。一个镜像可以创建多个容器(就像一个类可以创建多个对象)
Docker 的强大并非来自某项单一的技术,而是巧妙地组合了 Linux 内核的几项关键技术,主要实现资源隔离和资源限制。
1. Namespaces(命名空间) - 实现隔离
命名空间负责提供隔离性,让每个容器觉得自己拥有一个独立的系统环境,看不到其他容器或主机上的进程。
- PID Namespace: 隔离进程 ID。容器内的第一个进程 PID 为 1,它看不到主机上的其他进程。
- Net Namespace: 隔离网络栈。每个容器有自己的网络设备(如 eth0)、IP 地址、端口和路由表。
- Mount Namespace: 隔离文件系统挂载点。容器只能看到自己的文件系统视图。
- UTS Namespace: 隔离主机名和域名。允许容器拥有自己的
hostname。 - IPC Namespace: 隔离进程间通信资源。
- User Namespace: 隔离用户和用户组 ID。
2. Cgroups(Control Groups,控制组) - 实现资源限制
Cgroups 负责限制和记录一个进程组所使用的物理资源,防止某个容器耗尽主机上的所有资源。
- 限制资源: 可以设置容器使用的CPU、内存、磁盘 I/O 等资源的上限。
- 优先级: 可以设置资源使用的优先级。
- 计量: 监控资源的实际使用情况。
3. Union File Systems(联合文件系统) - 实现镜像分层
UnionFS 是一种分层、轻量级并且高性能的文件系统。它支持将不同目录(称为层)的内容透明地叠加,形成一个单一连贯的文件系统视图。
- Docker 镜像: 就是由一系列只读的 UnionFS 层组成的。
- Docker 容器: 在启动时,会在镜像的所有只读层之上添加一个可写的空白层。所有对容器的修改(写操作)都会应用到这个可写层(这被称为“写时复制”,Copy-on-Write)。
- 常见的驱动有:
overlay2,aufs,devicemapper。
4. 容器运行时(Container Runtime)
虽然 Docker 最初使用自己的 runc,但现在它遵循 OCI(开放容器倡议) 标准。其核心是一个低级别的运行时工具,负责与操作系统内核交互,直接创建和运行容器。
containerd: 是一个负责管理容器生命周期(pull镜像、创建、启动、停止容器)的守护进程。Docker Engine 通过containerd来操作容器。runc: 是一个轻量级的命令行工具,它根据 OCI 规范来真正地创建和运行容器。containerd会调用runc来执行具体任务。
docker client、docker daemon、containerd 都是什么?
- Docker Client (客户端) :就是你平时在命令行里打的
docker命令(如docker run,docker ps)。它的唯一工作就是告诉Docker守护进程该做什么。 - Docker Daemon (守护进程 -
dockerd) :这是一个常驻在后台运行的进程。它是Docker的核心引擎,接收来自Client的命令,并负责高级功能,如构建镜像(docker build)、管理网络、管理数据卷等。它把关于容器生命周期(运行、停止)的具体操作都交给containerd去办。 containerd:也是一个常驻在后台的守护进程。它是一个更专注的容器运行时管理器,专门负责容器的生命周期操作——拉取镜像、创建、启动、停止、销毁容器。它被设计成可以被其他系统(比如Kubernetes)直接调用,而无需经过Docker Daemon。它在Docker生态中承上启下的作用。
runc 是什么?和 containerd 啥关系?
runc:它是一个极其简单、轻量级的命令行工具(不是守护进程)。它只做一件事——根据OCI标准(一个开放容器格式的规范)来创建和运行容器。它直接调用操作系统内核功能,是真正“创建”容器进程的那个点。- 关系:
containerd是管理者,runc是执行者。containerd为了完成“启动一个容器”这个任务,它会去启动一个runc进程,并告诉它:“去,用这个镜像,用这个配置,给我跑一个容器出来”。一个containerd可以管理无数个runc进程。
核心比喻:餐厅厨房
我们把整个Docker工作流程想象成一家餐厅的厨房:
- 你(用户) :顾客,来点菜。
docker命令(Docker Client) :服务员。你告诉服务员你想要什么(比如“一份清炒时蔬”)。- Docker 守护进程(Docker Daemon -
dockerd) :餐厅经理。服务员把订单交给经理。经理负责统筹全局,理解订单,但自己不亲自做菜。他决定需要哪些食材(镜像),并命令厨师长去执行。 containerd:厨师长。经理把任务派给厨师长。厨师长管理着所有厨房资源,负责整个做菜的流程:从仓库取食材、安排厨师干活、监督菜品制作过程。他同样不亲自切菜炒菜。runc:炒菜厨师。厨师长命令一个厨师去真正地开火、炒菜。这个厨师是真正动手干活的人,但他只负责执行这一个具体命令。- 容器:做好的那盘菜。是最终运行的实例。
流程回顾(点菜过程) :
你(顾客)说:docker run nginx(服务员,来份nginx)
-> Docker Client(服务员)把命令告诉 Docker Daemon(经理)
-> Docker Daemon(经理)说:containerd(厨师长),我们需要运行一个nginx容器,你去搞定
-> containerd(厨师长)发现没有nginx镜像,就让手下(但通过经理)从仓库(Docker Hub)拉取镜像(取食材)。然后它命令 runc(炒菜厨师):你,用这个镜像当菜谱,给我做盘菜(启动容器)!
-> runc(炒菜厨师)调用Linux内核的各项技术(Namespace, Cgroups等)这个“厨房设备”,开始炒菜,最终把做好的菜(容器)端出来。
结论:docker (Client) 是入口,dockerd (Daemon) 是大脑,containerd 是管家,runc 是干粗活的小工。
+-----------------------------------+
| 你敲的命令行: docker run ... | -> Docker Client
+-----------------------------------+
| (通过REST API通信)
+-----------------------------------+
| Docker Daemon (dockerd) | -> 大脑/经理 (管理镜像、网络、卷等)
+-----------------------------------+
| (内部gRPC调用)
+-----------------------------------+
| containerd | -> 管家/厨师长 (专注容器生命周期管理)
+-----------------------------------+
| (遵守OCI规范调用)
+-----------------------------------+
| runc | -> 小工/厨师 (真正创建容器进程)
+-----------------------------------+
| (调用Linux内核API)
+-----------------------------------+
| Linux Kernel (Namespaces, etc.) | -> 厨房设备
+-----------------------------------+
docker 镜像管理命令
-
docker pull 下载镜像
功能:从 Docker 仓库下载镜像到本地
完整的 docker pull 命令 由四个部分组成 [registry_address/][namespace/][image_name][:tag]
如
docker pull docker.io/library/nignx:lates- registry_address 是Docker仓库的注册表地址。这里docker.io 是 Docker Hub官方仓库,可省略
- namespace 是命名空间,通常是作者或者组织名称。这里的library 是 Docker官方仓库的命名空间,可省略
- image_name 是镜像的名字
- tag 是镜像的标签名,通常表示版本号,lastest 表示最新版本,可省略
-
docker images 列出本地镜像
功能:列出本地镜像
REPOSITORY TAG IMAGE ID CREATED SIZE redis latest f1285ef3611d 4 weeks ago 137MB nginx latest 41f689c20910 5 weeks ago 192MB -
docker rmi 删除镜像
功能:删除本地镜像
参数:指定镜像名称或ID
docker 容器管理命令
-
docker run 创建并运行容器
功能:使用指定的镜像创建并运行一个容器,如果本地不存在指定镜像,docker 会自动拉取,再创建并运行
docker run nginx/docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration /docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/ /docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh 10-listen-on-ipv6-by-default.sh: info: Getting the checksum of /etc/nginx/conf.d/default.conf 10-listen-on-ipv6-by-default.sh: info: Enabled listen on IPv6 in /etc/nginx/conf.d/default.conf /docker-entrypoint.sh: Sourcing /docker-entrypoint.d/15-local-resolvers.envsh /docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh /docker-entrypoint.sh: Launching /docker-entrypoint.d/30-tune-worker-processes.sh /docker-entrypoint.sh: Configuration complete; ready for start up 2025/09/21 07:59:46 [notice] 1#1: using the "epoll" event method 2025/09/21 07:59:46 [notice] 1#1: nginx/1.29.1 2025/09/21 07:59:46 [notice] 1#1: built by gcc 12.2.0 (Debian 12.2.0-14+deb12u1) 2025/09/21 07:59:46 [notice] 1#1: OS: Linux 5.15.0-153-generic 2025/09/21 07:59:46 [notice] 1#1: getrlimit(RLIMIT_NOFILE): 1048576:1048576 2025/09/21 07:59:46 [notice] 1#1: start worker processes 2025/09/21 07:59:46 [notice] 1#1: start worker process 30 2025/09/21 07:59:46 [notice] 1#1: start worker process 31-
-d(detached mode)功能:让容器在后台执行,不阻塞当前终端窗口
docker run -d redis220f46accaa4513400c186ae8a132fe30a1a504810dfa4f5c5c60be7daeef9a9 -
-p(port mapping/端口映射)docker 容器运行在独立的虚拟网络中,默认无法直接从宿主机访问内部网络
功能:将宿主机的端口映射到容器内部的端口
docker run -p 5000:6379 redis将宿主机的 5000 端口映射到 redis 容器内部 6379 端口
-
-v(volumemounting / 挂载卷)功能:将宿主机的文件目录与容器内部的文件目录进行绑定 目的:实现数据的持久化,当容器被删除时,容器内部的数据也会被删除,但挂载卷后可以把数据保存到宿主机上
docker run -d -p 80:80 -v /website/html:/usr/share/nginx/html nginx -
-e(环境变量)功能:向容器内部传递环境变量
语法:
-e <key>=<value> -
--name(自定义容器名称)功能:为容器指定一个自定义的名称
docker run --name my_redis redis -
-
it(interactive & tty / 交互式终端)docker run -it <镜像名称> /bin/bash (或 /bin/sh) -
--rm(运行结束后自动删除)功能:当容器停止时,自动将其从宿主机删除
docker run --rm redis常与
-it组合使用,用于调试场景 -
--restart(重启策略)功能:配置容器停止时的行为 常用策略:
- always:只要容器停止(包括内部错误、断电等),就会立即重启
- unless-stopped:除非手动停止容器,否则都会尝试重启
-
-
容器启动与管理
- doker stop <容器id或名称>:停止一个正在运行的容器
- docker start <容器id或名称>:重新启动一个已经停止的容器
- docker inspect <容器id或名称>:查看容器的详细配置信息
- docker create <镜像名称>:只创建容器,但不立即启动
- docker rm <容器id或名称>:删除一个已经停止的镜像
-f强制正在运行的容器
- docker ps:查看正在运行的容器
-a查看所有的容器,包括已经停止的
-
容器内部操作与调试
-
docker logs <容器id或名称>:查看容器的运行日志
-f滚动查看日志、实时刷新
-
docker exec 在容器内部执行命令
功能:在一个正在运行的容器内部执行 Linux 命令
docker exec my_nginx ps -ef查看容器内部的进程进入交互式命令行环境:
docker exec -it <容器id或名称> /bin/bash(或/bin/sh)
-