一招解决开发环境问题——远程容器开发指南

news2024/11/29 0:34:42

前言

使用C++作为主要开发语言的程序猿们应该会认同搭建开发环境是一件烦人的事情。为了编译一个程序不仅需要下载各种依赖包,还可能面临本地系统不兼容、编译器版本不一致、包版本冲突等各种问题。笔者在运营iLogtail开源社区的过程中发现开发和调试环境问题也是成员问的最多的问题之一,那么有没有一种方法可以彻底解决这一问题呢?

有。容器技术使应用在各种环境可以一键部署,一致执行,同样的原理也适用于开发环境部署。利用 VSCode 的 Remote-Development 插件就可以使整个开发环境运行在远程容器中。使用这种方式不但可以直接使用一致的环境开发编译,而且还自然实现了多个开发环境的隔离。下面让就我们由浅到深搭建这样的远端容器开发环境。

原理简介

为什么要远程+容器?远程解决的是开发机资源问题和代码安全问题,本地电脑的CPU和内存比较有限,为了提高编译、测试效率一般都会准备一台专门用于开发测试的机器,而部分公司为了防止代码外泄,只允许内部开发机访问代码库。容器解决的是开发环境一致性问题。两者结合起来便能构建最理想的开发环境。

在使用 Remote-Development 插件时,插件会ssh连接到远程开发机,然后根据配置直接启动或是铸造开发环境镜像后启动开发环境容器。启动时将开发机的Workspace目录作为源挂载到容器中。开发环境容器启动后,插件会自动安装VS Code Server,并安装配置指定的VS Code插件。一旦容器内的VS Code Server启动后,本地的VS Code就会直接与容器内的VS Code Server建立通信。容器内可以访问Workspace所有文件,并且修改不会因容器退出而丢失。容器开发环境可以使用的VS Code插件,在Workspace的devcontainer.json配置中指定,下文会有详细描述。

为了提高启动速度并保留容器内插件的配置,开发容器内的/vscode目录其实挂载了一个docker volume,不会自动随docker退出而回收,因此从第二次连接容器开发环境开始,无需重新安装VS Code Server、插件等,启动速度大大提高。

环境准备

要使VS Code可以远程连接开发机,最好使用ssh密钥建立本地电脑和开发机的信任关系。要使用容器进行开发,开发机上必须安装Docker。这两步相关教程网上较多,在这里就不再赘述。

需要注意的是,要使VS Code通过ssh连上开发机并通过docker启动开发环境容器,建立信任关系的账户必须具备docker使用权限。如果使用root账户,那么自然具备。如果非root则可以使用任意一种方式使账户获得docker使用权限:

  1. 将用户加入docker组。参考Post-installation steps for Linux(https://docs.docker.com/engine/install/linux-postinstall)。
    sudo usermod -aG docker $USER
  2. 将docker.sock权限修改为777(不太推荐,除非上述方法无法奏效)。
    sudo chmod 777 /var/run/docker.sock

下面假设开发机使用的是Linux系统,并且与本地电脑已经建立好信任关系,而且安装并具备Docker访问权限。

安装插件

在VS Code的Marketplace中搜索“Remote Development”安装插件。

安装完成后,会发现多出了3个子插件。

  • Remote - Containers:连接容器开发
  • Remote - SSH:连接ssh远程开发
  • Remote - WSL:连接WSL(Windows Linux子系统)开发

使用镜像开发

使用 Remote Development 插件最直接的方式就是利用现成的编译镜像启动开发容器。这里以使用C++和Go语言编写、依赖环境相对复杂的开源项目iLogtail数据采集器项目为例,说明如何利用 Remote Development 插件进行远程容器开发。

1. 创建Remote Development配置

在iLogtail Workspace的顶层目录创建.devcontainer目录,并在里面创建devcontainer.json文件。

配置文件的内容如下:

{
  "image": "sls-opensource-registry.cn-shanghai.cr.aliyuncs.com/ilogtail-community-edition/ilogtail-build-linux:latest",
  "customizations": {
    "vscode": {
      "extensions": [
        "golang.Go",
        "ms-vscode.cpptools-extension-pack"
      ]
    }
  }
}

其中,image字段是Remote Development插件启动开发环境的镜像地址,customizations.vscode.extensions指定了开发环境的插件。部分插件介绍如下,开发者也可以按照自己的习惯进行修改。

插件名用途
golang.GoGo开发必备插件
ms-vscode.cpptools-extension-packC++开发必备插件

2. 在容器中打开代码库

使用Shift + Command + P(Mac)或Ctrl + Shift + P(Win)打开命令面板,输入reopen,选择Remote-Containers: Reopen in Container

或者若出现如下图提示,则可以直接点击在容器中重新打开。

首次打开时会比较慢,因为要下载镜像并安装插件,后面再次打开时速度会很快。按照提示进行镜像Build。

完成上述步骤后,我们已经可以使用VS Code进行代码编辑,并在其中进行代码编译。

注:如果以前拉取过编译镜像,可能需要触发Remote-Containers: Rebuild Container重新构建。

3. 在容器中进行开发

开发容器启动后,我们已经可以在VS Code中浏览Workspace代码了。但是随便打开一个文件,满眼都是错误提示,代码的跳转功能也不能正常工作。这是因为C++开发环境的includePath没有被正确配置。

打开命令面板,输入C++ config,选择C/C++: Edit Configurations(UI)

找到Include path,输入镜像内依赖库的路径。

再回来看代码时,错误提示都消失了,并且函数定义跳转正常。

4. 在容器中进行编译

打开新Terminal(找不到的可以在命令面板中输入Terminal,选择新开一个)

  • 编译iLogtail Go插件

make vendor # 若需要更新插件依赖库 make plugin_local # 每次更新插件代码后从这里开始

  • 编译iLogtail C++代码

mkdir -p core/build # 若之前没有建过 cd core/build cmake .. # 若增删文件,修改CMakeLists.txt后需要重新执行 make -sj$(nproc) # 每次更新core代码后从这里开始

5. 获取编译产出

由于VS Code是直接将代码库目录挂载到镜像内的,因此主机上可以直接访问镜像内的编译产出。

到这里,如果要求不高的话就可以结束了,但细心的读者一定发现了一个问题,容器内生成的文件在主机上都是root权限,必须执行sudo chown -R $USER .进行修复。如果社区的成员开发机没有sudo权限怎么办?作为iLogtail社区核心贡献者,当然不能把这样的坑留给队友了。

使用Dockerfile开发

那有没有办法做到容器内权限自动适配主机呢?这样的问题当然不会难倒VS Code了。Remote Development 插件支持使用 Dockerfile 在容器中进行开发,即在启动开发容器前先使用docker build一个开发镜像,这给了修正容器内账户权限的机会。

修正的原理如下:

  1. 在Remote Development 插件 docker build 前将开发机的账户名、账户ID、组名和组ID暴露给 docker。
  2. docker build时利用这些账户信息修正容器执行账户和容器内文件权限。

接下来我们进行实际操作。

1. 修改.devcontainer.json配置文件

在配置文件中,将image部分修改为build部分,使用Dockerfile启动开发容器。同时,加入initializeCommand,在build镜像前,将账户信息暴露给docker。

{
  "build": {
    "dockerfile": "Dockerfile",
    "args": {
      "USERNAME": "${localEnv:USER}"
    }
  },
  "initializeCommand": ".devcontainer/gen_env.sh",
  "onCreateCommand": "sudo chown -R $(id -un):$(id -gn) /root",
  "customizations": {
    "vscode": {
      "extensions": [
        "golang.Go",
        "ms-vscode.cpptools-extension-pack"
      ]
    }
  }
}

2. 创建Dockerfile

以编译镜像作为基础镜像,编写Dockerfile对镜像内账户和文件权限进行修正。

FROM sls-opensource-registry.cn-shanghai.cr.aliyuncs.com/ilogtail-community-edition/ilogtail-build-linux:latest
ARG USERNAME=admin
USER root
# Create the user
COPY .env /tmp/.env
RUN source /tmp/.env && rm /tmp/.env; \
    if getent passwd $USERNAME; then userdel -f $USERNAME; fi; \
    if [ $HOST_OS = "Linux" ]; then \
    if getent group $GROUPNAME; then groupdel $GROUPNAME; fi; \
    groupadd --gid $GROUP_GID $GROUPNAME; \
    fi; \
    useradd --uid $USER_UID --gid $GROUP_GID -m $USERNAME; \
    echo $USERNAME ALL=\(root\) NOPASSWD:ALL > /etc/sudoers.d/$USERNAME; \
    chmod 0440 /etc/sudoers.d/$USERNAME; \
    chown -R $USERNAME:$GROUPNAME /opt/logtail $(eval echo ~$USERNAME); \
    chmod 755 $(eval echo ~$USERNAME);
USER $USERNAME

COPY .env /tmp/.env将主机的账户信息通过文件形式复制到容器中。

接下来的几行根据这些信息在容器内创建对应的账户。

echo $USERNAME ALL=\(root\) NOPASSWD:ALL > /etc/sudoers.d/$USERNAME;授予该用户sudo权限。

chmodchown的几行对文件权限进行修正,使新建的用户有权限读写对应目录。其中对HOME(~$USERNAME)目录的修正必须在这里进行,否则会导致VS Code Sever没有权限安装,导致插件启动失败。

3. 创建脚本暴露主机账户信息

gen_env.sh脚本内容如下。该脚本对开发机为Mac系统也做了兼容。

bset -ue
set -o pipefail
if uname -s | grep Linux; then
  echo -e "HOST_OS=Linux\nUSERNAME=$USER\nUSER_UID=$(id -u $USER)\nGROUPNAME=$(id -gn $USER)\nGROUP_GID=$(id -g $USER)" > .devcontainer/.env;
else
  echo "HOST_OS=Darwin\nUSERNAME=$USER\nUSER_UID=$(id -u $USER)\nGROUPNAME=root\nGROUP_GID=0" > .devcontainer/.env;  
fi

前3步完成后,Workspace中的配置目录应该有这样3个文件:

4. 运行观察效果

使用Shift + Command + P(Mac)或Ctrl + Shift + P(Win)打开命令面板,输入reopen,选择Remote-Containers: Rebuild Container

在容器内重新执行id命令查看账户信息,可以看到与开发机一致。

在容器内重新执行之前的编译命令。然后会到开发机上查看生成的文件权限,可以看到容器内生成的文件,在开发机上都已经变成正确的权限了。

在容器内调试

除了编译代码,开发环境另一个重要功能是进行本地调试。打开一个iLogtail插件的单元测试文件,设置断电然后点击“debug test”。

什么?Failed to launch: could not launch process: fork/fork/exec ...: operation not permitted,出错了!

查阅资料,原来是docker默认的安全策略使用Secure computing mode (seccomp)仅允许白名单系统调用,debug所需的系统调用被拒绝了。我们尝试在配置文件中添加一行"runArgs": [ "--cap-add=SYS_PTRACE", "--security-opt", "seccomp=unconfined" ],禁用该功能。

{
  "build": {
    "dockerfile": "Dockerfile",
    "args": {
      "USERNAME": "${localEnv:USER}"
    }
  },
  "initializeCommand": ".devcontainer/gen_env.sh",
  "runArgs": [ "--cap-add=SYS_PTRACE", "--security-opt", "seccomp=unconfined" ],
  "customizations": {
    "vscode": {
      "extensions": [
        "golang.Go",
        "ms-vscode.cpptools-extension-pack",
        "DavidAnson.vscode-markdownlint"
      ]
    }
  }
}

Rebuild Container后,再次尝试调试功能。It works!

总结

至此,我们已经可以happy地通过VS Code的Remote Development插件在远程容器内开发了。并且使用的编译镜像和插件配置文件都是可移植,可重复的,CI到代码库后可以供任何开发者使用。文章中提到的代码都可以到iLogtaill的GitHub仓库(https://github.com/alibaba/ilogtail)获取。

Remote Development插件还有很多的功能没有在本篇文章中使用到,感兴趣的读者可以根据文末参考资料进一步研究探索。

参考资料

  1. Developing inside a Container using Visual Studio Code Remote Development: https://code.visualstudio.com/docs/remote/containers
  2. Create a development container using Visual Studio Code Remote Development: https://code.visualstudio.com/docs/remote/create-dev-container
  3. Running Docker Containers as Current Host User - Juan Treminio - Senior Web Developer Blog: https://jtreminio.com/blog/running-docker-containers-as-current-host-user/
  4. Add non-root user to a container: https://code.visualstudio.com/remote/advancedcontainers/add-nonroot-user
  5. devcontainer.json reference: https://code.visualstudio.com/remote/advancedcontainers/add-nonroot-user
  6. Seccomp security profiles for Docker: https://docs.docker.com/engine/security/seccomp/
  7. alibaba/ilogtail: Fast and Lightweight Observability Data Collector: https://github.com/alibaba/ilogtail

原文链接

本文为阿里云原创内容,未经允许不得转载。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/85335.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

web网页设计期末课程大作业——HTML+CSS+JavaScript美食餐饮文化主题网站设计与实现

👨‍🎓静态网站的编写主要是用HTML DIVCSS JS等来完成页面的排版设计👩‍🎓,常用的网页设计软件有Dreamweaver、EditPlus、HBuilderX、VScode 、Webstorm、Animate等等,用的最多的还是DW,当然不同软件写出的…

为云原生插上翅膀,天翼云弹性存储CStor-CSI助力容器腾飞

云原生是一种新型技术体系,已成为云计算未来的发展方向,越来越多的数字化项目与云原生紧密相连。作为云原生的基座,容器是必不可少的核心技术。然而,以Docker为代表的容器引擎,并不能满足大批量的容器业务需求&#xf…

推荐一套yyds的Java学习资料(非常经典)

Java 是全球最受欢迎的编程语言之一,在世界编程语言排行榜 TIOBE 中,Java 一直霸占着前三名,有好多年甚至都是第一名。 最近几年,全球约有 1/3 的专业程序员将 Java 作为主要编程语言,这一比例在我国更是高达 1/2&…

CTFSHOW web入门 java反序列化篇 web855

web855 得到源码后看到readObject里面有两条路可以走 1、写文件,文件名固定,文件内容开头固定后面内容可以通过write写入 2、执行命令,但是shellcodoe是不可控的(static) 如果两条路分开来看都没啥可利用的价值&…

ai绘画新功能上线,说一句话就能生成好看的AI画作

ai绘画可以将自己的图片生成二次元,还可以通过关键词描述生成好看的画作,这些我们都早已尝试过了,并且也玩得不亦乐乎,但AI绘画还能进行语音创作,只需要同AI说一句话,它就能创造出相关的画作,所…

【Linux开发笔记】VSCode+WSL——Windows搭建最轻量便捷的Ubuntu/Linux开发环境

1.概述 我们一般搭建Ubuntu开发环境都是采用VMware或者VirtualBox的虚拟机安装Ubuntu的方案,但是这样的方案会有几个弊端: 安装、启动慢;使用图形桌面时卡顿、鼠标不跟手、打字有延迟;磁盘空间占用比较大;内存资源占用…

安卓开发Android studio学习笔记21:ViewPager两种方式实现引导页

实现引导页一、ViewPager实现引导页第一步:创建三个xml1.page1.xml2.page2.xml3.page3.xml第二步:创建适配器GuideAdapter第三步:创建引导页原点1.activity_guide.xml2.GuideActivity.java二、 ViewPager(2)实现引导页…

[附源码]Node.js计算机毕业设计电影售票管理系统Express

项目运行 环境配置: Node.js最新版 Vscode Mysql5.7 HBuilderXNavicat11Vue。 项目技术: Express框架 Node.js Vue 等等组成,B/S模式 Vscode管理前后端分离等等。 环境需要 1.运行环境:最好是Nodejs最新版,我…

Docker中的bridge模式,可以这么设置

最近有几个已经就业的小伙伴,过来问千锋健哥关于Docker网络配置的问题,他们在实际开发中还是有些疑问。关于Docker网络这一块的内容确实很多,为了让大家搞清楚这个问题,健哥准备搞几篇系列文章,来为各位小伙伴解惑。这…

小游戏开发者流量变现指南

2018年微信在其6.6.1版本中宣布支持小游戏,之后的几年,但凡能掀起各大社交平台上病毒式传播的,几乎都是小游戏。 小游戏玩法简单,传播机制简单,套路简单,连赚钱的本质也简单。就拿近期火爆的《羊了个羊》小…

程序员也可以很浪漫,精选10个圣诞节特效及源码

最近离圣诞节不远了、整理了一些关于圣诞相关的前端特效网页设计和小游戏的代码送大家、直接上效果吧。 代码过长的 可预览获取 圣诞节快乐 - 文字渐入动画 <body><svg viewport"0 0 300 300"><text class"Merry" x"150" y&qu…

货淋室及货通道维护要点有哪些

货淋室及货淋通道维护要点&#xff0c;货淋室是货物进入洁净室所必需的通道&#xff0c;它可以减少货物进出洁净室所带来的污染问题。 货淋室及货淋通道维护要点&#xff1a; 1、定期使用仪器测定设备的各项技术指标&#xff0c;如不符合技术参数要求应及时予以处理。 2、根…

高低jdk版本中jndi注入(下)

目录 0x01 绕过高版本JDK&#xff08;8u191&#xff09;限制 如下两种绕过方式&#xff1a; 0x02 利用本地恶意Class作为Reference Factory 2.1 攻击利用 1. 服务端 2. 服务端 2.2 几种变体的表达式 调试分析 小结 0x03 利用LDAP返回序列化数据&#xff0c;触发本地Gadg…

nacos--基础--5.1--集成--SpringCloud--配置管理、服务发现、服务注册

nacos–基础–5.1–集成–SpringCloud–配置管理、服务发现、服务注册 代码位置 https://gitee.com/DanShenGuiZu/learnDemo/tree/master/nacos-learn/nacos-spring-cloud1、介绍 主要面向 Spring 的使用者通过2个实例&#xff0c;来介绍nacos和Spring的集成 配置管理服务注册…

运行时发现文件路径输出404

运行时发现文件路径输出404 tomcat不能显示中文原因主要是编码的问题&#xff0c; 因为Tomcat5的http Connector所用的URI解码默认用的是 ISO-8859-1&#xff0c; 而一般浏览器默认用的发送编码为UTF-8&#xff0c;这样问题就出现了&#xff0c; 初步的解决方法如下&#xff1a…

Mentor-dft 学习笔记 day40-Basic Test Data Formats for Patterns

Reduce Serial Loading Simulation Time with Sampling 使用write_patterns命令时&#xff0c;可以使用-sample开关保存完整pattern集的样本。这将减少pattern文件中的pattern数量&#xff0c;从而减少模拟时间。此外&#xff0c;-Sample开关允许您控制样本中包含的每种类型的p…

回归预测 | MATLAB实现WOA-BiLSTM鲸鱼算法优化双向长短期记忆神经网络多输入单输出航空寿命数据回归预测

✅作者简介&#xff1a;热爱科研的Matlab仿真开发者&#xff0c;修心和技术同步精进&#xff0c;matlab项目合作可私信。 &#x1f34e;个人主页&#xff1a;Matlab科研工作室 &#x1f34a;个人信条&#xff1a;格物致知。 更多Matlab仿真内容点击&#x1f447; 智能优化算法 …

ADI Blackfin DSP处理器-BF533的开发详解48:图像处理专题-Rotation (图像旋转处理)(含源码)

硬件准备 ADSP-EDU-BF533&#xff1a;BF533开发板 AD-HP530ICE&#xff1a;ADI DSP仿真器 软件准备 Visual DSP软件 硬件链接 功能介绍 代码实现了图像旋转处理&#xff0c;代码运行时&#xff0c;会通过文件系统打开工程文件根目下" …/ImageView"路径中的 tes…

【OpenCV-Python】教程:5-1 背景减法

OpenCV Python 背景减法 【目标】 读视频与显示视频创建背景模型与更新背景模型 【概述】 背景相减&#xff08;BS&#xff09;是一种常用且广泛使用的技术&#xff0c;用于通过使用静态相机来生成前景掩模&#xff08;即&#xff0c;包含属于场景中运动对象的像素的二值图…

UEFI固件使用OpenSSL暴露了软件材料清单(SBOM)

Binarly REsearch团队近日深入研究了最近的OpenSSL安全更新给UEFI固件供应链生态系统带来怎样的影响以及OpenSSL版本在固件环境中是如何广泛使用的。研究结果不容乐观。 科技行业正在积极讨论使用“软件材料清单”&#xff08;SBOM&#xff09;来化解供应链安全风险。为了确保…