GitLab这玩意,搞研发的同学应该都不陌生。它本质上是基于Git的代码托管平台,提供了完整的分支管理、Merge Request、Issue跟踪、CI/CD流水线,甚至容器镜像仓库。很多团队上了GitLab之后,基本就可以把代码管理、自动化构建、部署上线这些环节串成一条龙。不过它最大的特点或者说“门槛”,在于部署方式——很多人一听到搭GitLab,第一反应就是要找一台专门的服务器,跑一堆安装脚本,配置数据库、Redis、Nginx,想想就头大。
我自己刚接触这套东西的时候也踩过不少坑,后来发现用Docker Desktop来部署GitLab社区版,其实是一个特别适合中小团队和个人开发者上手的方式。Docker把这些依赖全部打包进容器,你不需要关心Ruby、PostgreSQL、Redis的版本冲突,只需要几百兆的镜像拉下来,一条命令就能把整套服务跑起来。这篇文章就专门写一下,怎么用Docker Desktop在本地Windows/Mac环境下把GitLab搭起来,然后怎么初始化、建项目、配SSH、传代码,顺便把那些我实际遇到过的高频报错和解决方案一起整理出来,给后来人省点时间。
1. 为什么选Docker Desktop部署,而不是直接裸装
1.1 自建GitLab的几种常见方案对比
在决定用Docker Desktop之前,我把常见的部署方式都大概过了一遍,这里先给你们捋清楚。第一种是直接在服务器上裸装GitLab Omnibus包,这种方式也就是我们常说的“传统安装”,官方提供了deb/rpm包,安装之后会帮你把Nginx、PostgreSQL、Redis这些服务全部装好并配置好,用起来确实很“一体化”,但缺点也明显——它对系统资源的占用比较大,而且升级的时候如果系统环境比较旧,很容易出现依赖冲突。我自己以前在Ubuntu 20.04上装过一次,光是解决ruby版本问题就得折腾半天,还不敢乱动系统里已有的组件。
第二种方式是找一台云主机,用docker run或者Docker Compose把GitLab拉起来。这种方式部署起来快,资源隔离做得也好,升级就是换个镜像的事,算是我比较推荐的生产环境做法。但问题在于,云主机毕竟不是每个人都有,而且不少团队早期只是想本地搭一套来联调或者学习,没必要花钱买服务器。
第三种就是今天的主角:Docker Desktop + GitLab社区版镜像,在本地电脑上直接把服务跑起来。它的核心优势在于零系统侵入,你电脑上已有的Node.js、MySQL、Redis全都不受影响,GitLab需要的所有依赖都在容器里。开发机默认配的就是Windows或者macOS,装一个Docker Desktop并不难,后续想要迁移到云服务器,也只需要把docker-compose.yml文件搬过去,命令一样,体验一致。
1.2 本地部署GitLab的典型场景
用Docker Desktop跑GitLab,最常见的几类场景我也梳理一下,你们可以对号入座。第一类是个人开发者想在本地做版本管理,同时想体验一下GitLab的完整流程,比如Merge Request、CI/CD这些,而不是只装一个裸Git。第二类是团队内网没有外网代码托管条件的,或者出于安全要求必须把代码放在自己服务器上的,可以先在本地用Docker Desktop搭一套原型,确认流程没问题后再迁到内网主机。第三类是前端、测试或运维同学想学习GitLab CI/CD、Webhook这些功能,又不想搞一台生产机器折腾,直接在笔记本电脑上跑最方便。
我自己的实际感受是,Docker Desktop这套方案最适合“先跑起来看看”这种心态。因为GitLab的初始化过程其实有几个容易卡住的点,比如内存不足、端口冲突、权限问题,这些在容器里都比较好排查,就算弄坏了,删掉容器重建也就是几分钟的事,完全不用担心系统被搞坏。
2. 部署前置条件:Docker Desktop安装与镜像选型
2.1 Windows上安装Docker Desktop的硬性要求
如果你是在Windows上操作,安装Docker Desktop之前,有几个前置条件必须先确认,否则大概率会在启动阶段就报错。我先说硬性要求:Windows 10 64位专业版/企业版/教育版,或者Windows 11;必须开启CPU虚拟化;内存建议不低于8GB,最好是16GB,因为GitLab默认配置吃内存比较猛,后面我会专门讲怎么限制。还有一点,BIOS里要确保虚拟化技术(比如Intel VT-x或AMD-V)是开启的,这个很多人会忽略。
安装完成之后,Docker Desktop经常会弹出一个报错,内容大概是“Docker Desktop failed to start because virtualization support wasn’t detected”或者“virtualization support not detected”,意思是检测不到虚拟化支持。遇到这个情况,先别急着卸载重装,大概率是下面几个原因之一:WSL2没有启用、Hyper-V没有启用,或者BIOS虚拟化没开。
解决办法是按顺序排查。先用快捷键Win+E打开资源管理器,然后输入wsl --status看下WSL的状态,如果显示没有安装发行版,就先打开PowerShell(管理员权限),执行wsl --install,装完后重启电脑。接着再确认Hyper-V,在“控制面板—程序—启用或关闭Windows功能”里找到“Hyper-V”和“适用于Linux的Windows子系统”,把这两个都勾上。如果这两项都没问题但还是报错,那就进BIOS,找到“Intel Virtualization Technology”或者“SVM Mode”这类选项,确保它是Enabled状态。
2.2 镜像选型:ce版和ee版要分清
Docker Hub上GitLab相关的镜像有两个,gitlab/gitlab-ce和gitlab/gitlab-ee。CE是社区版,功能上对于绝大多数团队已经完全够用,像代码托管、Merge Request、Issue、CI/CD这些核心功能都在;EE是企业版,多了LDAP集成增强、多集群管理、审计事件这些高级特性,个人或小团队基本用不上,而且它是带许可机制的,不需要为了尝鲜去碰EE。所以这篇内容默认都用gitlab/gitlab-ce,这也是我实际在用的版本。
有个小提醒:GitLab镜像的体积不小,CE版大概在800MB到1GB左右,第一次pull的时候要有耐心,网络稳定的话几分钟也能搞定。如果拉取速度很慢,可以考虑配置Docker的镜像加速器,但注意不要涉及到任何不合适的工具,按你们公司常规配置走就行。
2.3 端口规划和目录挂载,这一步省不了
部署GitLab必须规划好三类内容:端口、挂载目录、环境变量。先说端口,GitLab容器内部默认使用80端口提供Web访问,22端口走SSH。这意味着如果Docker宿主机上已经有Nginx或者SSH服务,直接映射80和22会冲突。我的做法是给宿主机换一套映射关系,比如Web访问用8929:80,SSH用2222:22,这样既不用动宿主机现有服务,也能给GitLab开个独立入口。
挂载目录方面,GitLab有三个关键目录要持久化:/etc/gitlab存放配置、/var/log/gitlab存放日志、/var/opt/gitlab存放仓库和数据库数据。如果不做数据卷挂载,容器一删,所有代码和用户数据全没了,到时候真就是“代码全丢,欲哭无泪”。所以在启动命令里一定要配置好-v参数,或者用Docker Compose的volumes字段,把宿主机的目录映射进去。
环境变量里最重要的是GITLAB_ROOT_PASSWORD,可以用来自定义root管理员的初始密码,没配置的话GitLab会自动生成一个随机密码存到容器里,首次登录比较麻烦,所以建议在启动时就显式设置好。
3. Docker Compose部署GitLab完整实操
3.1 编写docker-compose.yml文件
我个人比较推荐直接用Docker Compose来部署,而不是一大长串的docker run命令。原因很简单:docker run命令行写长了,可读性差,下次想改配置还得重新找历史命令,而compose文件可以提交到Git里做版本管理,团队共享也方便。下面是一个我实际在用的docker-compose.yml,你们可以直接抄作业。
version: '3.6' services: gitlab: image: gitlab/gitlab-ce:latest container_name: gitlab restart: always hostname: gitlab.local environment: GITLAB_OMNIBUS_CONFIG: | external_url 'http://gitlab.local:8929' gitlab_rails['gitlab_shell_ssh_port'] = 2222 GITLAB_ROOT_PASSWORD: 'YourRootPassword123' ports: - '8929:80' - '2222:22' volumes: - '/d/docker/gitlab/config:/etc/gitlab' - '/d/docker/gitlab/logs:/var/log/gitlab' - '/d/docker/gitlab/data:/var/opt/gitlab' - '/etc/localtime:/etc/localtime:ro' shm_size: '256m'这段配置里有几个细节我重点说明一下。hostname我写的是gitlab.local,external_url也对应改成http://gitlab.local:8929,这样GitLab生成的克隆地址就是基于这个域名来的。如果你不设置hostname,GitLab默认会拿容器ID当主机名,生成的clone地址会是一串乱七八糟的字符,用起来非常别扭。GITLAB_OMNIBUS_CONFIG这个环境变量是GitLab镜像的特色,可以往/etc/gitlab/gitlab.rb里注入自定义配置,我在这里就把SSH端口改成了2222,让容器内的SSH服务对外暴露在宿主机2222端口。
shm_size这一段也很关键。GitLab内部使用Puma和Sidekiq,对共享内存有一定需求,Docker默认的64MB很可能不够用,导致启动报错或者运行一段时间后进程挂掉。我设成256m,实测下来很稳。
3.2 启动、初始化和容器状态检查
配置文件准备好之后,在docker-compose.yml所在目录下打开终端,执行docker compose up -d。注意新版Docker Compose命令已经是docker compose(中间有空格),老版本的docker-compose在部分系统上也能用,但如果执行报错提示docker-compose: command not found,就说明你装的是新版Docker插件,直接用空格版即可。
启动之后先别急着访问页面,GitLab的首次初始化是个磨人的过程。容器内部要做数据库迁移、编译静态资源、启动一堆组件,整个过程在一般配置的电脑上大概需要3到5分钟,服务器快一点也得1到2分钟。这段时间你可以执行docker logs -f gitlab实时看日志。当看到日志里出现GitLab is ready!或者类似Running gitlab-rails-...字样时,说明服务已经起来了。如果想更直观地确认,可以等一会儿再执行docker ps,看到STATUS一栏从health: starting变成healthy,就说明一切正常。
启动过程中我还要插一句:如果是在本地Windows上用Docker Desktop,注意右下角Docker Desktop图标是否处于Running状态。有时候电脑休眠唤醒之后,Docker Desktop会变成stopped,这个时候GitLab容器自然也就跟着挂了,记得先确认Docker Desktop状态再讨论GitLab问题。
3.3 首次登录root账号和密码获取
浏览器访问http://localhost:8929,第一次打开会看到GitLab的登录页。如果你设置了GITLAB_ROOT_PASSWORD环境变量,直接用root和你设置的密码登录即可。如果当时没设,GitLab会把初始密码写入容器的/etc/gitlab/initial_root_password文件里,执行下面的命令查看:
docker exec -it gitlab grep 'Password:' /etc/gitlab/initial_root_password登录后建议立刻修改root密码,因为GitLab官方为了安全,会在第一次密码生成后的24小时内自动删除initial_root_password文件,而且明文的初始密码放在文件里总归不踏实。
这里再补充一个我踩过的坑:如果你在GITLAB_OMNIBUS_CONFIG里通过gitlab_rails['initial_root_password']配置过密码,那么initial_root_password文件可能根本不会生成,所以最好的做法还是老实设环境变量,一劳永逸。
4. GitLab核心操作:创建项目、配SSH、导入代码
4.1 新增项目流程,走一遍就熟了
GitLab的项目创建逻辑,说白了就是“组里面建项目”,或者直接在个人命名空间下建。登录后左侧菜单有个“新建项目”按钮,点进去会有三个选项:创建一个空白项目、导入项目、经典创建流程。我建议新手直接用最显眼的“创建空白项目”。
填写项目名时注意一个细节:项目名称里尽量不要用中文或空格,GitLab虽然支持,但会生成类似project-name-1这种转义后的路径,后续clone的时候很容易出歧义。可见性级别选择上,个人学习直接选“私有”(Private),团队协作也要选私有,避免代码泄露。项目建好之后,会跳转到项目首页,页面右上角会显示类似git clone http://gitlab.local:8929/yourname/yourproject.git这样的地址,这就是后续push和pull用的远程仓库地址。
4.2 SSH密钥配置,Push免密的关键
用HTTP方式clone代码,每次push都要输用户名密码,麻烦不说,还容易因为特殊字符转义问题报错。所以我到任何GitLab上都是先配SSH密钥。GitLab的SSH认证逻辑很简单:你把本地生成的公钥放到GitLab后台,GitLab之后就会根据你发起SSH连接时提供的私钥来识别你的身份。
第一步,本地生成密钥对。在Windows上打开PowerShell,在macOS/Linux上打开终端,执行:
ssh-keygen -t rsa -b 4096 -C "your_email@example.com"一路回车即可,默认会生成在~/.ssh/id_rsa.pub和~/.ssh/id_rsa。如果之前已经生成过,想单独为GitLab建一个密钥,可以这样指定文件名:
ssh-keygen -t rsa -b 4096 -f ~/.ssh/gitlab_id_rsa -C "your_email@example.com"第二步,把公钥内容复制到GitLab。用cat ~/.ssh/gitlab_id_rsa.pub把内容打出来,全选复制,然后到GitLab右上角头像→“偏好设置”→“SSH密钥”,粘贴进去,起个名字,点新增密钥。这里要特别注意,公钥内容是一整行长字符串,复制的时候不要漏掉结尾的注释内容,我见过有人只复制了前半段导致密钥无效的情况。
第三步,测试连通性。在终端执行:
ssh -T git@localhost -p 2222如果看到类似Welcome to GitLab, @yourname!的回显,就说明SSH链路已经通了。之后clone地址记得用SSH协议,也就是ssh://git@localhost:2222/yourname/yourproject.git或者对应gitlab.local域名,而不是HTTP地址。
4.3 本地项目导入GitLab,两种方式都交给你
本地已经有一个项目,想把它导入到GitLab,这是很多同学上来就问的问题。我分享两种方式,按场景选。
第一种,用Git命令推上去。这种方式最通用,不依赖任何IDE插件。假设你的本地项目在D:\my-project目录,先在这个目录里初始化Git仓库,然后添加远程地址:
cd D:\my-project git init git add . git commit -m "init project" git remote add origin ssh://git@localhost:2222/yourname/my-project.git git push -u origin master这里有两个容易踩坑的点。一个是用-u origin master还是main,要看你本地仓库默认分支名是什么,GitLab新建项目默认分支是master还是main跟版本有关,但push的时候分支名不匹配也不会报错,只是会生成两个分支,后续合并不太优雅。另一个是如果你的本地项目里已经包含.git目录,就不要再执行git init了,直接git remote add origin就行,否则会把历史提交记录清空。
第二种,用GitLab自带的“导入项目”功能。在“新建项目”→“导入项目”里,GitLab支持从GitHub、Bitbucket、Gitee,甚至任意Git URL导入。如果你的源码在某个远程仓库里,填一下URL和认证信息,GitLab会自动帮你拉镜像,这个功能对迁移场景特别实用。热词里有“gitlab导入项目”,说的基本就是这俩方法,推荐都试一下。
4.4 查看代码量与项目活跃度
热词里有一个“‘gitlab 代码量怎么看’”,这个炒得挺热。简单说,GitLab自带了一套统计工具,不需要任何第三方插件。进入项目页面,左侧菜单找到“分析”或者“代码仓库”相关入口,里面能看到代码行数变化趋势、提交频率、参与人员统计、代码量排名这些维度。如果你是管理员,还可以在项目设置里开启“仓库分析”功能,最直观的方式是看项目首页的“存储统计”和“提交统计”,代码量、文件数、最近提交一目了然。对于团队管理者来说,这个功能用来把握开发节奏挺方便的,但也要注意不要过度依赖指标去评价个人工作量,代码质量不是行数能衡量的,这里只是说功能上能看。
5. 部署之后的高频问题与排查经验笔记
5.1 Docker Desktop启动失败,虚拟化报错怎么治
这个问题在热词里出现的频率极高,报错信息基本是Docker Desktop failed to start because virtualization support wasn’t detected之类。这其实不是Docker Desktop本身坏了,而是它赖以运行的环境没准备好。从Windows的角度,Docker Desktop有两个后端引擎,一个基于Hyper-V,一个基于WSL2,现在主流是WSL2,所以需确保Windows功能里的“适用于Linux的Windows子系统”和“虚拟机平台”都已启用。
我的排查顺序是这样:先运行wsl --status看WSL状态,如果是旧版本,就执行wsl --update升级到WSL2的完整版本。再进入“启用或关闭Windows功能”确认Hyper-V、虚拟机平台、适用于Linux的Windows子系统三者都勾选。如果都不缺,就检查BIOS虚拟化,开机进BIOS把SVM Mode或者Intel VT-x设为Enabled。还有一个小概率问题是Windows沙盒和Docker冲突,有些刚重装完系统的机器默认开了“内核隔离”或者“内存完整性”,把这个关掉再试。
5.2 GitLab容器起不来,内存是第一个怀疑对象
GitLab社区版有个比较著名的毛病:默认配置对内存的要求偏高。官方建议是4GB内存,但如果你只是在Windows笔记本上跑,可能根本没那么多资源留给虚拟机。我遇到过容器一会儿起一会儿挂的情况,看日志是puma进程频繁被OOM Killer干掉了。
解决办法是通过环境变量限制GitLab的内存占用。在GITLAB_OMNIBUS_CONFIG里加入下面几行:
puma['worker_processes'] = 2 sidekiq['max_concurrency'] = 5 postgresql['shared_buffers'] = "256MB"这样可以把整体内存占用控制在2GB左右,虽然性能上不算强,但本地开发完全够用。因此如果你机器内存只有8GB,这种瘦身配置是必须的,不加的话Docker Desktop本身还要吃掉几百MB,非常紧张。
5.3 IDEA/GitLab插件登录报错怎么办
热词里那句login failed. check api token or gitlab version. log in via git if the version...,我第一眼看到就觉得眼熟。这通常是你在IntelliJ IDEA或者VS Code的GitLab插件里,想通过“生成API Token”的方式登录GitLab时出现的报错。
这个问题的根源,多半是你的GitLab版本较老,插件调用的API接口跟服务端版本不完全匹配,或者注册个人访问令牌时权限选项没勾完整。解决思路有两个:一个是确保你创建的Personal Access Token拥有api和read_repository权限,创建位置是“偏好设置→访问令牌”,勾选好后生成,复制出来的字符串以glpat-开头;另一个是在插件登录时,如果GitLab版本太老,直接改用“Username and Password”或者“SSH key”方式登录,不用API Token,本质绕开了版本兼容问题。
5.4 SourceTree连接私有GitLab的配置方法
热词里有“Source Tree 如何配置私有GitLab 服务”,我用SourceTree连私有GitLab的经验也算典型。SourceTree本质是一个Git图形客户端,它跟GitLab对接主要走SSH或者是HTTPS。
我的推荐是SSH方式。首先,确保SourceTree使用的SSH key是你的本地私钥,配置路径在“工具→选项→一般→SSH客户端配置”,把~/.ssh/gitlab_id_rsa这个私钥添加进去,而不是用SourceTree内置的PuTTY Key格式,否则会一直提示认证失败。接着,在SourceTree里选择“克隆”,填上GitLab项目页面的SSH地址,格式是ssh://git@gitlab.local:2222/yourname/yourproject.git,注意这里一定要带-p 2222对应的端口写法。搞定之后,SourceTree就能正常拉取和推送代码了。如果非要用HTTPS方式的话,用户名用你的GitLab用户名,密码用Personal Access Token而不是登录密码,否则也会认证失败。
5.5 GitLab版本升级和漏洞修复思路
GitLab社区版发布比较频繁,隔三差五会推出安全补丁。如果部署的是最新的latest镜像,升级流程其实很简单:先备份卷目录,也就是/d/docker/gitlab下那个文件夹,然后拉取新镜像docker pull gitlab/gitlab-ce:latest,最后docker compose down && docker compose up -d。因为配置和数据都在挂载目录里,容器重建不会有数据丢失。但我强烈建议升级前确认版本之间的升级路径,跨大版本升级GitLab有时候需要逐级升级,不能直接跳级,否则会报数据库迁移异常。具体是否支持跳级,看官方文档的升级路径图,怕麻烦的话就保持稳定版,不要追最新的rc版本。
关于GitLab的高危漏洞修复,需要特别强调一点:不要使用那类“离线热修复脚本”或者第三方补丁文件。最安全、最正规的方案就是升级到已修复漏洞的版本。你把GitLab当成一个长效运行的服务,定期关注它的安全公告,是每个维护者应尽的义务,毕竟代码仓库可是团队的命根子。
结尾的几句实在话
文章写到这里,该讲的实操差不多都讲完了。最后分享一点我自己的体会:用Docker Desktop跑GitLab,最大的价值并不是“省了一台服务器”,而是给了你一个随意折腾的环境。你可以放心地配CI/CD、玩Webhook、试试代码扫描,甚至把它打崩了再重建,整个过程不会影响本机其他环境,这种试错成本几乎为零的体验,对学习和对团队流程设计来说,都是非常珍贵的。
另外,如果后面想把它迁移到云服务器上,思路是完全不变的:装好Docker,把docker-compose.yml和挂载目录整个复制过去,改一下external_url为服务器的IP或域名,启动即可。路径通了一条,以后不管换什么环境,心里都有底。遇到问题的时候先别急着怀疑是GitLab坏了,先看Docker Desktop有没有在跑,再看容器状态,最后翻日志,按这个顺序排查,八成问题都能自己解掉。祝各位都能在自己的机器上顺利把GitLab跑起来,然后舒舒服服地用这套流程管理代码。