CGO_ENABLED=0是部署Iris项目的前提,否则二进制因动态链接libc失败而报“no such file or directory”;需配合systemd正确配置StandardOutput、User、WorkingDirectory;Nginx反代为必需,Iris仅监听内网端口;日志须显式落盘,不可依赖默认stdout。

CGO_ENABLED=0 静态编译是部署 Iris 项目的前提,否则二进制在目标服务器上大概率直接报 no such file or directory——这不是路径写错,而是动态链接 libc 失败。
必须用 CGO_ENABLED=0 编译,除非你明确需要 cgo
Go 默认启用 cgo,一旦用了 net.Resolver、sqlite3 或任何带 C binding 的包,生成的二进制就会依赖系统 libc。Alpine、极简 CentOS 或旧版 RHEL 上一运行就崩:standard_init_linux.go:228: exec user process caused: no such file or directory。
常见错误现象:本地能跑,传到服务器 ./myapp 直接报错退出,ldd myapp 显示一堆 not a dynamic executable 或提示缺失 libc.so。
正确做法:
- 普通 HTTP 服务(DNS 解析走纯 Go 实现):CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o myapp ./main.go
- 真要用 cgo(比如连 SQLite):设 CGO_ENABLED=1,并确认目标服务器 glibc 版本兼容(如 RHEL 7 要 ≥2.17),不能部署到 Alpine
systemd 服务配置里最容易丢的三行
很多人写完 ExecStart=/opt/myapp/myapp 就以为完事了,结果服务启动失败却查不到日志,或启动后立即退出。
关键配置项必须显式声明:
- StandardOutput=journal 和 StandardError=journal:否则 journalctl -u myapp 一片空白
- User=www-data:该用户需提前创建,且对 /opt/myapp/ 有读+执行权限(chmod 755 /opt/myapp)
- WorkingDirectory=/opt/myapp:Iris 加载静态文件、配置文件时依赖当前工作目录,漏掉会导致 open assets/index.html: no such file 类错误
Nginx 反向代理不是可选项,是生产必需
Iris 自己监听 :80 或 :443 是危险操作:没 TLS 终止、没请求限速、没 X-Forwarded-* 头透传,更没法处理 SNI 和 OCSP stapling。
正确分工:
- Iris 只监听内网端口,例如 --port=8080
- Nginx 做反代,必须加:proxy_set_header X-Forwarded-For $remote_addr;proxy_set_header X-Forwarded-Proto $scheme;
- 若 Iris 返回流式响应(SSE、大文件下载),Nginx 需配 proxy_buffering off;
- 别让 Iris load cert:它不支持多域名证书、不自动续期、不处理 TLS 1.3 优化
日志不会自动落地,得自己接管 stdout
Iris 的 iris.Logger() 默认只打到 stdout,而 systemd 会截断长日志行、不持久化存储。
这意味着:
- journalctl -u myapp 可能看不到完整错误栈
- 没有访问日志文件,无法做日志轮转或对接 ELK
解决办法:
- 在代码里把 iris.Logger().SetOutput() 指向一个带轮转的文件(如用 lumberjack)
- 或用 systemd 的 SystemMaxUse= 和 MaxFileSec= 控制 journal 大小与保留时间
- 更稳妥的是:Nginx 记访问日志,Iris 只记业务/错误日志,两者分开落盘
真正容易被忽略的点是:Iris 二进制本身没有“日志文件”概念,它只输出到 stdout;而 systemd 对 stdout 的处理方式,和你是否配了 StandardOutput=journal、是否设了 WorkingDirectory、是否用了 CGO_ENABLED=0,全部环环相扣。少一个,部署就卡在某个看似无关的环节。











