0


(多种方法)VSCode调试docker容器里的程序

目录

概述

有时候我们需要调试docker容器里的c++程序,可以使用命令行运行gdb调试,但是不如vscode的图形界面调试着直观。如何使用VSCode调试docker容器里的c++程序。

目前,我知道的有三种方法:

1. 通过vscode的remote-container插件

  • 优点:通过这个插件,会让你开发的时候感觉像是在直接在操作,几乎感受不到容器的存在。
  • 缺点:(1)不知道是不是服务器有点辣鸡,但是总感觉开了这个之后,ssh老是断开连接,我感觉可能是开销比较大。(2)有时候在安装vscode的server时,会出现权限的问题,需要改改权限之类的。
  • ps:如果要调试远程服务器上的容器,那需要先使用remote-ssh连接远程服务器,再用remote-container插件。

2. 通过ssh远程调试容器内部

开启容器的时候,设置一下端口映射,让主机可以通过ssh服务访问docker容器。然后,利用gdb的远程调试功能,就可以在主机上面调试docker容器里的代码了。参考:https://lemariva.com/blog/2020/10/vscode-c-development-and-debugging-containers

  • 优点:开销没那么大
  • 缺点:在安装容器的时候需要安装sshd服务才行。除此之外,没有remote-container插件那么强大。

3. (个人感觉是最优解) 通过vscode的pipeTransport功能

参考文档: https://code.visualstudio.com/docs/cpp/pipe-transport。

方法一、通过vscode的remote-container插件

只需要在应用商店搜索该插件即可,方法很简单,与remote-ssh插件基本一样。
在主机上面运行过docker之后(

docker run ...

,可以用

--name

指定名词),remote-container插件即可检索到这个容器,右键容器,再找到对应的选项,即可连接进去容器内部。具体略。
可以参考博客

方法二、通过ssh远程调试容器内部

2.1、基于你原来的镜像,然后再加一层,该层主要是安装gdb、openssh-server,然后开启sshd服务,暴露出来22端口

参考dockerfile(参考连接)

# 原始镜像
FROM debian:bullseye

LABEL description="Container for use with VSCode"# install build dependencies to build and debug 
RUN apt-get update \&&apt-getinstall-y g++ build-essential make cmake gdb gdbserver \rsynczip openssh-server git# configure SSH for communication with VSCode
RUN mkdir-p /var/run/sshd

# chpasswd用来更改root用户的密码,"root:root"即将root用户密码设置为root# 然后使用sed修改sshd_config文件里的"PermitRootLogin prohibit-password"为"PermitRootLogin yes"# 再修改/etc/pam.d/sshd里的“session\s*required\s*pam_loginuid.so”为"session optional pam_loginuid.so"??
RUN echo'root:root'| chpasswd \&&sed-i's/#PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/sshd_config \&&sed's@session\s*required\s*pam_loginuid.so@session optional pam_loginuid.so@g'-i /etc/pam.d/sshd
    
WORKDIR /

CMD ["/usr/sbin/sshd", "-D"]# 开放22端口
EXPOSE 22

2.2、编译程序

2.2.1 方案

从编译方法上,有两种方法:
(1)直接通过

docker run

进入容器内部进行编译
(2)通过ssh进入容器内部进行编译
从编译途径上,有两种途径:
(1)手动输入命令,或者写个shell脚本编译。
(2)使用vscode的task.json
我个人喜欢写个脚本,里面使用

docker run ...

进行编译,不过还是贴上task.json的方法,因为感觉以后可能有地方会用到。

2.2.2 [手动] 配置tasks.json文件自动编译

(参考连接)

2.2.2.1 通过ssh进入容器内部进行编译"的配置
  1. 主机需要安装sshpass工具,这个工具可以在命令行直接通过-p参数输入用户密码然后进行ssh登录(当然其它的办法也可以,比如设置免密登录之类的)
sudoapt-getinstall sshpass
  1. 编写配置文件 tasks.json文件内容如下(注意编译命令需要自行设置):
{"version":"2.0.0","tasks":[{"label":"build-in-container","type":"shell","command":"/usr/bin/sshpass","args":["-p","root",// "-p"参数指定密码"ssh","root@localhost",// user@ip"-p","2222",// 端口映射"/source/build.sh"// 这里的编译命令需要自行设置],"problemMatcher":["$gcc"],"group":{"kind":"build","isDefault":true}}]}
2.2.2.2 通过
docker run

进入容器内部进行编译"的配置

理论上也可以配置一下task.json里的命令,让他通过

docker run

来编译,具体略

2.3 配置launch.json文件

launch.json文件模板示例(依然是通过sshpass,然后利用vscode的Pipe transport,vscode官方docker示例):

{"version":"0.2.0","configurations":[{"name":"(gdb) Launch","type":"cppdbg","request":"launch","program":"build/app",// [需修改] 目标文件"args":[],"stopAtEntry":true,// 默认在程序入口处,即main函数处停下来"cwd":"/source",// [需修改] 工作目录"environment":[],"externalConsole":true,// [可选] sourceFileMap是用来做主机与客机的路径映射// 参考 https://code.visualstudio.com/docs/cpp/pipe-transport"sourceFileMap":{"/source":"${workspaceFolder}"},"pipeTransport":{// "debuggerPath":"/usr/bin/gdb","pipeProgram":"/usr/bin/sshpass",// 类似task.json里面的"pipeArgs":["-p","root","ssh","root@localhost","-p","2222"],"pipeCwd":""},"MIMode":"gdb"}]}

2.4、运行容器

docker run -d-p2222:22 --security-opt seccomp:unconfined -v$PWD:/source --name gdb-cpp-image gdb-cpp-image

2.5、调试代码

按键F5

方法三 通过vscode的pipeTransport功能

3.1 运行容器

sudodocker run -d --security-opt seccomp:unconfined -v$hostPath:$guestpath--name gdb-cpp-image imagename

3.2 配置launch.json

launch.json文件类似于方法二的,不同的是里面的pipeTransport参数,这里不是通过ssh,而是直接通过docker

"pipeTransport":{"pipeCwd":"${workspaceFolder}","pipeProgram":"docker","pipeArgs":["exec","-i","hello_gdb","sh","-c"],"debuggerPath":"/usr/bin/gdb"},

完整的参考示例

{"version":"0.2.0","configurations":[{"name":"(gdb) Launch","type":"cppdbg","request":"launch","program":"build/a.out",// [需修改] 目标文件"args":["arg1","arg2",],// 参数"stopAtEntry":true,"cwd":"/home/...",// [需修改] 工作目录"environment":[],"externalConsole":true,// [可选] sourceFileMap是用来做主机与客机的路径映射// 参考 https://code.visualstudio.com/docs/cpp/pipe-transport"sourceFileMap":{"/source":"${workspaceFolder}"},"pipeTransport":{"pipeCwd":"${workspaceFolder}","pipeProgram":"docker","pipeArgs":["exec",// exec是运行已有的容器,也可以使用docker run,原理差不多"-i","gdb-cpp-image",// 镜像名字"sh","-c"],"debuggerPath":"/usr/bin/gdb"},"MIMode":"gdb"}]}

3.3 调试

按键F5

断点不生效的解决办法

我测试方法三的时候,有时候出现设置了断点,但是断点不能准确被触发,貌似是因为vscode一开始没检索到那个断点的位置,于是我尝试在调试控制台直接用

-exec b 断点位置

,发现可以正常触发。
如下图,vscode提示

Module containing this breaknoint has not vet loaded or the breaknoint address could not be obtained

在这里插入图片描述
如下图,断点被成功触发,虽然显示是异常,但是不影响。
不过这样需要每次调试运行之后都输入一次。(在便捷性上还是remote-container插件更强大一些)
在这里插入图片描述

标签: vscode docker gdb

本文转载自: https://blog.csdn.net/qq_29809823/article/details/128445308
版权归原作者 名扬569 所有, 如有侵权,请联系我们删除。

“(多种方法)VSCode调试docker容器里的程序”的评论:

还没有评论