一、先搞懂 Docker 的几个核心概念
很多站长把 VPS 买回来之后,第一件事是装宝塔、传源码、绑域名,网站跑起来就算完事。可一旦项目多了,问题就来了:PHP 版本冲突、MySQL 和 Redis 环境互相干扰、换一台机器要把环境从头再装一遍。Docker 把"应用 + 环境"打包成一个标准化的容器,配置一次、到处运行,换机器、迁移、多项目隔离都变得非常简单。这篇按实际操作顺序,把 Docker 从安装、跑网站、数据持久化到自动更新一次讲清。
动手之前,先把四个概念搞清楚,后面就不会绕晕:
- 镜像(Image):把应用和它依赖的环境打包成的只读模板,相当于"安装光盘"。
- 容器(Container):镜像运行起来的实例,相当于"装好的系统",可以启动、停止、删除。
- 数据卷(Volume):容器删掉后里面写的数据会全丢,数据卷就是专门把数据存到容器外的"外接硬盘"。
- Compose:用一份 yml 文件同时管理多个容器(比如 Nginx、PHP、MySQL 一组),一条命令全部启动。
一个常见的误区是拿 Docker 当虚拟机用:进容器里装宝塔、再拖源码。容器的设计哲学是"一个容器只跑一个进程",正确用法是把每个服务拆成一个容器,互相通过网络通信,各管各的、互不污染。
二、安装 Docker
官方安装脚本一行搞定(需要 root 权限):
curl -fsSL https://get.docker.com | sh
装完查看版本验证是否成功:
docker --version
国内服务器建议把镜像源换成加速器,否则拉镜像经常超时。编辑 /etc/docker/daemon.json:
{
"registry-mirrors": ["https://docker.m.daocloud.io"]
}
保存后重启 Docker 生效:
systemctl restart docker
三、用 Docker 跑一个最简单的网站
先用一条命令验证整个链路是否通畅,以 Nginx 为例:
docker run -d --name web -p 8080:80 nginx:alpine
- -d 后台运行,不占终端;
- --name web 给容器起个名字,后面管理都靠它;
- -p 8080:80 把宿主机的 8080 端口映射到容器内的 80 端口。
浏览器访问 http://服务器IP:8080,看到 Nginx 欢迎页,说明 Docker 已经跑通。第一次会自动拉取 nginx:alpine 镜像,这个精简版只有几十兆,比完整版快很多。
四、容器化部署一个 PHP 网站(Nginx + PHP + MySQL)
只跑一个 Nginx 没有实际意义,真实场景是 Nginx + PHP + MySQL 的组合。手写三条 docker run 麻烦且容易出错,推荐用 docker-compose。在项目目录创建 docker-compose.yml:
services:
nginx:
image: nginx:alpine
ports:
- "8080:80"
volumes:
- ./html:/usr/share/nginx/html
php:
image: php:8.2-fpm-alpine
volumes:
- ./html:/var/www/html
mysql:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: yourpassword
volumes:
- db_data:/var/lib/mysql
volumes:
db_data:
然后一条命令启动整组:
docker compose up -d
两个关键点:
- ./html 是目录挂载:宿主机直接改代码,容器内即时生效,不用重新构建镜像,开发调试非常顺手。
- db_data 是命名数据卷:MySQL 数据存在宿主机上,容器删了重建数据也不丢。
五、数据持久化:容器可以删,数据不能丢
容器天生是"一次性"的:删掉容器,里面写的文件全都没了。所以数据库、上传目录这些重要数据,必须用数据卷或目录挂载的方式存到宿主机。备份时直接备份宿主机的挂载目录就行:
tar czf backup.tar.gz /opt/project/html /var/lib/docker/volumes
恢复就是先把目录解压回原位,再 docker compose up -d 把容器拉起来,比传统环境迁移省事得多,这也是容器最大的优势之一。
六、开机自启与日志查看
容器默认不会随服务器重启自动运行,服务器一断电,重启后所有容器都是停的。给容器加上重启策略:
docker update --restart=always web
或者建容器时就带上 --restart=always。这样服务器意外重启后,容器会自动拉起来,不用每次手动去点。
看日志也不用进容器,一条命令:
docker logs -f --tail 100 web
-f 持续跟踪输出,--tail 100 只看最后 100 行,排查问题基本够用。
七、镜像更新与自动更新
手动更新一个容器的完整流程是:拉新镜像 → 停旧容器 → 删旧容器 → 用新镜像重新创建。项目少的时候手动还行,多了就推荐用 watchtower 自动更新:
docker run -d --name watchtower \
-v /var/run/docker.sock:/var/run/docker.sock \
containrrr/watchtower --cleanup --schedule "0 3 * * *"
这样每天凌晨 3 点,watchtower 会自动拉取并更新所有容器,--cleanup 会顺带清理掉旧镜像,磁盘不会越堆越大。注意数据库容器别让它自动更新,避免意外升级导致数据不兼容,可以在 compose 文件里给数据库容器加 label 排除掉。
八、常用排查命令清单
- 查看所有容器状态:docker ps -a
- 进入容器执行命令:docker exec -it web sh
- 查看容器资源占用:docker stats
- 删掉所有已停止的容器:docker container prune
- 清理用不上的镜像:docker image prune -a
总结
Docker 的核心价值在于"环境与代码一起交付":配置一次,换机器、多项目隔离、快速回滚都变得简单。新手按这个顺序走:装好 Docker → 用 docker run 跑通一个 Nginx → 用 docker-compose 部署完整的 PHP + MySQL 站点 → 把数据和日志目录挂载出来 → 加 --restart=always 和 watchtower 做自动更新。这五步跑通,日常建站和运维基本就够用了。