如果你曾被“在我电脑上能跑”的部署难题折磨,或为服务器资源占用过高而头疼,那Docker一定是你的救星。作为容器化技术的标杆,Docker彻底改变了应用的开发、测试和部署模式。本文将从核心原理到实操步骤,带你系统性掌握Docker,让容器化技术落地到实际开发中。
一、Docker核心原理:看透容器化的本质
Docker的核心思想是“封装”与“隔离”,它不仅是工具,更是一种DevOps理念的落地。
在学习操作前,我们必须先搞懂:Docker到底是什么?它凭什么实现“一次构建,到处运行”?这就需要从其解决的痛点和底层技术说起。
1.1 为什么需要Docker?传统部署的三大痛点
在Docker出现前,开发者和运维人员常陷入这些困境:
- 环境不一致:开发机上跑的好好的代码,部署到测试机或生产机就报错,原因可能是依赖版本、系统配置不同,俗称“环境污染”。
- 资源占用高:为了解决环境隔离,传统方案用虚拟机(VM),但每个VM都需要独立的操作系统,存在占用内存、CPU资源多,启动慢等问题。
- 部署效率低:部署一个应用需要手动安装依赖、配置环境,步骤繁琐且易出错,无法快速规模化复制。
Docker的核心价值就是解决这些问题:通过容器化技术,实现环境一致性、轻量级隔离和高效部署。而这一切的背后,依赖于Linux内核的三大核心技术——镜像、容器、仓库。
1.2 Docker核心概念:镜像、容器、仓库
Docker有三个最基础的概念,理解它们就理解了Docker的80%:
- 镜像(Image):可理解为“应用的模板”,包含了运行应用所需的代码、依赖、系统库、配置等所有内容。比如“nginx镜像”就是包含nginx服务的完整环境模板,镜像本身是只读的,不能修改。
- 容器(Container):镜像的“运行实例”,是一个独立的可执行单元。相当于基于镜像创建的“临时沙箱”,可以启动、停止、删除。容器和镜像的关系,就像“类和对象”的关系——一个镜像可以创建多个容器。
- 仓库(Repository):存放镜像的“云端仓库”,类似GitHub等平台存放代码的逻辑。Docker官方提供了公共仓库Docker Hub,包含数十万现成镜像(如Nginx、MySQL等);企业或个人也可搭建私有仓库,用于存放内部业务镜像,保障安全性。
1.3 底层技术支撑:Docker为什么能“轻量级隔离”?
很多人会把Docker和虚拟机混淆,其实二者本质不同:虚拟机是“硬件级隔离”,需要模拟完整操作系统;而Docker是“内核级隔离”,共享宿主机内核,仅隔离应用所需的资源。这一切依赖Linux内核的三个关键技术:
- Namespace(命名空间):实现“环境隔离”的核心。Linux内核提供了PID(进程)、NET(网络)、Mount(文件系统)等多种命名空间,每个容器会被分配独立的命名空间。比如PID命名空间让容器内的进程以为自己是“进程1”(初始化进程),但在宿主机看来只是普通进程;NET命名空间让容器拥有独立的网卡、IP,实现网络隔离。
- Cgroups(控制组):实现“资源限制”的关键。用于限制容器对CPU、内存、磁盘IO等资源的占用,避免某个容器过度消耗资源影响其他容器。比如可限制某个容器最多使用1核CPU和2GB内存。
- UnionFS(联合文件系统):实现“镜像分层”和“写时复制”的基础。镜像由多个只读层叠加而成,比如一个Nginx镜像可能包含“操作系统基础层”“依赖库层”“Nginx应用层”,分层设计让镜像复用性更高(多个镜像可共享基础层)。容器启动时会在镜像顶层加一个“可写层”,所有修改都只作用于该层,镜像本身保持只读,这就是“写时复制”,既节省空间又保障镜像安全。
1.4 Podman和Docker
CentOS 8 及后续版本默认使用 Podman 替代 Docker,这是由红帽(Red Hat)主导的技术战略调整,核心原因包括架构革新、安全增强和生态适配。以下是具体原因分析:
- RHEL 8 官方弃用 Docker
- 自 RHEL 8 起,红帽不再将 Docker 作为官方支持的容器引擎,转而主推由其开发的 Podman + Buildah + CRI-O 工具链。这一策略直接影响了 CentOS 8 及后续发行版本(如 CentOS Stream 10)的默认配置。
- 红帽通过 Podman(容器运行时)、Buildah(镜像构建)、Skopeo(镜像传输)等工具,构建了一个基于 OCI 标准的模块化容器生态。这种设计更符合 Unix 哲学,每个工具专注解决单一问题,而非像 Docker 那样采用 “大而全” 的单体架构。
二、Docker实操教程:从安装到实战部署
原理讲透后,进入实操环节。以下步骤适配Windows、macOS、Linux三大系统,以“安装→核心操作→实战部署”为逻辑展开。
2.1 第一步:Docker安装(三大系统适配)
Docker分为社区版(CE)和企业版(EE),个人和中小企业用CE足够,免费且功能完整。如果需要私有化搭建一套镜像云仓库,可以采用由VMWare公司开源的容器镜像仓库——Harbor,搭建方式和流程具体可以访问Harbor - Harbor 镜像仓库文档查看详情。
2.1.1 Windows系统安装(Win10及以上)
由于Docker依赖Linux内核,那就需要在Windows系统上开启WSL环境支持。
WSL的本质是 Windows 内核中集成的轻量级 Linux 子系统,从WSL2开始不再依赖 Windows 内核翻译 Linux 系统调用,而是自带完整 Linux 内核(由微软编译维护),性能接近物理机或虚拟机,基于 Hyper-V 技术实现,但无需完整虚拟机的资源开销,核心是让 Linux 环境在 Windows 上 “原生运行” 而非模拟。
- 开启“虚拟化”:进入BIOS(开机时按ESC/F2/F10/F12等,不同主板不同),找到“Virtualization Technology”等类似选项并开启。
- 安装WSL2(适用于Windows的Linux子系统):Docker Desktop依赖WSL2运行,Win10需升级到2004版本以上,通过“设置→应用→可选功能→更多Windows功能”勾选“适用于Linux的Windows子系统”和“虚拟机平台”,重启电脑后安装WSL2(可参考微软官方文档)。
- 下载Docker Desktop:从Docker官网下载Windows版本,双击安装,启动后桌面右下角托盘处出现鲸鱼图标,即表示安装成功。
2.1.2 macOS系统安装
- 检查系统版本:需macOS 11(Big Sur)及以上版本,M1/M2芯片和Intel芯片均适配。
- 下载安装:从Docker官网下载macOS版本,拖拽到应用文件夹,启动后在顶部菜单栏出现鲸鱼图标,打开终端输入
docker --version,显示版本信息即安装成功。
输出内容示例:
[root@data ~]# docker --version
Docker version 28.4.0, build d8eb465
2.1.3 Linux系统安装(以CentOS 8为例)
CentOS默认安装
-
卸载旧版本(若有):
[root@data ~]# yum remove -y docker docker-client docker-client-latest docker-common docker-latest docker-latest-logrotate docker-logrotate docker-engine -
安装依赖:
[root@data ~]# yum install -y yum-utils device-mapper-persistent-data lvm2 -
设置镜像源:使用阿里云镜像源加速
[root@data ~]# yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo -
安装Docker CE:
[root@data ~]# yum install -y docker-ce docker-ce-cli containerd.io -
启动Docker并设置开机自启:sudo
[root@data ~]# systemctl enable --now docker -
验证:
sudo docker --version,显示版本信息即成功。[root@data ~]# docker --version Docker version 28.4.0, build d8eb465
2.2 核心操作:镜像与容器的常用命令
Docker的操作核心围绕“镜像”和“容器”展开,记住以下命令,就能应对80%的日常场景。建议先打开终端(Windows用PowerShell,Linux/macOS用终端),跟着实操。
2.2.1 镜像操作:拉取、查看、删除
| 操作目的 | 命令 | 说明 |
|---|---|---|
| 拉取镜像 | docker pull 镜像名:标签 |
标签指定版本, 如:docker pull nginx:1.24(不写标签默认latest) |
| 查看本地镜像 | docker images |
显示镜像ID、标签、大小等信息 |
| 删除镜像 | docker rmi 镜像ID/镜像名:标签 |
需先删除依赖该镜像的容器,加 -f强制删除 |
| 搜索镜像 | docker search 镜像名 |
从Docker Hub搜索镜像,如 docker search mysql |
2.2.2 容器操作:创建、启动、进入、删除
| 操作目的 | 命令 | 说明 |
|---|---|---|
| 创建并启动容器 | docker run [参数] 镜像名:标签 |
最核心命令,常用参数:-d 后台运行-p 宿主机端口:容器端口(端口映射)--name 容器名(自定义名称)--rm 运行一次,容器停止后自动移除挂载本机目录到容器目录 |
| 查看运行中容器 | docker ps |
加 -a查看所有容器(包括停止的) |
| 进入运行中容器 | docker exec -it 容器ID/容器名 /bin/bash |
-it 实现交互模式 /bin/bash进入容器终端(部分容器用sh)容器ID可输入部分内容,容器名称需要完整输入 |
| 启动/停止容器 | docker start/stop 容器ID/容器名 |
停止后可重新启动,无需重新创建 |
| 删除容器 | docker rm 容器ID/容器名 |
需先停止容器,加-f强制删除运行中的容器 |
| 查看容器日志 | docker logs -f 容器ID/容器名 |
-f 实时跟踪日志输出,排查问题常用 |
| 复制文件命令 | docker cp 宿主机目录 容器ID/容器名:路径 |
将容器内容复制到宿主机:docker cp 容器ID/容器名:路径 宿主机路径 |
重点提示:端口映射是容器对外提供服务的关键,比如 docker run -d -p 8080:80 --name mynginx nginx,表示将宿主机8080端口映射到容器80端口,访问宿主机 IP:8080即可进入Nginx首页。
命令示例:
docker ps :
[root@data volumes]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
1916a6118e62 docker.1ms.run/openlistteam/openlist:latest "/entrypoint.sh" 2 weeks ago Up 2 weeks 0.0.0.0:5244->5244/tcp, [::]:5244->5244/tcp, 5245/tcp openlist
80e2b0cce056 1panel/node:20.14.0 "docker-entrypoint.s…" 4 weeks ago Up 4 weeks 0.0.0.0:8801->8000/tcp SoftEtherAdmin-ns1
b7d80b27e64a 1panel/node:20.14.0 "docker-entrypoint.s…" 4 weeks ago Up 4 weeks 0.0.0.0:8800->8000/tcp SoftEtherAdmin-90
054180110f19 homeassistant/home-assistant:2025.10.1 "/init" 4 weeks ago Up 4 weeks home-assistant
addf356c6e41 docker.1ms.run/emqx/emqx:6.0.0 "/usr/bin/docker-ent…" 4 weeks ago Up 4 weeks (healthy) 4370/tcp, 0.0.0.0:1883->1883/tcp, [::]:1883->1883/tcp, 0.0.0.0:8883->8883/tcp, [::]:8883->8883/tcp, 5369/tcp, 0.0.0.0:8882->8083/tcp, [::]:8882->8083/tcp, 0.0.0.0:8884->8084/tcp, [::]:8884->8084/tcp, 0.0.0.0:8073->18083/tcp, [::]:8073->18083/tcp emqx
7e98d02e92ce docker.1ms.run/grafana/promtail:1.5.0 "/usr/bin/promtail -…" 5 weeks ago Up 5 weeks promtail
6cdd1a81cfa7 docker.1ms.run/grafana/loki:1.5.0 "/usr/bin/loki -conf…" 5 weeks ago Up 5 weeks 0.0.0.0:3100->3100/tcp, [::]:3100->3100/tcp loki
c4100dc56acc docker.1ms.run/houyuxi/mobakey:x86 "/docker-entrypoint.…" 6 weeks ago Up 6 weeks 0.0.0.0:8083->80/tcp, [::]:8083->80/tcp mobaxterm-license
9e324c2c326e docker.1ms.run/mayswind/ezbookkeeping:latest "/docker-entrypoint.…" 6 weeks ago Up 3 weeks 0.0.0.0:8076->8080/tcp, [::]:8076->8080/tcp ezbookkeeping
a349b1802c01 docker.1ms.run/vaultwarden/server:latest "/start.sh" 7 weeks ago Up 7 weeks (healthy) 0.0.0.0:5080->80/tcp, [::]:5080->80/tcp vaultwarden
bc77bb2a9541 docker.1ms.run/geekyouth/moodist:v1.2.0 "/docker-entrypoint.…" 7 weeks ago Up 7 weeks 80/tcp, 0.0.0.0:8095->8080/tcp, [::]:8095->8080/tcp moodist
255b332ce515 docker.1ms.run/monday1/threat-intel-hub:latest "python app.py" 7 weeks ago Up 7 weeks 0.0.0.0:8891->8891/tcp, [::]:8891->8891/tcp threat-intel-hub-app
eab119505e89 php:8.0.30-fpm-alpine "docker-php-entrypoi…" 7 weeks ago Up 7 weeks 127.0.0.1:9009->9000/tcp 1Panel-php8-uYLI
148b47d1a4ef 1panel/node:20.14.0 "docker-entrypoint.s…" 8 weeks ago Up 8 weeks 0.0.0.0:3008->3000/tcp OfficeHub
d2b54491f9a5 1panel/node:20.14.0 "docker-entrypoint.s…" 8 weeks ago Up 8 weeks 0.0.0.0:8043->80/tcp miku
3f7eb3bc5662 docker.1ms.run/yunyoujun/cook:latest "/docker-entrypoint.…" 2 months ago Up 2 months 0.0.0.0:5091->80/tcp, [::]:5091->80/tcp
2.3 进阶操作:自定义镜像(Dockerfile)
现成镜像无法满足所有需求,比如我们需要一个包含自定义代码的 Python应用镜像,这就需要用 Dockerfile构建自定义镜像。Dockerfile是一个文本文件,包含构建镜像的指令集合。
2.3.1 Dockerfile核心指令
| 指令 | 作用 |
|---|---|
| FROM | 指定基础镜像,如:FROM python:3.9(基于Python 3.9镜像构建) |
WORKDIR |
设置容器工作目录,后续指令在此目录执行,如:WORKDIR /app (工作目录为 /app) |
COPY |
将宿主机文件复制到镜像中,如:COPY . /app(复制当前shell所在目录到镜像 /app目录) |
RUN |
构建镜像时执行的命令,如:RUN pip install -r requirements.txt(安装依赖) |
EXPOSE |
声明容器运行时监听的端口(仅声明,不映射) |
CMD |
容器启动时执行的命令,如:CMD ["python", "app.py"](启动Python应用) |
Dockerfile示例:
FROM docker.1ms.run/node:21
# 设置工作目录
WORKDIR /app
# 复制项目文件到容器中
COPY ./ /app
# 安装依赖
#RUN ping -w 3 so.com
RUN npm config set registry http://mirrors.cloud.tencent.com/npm && npm install -f
# 构建项目
RUN npm config set registry http://mirrors.cloud.tencent.com/npm && npm run build
# 暴露端口
EXPOSE 3000
# 启动服务
CMD ["npm", "run", "start"]
2.3.2 构建自定义镜像实操
以构建一个简单的Python Flask应用镜像为例:
准备应用文件:创建文件夹app,内有app.py(Flask代码)和requirements.txt(依赖列表,写flask)。
- 编写Dockerfile:在app文件夹内创建Dockerfile,内容如下:
# 基础镜像 FROM python:3.9 # 工作目录 WORKDIR /app # 复制依赖文件 COPY requirements.txt # 安装依赖 RUN pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple # 复制应用代码 COPY . # 声明端口 EXPOSE 5000 # 启动命令 CMD ["python", "app.py"] - 构建镜像:进入app文件夹,执行命令
docker build -t myflask:1.0 .其中-t指定镜像名和标签,.表示Dockerfile所在目录。
启动容器:docker run -d -p 5000:5000 --name myflaskapp myflask:1.0,访问宿主机IP:5000即可看到Flask应用页面。
2.4 实战案例:用Docker部署Nginx并挂载配置
实际开发中,常需要修改容器配置文件,直接进入容器修改会丢失(容器删除后配置消失),因此需要“数据挂载”——将宿主机文件挂载到容器,实现配置持久化。以Nginx为例:
- 宿主机准备配置:创建文件夹/nginx/conf,将Nginx配置文件
nginx.conf放入该目录(可从容器中复制默认配置:docker cp mynginx:/etc/nginx/nginx.conf /nginx/conf/,mynginx是临时启动的容器名)。 - 挂载启动容器:
docker run -d -p 80:80 --name mynginx -v /nginx/conf/nginx.conf:/etc/nginx/nginx.conf nginx,其中-v表示挂载,格式为“宿主机路径:容器路径”。 - 修改配置:直接修改
宿主机/nginx/conf/nginx.conf,执行docker restart mynginx重启容器,配置即可生效,无需重新构建镜像。
三、Docker常用技巧与注意事项
3.1 镜像加速:解决拉取镜像慢的问题
国内访问Docker Hub速度较慢,可配置国内镜像源(如阿里云、网易云):
-
Windows/macOS:打开Docker Desktop,进入Settings→Docker Engine,在配置文件中添加:
"registry-mirrors": ["https://xxx.mirror.aliyuncs.com"]```bash -
Linux:创建
/etc/docker/daemon.json文件,写入:{ "registry-mirrors": ["https://xxx.mirror.aliyuncs.com"] }然后执行
systemctl daemon-reload && sudo systemctl restart docker。 -
具体Docker加速源可以在网上可以查找到:
常用加速源示例 1. 常见国内加速源 阿里云: https://<你的专属加速器地址>(需登录阿里云获取) 腾讯云: https://mirror.ccs.tencentyun.com 网易云: https://hub-mirror.c.163.com 华为云: https://repo.huaweicloud.com 中国科技大学(已改为科大内网使用): https://docker.mirrors.ustc.edu.cn
3.2 数据持久化:容器数据不丢失的关键
容器删除后,内部数据会丢失,除了上述“绑定挂载”(-v 宿主机路径:容器路径),还可使用“数据卷”(Docker管理的宿主机目录,更安全):
- 创建数据卷:
docker volume create nginx-vol - 挂载数据卷启动:
docker run -d -p 80:80 -v nginx-vol:/etc/nginx/conf nginx,Docker会将数据卷映射到宿主机/var/lib/docker/volumes/nginx-vol/目录。
3.3 常见问题示例和排查
创建容器启动失败输出内容示例:
-
端口已经被其他进程绑定
Error response from daemon: Ports are not available: exposing port TCP 0.0.0.0:8080 -> 0.0.0.0:0: listen tcp 0.0.0.0:8080: bind: address already in use -
镜像不存在:
Error response from daemon: pull access denied for myapp, repository does not exist or may require 'docker login': denied: requested access to the resource is denied -
标签类
Error response from daemon: No such image: myapp:v1.0 (tag: v1.0, digest: none) -
权限类
Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Post "http://%2Fvar%2Frun%2Fdocker.sock/v1.24/containers/create": dial unix /var/run/docker.sock: connect: permission denied
四、网络
在 Docker 容器化部署中,网络是连接容器与容器、容器与宿主机、容器与外部网络的核心桥梁。无论是单机部署的多容器协作,还是跨主机的集群通信,理解 Docker 网络的工作机制都是实现灵活、可靠部署的关键。本文将从基础概念出发,逐步拆解 Docker 的网络模式、核心原理、实战配置及常见问题,帮助你全面掌握 Docker 网络。
4.1 Docker 网络核心概念
在深入网络模式前,先明确几个关键术语,避免理解偏差:
- Docker 守护进程(Docker Daemon):管理容器生命周期的核心服务,网络功能由其内置的网络驱动实现。
- 网络命名空间(Network Namespace):Linux 内核提供的网络隔离技术,每个容器默认拥有独立的命名空间,包含独立的网卡、IP、路由表、端口等网络资源,实现容器间网络隔离。
- 网络驱动(Network Driver):Docker 通过不同的网络驱动支持多种网络模式,默认包含 bridge、host、none、overlay 等,也支持第三方驱动(如 macvlan、calico)。
- 容器网络栈(Container Network Stack):容器的网络配置集合,包括网卡(eth0)、回环设备(lo)、路由规则、DNS 配置等,由 Docker 根据网络模式自动配置或自定义配置。
4.2 Docker 默认网络模式详解
Docker 安装后会自动创建 3 种默认网络,可通过 docker network ls 查看:
[root@data ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
efafba1633bd bridge bridge local
575d852f775a host host local
ced83d6171f4 none null local
4.2.1 bridge 模式(默认模式)
工作原理
- 当启动容器时,若未指定网络模式,Docker 会自动将容器连接到
bridge网络(默认名称为bridge,可自定义)。 - Docker 在宿主机上创建一个虚拟网桥
docker0(默认 IP 为 172.17.0.1/16),每个容器会获得一个虚拟网卡eth0,并分配该网段内的私有 IP(如 172.17.0.2)。 - 容器通过
docker0网桥与宿主机、其他容器通信,宿主机通过 NAT(网络地址转换)实现容器访问外部网络,外部网络通过端口映射(-p)访问容器。
核心特点
- 隔离性:容器间默认可通过 IP 通信,但需暴露端口才能被外部访问。
- 灵活性:支持端口映射、自定义 IP、DNS 配置,满足大多数单机多容器场景(如前端 + 后端 + 数据库的组合部署)。
- 局限性:跨主机容器通信需额外配置(如端口映射、overlay 网络),默认不支持容器名称直接通信(需通过
--link或自定义网络实现)。
示例
# 1. 启动两个容器(默认连接bridge网络)
docker run -d --name app1 nginx
docker run -d --name app2 tomcat
# 2. 查看容器IP(通过inspect命令)
docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' app1 # 输出172.17.0.2
docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' app2 # 输出172.17.0.3
3. 容器间通信(通过IP)
docker exec -it app1 ping 172.17.0.3 # app1可ping通app2
4. 端口映射(外部访问容器)
docker run -d --name app3 -p 8080:80 nginx # 宿主机8080端口映射容器80端口
外部通过 http://宿主机IP:8080 访问nginx
4.2.2 host 模式
工作原理
- 容器直接使用宿主机的网络命名空间,不创建独立的网卡和 IP,容器内的端口直接映射到宿主机的对应端口。
- 容器内的网络配置(IP、路由、DNS)与宿主机完全一致,相当于在宿主机上直接运行应用程序。
核心特点
- 性能最优:无网络隔离开销,网络通信效率与宿主机原生应用一致。
- 无端口映射:容器端口直接暴露在宿主机,无需通过
-p参数映射(如容器内启动 80 端口,外部直接访问宿主机 IP:80 即可)。 - 局限性:端口冲突风险高(多个容器不能使用同一端口),网络隔离性差(容器可访问宿主机所有网络资源),不支持跨平台(Docker Desktop for Mac/Windows 不支持 host 模式)。
示例
# 启动容器使用host模式(注意:宿主机80端口需未被占用)
docker run -d --name app4 --network host nginx
# 外部直接访问宿主机IP:80(无需端口映射)
curl http://宿主机IP # 即可访问nginx默认页面
4.2.3 none 模式
工作原理
- 容器拥有独立的网络命名空间,但 Docker 不配置任何网络资源(无网卡、IP、路由),容器仅能通过回环设备(lo)进行内部通信。
- 适用于无需网络通信的场景(如离线数据处理、本地计算任务),或需要完全自定义网络配置的场景(如手动配置网卡、IP)。
核心特点
- 完全隔离:与外部网络、其他容器、宿主机均无网络连接。
- 高度自定义:需手动通过
ip命令配置网络(如添加网卡、设置 IP),灵活性极高但配置复杂。
示例
# 启动容器使用none模式
docker run -it --name app5 --network none alpine
# 容器内查看网络配置(仅lo设备)
ip addr # 输出:1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1000
4.2.4 overlay 模式(跨主机网络)
工作原理
- overlay 网络是 Docker Swarm(Docker 原生集群编排工具)的默认跨主机网络模式,基于 VXLAN(虚拟扩展局域网)技术,将多个宿主机的网络连接成一个虚拟网络。
- 每个 overlay 网络包含两个子网:一个用于容器间通信(虚拟子网),一个用于宿主机间的控制平面通信( gossip 协议),容器在跨主机通信时,数据包通过 VXLAN 隧道加密传输。
核心特点
- 跨主机通信:不同宿主机上的容器可在同一 overlay 网络中直接通信,无需端口映射。
- 服务发现:支持通过 Docker Swarm 的服务名称(Service Name)自动解析 IP,实现容器间服务发现。
- 局限性:依赖 Docker Swarm 或第三方编排工具(如 Kubernetes),单机场景下无意义,配置相对复杂。
示例(Docker Swarm 环境)
# 1. 初始化Docker Swarm(主节点)
docker swarm init --advertise-addr 宿主机IP
# 2. 创建overlay网络
docker network create -d overlay my-overlay-network
# 3. 部署服务到overlay网络(跨主机可访问)
docker service create --name web --network my-overlay-network -p 80:80 nginx
# 4. 其他宿主机加入Swarm后,服务会自动调度,容器间可通过服务名通信
4.2.5 macvlan 模式(模拟物理网络)
工作原理
- macvlan 网络允许容器直接使用宿主机的物理网卡,为每个容器分配独立的 MAC 地址和 IP 地址(与宿主机在同一网段),相当于将容器伪装成物理网络中的独立设备。
- 容器与宿主机、其他物理设备在同一广播域,可直接通过 IP/MAC 通信,无需 NAT 或端口映射。
核心特点
- 物理网络集成:容器完全融入现有物理网络,适用于需要与物理设备(如打印机、IoT 设备)通信的场景。
- 无网络转发开销:通信效率接近物理机,无 NAT 转发损耗。
- 局限性:需宿主机网卡支持混杂模式(Promiscuous Mode),可能与部分网络设备(如路由器)不兼容,IP 地址需手动规划(避免与物理设备冲突)。
示例
# 1. 创建macvlan网络(指定宿主机物理网卡eth0,子网与宿主机一致)
docker network create -d macvlan \
--subnet=192.168.1.0/24 \ # 宿主机所在子网
--gateway=192.168.1.1 \ # 网关(与宿主机一致)
--ip-range=192.168.1.100/28 \ # 容器IP地址范围
-o parent=eth0 \ # 宿主机物理网卡
my-macvlan-network
# 2. 启动容器使用macvlan网络
docker run -d --name app6 --network my-macvlan-network --ip 192.168.1.101 nginx
# 3. 物理网络中的设备可直接访问192.168.1.101(无需端口映射)
4.3 Docker 网络核心原理
1. 网络命名空间隔离
- Linux 内核通过
network namespace实现网络资源隔离,每个容器启动时,Docker 会调用ip netns add命令创建独立的命名空间。 - 容器的网络命名空间与宿主机、其他容器完全隔离,仅通过虚拟设备(如 veth pair、网桥)实现通信。
2. 虚拟设备通信
- veth pair(虚拟网卡对):Docker 为每个 bridge 模式的容器创建一对虚拟网卡(veth0 和 veth1),一端绑定到容器的网络命名空间(eth0),另一端连接到宿主机的 docker0 网桥,实现容器与网桥的通信。
- docker0 网桥:宿主机上的虚拟网桥,相当于一个交换机,连接所有 bridge 模式的容器,负责转发容器间、容器与宿主机的网络数据包。
3. 网络地址转换(NAT)
- 容器访问外部网络:容器发出的数据包经 docker0 网桥转发到宿主机,宿主机通过 SNAT(源地址转换)将容器私有 IP 转换为宿主机公网 IP,实现外部网络访问。
- 外部访问容器:通过
-p 宿主机端口:容器端口配置 DNAT(目的地址转换),外部数据包访问宿主机端口时,被转发到对应容器的端口。
4. DNS 与服务发现
- Docker 内置 DNS 服务(默认监听 127.0.0.11:53),容器内的 DNS 配置默认指向该服务,实现:
- 容器名称解析(自定义网络中,容器可通过名称直接通信,无需 IP);
- 服务名称解析(Docker Swarm 或 Kubernetes 环境中,通过服务名自动解析到容器 IP)。
4.4 Docker 网络配置
1. 自定义 bridge 网络(推荐)
默认的 bridge 网络不支持容器名称解析,自定义 bridge 网络可解决该问题,且支持更多配置(如子网、网关、DNS):
# 1. 创建自定义bridge网络
docker network create \
--driver bridge \
--subnet=172.20.0.0/16 \ # 自定义子网
--gateway=172.20.0.1 \ # 网关
--dns=8.8.8.8 \ # DNS服务器
my-bridge-network
# 2. 启动容器连接到自定义网络
docker run -d --name app7 --network my-bridge-network nginx
docker run -d --name app8 --network my-bridge-network tomcat
# 3. 容器间可通过名称通信(无需IP)
docker exec -it app7 ping app8 # 直接ping容器名称,自动解析IP
2. 容器网络连接与断开
# 1. 为运行中的容器添加网络
docker network connect my-bridge-network app1 # 将app1连接到my-bridge-network
# 2. 断开容器与网络的连接
docker network disconnect my-bridge-network app1
# 3. 查看容器的网络连接状态
docker inspect -f '{{.NetworkSettings.Networks}}' app1
3. 端口映射高级配置
-
指定绑定 IP:仅允许特定 IP 访问容器端口
docker run -d --name app9 -p 192.168.1.10:8080:80 nginx # 仅宿主机192.168.1.10的8080端口映射容器80端口 -
UDP 端口映射:默认映射 TCP 端口,需显式指定 UDP
docker run -d --name app10 -p 53:53/udp dnsmasq # 映射UDP 53端口(DNS服务) -
随机端口映射:让 Docker 自动分配宿主机端口(范围 49153-65535)
docker run -d --name app11 -p 80 nginx # 宿主机随机端口映射容器80端口,通过docker ps查看端口
4. 网络数据卷与网络共享
通过 --mount 或 -v 挂载网络存储(如 NFS、Ceph),实现容器间数据共享:
# 挂载NFS网络存储到容器
docker run -d --name app12 -v nfs-server:/data nginx
4.5 Docker网络常见问题与排查
1. 容器间无法通信
- 检查容器是否在同一网络:
docker inspect -f '{{.NetworkSettings.Networks}}' 容器名 - 自定义网络支持名称解析,默认 bridge 网络需通过 IP 通信或
--link(不推荐) - 检查防火墙规则:宿主机防火墙(如 iptables、firewalld)是否阻止容器间通信
2. 外部无法访问容器
- 检查端口映射配置:
docker ps查看端口映射是否正确(如宿主机端口是否被占用) - 检查容器状态:容器是否正常运行(
docker ps查看状态为 up) - 检查宿主机 IP:外部访问需使用宿主机的公网 IP(云服务器需配置安全组开放端口)
3. 容器无法访问外部网络
- 检查 DNS 配置:容器内
cat /etc/resolv.conf查看 DNS 是否正确(可自定义--dns参数) - 检查宿主机网络:宿主机是否能正常访问外部网络(如
ping 8.8.8.8) - 检查 iptables 规则:宿主机 iptables 是否禁止 NAT 转发(可通过
iptables -L -n查看)
4. 网络冲突
- 自定义网络子网避免与宿主机、其他网络重叠(如默认 bridge 网络是 172.17.0.0/16,自定义网络可使用 172.20.0.0/16)
- macvlan 网络的 IP 地址需避免与物理网络中的设备冲突
五、总结与进阶方向
本文从原理到实操覆盖了Docker的核心内容:通过Namespace、Cgroups、UnionFS三大技术实现轻量级隔离的原理,镜像、容器、仓库的核心概念,以及安装、命令操作、自定义镜像、实战部署的完整流程。掌握这些内容后,你已经能应对日常开发中的容器化需求。
进阶方向建议:
- 容器编排:学习Docker Compose(管理多容器应用)、Kubernetes(大规模容器集群编排)。
- 镜像优化:减少镜像体积(如使用多阶段构建、精简基础镜像)。
- CI/CD集成:将Docker与Jenkins等工具结合,实现自动化构建、测试、部署。
