有时候你可能想用 Docker 作为 C++ 项目的开发环境,就像 Python 用 Pyenv 作为开发环境一样。
本文就介绍了 Clion 的实现方式,实际体验效果非常令人满意,除了 Debug 的时候稍微麻烦一点(要多敲一个命令)。
一. 基本思路
Clion 可以通过 ssh 使用远程服务器作为开发环境,我们把 Docker Container 也当做一个远程服务器来看待就好了。
此时,我们只需要解决以下几个问题:
1.1 如何跑起来一个有运行环境的 Container?
- 如何在 Container 里面搭建环境?(Dockerfile)
1.2 Clion 如何连接到 Container?
- Container 的 IP 地址是什么?(docker-compose networks)
- Container 如何启动 SSH 服务?(docker-compose command)
- Container 如何常驻?(docker-compose command)
1.3 Clion 如何使用 Container 里面的环境?
- 如何使用 Container 里面的 Cmake 和各种依赖库?(Clion 设置)
- 如何远程 Debug ?(Container gdb server 和 Clion 远程 Debug 设置)
1.4 本地和 Container 如何及时进行文件同步
- 本地源代码如何及时推送到 Container 里面?(Docker volume)
- Container 里面程序的输出如何及时拉取到本地?(Docker volume)
二. 实现细节
接下来逐个解决上述几个问题。
2.1 如何跑起来一个有运行环境的 Container?
直接用 Dockerfile 安装好必要的依赖,确认安装好 ssh server 和 gdb server。
建议创建一个非 root 用户,并且赋予这个用户不用密码进行 sudo 的权限。
1 | FROM ubuntu:14.04 |
这份 Dockerfile 除了安装必要环境和创建用户之外,还创建了一个工作区文件夹 /home/deploy/my-project
。
之后我们会把源代码同步到这个文件夹里面。
2.2 Clion 如何连接到 Container?
要想 Clion 连接到 Container,必须要获知 Container 的 IP 地址,并且要启动 Container 里面的 SSH Server。当然,Container 还得常驻。
这三个要求都能用 docker-compose 实现。
1 | version: "3.4" |
这个 docker-compose.yml 文件指定了 network 的子网段,并且以 sudo service ssh restart && tail -f /dev/null
的启动命令来同时实现了“开启 SSH Server” 和“保持 Container 常驻”的功能。
通过 Docker Volume 把当前目录 mount 到了 Container 里面的 /home/deploy/my-project
文件夹,实现实时同步代码的功能。
security_opt
的选项是必要的,否则会启动不了 gdb server。
2.3 Clion 如何使用 Container 里面的环境并及时文件同步?
Clion 本身就支持 SSH 到远程服务器作为开发环境,也支持使用 GDB 进行远程调试,所以主要是怎么对 Clion 进行设置。
首先我们把 Docker Container 跑起来:
1 | docker-compose build |
在 Clion Settings-Build,Execution,Deployment-Toolchains
页面先新建一个 Toolchains 设置,名字叫 my-project 吧,类型选 Remote Host。 Credential 设置里面填入 Container 的 IP, 如果使用上述的 docker-compose.yml 来启动 Container 的话,IP 一般是 172.129.2.2
。端口、用户名和密码按自己创建 Docker 镜像的时候来设置。由于我是从源码编译的 Cmake,所以需要变更一下 Cmake 地址为 /usr/local/bin/cmake
。大家自己会意,按情况来改就好:
创建 Toolchains 配置后,在 Settings-Build,Execution,Deployment-CMake
页面的 Toolchain 下拉菜单里面选择刚才创建的 my-project
。 然后点击 Apply 保存到目前为止的配置:
由于我们使用 Docker 的 Volume 进行文件同步,所以不再需要使用 Clion 的 SFTP 了。这个可以在 Settings-Build,Execution,Deployment-Deployment
里面进行更改。
当 Clion 成功连接到 Container 后,会自动创建一个对应于 ToolChain 名字的 Deployment 配置。我们需要对它进行微调, 把本地代码目录(比如说 /home/john/git/github/my-project
) Map 到 Container 里面的工作目录 /home/deploy/my-project
,然后禁用 Clion 使用 SFTP 对 Container 里面的工作目录进行同步。
默认 Connection 配置不用更改:
把本地 /home/john/git/github/my-project
映射到 Container 里面的 /home/deploy/my-project
:
在添加 Exclude Path 的时候,类型选 SFTP,并设置为 Container 里面的 /home/deploy/my-project
:
这样我们就直接使用 Docker Volume 进行实时的文件同步了,比 SFTP 更方便。
2.4 Clion 如何使用 Container 来远程 Debug?
基本思路是在 Container 里面跑起来 gdb server,然后使用 Clion 的 Remote GDB Debug 来进行常规的断点等操作。
首先在 Clion 右上角的 RUN/Debug Configurations 添加 GBD 远程 Debug 的配置:
然后在 Container 里面启动 GDB Server:
1 | gdbserver :1234 cmake-build-debug/my_project_exec arg1 arg2 arg_etc |
这里其实就是在 Container 里面运行构建的程序,并且把参数也一并输入。
执行后,会有类似的输出:
1 | Process cmake-build-debug/my_project_exec created; pid = 7252 |
这时候,从 Clion 右上角的 RUN/Debug Configurations 下拉菜单中选择 my-project, 然后点击 Debug 的 Icon 就能像往常一样进行 Debug 了。
三. 进一步优化
对于一些很常见的操作,我们可以写出一个 Shell 脚本:
1 |
|
如此,我们想要 Debug 的话,只需要执行 ./docker.sh debug arg1 arg2 arg_etc
就好了, 方便很多。
四. 总结
Clion 使用 Docker 作为开发环境,本质上就是把 Container 当做一个远程服务器来配置。
由于 Docker 可以使用 Volume 来进行文件同步,所以可以禁用 SFTP,体验更好。