核心是配置、时区、权限、依赖四者协同;必须用 alpine 镜像+显式 chmod +x+环境变量注入,配 healthcheck 确保 mysql 就绪,加 tzdata/lang 解决中文乱码及时区问题。

beego 项目用 docker-compose 编排,核心不是“能不能”,而是“怎么让配置、时区、权限、依赖三者不互相打架”。直接上结论:别用 golang:latest 镜像打生产包,alpine + 手动 chmod +x + 环境变量注入才是稳定组合。
为什么 docker-compose up 启动后容器立刻退出?
常见现象:docker logs mindoc 或 docker logs go_mybeego 显示 permission denied 或空输出,docker ps -a 看到状态是 Exited (1)。
根本原因不是代码写错,而是镜像里二进制文件没执行权限,或入口命令路径不对。Beego 编译出的可执行文件(比如 myapp)在 alpine 镜像中默认不可执行,尤其当你用 COPY --chown 或挂载卷方式传入时更易触发。
- 构建阶段用
RUN chmod +x /go/src/myapp显式授权 - 运行阶段避免只写
command: ./myapp,改用command: /bin/sh -c "chmod +x /go/src/myapp && /go/src/myapp" - 若用
volumes挂载本地编译好的二进制,宿主机文件权限不会自动同步进容器,必须在command中补授权
docker-compose.yml 里怎么配 Beego 的端口和环境?
Beego 默认监听 8080,但实际部署常需映射到宿主机 80 或 443;同时它依赖 APP_ENV、HTTP_PORT、数据库地址等环境变量,这些不能硬编码进镜像。
-
ports字段只做宿主与容器端口映射,不影响 Beego 内部监听行为 —— Beego 是否真监听8080,取决于conf/app.conf里的httpport = 8080和环境变量覆盖逻辑 - 务必通过
environment注入:- HTTP_PORT=8080、- APP_ENV=prod、- MYSQL_HOST=mysql - 如果用了
bee run开发模式,docker-compose中不要保留该命令;生产必须用编译后的二进制,否则会因缺少bee工具而失败
MySQL 连不上?检查三个真实断点
Beego 应用启动后报 dial tcp: lookup mysql on 127.0.0.11:53: no such host 或 connection refused,问题几乎都卡在这三处:
-
depends_on只控制启动顺序,不保证 MySQL 已 ready —— 加healthcheck到 MySQL 服务定义里,再让 Beego 服务加restart: on-failure -
MYSQL_HOST值必须填mysql(即services.mysql.service_name),不能填localhost或127.0.0.1—— Docker 网络下它们指向容器自身 - Beego 的
conf/app.conf若写了mysqluser = root但没设mysqlpass,而 MySQL 容器要求密码,就会静默失败;建议统一用环境变量驱动连接串:dataSource = "${MYSQL_USER}:${MYSQL_PASSWORD}@tcp(${MYSQL_HOST}:${MYSQL_PORT})/${MYSQL_NAME}"
Alpine 镜像下中文日志乱码、时区错误怎么办?
用 alpine 是为了体积小,但代价是缺 tzdata、缺 ca-certificates、缺字体支持 —— Beego 的 logs 输出中文变 ???,time.Now().Format() 返回 UTC 时间,都是典型症状。
- 在
Dockerfile构建阶段加上:RUN apk add --no-cache tzdata ca-certificates,再COPY --from=0 /usr/share/zoneinfo/Asia/Shanghai /etc/localtime - Beego 日志编码依赖系统 locale,Alpine 默认无
en_US.UTF-8,所以中文日志乱码;解决办法是启动时加环境变量:- LANG=C.UTF-8 - 别信 “Docker 时间就是 UTC,改不了” —— 改
/etc/localtime+LANG环境变量后,time.Now()和logs全部同步为本地时区
Beego 和 docker-compose 的配合难点不在语法,而在对容器生命周期的理解:它不帮你等数据库就绪,不自动修复文件权限,也不默认加载中文环境。每一步都要显式声明,少一个环节,就多一个 Exited (1)。











