云原生启蒙:对Docker的基础认知
在云原生飞速发展的今天,Docker早已成为入门云原生的必备工具——它打破了“代码在我电脑上能跑,到服务器就崩”的困境,让应用部署、迁移变得简单高效。吃透Docker的核心概念和基础操作,就相当于打通了云原生学习的“第一关”。
一、Docker核心概念:镜像、容器、存储卷
学习Docker,首先要分清三个最基础、最核心的概念:镜像(Image)、容器(Container)、存储卷(Volume),三者相辅相成,构成了Docker的基础架构。
1. 镜像(Image):容器的“模板”
镜像可以理解为一个“只读的模板”,包含了运行应用所需的所有环境、代码、依赖包和配置文件。比如你要运行一个Nginx服务,Docker镜像就会包含Nginx的可执行文件、配置文件、基础操作系统(如Alpine、Ubuntu)等所有必要组件。
核心特点:
- 只读性:镜像一旦构建完成,就无法修改,若需修改,只能基于原镜像创建新的镜像层;
- 分层存储:镜像采用分层结构(类似叠积木),每一次修改都会新增一个层,底层镜像可被多个上层镜像共享,大大节省存储空间;
- 可复用:一个镜像可以创建多个容器,比如用一个Nginx镜像,能同时启动10个Nginx容器提供服务。
2. 容器(Container):镜像的“运行实例”
容器是镜像的“可运行实例”,相当于在镜像的基础上,增加了一个“可写层”,用于存储容器运行过程中产生的临时数据(如日志、临时文件)。如果说镜像是“静态模板”,那么容器就是“动态运行的应用”。
核心特点:
- 独立性:每个容器都是一个独立的隔离环境,拥有自己的文件系统、网络空间,互不干扰,就像一台台独立的“微型虚拟机”,但比虚拟机更轻量;
- 可启停:容器可以随时启动、停止、重启、删除,启动速度通常在秒级;
- 临时性:容器默认的存储是临时的,一旦容器被删除,容器内的临时数据会全部丢失(这也是存储卷存在的意义)。
3. 存储卷(Volume):容器的“持久化存储工具”
正如上面所说,容器的默认存储是临时的,为了保存容器运行过程中产生的重要数据(如数据库数据、配置文件),就需要用到存储卷(Volume)。
核心作用:
- 数据持久化:将容器内的目录挂载到宿主机的目录或网络存储上,即使容器被删除,数据依然保存在挂载点,不会丢失;
- 数据共享:多个容器可以挂载同一个存储卷,实现容器间的数据共享(比如一个容器写入数据,另一个容器读取数据);
- 简化备份:直接备份宿主机上的挂载目录,即可实现容器数据的备份,无需进入容器操作。
二、必备命令:docker image与docker container
掌握镜像和容器的常用命令,是实操Docker的基础。
1. 镜像相关命令(docker image)
docker pull <镜像名:标签>:从Docker Hub(官方镜像仓库)拉取镜像,例:docker pull nginx:latest(拉取最新版Nginx镜像);docker images:查看本地所有镜像,显示镜像ID、标签、大小等信息;docker image inspect <镜像ID/镜像名>:查看镜像的详细信息(如分层结构、环境变量、启动命令);docker rmi <镜像ID/镜像名>:删除本地镜像(注意:若该镜像有运行中的容器,需先停止容器才能删除);docker build -t <镜像名:标签> <Dockerfile路径>:根据Dockerfile构建自定义镜像(后续进阶会用到)。
2. 容器相关命令(docker container)
docker run <参数> <镜像名>:基于镜像创建并启动容器(最常用命令),例:docker run -d -p 80:80 nginx(-d后台运行,-p端口映射,将容器80端口映射到宿主机80端口);docker ps:查看当前运行中的容器;docker ps -a:查看所有容器(包括已停止的);docker start/stop/restart <容器ID/容器名>:启动、停止、重启容器;docker exec -it <容器ID/容器名> /bin/bash:进入容器内部,进行交互操作(-it表示交互式终端);docker logs <容器ID/容器名>:查看容器运行日志;docker rm <容器ID/容器名>:删除容器(已停止的容器才能删除,强制删除加-f参数)。
三、容器重启策略:保障应用持续运行
在实际生产环境中,我们希望容器能在意外停止(如进程崩溃、服务器重启)后自动重启,避免应用中断——这就需要设置容器的重启策略。Docker提供了4种重启策略,可在docker run时通过--restart参数指定。
- no(默认) :容器停止后,不自动重启,即使宿主机重启也不会启动;
- on-failure[:max-retries] :只有当容器因非0退出码(运行失败)时,才自动重启,可指定最大重启次数(如on-failure:3,最多重启3次);
- always:无论容器以何种方式停止(正常停止、异常停止),都会自动重启,即使宿主机重启,容器也会跟着启动;
- unless-stopped:除非手动停止容器(docker stop),否则容器停止后会自动重启,宿主机重启后也会启动。
示例:docker run -d --restart always nginx,启动Nginx容器,设置为始终自动重启,保障服务不中断。
四、数据持久化:避免数据丢失的关键
前面提到,容器的默认存储是临时的,一旦容器删除,数据就会丢失。除了存储卷(Volume),Docker还有两种数据持久化方式,三种方式各有适用场景。
1. 存储卷(Volume):Docker推荐方式
由Docker管理,存储在宿主机的特定目录(通常是/var/lib/docker/volumes/),与容器解耦,可被多个容器共享,删除容器后,卷依然存在,数据不会丢失。
常用命令:
docker volume create <卷名>:创建自定义卷;docker run -d -v <卷名>:<容器内目录> nginx:将卷挂载到容器内目录;docker volume ls:查看所有卷;docker volume rm <卷名>:删除卷。
2. 绑定挂载(Bind Mount):手动指定宿主机目录
将宿主机的任意目录直接挂载到容器内目录,由用户手动管理宿主机目录,灵活性高,但耦合度高(若宿主机目录路径变更,容器会挂载失败)。
示例:docker run -d -v /home/nginx/html:/usr/share/nginx/html nginx,将宿主机/home/nginx/html目录挂载到容器内Nginx的静态文件目录,修改宿主机该目录下的文件,容器内会实时同步。
3. tmpfs挂载:临时内存存储
将数据存储在宿主机的内存中,容器停止后,数据立即丢失,适用于临时缓存、临时文件等无需持久化的场景。
示例:docker run -d --tmpfs /tmp nginx,将容器内/tmp目录挂载到宿主机内存。
五、Docker网络类型:实现容器间通信(后面会讲为什么说Docker的网络是一坨屎)
Docker默认提供了4种网络类型,用于实现容器与容器、容器与宿主机、容器与外部网络的通信,新手重点掌握前3种即可。
1. bridge
Docker安装后会自动创建一个名为docker0的桥接网络,所有未指定网络的容器,都会默认连接到这个网络。同一桥接网络下的容器可以相互通信,容器通过端口映射(-p)与宿主机、外部网络通信。
特点:最常用,适合单机环境下的容器通信,隔离性较好。
2. host
容器直接使用宿主机的网络空间,容器内的端口直接暴露在宿主机上,无需进行端口映射。比如容器启动时指定--net=host,那么容器内的80端口,直接对应宿主机的80端口。
特点:性能好,但隔离性差(容器与宿主机可能出现端口冲突)。
3. none
容器不配置任何网络,无法与外界通信,仅用于内部测试、无需网络的场景(如离线数据处理)。
4. overlay
用于多机环境,实现不同宿主机上的容器相互通信,是Docker集群化部署的核心网络类型,新手入门阶段可暂不深入。
六、Docker底层依赖的Linux技术
Docker之所以能实现“轻量级隔离”,核心是依赖了Linux内核的几个底层技术,这些技术并非Docker发明,而是Docker对其进行了封装,让用户无需关注底层细节,就能轻松使用隔离功能。
- namespace(命名空间) :实现“资源隔离”的核心。Linux通过namespace将系统资源(进程、网络、文件系统、用户、主机名等)进行隔离,每个容器都有自己独立的namespace,容器内的进程只能看到自己namespace内的资源,无法访问宿主机或其他容器的资源,从而实现了容器的独立性。
- cgroups(控制组) :实现“资源限制”。cgroups可以限制容器对CPU、内存、磁盘I/O、网络带宽等资源的使用,比如限制某个容器最多使用1核CPU、2GB内存,避免单个容器占用过多资源,影响其他容器或宿主机。
- overlayFS(叠加文件系统) :实现镜像的分层存储。overlayFS允许将多个文件系统叠加在一起,形成一个统一的文件系统,Docker镜像的分层结构就是基于overlayFS实现的,底层镜像可共享,上层镜像仅存储修改的部分,大大节省存储空间。
- chroot:实现“文件系统隔离”。chroot可以改变进程的根目录,让进程只能访问根目录下的文件和目录,无法访问宿主机的其他目录,Docker通过chroot为每个容器提供了独立的文件系统环境。
- iptables:实现容器网络的转发和隔离。Docker的端口映射、容器间通信、容器与外部网络的通信,都是通过iptables的规则来实现的,iptables负责转发网络数据包,同时隔离不同容器的网络。
先写这么多,后面有时间再多写点干货🤭。