Linux系统下使用Docker+VScode+Dev Containers构建隔离开发环境
一、引言
在开发不同的项目时,每个项目往往需要不同的第三方库,它们或通过apt安装或通过源码,久而久之系统会变得臃肿。本文正是在这种问题前提下,提出了使用Docker容器做项目环境隔离,使每个项目都可以拥有独立的开发环境互不干扰。为了实现这一目的,需要对隔离环境有如下要求:
- 项目开发环境相互独立互不干扰
- 可进行可视化操作,运行可视化程序,如OpenCV、Pangolin、PCL等可视化库
- 像在本地主机电脑一样可以方便地调试编写程序
二、介绍
1、VScode介绍
跨平台代码编辑器。其本身不带编译器或解释器,体量不大,可以配合许多插件进行个性化设置,提高编码效率。采用VScode编辑器作为隔离环境搭建的编辑器的原因是其拥有Dev Containers插件,可以实现在容器内调试编写代码。
2、Docker介绍
Docker是一种任务级隔离容器。如下图所示,其会在主机系统下构建多个容器,用来隔离应用任务系统运行环境,容器共享主机内核。
3、Dev Containers介绍
VScode中的一个插件。可以很方便的连接容器,它允许您打开容器内的任何文件夹(或装入容器),并利用VisualStudioCode的完整功能集。
三、安装
1、VScode安装
-
VScode官网连接:
https://code.visualstudio.com/
- VScode安装较为简单,直接官网下载安装程序进行安装即可
2、Docker安装
-
Docker官网:
- 注意:选择安装的是Docker Engine,不是Docker Desktop
-
可以参考官网在Ubuntu上安装的文档进行安装:
https://docs.docker.com/engine/install/ubuntu/
3、Dev Containers安装
VScode内搜索扩展Dev Containers点击install进行安装,如下图所示。(作者已经安装,所以显示的是uninstall)
四、操作使用
1、Docker常用命名
- 拉取镜像
docker pull <image_name>
- 创建容器
docker run -it <image_name>
- 保存镜像
docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]
- 镜像下载
docker save [OPTIONS] IMAGE [IMAGE...]
2、Dev Containers操作使用
-
新建工程
如下图所示,点击Open Folder in Container打开工程文件夹(可以是个空的文件夹) 。
之后选择:工程属性(如c++)>> 镜像系统(如ubuntu:18.04)>> 其它配置(无)OK。
-
工程介绍
在工程文件夹下会生成一个/.devcontainer的文件夹,其中devcontainer.json配置的是Docker的启动,Dockerfile配置的是镜像。Dev Containers插件会根据这两个文件配置合适的容器环境,共开发使用,使得像在本地环境开发一样,可以在容器环境内开发工程文件夹下的程序,并且如果容器环境内配置有第三方库,VScode搭配Dev Containers也可以找到第三方库,在写代码时,会像在本地开发一样有库函数提示。
3、可视化程序运行
- 安装xserver
#安装xserver
$sudo apt install x11-xserver-utils
#许可所有用户都可访问xserver
$xhost +
# 查看当前显示的环境变量值
$echo $DISPLAY #假设为:0
- Docker内外路径挂载
-v /tmp/.X11-unix:/tmp/.X11-unix
-e DISPLAY=:0
使用image创建docker容器时,通过-v参数设置docker内外路径挂载,使显示xserver设备的socket文件在docker内也可以访问。并通过-e参数设置docker内的DISPLAY参数和宿主机一致。
例如:
docker run -it -v /tmp/.X11-unix:/tmp/.X11-unix -e DISPLAY=:0 <image_name> /bin/bash
- 测试
docker run -it -v /tmp/.X11-unix:/tmp/.X11-unix -e DISPLAY=:0 <image_name> /bin/bash
sudo apt-get install xarclock
xarclock
- 注意:每次重启宿主机都要在终端输入xhost + 开启所有用户访问xserver的权限
五、 PCL点云项目演示
- 容器内安装PCL库
sudo apt-get install libpcl-dev
- 代码
#include <iostream>
#include <pcl/common/common_headers.h>
#include <pcl/io/pcd_io.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <pcl/visualization/cloud_viewer.h>
#include <pcl/console/parse.h>
int main(int argc, char **argv)
{
std::cout << "Test PCL !!!" << std::endl;
pcl::PointCloud<pcl::PointXYZRGB>::Ptr point_cloud_ptr (new pcl::PointCloud<pcl::PointXYZRGB>);
uint8_t r(255), g(15), b(15);
for (float z(-1.0); z <= 1.0; z += 0.05)
{
for (float angle(0.0); angle <= 360.0; angle += 5.0)
{
pcl::PointXYZRGB point;
point.x = 0.5 * cosf (pcl::deg2rad(angle));
point.y = sinf (pcl::deg2rad(angle));
point.z = z;
uint32_t rgb = (static_cast<uint32_t>(r) << 16 | static_cast<uint32_t>(g) << 8 | static_cast<uint32_t>(b));
point.rgb = *reinterpret_cast<float*>(&rgb);
point_cloud_ptr->points.push_back (point);
}
if (z < 0.0)
{
r -= 12;
g += 12;
}
else
{
g -= 12;
b += 12;
}
}
point_cloud_ptr->width = (int) point_cloud_ptr->points.size ();
point_cloud_ptr->height = 1;
pcl::visualization::CloudViewer viewer ("test");
viewer.showCloud(point_cloud_ptr);
while (!viewer.wasStopped())
{
};
return 0;
}
- CMake
cmake_minimum_required(VERSION 2.6)
project(pcltest)
find_package(PCL 1.2 REQUIRED)
include_directories(${PCL_INCLUDE_DIRS})
link_directories(${PCL_LIBRARY_DIRS})
add_definitions(${PCL_DEFINITIONS})
add_executable(pcltest test.cpp)
target_link_libraries (pcltest ${PCL_LIBRARIES})
install(TARGETS pcltest RUNTIME DESTINATION bin)
-
结果