前言:从“能跑”到“会玩”,你卡在哪一步?
💡 推荐阅读:Linux 服务器安全防护,别只装个杀毒就完事:生产环境下的纵深防御与调优手记
很多朋友在接触服务器运维时,都绕不开 Docker 这道坎。刚开始接触那会儿,笔者也觉得这玩意儿不就是个高级点的虚拟机嘛,`docker run` 一把梭,能启动就行。但真到了要把一个项目稳定跑起来、甚至要迁移服务器的时候,才发现里面的水有多深:容器一删数据全没了、端口冲突搞得焦头烂额、日志把磁盘塞满……
今天这篇文章,咱们不聊那些虚头巴脑的理论,直接从一个真实场景切入:如何在一台全新的云服务器上,从零开始部署一套带数据库的 Web 应用,并且保证容器删了数据还在。这套流程走通了,你基本就能告别“小白”阶段,进入“会用”的境界了。
环境准备:磨刀不误砍柴工
💡 延伸阅读:别再盯着K8s不放了!手把手用开源Docker平台,十分钟玩转轻量级容器编排
在开始敲命令之前,你得先有一台能联网的 Linux 服务器。无论是 CentOS、Ubuntu 还是 Debian,操作逻辑大同小异。如果你还没服务器,笔者建议你选个靠谱的云厂商,新用户一般有优惠,带宽选 3M 以上,系统盘 40G 起步,这样后续折腾起来才不憋屈。
安装 Docker 这一步很简单,官方给了一键脚本,但为了稳妥,咱们还是走软件源安装。以 Ubuntu 为例:
# 更新软件源索引
sudo apt update
# 安装依赖包,允许通过 HTTPS 使用仓库
sudo apt install -y ca-certificates curl gnupg lsb-release
# 添加 Docker 官方 GPG 密钥
sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
# 设置稳定版仓库
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
# 安装 Docker 引擎
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io
# 验证安装
sudo docker version
看到 Client 和 Server 两段信息都输出正常,说明 Docker 已经装好了。这里提醒一句:别忘了把当前用户加入 docker 组,不然每次都得敲 sudo,很烦人。
sudo usermod -aG docker $USER
# 退出终端重新登录,让组权限生效
核心实操:部署一个带 MySQL 的博客应用
💡 深度技术指南:Nginx反向代理总是被恶意IP刷爆?手把手教你配置一套真正能用的黑名单封禁体系
光装好 Docker 不算本事,咱们得让它干活。下面笔者带你部署一套经典的 WordPress + MySQL 环境。别急着说“这太简单了”,咱们重点在于理解 数据卷(Volume) 和 网络(Network) 的概念,这才是容器化部署的精髓。
第一步:创建专属网络环境
容器之间通信,最好用自定义网络。别用默认的 bridge,因为自定义网络支持 DNS 解析,也就是说容器之间可以直接用“名字”互相访问,而不是靠 IP 地址(IP 一变就抓瞎)。
# 创建一个 bridge 网络,名字叫 webnet
docker network create webnet
# 查看网络列表确认一下
docker network ls
第二步:部署 MySQL 并挂载数据卷
这是最关键的一步。数据库里的数据是最宝贵的,绝对不能放在容器可写层里。一旦容器被删,数据就跟着“陪葬”了。我们必须把数据目录挂载到宿主机上。
# 运行 MySQL 5.7 容器
docker run -d \
--name mysql-db \
--network webnet \
-e MYSQL_ROOT_PASSWORD=YourStrongPass@123 \
-e MYSQL_DATABASE=wordpress \
-v mysql_data:/var/lib/mysql \
mysql:5.7
# 参数详解:
# -d:后台运行
# --name:给容器起名字
# --network:指定网络
# -e:设置环境变量(这里设置了 root 密码和初始数据库)
# -v:挂载数据卷,mysql_data 是卷名,/var/lib/mysql 是容器内数据路径
这里用到了命名卷 mysql_data。你可以用 docker volume inspect mysql_data 查看它实际存在宿主机的哪个目录下。以后就算你 docker rm -f mysql-db 把容器删了,只要卷还在,数据就安然无恙。
第三步:部署 WordPress 并关联数据库
有了数据库,咱们再把应用跑起来。注意看 WordPress 容器是怎么通过名字找到数据库的:
# 运行 WordPress 容器
docker run -d \
--name wp-site \
--network webnet \
-p 8080:80 \
-e WORDPRESS_DB_HOST=mysql-db:3306 \
-e WORDPRESS_DB_USER=root \
-e WORDPRESS_DB_PASSWORD=YourStrongPass@123 \
-e WORDPRESS_DB_NAME=wordpress \
-v wp_data:/var/www/html \
wordpress:latest
# -p:端口映射,宿主机 8080 端口映射到容器 80 端口
# WORDPRESS_DB_HOST:数据库地址,直接写容器名 mysql-db,这就是自定义网络的好处
看到这里,你应该明白了:容器化的核心不是“装系统”,而是“编排服务”。现在打开浏览器,访问 http://你的服务器IP:8080,应该就能看到 WordPress 的安装界面了。
第四步:验证数据持久化
咱们做个实验,来证明数据卷的价值:
# 强制删除 WordPress 容器
docker rm -f wp-site
# 用同样的命令再跑一个
docker run -d \
--name wp-site-new \
--network webnet \
-p 8080:80 \
-e WORDPRESS_DB_HOST=mysql-db:3306 \
-e WORDPRESS_DB_USER=root \
-e WORDPRESS_DB_PASSWORD=YourStrongPass@123 \
-e WORDPRESS_DB_NAME=wordpress \
-v wp_data:/var/www/html \
wordpress:latest
刷新浏览器,你会发现网站设置、主题、插件都还在,就像什么都没发生过一样。这就是数据卷的魅力。
进阶操作:用 Docker Compose 一键编排
手动敲这么多 docker run 命令,容易出错且难以维护。真实项目里,我们更推荐用 Docker Compose 把服务定义在文件里,实现“一键启停”。
先创建一个项目目录,咱们把刚才的两兄弟写进一个 YAML 文件里:
mkdir ~/wordpress-stack && cd ~/wordpress-stack
vim docker-compose.yml
写入以下内容:
version: '3.8'
services:
db:
image: mysql:5.7
volumes:
- mysql_data:/var/lib/mysql
restart: always
environment:
MYSQL_ROOT_PASSWORD: YourStrongPass@123
MYSQL_DATABASE: wordpress
wordpress:
depends_on:
- db
image: wordpress:latest
ports:
- "8080:80"
restart: always
environment:
WORDPRESS_DB_HOST: db:3306
WORDPRESS_DB_USER: root
WORDPRESS_DB_PASSWORD: YourStrongPass@123
WORDPRESS_DB_NAME: wordpress
volumes:
- wp_data:/var/www/html
volumes:
mysql_data:
wp_data:
保存退出后,执行一条命令即可完成部署:
# 启动所有服务(-d 表示后台)
docker compose up -d
# 查看运行状态
docker compose ps
# 查看日志(排查错误很有用)
docker compose logs -f
# 停止并移除所有容器(数据卷会保留)
docker compose down
以后迁移服务器,只需要把这个 docker-compose.yml 文件拷过去,再执行一次 docker compose up -d,整个世界都清净了。笔者现在管理服务器上的应用,基本都靠 Compose 文件,清晰明了,哪怕是半年后再回来看,也能一眼看懂这玩意儿是干嘛的。
避坑清单:这些坑笔者都替你踩过了
光看教程不踩坑是不可能的,但有些坑完全可以避免。下面这几条,是笔者在长期使用中总结出的“血泪教训”:
- 时区问题:默认容器时区是 UTC,比北京时间慢 8 小时。如果应用有日志记录功能,时间对不上会非常头疼。解决方案是在 Compose 文件里加
environment: - TZ=Asia/Shanghai。 - 日志膨胀:容器默认会把所有 stdout 日志存下来,如果不加限制,几个月就能把磁盘写满。强烈建议在 Compose 里配置日志轮转:
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
- 不要用 latest 标签跑生产:今天部署没问题,明天
docker compose pull一下可能就把版本升上去了,导致不兼容。最好锁定具体版本号,比如mysql:5.7.44。 - 端口冲突:启动容器报
port is already allocated,说明宿主机端口被占了。用netstat -tlnp | grep 8080查一下是谁占用的。 - 容器内文件修改不生效:如果你改了挂载目录里的文件但没反应,检查一下是不是权限问题。容器内用户 UID 和宿主机不一致会导致写不进去,必要时用
chown -R 1000:1000调整权限。
写在最后:容器化是一种思维转变
学会了 Docker 的基本操作,你会发现部署应用变成了一件“标准化”的事。不再需要写冗长的部署文档,一个 YAML 文件就能搞定一切。当然,这只是容器化世界的冰山一角——K8s、Service Mesh、Serverless 这些概念,都是建立在“容器”这个基石之上的。
笔者建议你,别光看,一定要动手。找一台云服务器,哪怕是配置最低的,把今天讲的 WordPress 流程走一遍,再试试删除容器、重建容器,感受一下数据卷带来的安全感。只有亲手踩过坑,才能真正把技术变成自己的东西。
好了,今天的分享就到这里。如果你在实操中遇到了什么奇怪的问题,欢迎在评论区留言,咱们一起探讨。下次见!
相关技术专题与延伸阅读
- Linux 服务器安全防护,别只装个杀毒就完事:生产环境下的纵深防御与调优手记
- 别再盯着K8s不放了!手把手用开源Docker平台,十分钟玩转轻量级容器编排
- Nginx反向代理总是被恶意IP刷爆?手把手教你配置一套真正能用的黑名单封禁体系
- 别再被问懵了!一文搞懂 Docker 到底是开源还是商业软件,附避坑实操指南
📦 【资源免费领】本文全套实操配置文件与避坑手册下载
本文涉及的全套 Docker Compose 配置文件、服务器运维避坑清单及 AI 提效指令库已完整打包,可免费极速转存:
💡 提示:推荐使用手机【夸克网盘 App】打开保存,新用户首月免费赠送 1TB 超大空间与免流量极速下载特权。