Docker 网络与存储:容器之间怎么通信、数据放哪

Docker 入门之后最先撞上的两个问题:容器之间怎么访问?数据存在哪、删容器会不会丢?这篇讲清这两件事。

一、网络模式

模式说明适用场景
bridge默认,容器在私有网段,通过 NAT 出网绝大多数
host直接用宿主机网络栈,无隔离需要最高网络性能
none无网络离线任务
container共享另一个容器的网络sidecar 模式
bash
docker network ls
docker network inspect bridge

# 自定义网络(推荐,自带 DNS 解析)
docker network create app-net
docker run -d --name web --network app-net nginx
docker run -d --name db  --network app-net postgres

二、容器之间怎么访问

用容器名(或服务名)当主机名,Docker 内置 DNS 会解析:

bash
# 在 web 容器里
docker exec web ping db          # 通
docker exec web curl http://db:5432
yaml
# compose 里更简单,服务名即主机名
services:
  web:
    image: nginx
    depends_on: [db]
  db:
    image: postgres:16-alpine
# web 里连数据库写 db:5432

三个高频坑

  1. 容器内不能用 127.0.0.1 访问其他容器 —— 每个容器有独立网络栈,localhost 是它自己;
  2. 容器内访问宿主机host.docker.internal(Docker 20.10+)或 172.17.0.1(bridge 网关);
  3. 默认 bridge 网络不解析容器名,必须用自定义网络(docker network create)。
bash
# 查 bridge 网关地址
docker network inspect bridge | grep Gateway

# Linux 上让 host.docker.internal 可用
docker run --add-host=host.docker.internal:host-gateway ...

三、端口映射

bash
docker run -p 8080:80 nginx            # 宿主机 8080 → 容器 80
docker run -p 127.0.0.1:8080:80 nginx  # 只监听本机(推荐)
docker run -P nginx                    # 随机映射所有 EXPOSE 端口
yaml
ports:
  - "127.0.0.1:8080:80"     # 只有本机可访问,外网靠 Nginx 反代

强烈建议加 127.0.0.1:。直接 -p 8080:80 会绕过 ufw 防火墙(详见「iptables 与 nftables」那篇),等于把服务直接暴露到公网。

四、存储:三种方式

方式写法特点
volume-v mydata:/dataDocker 管理,推荐,易备份迁移
bind mount-v /host/path:/data直接挂宿主机目录,方便改配置
tmpfs--tmpfs /tmp内存,重启丢失
bash
# volume
docker volume create pgdata
docker run -v pgdata:/var/lib/postgresql/data postgres
docker volume ls
docker volume inspect pgdata

# bind mount(改配置很方便)
docker run -v /srv/nginx.conf:/etc/nginx/nginx.conf:ro nginx

# 匿名卷(不推荐,难管理)
docker run -v /data postgres

选择建议:

  • 数据库数据 → volume;
  • 配置文件 → bind mount(只读 :ro);
  • 日志 → bind mount 到宿主机,方便 logrotate;
  • 临时文件 → tmpfs。

五、数据会丢吗

操作volume 数据容器内非挂载目录
docker stop / start保留保留
docker rm 删容器保留丢失
docker compose down保留丢失
docker compose down -v丢失丢失
docker volume rm丢失

所以:数据库必须挂 volumedocker compose down 别加 -v(除非你确定要清库)。

六、备份与迁移 volume

bash
# 备份:起个临时容器打包
docker run --rm -v pgdata:/data -v $(pwd):/backup alpine \
  tar czf /backup/pgdata-$(date +%F).tar.gz -C /data .

# 恢复
docker run --rm -v pgdata:/data -v $(pwd):/backup alpine \
  tar xzf /backup/pgdata-2026-05-07.tar.gz -C /data

# 或者先导出数据库逻辑备份(更可靠,可跨版本)
docker exec db pg_dump -U postgres mydb > mydb.sql

七、看容器用了多少磁盘

bash
docker system df              # 总览
docker system df -v           # 明细

# /var/lib/docker 占多少
du -sh /var/lib/docker
du -sh /var/lib/docker/*| sort -rh | head

# 清理
docker container prune        # 停止的容器
docker image prune -a         # 未使用的镜像
docker volume prune           # 未使用的卷(谨慎)
docker system prune -a        # 全部(谨慎)

docker volume prune 会删掉「没有被任何容器引用」的卷。如果你刚 down 了服务,数据卷就变成未引用了——别在停机维护时跑这条

八、日志膨胀

容器日志默认无限制增长,能把磁盘写满:

json
{
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "10m",
    "max-file": "3"
  }
}

写进 /etc/docker/daemon.json,重启 Docker 生效(只对新建容器有效)。

bash
# 单个容器日志在哪
docker inspect --format='{{.LogPath}}' <容器>

# 紧急清空某个容器的日志
sudo truncate -s 0 $(docker inspect --format='{{.LogPath}}' <容器>)

九、迁移 /var/lib/docker

空间不够时把 Docker 数据目录挪到大盘:

bash
sudo systemctl stop docker
sudo rsync -avz /var/lib/docker/ /data/docker/
sudo vim /etc/docker/daemon.json
# {"data-root": "/data/docker"}
sudo systemctl start docker
docker info | grep "Docker Root Dir"

记住两句:容器之间用服务名访问,重要数据一定挂 volume。