Docker 进阶:镜像分层、数据卷与网络
理解镜像的分层缓存,用数据卷做持久化,用自定义网络让容器互联,并定期清理磁盘。
在你的服务器 / VPS 上跑通第一个容器之后,下一步是搞懂 Docker 背后的三件事:镜像怎么分层、数据存在哪里、容器之间怎么通信。本文以 Ubuntu / Debian 为例。
镜像分层与缓存
Docker 镜像由只读层叠加而成,每条 Dockerfile 指令生成一层。运行容器时,顶部再加一个可写层。理解这一点能显著加快构建速度。
关键规律:构建时 Docker 逐层比对,只要某层的指令和上下文没变,就直接命中缓存;一旦某层变了,它之后的所有层都会重建。所以应把不常变的步骤放前面。
# 反例:改一行代码就重装依赖
COPY . /app
RUN npm install
# 正例:先拷依赖清单并安装,再拷源码
COPY package*.json /app/
RUN npm install
COPY . /app
查看镜像的分层历史:
docker history <镜像名>
docker image ls # 查看各镜像体积
数据持久化:volume 与 bind mount
容器一删,其可写层里的数据就没了。要持久化必须把数据放到容器外,有两种方式。
- 命名卷(volume):由 Docker 管理,存于 /var/lib/docker/volumes/,适合数据库等生产数据。
- 绑定挂载(bind mount):直接映射宿主机某个目录,适合开发时挂源码、挂配置文件。
# 命名卷
docker volume create pgdata
docker run -d --name pg -v pgdata:/var/lib/postgresql/data postgres
# 绑定挂载(宿主机绝对路径:容器路径)
docker run -d -v /srv/site:/usr/share/nginx/html nginx
管理命令:
docker volume ls
docker volume inspect pgdata
docker volume rm pgdata # 卷未被容器占用才能删
网络模式与容器互联
Docker 默认提供三种网络:
- bridge:默认模式,容器接入虚拟网桥,通过端口映射 -p 对外暴露。
- host:直接共用宿主机网络栈,无需映射端口,但少了隔离。
- none:无网络,完全隔离。
默认 bridge 上的容器只能靠 IP 互访。正确做法是建自定义网络,同网络内的容器可直接用容器名当主机名通信,还自带 DNS 解析。
docker network create app-net
docker run -d --name db --network app-net postgres
docker run -d --name web --network app-net -p 8080:80 nginx
# web 内可直接用 db:5432 连接数据库
docker network ls
docker network inspect app-net
清理磁盘
镜像、停止的容器、悬空卷会悄悄吃满磁盘。定期清理:
docker system df # 先看占用
docker system prune # 清停止的容器、无用网络、悬空镜像
docker system prune -a --volumes # 更彻底:含未被引用的镜像和卷(慎用)
-a --volumes 会删掉所有未在用的镜像和卷,执行前务必确认没有需要保留的数据。
小结
镜像是分层且带缓存的,把稳定步骤前置能加速构建;持久化数据用命名卷(生产)或绑定挂载(开发);容器互联优先用自定义网络,靠容器名而非 IP;最后别忘了 docker system prune 给磁盘瘦身。掌握这四点,你就能在自己的服务器上稳妥地运维容器化应用了。