docker run 启动 Air 时必须显式挂载代码目录、指定工作目录(-w)、设置 air_wd 环境变量,并在 .air.toml 中配置 include_ext、绝对路径 bin、LF 换行等,否则因路径错位、文件不可见或解析失败导致热重载失效。

docker run 启动 Air 时必须显式挂载和指定工作目录
直接在容器里执行 air 命令会失败,因为 Air 默认在当前路径找 .air.toml,而容器启动时工作目录不一定是项目根目录。不指定 -w 和 -v,Air 根本看不到你的代码和配置文件。
正确做法是用完整参数启动:
-
-w "/go/src/myapp":强制设置容器内工作目录为项目路径(需与挂载路径一致) -
-v $(pwd):/go/src/myapp:把宿主机当前目录映射进去,确保 .go 文件、.air.toml、模板等都能被监听到 -
-p 8080:8080:把服务端口暴露出来,否则改完代码也访问不到 -
-e "air_wd=/go/src/myapp":显式告诉 Air 项目根在哪,避免它误判路径
示例命令:
docker run -it --rm \ -w "/go/src/myapp" \ -e "air_wd=/go/src/myapp" \ -v $(pwd):/go/src/myapp \ -p 8080:8080 \ cosmtrek/air
.air.toml 中的 bin 路径必须匹配容器内实际路径
你在本地开发时可能写 bin = "./tmp/main",但在容器里这个路径很可能不存在,或者权限不对——air 启动时会报 exec: "./tmp/main": file does not exist 或 permission denied。
解决方式是统一用绝对路径,并确保构建命令生成的二进制可执行:
cmd = "go build -o /go/src/myapp/tmp/main ."bin = "/go/src/myapp/tmp/main"- 在
cmd后追加&& chmod +x /go/src/myapp/tmp/main,防止 Linux 容器内无执行权限 -
tmp_dir = "tmp"保持默认即可,但要确认该目录不在exclude_dir列表中
容器内监听 HTML/YAML 模板需显式声明后缀
Gin 项目常读取 config.yaml、渲染 templates/*.html,但 Air 默认只监听 .go 文件。改了配置或模板,容器里 air 完全没反应,服务还是旧逻辑。
必须在 .air.toml 的 [watch] 或 [build] 区块里补全:
include_ext = ["go", "yaml", "yml", "html", "tpl", "tmpl"]- 如果模板放在子目录如
views/或resources/templates/,还要加include_dir = ["views", "resources/templates"] - 别漏掉
delay = 1000:防止快速连保存触发多次构建,导致tmp/main被覆盖中就尝试执行
Windows 或 macOS 主机运行时注意路径分隔符和换行符
虽然容器是 Linux 环境,但如果你在 Windows/macOS 上编辑 .air.toml,容易混入 CRLF 换行或反斜杠路径,导致 Air 解析失败、静默退出。
检查点:
- 用
file .air.toml确认是LF结尾(不是CRLF) - 所有路径用正斜杠
/,比如root = "/go/src/myapp",别写\go\src\myapp - 如果用 VS Code,关掉 “Auto Guess Encoding”,手动设编码为 UTF-8 without BOM
- 运行
docker run ... cosmtrek/air -c /go/src/myapp/.air.toml显式指定配置路径,避免 Air 自己猜错
最隐蔽的问题是:配置文件看着没错,但 Air 启动后日志里完全不打印 building,也不监听文件——八成是 TOML 格式被换行或不可见字符破坏了。


















