You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Golang Air时Postgres本地卷执行docker compose down后被删除

问题分析与解决方案

核心问题1:docker compose down删除Postgres数据目录

原因是Air配置中tmp_dir="tmp"与Postgres数据卷挂载的./tmp目录重合,且misc.clean_on_exit=true会在Air进程退出时清理指定的临时目录。当执行docker compose down时,app容器内的Air进程退出,触发清理操作,直接删掉了本地的./tmp目录(也就是Postgres的数据存储目录)。

解决步骤:

  • 修改air.toml,将Air的临时目录与Postgres数据目录分离:
root="."
# 把Air的临时目录改成独立的,比如.airtmp
tmp_dir=".airtmp"

[build]
cmd="go build -gcflags=\"all=-N -l\" -o ./bin/main ."
bin="/app/bin"
full_bin="/app/bin/main"
log="air_errors.log"
include_ext=["go", "yaml"]
# 排除新的临时目录和Postgres数据目录
exclude_dir=[".airtmp", "tmp"]
delay=1000

[log]
time=true

[misc]
clean_on_exit=true
  • 手动删除原有的./tmp目录,重新执行docker compose up -d,让Postgres重新初始化数据目录,此时Air的清理操作只会影响.airtmp,不会再删除Postgres的数据目录。

核心问题2:容器启动failed to initialize错误

结合你的配置和代码,大概率是以下两种原因:

原因A:Postgres未完成初始化,App提前尝试连接

depends_on: [db]仅保证db容器启动,但Postgres服务需要几秒时间完成初始化,此时App(通过Air启动)尝试连接DB会失败,触发Cannot connect to DB panic,进而导致容器failed to initialize。

解决方法:

在App的启动流程中添加DB连接等待逻辑,或者在local.Dockerfile中引入等待脚本:

  1. 在项目根目录创建wait-for-db.sh脚本:
#!/bin/bash
set -e

host="$1"
shift
cmd="$@"

until pg_isready -h "$host" -p 5432 -U "admin"; do
  >&2 echo "Postgres is unavailable - sleeping"
  sleep 1
done

>&2 echo "Postgres is up - executing command"
exec $cmd
  1. 给脚本加执行权限:chmod +x wait-for-db.sh
  2. 修改air.toml的cmd,先执行等待脚本再构建:
[build]
cmd="./wait-for-db.sh db && go build -gcflags=\"all=-N -l\" -o ./bin/main ."
  1. 确保local.Dockerfile中安装了postgresql-client(提供pg_isready命令),比如在Dockerfile中添加:
RUN apt-get update && apt-get install -y postgresql-client && rm -rf /var/lib/apt/lists/*

原因B:Postgres数据目录权限问题

如果./tmp目录被Air删除后重新创建,本地目录的权限可能是root用户所有,而Postgres容器内运行的是postgres用户(UID=999),无法写入该目录,导致Postgres启动失败,进而App连接失败。

解决方法:

  • 手动设置本地./tmp目录的权限:
sudo chown -R 999:999 ./tmp
  • 或者在docker-compose.yml的db服务中添加user配置,指定用root用户运行(仅本地开发临时使用):
db:
  image: postgres
  container_name: db
  ports:
    - "5432:5432"
  environment:         
    POSTGRES_USER: "admin"
    POSTGRES_PASSWORD: "pass"
    POSTGRES_DB: "test"
    TZ: "UTC"
    PGTZ: "UTC"
  volumes:
    - ./tmp:/var/lib/postgresql/data
  # 临时用root用户运行,避免权限问题
  user: "root"

验证步骤

  1. 停止并清理现有容器:docker compose down -v
  2. 删除原./tmp和.airtmp目录(如果存在)
  3. 应用上述所有配置修改
  4. 启动容器:docker compose up --build
  5. 检查容器日志:docker compose logs app和docker compose logs db,确认无错误后测试API连接。

内容的提问来源于stack exchange,提问作者HexaCrop

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 12:05:29