【Docker】解决 GitLab 容器启动 502 报错与 Permission denied 权限问题
前言
在使用 Docker 部署 GitLab 时(特别是使用 1Panel 等面板进行容器管理时),很多开发者会遇到容器无法正常启动,访问页面显示 502 Bad Gateway 的情况。
查看日志时,满屏的 Permission denied(权限被拒绝)让人头大。本文将记录一次真实的排查过程,并提供官方推荐的“一键”修复方案。
问题描述
最近在迁移或重启 GitLab Docker 容器后,发现服务一直处于 Unhealthy 状态,Web 界面无法访问。
通过 docker logs 查看容器日志,发现了大量关于权限的报错。
关键报错日志
1. Puma 服务无法写入日志(导致 502 错误的核心原因): 日志显示 Ruby 进程无法打开日志文件,直接导致 Web 服务崩溃。
Plaintext
! Unable to load application: Errno::EACCES: Permission denied @ rb_sysopen - /opt/gitlab/embedded/service/gitlab-rails/log/application_json.log [cite: 1067]
Rails Error: Unable to access log file. Please ensure that /opt/gitlab/embedded/service/gitlab-rails/log/production.log exists and is writable [cite: 1134]
2. Workhorse Socket 连接被拒绝: 由于权限问题,Nginx 无法通过 Unix Socket 连接到 GitLab 后端。
Plaintext
connect() to unix:/var/opt/gitlab/gitlab-workhorse/sockets/socket failed (13: Permission denied) while connecting to upstream [cite: 497]
3. Redis 无法持久化数据: Redis 因为无法写入磁盘,强制进入了只读模式,导致后台任务积压。
Plaintext
MISCONF Redis is configured to save RDB snapshots, but it's currently unable to persist to disk. [cite: 555]
原因分析
GitLab 容器内部并没有使用 root 用户来运行所有进程,而是使用了专用的 git (uid: 998)、gitlab-www、gitlab-redis 等用户。
当我们使用 Docker 挂载宿主机目录(如 /var/opt/gitlab)时,如果宿主机上的目录权限发生了变化(例如被误改为 root:root 且权限为 755),容器内部的非 root 用户就无法写入这些文件,从而导致服务全线崩溃。
解决方案
虽然我们可以在宿主机上手动使用 chown 修改目录权限,但由于 GitLab 涉及多个组件(PostgreSQL、Redis、Nginx 等),手动设置非常容易遗漏或设错。
最佳方案是使用 GitLab 容器内置的 update-permissions 工具,它会根据标准的 GitLab 目录结构自动修正所有文件的所有者和权限。
操作步骤
假设你的容器名称为 1Panel-gitlab-7lbz(请替换为你实际的容器名):
1. 进入容器执行修复命令
在宿主机终端执行以下命令:
Bash
docker exec -it 1Panel-gitlab-7lbz update-permissions
注:该命令会在日志中明确提示,专门用于修复此类启动失败的问题 。
2. 等待执行完成
该命令会遍历所有数据目录并修正权限,根据数据量大小,可能需要几秒到几分钟。
3. 重启容器
权限修复完成后,必须重启容器以重新加载服务:
Bash
docker restart 1Panel-gitlab-7lbz
验证结果
重启后,再次查看日志:
Bash
docker logs -f 1Panel-gitlab-7lbz
如果不出现 Errno::EACCES 或 Permission denied 字样,且看到类似 Puma starting in cluster mode... 以及 Server is ready to receive web requests 的提示,说明 GitLab 已经成功复活!
总结
在使用 Docker 运行复杂应用(如 GitLab、MySQL)时,目录映射的权限问题非常常见。GitLab 官方镜像非常贴心地内置了 update-permissions 脚本,这是最安全、最快捷的修复方式。
希望这篇文章能帮到同样遇到 502 错误的你!