博客部署后,我遇到的数据库、迁移和管理员初始化问题

预计阅读时间:9 分钟

这是「把自己部署到互联网上」系列的第 32 篇。

上一篇,把个人博客通过 Docker 部署起来了:

  • 项目目录有了,代码拉下来了

  • .env 配好了

  • Dockerfile 和 Compose 文件也整理了
  • 应用容器和数据库容器跑起来
  • 全局 Nginx 能转发请求
  • 域名和 HTTPS 也开始接入

到这一步,博客已经算基本部署成功。

但接着做下来我发现:容器跑起来,不等于博客真的可用,这篇文章主要记录下使用过程中踩到坑的问题,供大家参考下,避免再次踩坑。

遇到的问题

问题1 数据库容器正常运行,但应用连不上

查看容器日志,日志里可能会出现 connection refusedaccess deniedunknown hostdatabase does not exist

这不是容器的问题,而是配置没对上。

先检查应用里的数据库地址是否写成了 localhost

在 Docker 容器中,localhost 指当前容器自己,不是数据库容器。

如果数据库服务在 docker-compose.yml 里叫 db,应用应该写:

DB_HOST=db # 写容器名

而不是:

DB_HOST=localhost

再检查端口、用户名、密码、数据库名是否一致。Compose 里设置了 MYSQL_DATABASEMYSQL_USERMYSQL_PASSWORD,应用 .env 里就要对应 DB_NAMEDB_USERDB_PASSWORD

还要注意数据库容器状态是否已经 ready。

数据库容器 running,不代表数据库服务已经可连接。

depends_on 只能控制启动顺序,不保证数据库可用。

如果项目没有重试机制,应用可能比数据库更早启动,然后连接失败

这时可以等数据库就绪后重启应用,或者在应用侧增加重试和等待策略。

问题2 数据库初始化只在第一次生效

很多数据库镜像有一个特点:初始化环境变量通常只在数据目录为空时生效

比如第一次启动 MySQL 容器时,MYSQL_DATABASEMYSQL_USERMYSQL_PASSWORD 会创建数据库和用户。

但如果数据卷已经存在,后面修改 .env文件 再 docker compose up -d,这些用来初始化的变量不一定重新执行。

这很容易出现问题,比如第一次密码写错了,容器已经启动并创建了数据卷。

你后来改了 .env,以为新密码生效,但数据库里可能仍然是第一次初始化时的密码。

解决这类问题前,先判断当前是测试环境还是已有真实数据。

如果只是测试,可以在确认无重要数据后删除 volume 重新初始化;

如果已有真实数据,绝对不能随便删

查看 volume:

docker volume ls
docker volume inspect blog-db-data

数据库初始化不是普通配置修改,它和数据持久化绑定在一起,谨慎一点。

问题3 迁移文件没有执行

很多项目框架都有数据库迁移机制。Djangomigration,其他框架也可能有 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 初始化脚本不要重复执行

有些脚本会创建表、创建默认管理员、写入初始配置、导入示例数据或初始化站点设置。第一次部署执行没问题,但重复执行可能带来副作用:重复插入数据、重复创建管理员、覆盖配置、重置密码,甚至清空某些表。

小结:

把命令分成三类:

  1. 初始化命令,只在第一次部署时执行
  2. 迁移命令,项目升级时按需执行
  3. 管理命令,创建用户、修改配置、清理缓存等按场景执行

排查时常用的几条命令:

docker compose ps
docker compose logs -f app
docker compose logs -f db
docker compose exec app env | grep DB_

下一篇做阶段性复盘:从 HTTPS 到对象存储,我的博客终于有了上线条件。那篇会把证书、资源层和博客部署前置条件重新串起来,看距离稳定上线还差哪些收尾工作。


本文由 楸木 原创,转载请注明出处。

相关推荐

发现更多