想在mac上远程debug linux docker源码
目录
- 了解moby项目
- 环境信息
- 安装go
- 编译源码
- debug
- 总结
1、moby项目
2017 年,Docker 公司将 Docker 项目中的核心组件开源为 Moby,而 Docker 平台则作为基于这些组件的产品发布。这样子的好处是
其一:Docker 最初是一个完整的一体化平台,所有功能(如运行时、网络、存储等)都紧密耦合在一起,限制了功能的创新与更新。将 Docker 的核心功能拆解为独立的模块(如 containerd
、runc
、libnetwork
),每个组件可以独立开发、测试和发布,加速新功能的开发和测试。
其二:Docker 公司需要将更多资源投入到商业化产品(如 Docker Enterprise)中,而核心技术的开发和维护负担较重。通过 Moby 项目将核心技术交给社区维护,Docker 公司专注于构建基于 Moby 的商业产品,减轻 Docker 公司的开发和维护压力。
至于有什么模块,等后面学习的过程再继续了解,接下来先把环境弄好。
2、环境信息
本地是mac m2 air ,远程服务器是阿里云99元
linux版本信息
root@iZ7xv60bt3xh588holkr1fZ:~/moby# lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 24.04 LTS
Release: 24.04
Codename: noble
root@iZ7xv60bt3xh588holkr1fZ:~/moby# cat /proc/version
Linux version 6.8.0-40-generic (buildd@lcy02-amd64-075) (x86_64-linux-gnu-gcc-13 (Ubuntu 13.2.0-23ubuntu4) 13.2.0, GNU ld (GNU Binutils for Ubuntu) 2.42) #40-Ubuntu SMP PREEMPT_DYNAMIC Fri Jul 5 10:34:03 UTC 2024
更新于2024.12.12
在后续的containerd源码阅读中,发现dockerd依赖了containerd,所以这环境信息缺了一部分,下面是补上的
需要先通过apt
命令安装一遍docker
,目的是安装containerd
、runc
,否则dockerd
启动的时候会找不到containerd
。
docker版本是
Docker version 27.3.1, build ce12230
3、安装go
go官网下载安装包,选择linux版本的压缩包,版本是
https://go.dev/dl/
安装go,解压后路径为/root/go
tar -zxvf xxxxx.tar.gz
配置环境变量, vim ~/.bashrc
export GOROOT=/root/go
export GOPATH=/root/go_space
export PATH=$PATH:$GOROOT/bin:$GOPATH/bin
4、编译源码
克隆docker源码,
github clone https://github.com/moby/moby.git
命令行运行下面的命令
#
cd moby
#设置代理
go env -w GOPROXY=https://goproxy.cn,direct
#
go mod init
接下来,将vendor.mod中内容复制到go.mod文件中,再运行
go mod tidy
go mod vendor
4.1编译dockerd
编译dockerd程序,也就平时常说的Docker Daemon
, 是Docker的核心守护进程,负责执行实际操作,例如启动、停止、删除容器。询问GPT得到以下编译命令
go build \
-gcflags "all=-N -l" \
-ldflags "-X github.com/docker/docker/dockerversion.Version=27.1.x \
-X github.com/docker/docker/dockerversion.GitCommit=$(git rev-parse --short HEAD) \
-X github.com/docker/docker/dockerversion.BuildTime=$(date -u '+%Y-%m-%dT%H:%M:%SZ')" \
-o ./bundles/binary-daemon/dockerd ./cmd/dockerd
该命令会编译 ./cmd/dockerd
目录中的代码, 入口脚本是docker.go, 编译好的二进制文件放到./bundles/binary-daemon/
目录下,名字为dockerd
,其他参数说明如下:
-gcflags "all=-N -l"
-N
:关闭优化,以便调试器更容易跟踪代码执行。
-l
:禁止函数内联(inlining),确保所有函数都可以在调试器中完整查看。
-ldflags
版本信息的标志,便于在调试时了解当前的版本、提交信息和构建时间。
编译完成后,查看版本信息
./bundles/binary-daemon/dockerd -v
4.2编译cli
cli就是我们平时常用docker命令,cli的代码并不在moby项目中,因此需要再下一个仓库。。。
git clone https://github.com/docker/cli.git
cd cli
和前面一样
go mod init
接下来,将vendor.mod中内容复制到go.mod文件中,再运行
go mod tidy
go mod vendor
项目中提供了makefile脚本来编译cli工具
make -f docker.Makefile binary
但是这玩意会用到dockerd去构建一个docker镜像,然后在镜像实例中进行编译,所以我们要启动dockerd守护进程。由于国内的环境,要拉取镜像很麻烦,就算用了阿里云代理,你还得登录。
目前,我们此时还没有编译docker cli也就是docker 命令,pull 和 tag操作都搞不了,所以和dockerd
一样,都是直接go build
来编译.
再次询问GPT结果给出的编译命令是错的,只能自己找找看。
在scripts下找到了编译的命令,环境变量是在.variables中设置的,和dockerd一样,脚本逻辑不想看,有问题再回来看吧,先参考上面dockerd的写一个试试先
go build \
-gcflags "all=-N -l" \
-ldflags "-X github.com/docker/cli/cli/version.Version=27.1.x \
-X github.com/docker/cli/cli/version.GitCommit=$(git rev-parse --short HEAD) \
-X github.com/docker/cli/cli/version.BuildTime=$(date -u '+%Y-%m-%dT%H:%M:%SZ')" \
-o ./build/docker ./cmd/docker
编译完成后查看版本号
root@iZ7xv60bt3xh588holkr1fZ:~/cli# ./build/docker -v
Docker version 27.1.x, build 61b02e636d
启动dockerd
后,执行docker info
命令看看能返回dockerd
的信息,返回成功
5、debug配置
编译的目的就是为了debug。
vscode添加配置后,能入口打上断点,但是在有些函数的时候跳不过去,估计是因为我是mac的关系,go编译器忽略了部分代码导致了500+的error,看着难受。idea一开始也有这个问题,但可以设置编译选项后就没问题了
补充说明by 2024.12.03
idea因为插件里面go版本只支持到1.21,导致仍旧有部分代码是会报错的,没办法,要换工具了
换Goland ,同样是jetbrains 的,配置差不多,就不补图了
Settings
go插件
debug配置
在远程主机上,随便找个目录执行下面的命令,安装dlv
go install github.com/go-delve/delve/cmd/dlv@latest
在远程主机上,moby项目根目录下,通过 Delve 启动 dockerd
并启用远程调试模式:
dlv --listen=:8005 --headless=true --api-version=2 exec ./bundles/binary-daemon/dockerd -- --debug
启动后输出
root@iZ7xv60bt3xh588holkr1fZ:~/moby# dlv --listen=:8005 --headless=true --api-version=2 exec ./bundles/binary-daemon/dockerd -- --debug
API server listening at: [::]:8005
2024-12-02T10:19:38+08:00 warning layer=rpc Listening for remote connections (connections are not authenticated nor encrypted)
以docker images
命令为例,对应的请求是 /images/json
在 ..../moby/api/server/router/image/image.go
可以看到对应的处理方法是
getImagesJSON
打上断点后,idea启动debug, 等到命令行输出下面的内容后
...
DEBU[2024-12-02T10:41:24.032627719+08:00] Registering POST, /networks/{id:.*}/connect
DEBU[2024-12-02T10:41:24.032857336+08:00] Registering POST, /networks/{id:.*}/disconnect
DEBU[2024-12-02T10:41:24.033095076+08:00] Registering POST, /networks/prune
DEBU[2024-12-02T10:41:24.033262752+08:00] Registering DELETE, /networks/{id:.*}
INFO[2024-12-02T10:41:24.040106901+08:00] API listen on /var/run/docker.sock ```
另开一个远程会话,在cli项目的根目录下执行
```shell
./build/docker images
看到进来了!
总结
他喵的,不问gpt我都不知道moby这玩意…