第一关:优化配置,打好基础
我们从一份基础的 docker-compose.yml
文件开始。它能用,但不够健壮和安全。
原始配置存在的问题:
- 密码硬编码:将数据库密码、管理员密码直接写在文件里,有安全风险。
- 启动顺序不可靠:
links
是一个过时的功能,它不能保证在应用启动时,数据库已经完全准备就绪。 - 数据管理不便:使用绑定挂载 (
./data
) 会将数据直接与宿主机目录绑定,不利于迁移和管理。
优化后的配置: 我们引入了 Docker Compose 的几项最佳实践,对配置进行了“现代化改造”,使用 .env
文件来管理敏感信息,通过 healthcheck
确保服务启动顺序,并采用命名卷来管理数据。
优化的 docker-compose.yml
version: '3.8'
services:
picsur:
image: ghcr.io/caramelfur/picsur:latest
container_name: picsur
restart: always
ports:
- "${PICSUR_HOST_PORT:-8383}:8080"
environment:
PICSUR_DB_HOST: picsur_postgres
PICSUR_DB_USERNAME: ${POSTGRES_USER}
PICSUR_DB_PASSWORD: ${POSTGRES_PASSWORD}
PICSUR_DB_DATABASE: ${POSTGRES_DB}
PICSUR_ADMIN_PASSWORD: ${PICSUR_ADMIN_PASSWORD}
networks:
- picsur_net
depends_on:
picsur_postgres:
condition: service_healthy
picsur_postgres:
image: postgres:17-alpine
container_name: picsur_postgres
restart: always
environment:
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: ${POSTGRES_DB}
volumes:
- postgres_data:/var/lib/postgresql/data
networks:
- picsur_net
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]
interval: 10s
timeout: 5s
retries: 5
volumes:
postgres_data:
networks:
picsur_net:
配套的 .env
文件
# .env 文件
POSTGRES_USER=picsur
POSTGRES_PASSWORD=your_strong_password
PICSUR_ADMIN_PASSWORD=your_admin_password
学习点:通过使用
.env
文件、depends_on
、healthcheck
和命名卷,我们的配置变得更安全、更健壮、更专业。这是所有生产环境部署的推荐做法。
第二关:命令不存在?新旧版本的交替
配置完成后,我们信心满满地运行 docker-compose up -d
,结果…… Command 'docker-compose' not found
这是一个经典的“环境问题”。它揭示了 Docker Compose 的一个版本变迁:
- V1 版本:命令是
docker-compose
(带连字符)。 - V2 版本:命令是
docker compose
(带空格),作为 Docker 的一个插件存在。
由于服务器上已经有正在运行的 Docker 容器,我们不能粗暴地卸载重装。
解决方案:单独安装 V2 版本的 Compose 插件。
# 只安装缺失的插件,不影响现有 Docker 环境
sudo apt-get install docker-compose-plugin
学习点:技术在不断迭代。当遇到“命令不存在”时,除了检查是否安装,还要考虑是否是版本或命令格式发生了变化。使用
docker compose
是目前推荐的方式。
第三关:环境变量去哪了?
解决了命令问题后,我们再次尝试,又遇到了一堆黄色警告和红色错误。
WARN[0000] The "POSTGRES_USER" variable is not set...
Error: container picsur_postgres is unhealthy
日志清晰地告诉我们:所有在 .env
文件里设置的变量都没有被加载,导致数据库无法用正确的用户名和密码初始化,最终启动失败。
问题根源:Docker Compose 默认只会在当前目录下寻找名为 .env
的文件。这个问题 99% 的可能性是 .env
文件不存在、放错了位置,或者文件名不对(比如写成了 env
或 .env.txt
)。
解决方案:
- 清理失败的尝试:
docker compose down
。 - 检查文件:
ls -la
,确保能看到一个不多不少,正好名为.env
的文件。 - 确认无误后,重新启动:
docker compose up -d
。
学习点:魔鬼在细节中。一个标点符号、一个文件名的错误都可能导致整个应用启动失败。仔细阅读日志是排错的最快途径。
第四关:终极对决,为何登录不进去?
终于,所有容器都正常运行了!我们激动地打开浏览器,输入在 .env
文件里设置好的管理员账号 admin
和密码,却收到了无情的“Wrong username or password”提示。
这是最迷惑的一个问题,因为从表面看,一切都正常。
问题根源:这与应用的初始化逻辑和 Docker 数据卷的持久化特性有关。
PICSUR_ADMIN_PASSWORD
这个环境变量,只在数据库第一次为空时,用于创建初始管理员。- 在我们解决第三关问题之前,数据库容器可能已经启动过一次。那时由于
.env
文件没加载,应用可能用一个空的密码创建了admin
用户,并将这个用户数据保存在了postgres_data
这个数据卷里。 - 之后我们虽然修正了
.env
并重启,但应用检测到数据库里已经有admin
用户了,所以它不会去更新密码。而数据卷是持久的,它会一直保存着那份错误的数据。
解决方案:彻底重置,破釜沉舟!
- 停止并移除所有相关容器:
docker compose down
- 删除被污染的数据库数据卷(这是最关键的一步!):
docker volume rm picsur_postgres_data
- 从一个完全干净的状态重新启动:
docker compose up -d
这一次,应用面对的是一个全新的、空的数据库,它会忠实地使用我们 .env
文件里的正确密码来创建管理员。再次登录,成功!
学习点:理解 Docker 数据卷的持久化生命周期至关重要。当遇到与数据状态相关的奇怪问题时,要想到可能是旧的、错误的数据被持久化了。彻底清除数据卷是解决这类初始化问题的“大招”。
总结
这次部署 Picsur 的经历,完美地串联起了 Docker Compose 的几大核心知识点:配置管理、服务依赖、网络、数据持久化,以及最重要的——排错思路。每一次报错都是一次学习的机会。希望这篇记录能帮助你在 Docker 的世界里走得更远、更稳!
发表回复