这是「把自己部署到互联网上」系列的第 32 篇。
上一篇,把个人博客通过 Docker 部署起来了:
-
项目目录有了,代码拉下来了
-
.env配好了 - Dockerfile 和 Compose 文件也整理了
- 应用容器和数据库容器跑起来
- 全局
Nginx能转发请求 - 域名和 HTTPS 也开始接入
到这一步,博客已经算基本部署成功。
但接着做下来我发现:容器跑起来,不等于博客真的可用,这篇文章主要记录下使用过程中踩到坑的问题,供大家参考下,避免再次踩坑。
遇到的问题
问题1 数据库容器正常运行,但应用连不上
查看容器日志,日志里可能会出现 connection refused、access denied、unknown host、database does not exist。
这不是容器的问题,而是配置没对上。
先检查应用里的数据库地址是否写成了 localhost。
在 Docker 容器中,localhost 指当前容器自己,不是数据库容器。
如果数据库服务在 docker-compose.yml 里叫 db,应用应该写:
DB_HOST=db # 写容器名
而不是:
DB_HOST=localhost
再检查端口、用户名、密码、数据库名是否一致。Compose 里设置了 MYSQL_DATABASE、MYSQL_USER、MYSQL_PASSWORD,应用 .env 里就要对应 DB_NAME、DB_USER、DB_PASSWORD。
还要注意数据库容器状态是否已经 ready。
数据库容器 running,不代表数据库服务已经可连接。
depends_on 只能控制启动顺序,不保证数据库可用。
如果项目没有重试机制,应用可能比数据库更早启动,然后连接失败
这时可以等数据库就绪后重启应用,或者在应用侧增加重试和等待策略。
问题2 数据库初始化只在第一次生效
很多数据库镜像有一个特点:初始化环境变量通常只在数据目录为空时生效。
比如第一次启动 MySQL 容器时,MYSQL_DATABASE、MYSQL_USER、MYSQL_PASSWORD 会创建数据库和用户。
但如果数据卷已经存在,后面修改 .env文件 再 docker compose up -d,这些用来初始化的变量不一定重新执行。
这很容易出现问题,比如第一次密码写错了,容器已经启动并创建了数据卷。
你后来改了 .env,以为新密码生效,但数据库里可能仍然是第一次初始化时的密码。
解决这类问题前,先判断当前是测试环境还是已有真实数据。
如果只是测试,可以在确认无重要数据后删除 volume 重新初始化;
如果已有真实数据,绝对不能随便删。
查看 volume:
docker volume ls
docker volume inspect blog-db-data
数据库初始化不是普通配置修改,它和数据持久化绑定在一起,谨慎一点。
问题3 迁移文件没有执行
很多项目框架都有数据库迁移机制。Django 有 migration,其他框架也可能有 schema 初始化或 migrate 命令。
如果不执行迁移,可能出现页面报错、后台打不开、表不存在、字段缺失、新版本代码和旧数据库结构不匹配。
容器启动成功不代表迁移已经完成。Django 项目需要执行:
docker compose exec app python manage.py migrate
创建管理员可能是:
docker compose exec app python manage.py createsuperuser
其他框架按项目文档来。
我一般都会把迁移命令单独记录下来,每次项目升级、数据库结构变化时也可能需要执行。
已经有真实数据的项目,迁移前最好先备份。
问题4 管理员账号没有初始化
博客部署完成后,需要创建超级管理员账户。
不同系统方式不同:有的通过 CLI 创建超级管理员,有的通过环境变量初始化,有的第一次访问后台时引导创建。
要提前确认四件事:
- 管理员账号创建方式是什么
- 初始密码是否足够强
- 初始化命令能不能重复执行
- 后台入口路由是否太过简单
后台入口是高风险入口,至少要有强密码、HTTPS、必要的访问限制和日志观察。
问题5 是环境变量改了,但应用没变。
改了 .env,不代表容器里的进程自动读到了新值。
Compose 会在创建或启动容器时读取环境变量;
如果变量用于 Compose 插值、容器运行时环境或镜像构建,生效方式也不同。
修改 .env 后,可能需要重新创建容器:
docker compose up -d --force-recreate # 强制创建
如果变量参与镜像构建,还可能需要重新 build。
建议排查时不要猜,可以直接看容器里实际环境变量:
docker compose exec app env | grep DB_
问题6 是数据卷到底在哪里
数据库数据一般放在 Docker volume 或宿主机绑定目录。比如:
volumes:
- blog-db-data:/var/lib/mysql
这表示数据放在名为 blog-db-data 的 volume 里。容器删除后,只要 volume 不删,数据还在。
如果用绑定目录:
volumes:
- ./data/mysql:/var/lib/mysql
数据就在项目目录的 data/mysql 下。
两种方式都可以,我更习惯用第二种,目录清晰明了,关键是必须知道数据在哪里、怎么备份、迁移时要带走什么。
问题7 初始化脚本不要重复执行
有些脚本会创建表、创建默认管理员、写入初始配置、导入示例数据或初始化站点设置。第一次部署执行没问题,但重复执行可能带来副作用:重复插入数据、重复创建管理员、覆盖配置、重置密码,甚至清空某些表。
小结:
把命令分成三类:
- 初始化命令,只在第一次部署时执行
- 迁移命令,项目升级时按需执行
- 管理命令,创建用户、修改配置、清理缓存等按场景执行
排查时常用的几条命令:
docker compose ps
docker compose logs -f app
docker compose logs -f db
docker compose exec app env | grep DB_
下一篇做阶段性复盘:从 HTTPS 到对象存储,我的博客终于有了上线条件。那篇会把证书、资源层和博客部署前置条件重新串起来,看距离稳定上线还差哪些收尾工作。
本文由 楸木 原创,转载请注明出处。