容器删了数据没了、容器之间 ping 不通、数据库连不上、端口映射改了不生效——Docker 的坑一半在数据卷,一半在网络。这篇把卷(volume/bind/tmpfs)和五种网络模式讲透,配可抄的 compose 模板。游戏服、网站部署都用得上。
需要现成的游戏云服务器,可以看看财富云计算:一键开服面板,NAT 型无独立公网 IP,价格比独立 IP 机型省一半以上,主流游戏都能快速部署。
一、数据卷:容器里的数据怎么活下来
容器是「用后即焚」的:删了容器,容器内部文件系统一起消失。要留的数据必须放卷上。
三种挂载方式:
| 类型 | 写法 | 特点 | 适用 |
|---|---|---|---|
| 命名卷 | -v mydata:/var/lib/mysql | Docker 管理,路径在 /var/lib/docker/volumes/ | 数据库、应用数据 |
| 绑定挂载 | -v /host/path:/container/path | 直接映射宿主机目录 | 配置文件、代码目录 |
| tmpfs | --tmpfs /tmp | 内存盘,容器停就没了 | 临时文件、敏感缓存 |
1.1 命名卷(推荐默认)
services:
db:
image: mysql:8.0
volumes:
- db_data:/var/lib/mysql # 数据库文件进卷,删容器不丢
web:
image: nginx:1.27
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro # 配置文件绑定挂载,只读
volumes:
db_data: # 声明命名卷# 卷管理命令
docker volume ls # 列出所有卷
docker volume inspect db_data # 看详情和宿主机路径
docker volume rm db_data # 删除(数据真没了,慎用)
docker volume prune # 清所有没人用的卷1.2 绑定挂载的权限坑
# 现象:容器里写不了挂载目录
# Permission denied
# 原因:容器内用户 UID 和宿主机目录属主不匹配
ls -ld /host/path # 看宿主机目录属主
# 解法一:目录给对 UID(容器内跑 UID 1000 就 chown 1000)
sudo chown -R 1000:1000 /host/path
# 解法二:容器指定用户
docker run --user 1000:1000 ...游戏服场景:存档目录、配置目录用绑定挂载(方便直接改文件看效果),数据库用命名卷(不关心文件位置,只要不丢)。
1.3 游戏服存档持久化模板
services:
palworld:
image: thijsvanloef/palworld-server-docker:latest
volumes:
- ./data:/palworld/Pal/Saved # 存档+配置全在这,升级容器不丢档
- ./mods:/palworld/Pal/Mods # MOD 也挂出来,加 MOD 不用进容器
restart: unless-stopped升级服务端 = 删容器拉新镜像重建,数据卷岿然不动——这就是容器化最大的爽点,完整玩法见Docker 部署游戏服务器。
二、Docker 网络:五种模式
| 模式 | 隔离性 | 性能 | 适用 |
|---|---|---|---|
bridge(默认) | 容器独立网段,NAT 上网 | 好 | 单机多容器,默认用这个 |
host | 共享宿主机网络栈 | 最好 | 高性能游戏服(省一层 NAT) |
none | 无网络 | —— | 离线任务 |
container: | 和指定容器共享网络 | —— | sidecar 模式 |
| 自定义 bridge | 同 bridge 内可用容器名互访 | 好 | compose 默认,多服务互联用这个 |
2.1 端口映射:-p 的完整语法
docker run -p 8080:80 nginx
# 宿主机:容器
# 只绑本地(反代/安全场景)
docker run -p 127.0.0.1:8080:80 nginx
# 指定协议(UDP 游戏端口必须写!)
docker run -p 8211:8211/udp palworld
# 映射整个端口段(NAT 型映射多个端口)
docker run -p 8210-8220:8210-8220/udp palworldUDP 不写 /udp 默认走 TCP——游戏服连不上的经典原因之一。端口意义见端口速查表。
2.2 容器之间怎么通信
同一个 compose 项目里,直接用服务名当域名(自定义 bridge 内置 DNS):
services:
web:
image: nginx
environment:
- DB_HOST=db # 服务名直接当主机名!
- REDIS_HOST=cache
db:
image: mysql:8.0
cache:
image: redis:7web 容器里连 db:3306、cache:6379,Docker 自动解析。不要写 IP——容器重建 IP 就变。
跨 compose 项目/独立容器互联:
# 1. 建共享网络
docker network create appnet
# 2. 两个容器都接入
docker run -d --name db --network appnet mysql:8.0
docker run -d --name web --network appnet -e DB_HOST=db nginx# 网络排查命令
docker network ls # 列出网络
docker network inspect appnet # 看接了哪些容器
docker exec web ping db # 容器内测连通(要有 iputils)
docker exec web nc -zv db 3306 # 测端口通不通2.3 host 模式:游戏服的性能选项
services:
palworld:
network_mode: host # 容器直接用宿主机网络,无 NAT 损耗- 优点:少一层网络转发,延迟略低;UDP 游戏协议更稳
- 代价:
-p失效(端口就是宿主机的),多实例会端口冲突 - 适合:单游戏服独占机器;不适合:一机多服
2.4 NAT 型服务器 + Docker
NAT 型映射到宿主机的端口,Docker 再把宿主机端口映射进容器——两层映射:
玩家 → 公网IP:8211 →(NAT映射)→ 宿主机:8211 →(docker -p)→ 容器:8211# 宿主机 8211 必须映射进容器,且 UDP
docker run -p 8211:8211/udp palworld
# 控制台再配 NAT 映射: 外部8211/UDP → 内部8211/UDP任何一层漏了都连不上,排查方法见NAT 端口映射完全指南。
三、完整模板:Web + DB + Cache 一套
services:
web:
image: nginx:1.27-alpine
ports:
- "80:80"
- "443:443"
volumes:
- ./html:/usr/share/nginx/html:ro
- ./nginx.conf:/etc/nginx/conf.d/default.conf:ro
depends_on:
- app
restart: unless-stopped
networks: [frontend]
app:
image: php:8.3-fpm
volumes:
- ./html:/var/www/html
environment:
- DB_HOST=db
- REDIS_HOST=cache
networks: [frontend, backend]
db:
image: mysql:8.0
volumes:
- db_data:/var/lib/mysql
environment:
- MYSQL_ROOT_PASSWORD_FILE=/run/secrets/db_root_pw
secrets:
- db_root_pw
networks: [backend] # 数据库只在后端网络,不对外
cache:
image: redis:7-alpine
command: redis-server --requirepass ${REDIS_PASSWORD}
volumes:
- redis_data:/data
networks: [backend]
volumes:
db_data:
redis_data:
networks:
frontend:
backend: # internal 网络更安全,配 internal: true
secrets:
db_root_pw:
file: ./secrets/db_root_pw.txt结构解读:
db/cache只在backend网络,没有 ports 映射,外界碰不到- 密钥走 secrets,不进镜像历史,安全实践见Docker 安全加固与资源限制
- 挂载分「数据卷(不丢)」+「绑定挂载(好改)」两类,各司其职
docker compose up -d # 启动
docker compose ps # 看状态
docker compose logs -f web # 看日志
docker compose down # 停并删容器(卷不删)
docker compose down -v # 连卷一起删(数据全没!)四、常见问题速查
| 现象 | 原因 | 解法 |
|---|---|---|
| 删容器数据没了 | 数据在容器层,没挂卷 | 加 volumes |
| 容器写不了挂载目录 | UID 不匹配 | chown 或 --user |
| 容器内连不上另一个容器 | 不在同一网络 / 用了 IP | 服务名互联,别用 IP |
改了 -p 不生效 | 容器没重建 | docker compose up -d 重建 |
| 游戏端口 TCP 通了 UDP 不通 | -p 没写 /udp | -p 8211:8211/udp |
| 磁盘一直涨 | 卷和镜像堆积 | docker system df + prune |
| MySQL 连不上 | 容器刚起,初始化要十几秒 | 加 healthcheck + depends_on condition: service_healthy |
# 磁盘占用分析
docker system df
docker system df -v # 明细到每个镜像/容器/卷Dockerfile 编写规范见Dockerfile 编写与镜像优化,网站部署全流程见Docker 部署网站实战,Compose 编排基础见Docker Compose 编排实战。
数据卷和网络是 Docker 的两条命脉:卷决定数据活多久,网络决定容器怎么说话。记住三件事——要留的数据进卷、容器互访用服务名、UDP 端口必须写 /udp——Docker 运维就没什么能绊倒你了。
需要现成的游戏云服务器,可以看看财富云计算:一键开服面板,NAT 型无独立公网 IP,价格比独立 IP 机型省一半以上,主流游戏都能快速部署。延伸阅读:Docker 部署游戏服务器、Docker 常见故障排查、多游戏共存一台服务器。
延伸阅读
- 网站环境怎么选:LNMP 手动 / 宝塔面板 / Docker / 云开发
- 问卷表单系统搭建:SurveyKing / Formbricks,数据自己收
- 图床搭建:Lsky Pro / Lychee,自托管图片托管方案
- 邮件列表搭建:listmonk 自托管 Newsletter,把读者握在自己手里
- 文档站点搭建:MkDocs / VuePress / Docsify,产品文档与技术手册方案
- RSS 阅读器搭建:FreshRSS 自托管,把信息流拿回自己手里
- 短链接服务搭建:Shlink 自托管,链接数据自己掌握
- 网站状态监控页搭建:Uptime Kuma,服务器挂了第一时间知道

[...]docker exec registry bin/registry garbage-collect /etc/docker/registry/config.yml磁盘涨得最快的三样:CI 每次构建的新层、没人清理的旧标签、latest 反复覆盖的层。每周一次 GC + 保留策略(只留最近 10 个版本),仓库能长期健康。七、常见问题现象原因解法push 报 http: server gave HT[...]
2026-10-15 回复
[...]docker system prune -f --volumes六、扩展:往这套里加什么需求加什么自己的博客Typecho 容器(Typecho 搭建)数据库MySQL/PostgreSQL 容器(SQLite 与 MySQL 怎么选先想清楚)游戏服用容器跑也行(Docker 部署游戏服务器),但注意性能和存档位置密码管理Vaultwarden(Bitwarden 自建)RSS 阅读FreshRS[...]
2026-10-18 回复
[...]netsh advfirewall firewall add rule name="GameRange" dir=in action=allow protocol=UDP localport=26901-26903完整的 Windows 环境准备(远程桌面连接、运行库安装、SteamCMD 用法、开机自启、8 个常见坑)见:《Windows 云服务器开服通用前置教程》→ htt[...]
2026-10-18 回复
[...]db-data:换服务器 = 拷 compose 文件 + 数据卷,docker compose up -d,十分钟搬家完成。没有"我这环境怎么配的来着"的噩梦。Docker 系列教程站内很全:Docker 安装与基础命令、Compose 编排实战、一键部署常用服务、数据卷与网络详解。Docker 的安全功课:别拉来路不明的镜像、定期更新基础镜像、容器别用 root 跑、挂载 socket 要小心[...]
2026-10-18 回复