0. 背景知识
在C++开发中常遇到一些系统底层的问题,例如,即使同为Unix环境,在网络开发中,macOS与Ubuntu也存在头文件、接口的不同,这时必须要在目标系统环境中开发。一般来说,可行的解决方案有这么几种:
- 直接在目标系统开发;
- SSH+SFTP到远端主机;
- 在本机开启虚拟机,SSH+SFTP到本地虚拟机;
- 使用Docker在本地搭建开发环境,SSH+SFTP连接。
其实2/3/4在本质上相同,区别在于3/4位于本地环境,而2需要经过网络路由(无论是内网还是外网)。而在macOS与Windows下,Docker的原理也是启动一个虚拟机,因而3/4本质也是相同的,区别在于Docker可以使用Dockerfile来初始化镜像,而且移植较为方便。因此本文拟探讨一下使用Docker的C++开发环境的配置。
1. Docker镜像配置
我们使用docker-compose + Dockerfile的方式进行配置,优点在于可移植性强,且修改配置较为方便,无需每次启动时都使用很长的docker run -d --name xxx --port......
的命令。
假设你的项目存放于本地文件夹/home/user/projects/
,那么你需要创建一个/home/user/projects/.devcontainer/
以放置Dockerfile
与docker-compose.yml
。配置中使用的是相对路径,因而如果有放在其它文件夹的项目,只需要将.devcontainer/
拷贝过去即可,无需修改配置文件。
在Dockerfile中,以ubuntu:18.04为基础镜像,首先添加阿里云镜像(不需要的可以去掉),然后安装一些开发中会用到的包,最后添加一个部署用户并赋予sudo权限:
FROM ubuntu:18.04
ENV USER=deploy
ENV PASSWD=deploy
ENV WORKDIR=projects
# 替换为阿里云镜像,如不需要可以去掉本部分
RUN printf '\n\
deb http://mirrors.aliyun.com/ubuntu/ bionic main restricted universe multiverse \n\
deb http://mirrors.aliyun.com/ubuntu/ bionic-security main restricted universe multiverse \n\
deb http://mirrors.aliyun.com/ubuntu/ bionic-updates main restricted universe multiverse \n\
deb http://mirrors.aliyun.com/ubuntu/ bionic-proposed main restricted universe multiverse \n\
deb http://mirrors.aliyun.com/ubuntu/ bionic-backports main restricted universe multiverse \n\
deb-src http://mirrors.aliyun.com/ubuntu/ bionic main restricted universe multiverse \n\
deb-src http://mirrors.aliyun.com/ubuntu/ bionic-security main restricted universe multiverse \n\
deb-src http://mirrors.aliyun.com/ubuntu/ bionic-updates main restricted universe multiverse \n\
deb-src http://mirrors.aliyun.com/ubuntu/ bionic-proposed main restricted universe multiverse \n\
deb-src http://mirrors.aliyun.com/ubuntu/ bionic-backports main restricted universe multiverse' > /etc/apt/sources.list
# 安装开发环境必要的包
RUN apt-get update \
&& apt-get install -y ssh openssh-server build-essential \
gcc g++ gdb gdbserver cmake \
# 无需libboost可以去掉下一行
libboost-dev \
# net-tools 提供了ifconfig
net-tools tar rsync \
# 无需python3可以去掉下一行
python3 python3-pip \
sudo git\
&& apt-get clean
# 添加用户并配置密码
RUN useradd -m ${USER} && yes ${PASSWD} | passwd ${USER}
# 赋予sudo权限并允许无密码sudo
RUN echo ${USER}' ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers
RUN chmod 644 /etc/sudoers
CMD ["/usr/sbin/sshd", "-D"]
USER ${USER}
RUN mkdir -p /home/${USER}/${WORKDIR}/
ENV LC_ALL C.UTF-8
接下来是对docker-compose的配置,有几个比较重要的地方在文件中以注释形式标注了出来:
version: "3.4"
x-defaults: &default
restart: unless-stopped
# 使用当前目录的 Dockerfile 来构建 docker 镜像
build: .
volumes:
# 本文件存放于.devcontainer/中,因而此处要把上级目录(源代码目录)挂载到工作目录
- ..:/home/deploy/projects/
services:
projects-dev:
<<: *default
container_name: projects-dev
hostname: "projects"
# 如果在Dockerfile中修改过用户名,此处也要对应修改用户名和工作目录
user: deploy
working_dir: /home/deploy/projects
# 修改安全配置,以运行gdb server
security_opt:
- seccomp:unconfined
cap_add:
- SYS_PTRACE
# 开启 ssh 服务,这样 clion 就能通过 ssh 连接进来了
# 同时通过 tailf 命令保持 container 不要退出的状态
command:
bash -c "sudo service ssh restart && tail -f /dev/null"
# 此处将容器的22端口映射到主机的2222上,且仅对本机开放
ports:
- "127.0.0.1:2222:22"
如果是在CLion中使用,Docker配置即可到此结束;如果在VSCode中使用,则还要进行下一步配置,见第3节。
2. CLion配置
在CLion中,并没有直接连接到Docker开发的功能。尽管CLion提供了Docker插件,但那不是为了这种场景使用的。因此,我们需要使用在Terminal中启动容器,然后使用CLion的远程Toolchains开发。
Terminal中,假定你在/home/user/projects/
目录下,运行:
docker-compose -f .devcontainer/docker-compose.yml up -d
可以使用docker ps
检查运行状态,只要STATUS
一栏显示不是Restarting (1) 21 seconds ago
类似的错误即说明成功启动,接下来可以开始使用CLion进行开发。
此处以muduo网络库为例进行编译和测试,假设已经将该项目git clone https://github.com/chenshuo/muduo.git
到./muduo/
目录。
CLion中需要修改三处配置,位于 Preferences - Build, Execution, Deployment下的:
- Toolchains
- CMake
- Deployment
下面分别进行说明。
(1) Toolchains
在此处添加一个配置(无需设为默认),用户名与密码均为deploy
,地址为localhost
,端口为2222
,其余配置均由CLion自动检测。
(2) CMake
如果无需在本地编译,可以直接修改当前配置的Toolchain,使用上一步的配置。如果需要在本地编译、或者连接到多个Remote,就增加对应的配置即可。
(3) Deployment
首先在Connection中配置好连接。注意:不要修改图中两个蓝框,否则CMake会不可用。
其次,添加目录映射,如图所示,你可以直接点远程端的查看目录按钮选择,无须手动输入:
最后,因为我们使用的是目录挂载,因此并不需要由CMake接管文件同步,所以在Excluded Paths
中直接将项目文件夹全部排除掉:
这样我们就完成了项目的配置,可以使用CMake进行Build了。同样,也可以在代码中加入断点进行变量监控等操作:
提示:Muduo网络库CMakeFiles.txt部分配置有问题,直接Build可能会出错。本文不涉及这部分的修复工作,因此遇到时可以在CLion右上角的Build config中加入环境变量:MUDUO_BUILD_EXAMPLES=false
以跳过出错部分的编译。
3. VSCode配置
VSCode远程连接Docker开发环境需要安装Remote - Containers
(by Microsoft) 插件,但其实更推荐直接安装Remote Development
(by Microsoft) 插件组合包。
在VSCode中配置相对简单,只是需要在.devcontainer
目录中添加一个额外的文件:devcontainer.json
,文件内容如下,实际配置中有出入的地方也需要随之修改。
{
"name": "Project Develop Env",
"dockerComposeFile": "docker-compose.yml",
"service": "projects-dev",
"workspaceFolder": "/home/deploy/projects/",
// Set *default* container specific settings.json values on container create.
"settings": {
"terminal.integrated.shell.linux": "/bin/bash"
},
// Uncomment to connect as a non-root user. See https://aka.ms/vscode-remote/containers/non-root.
"remoteUser": "deploy"
}
将.devcontainer
文件夹放置在项目目录下(推荐放在与根CMakeFiles.txt相同目录中),点击窗口最左下角的远程连接图标,选择Open folder in Container
,VSCode将自动识别并加载项目文件。
远程Debug时,需要在VSCode中远程安装C++插件、CMake插件,在源代码中加入断点,在CMake插件中对应的Target上点击右键选择Debug即可。
4. 总结
本文介绍了在CLion与VSCode中分别配置Docker下C++开发环境的方法。需要注意的是,CLion允许任意工作目录,然而VSCode存在CMake插件的限制需要一些手动配置的步骤(如果工作路径没有CMakeLists.txt则需要手动指定源代码路径,本文没有详细说明)。
本文以Muduo网络库为例进行测试,实验了配置环境的可行性。当然,在应用中也需要根据不同的配置对上述文件进行修改,相信对各位来说不是难事,就不再赘述了。
本文的最终配置文件已发布在Github:Remote-Development-on-Docker。
3 条评论
真棒!
哈哈哈,写的太好了https://www.cscnn.com/
不错不错,我喜欢看 www.jiwenlaw.com