构建一个基于容器的开发环境
前言:GNU/Linux(以下简称Linux)是目前服务器使用广泛的系统,而开发人员使用的操作系统大多数却是Windows。虽然现在主流的语言几乎都支持跨平台的特性,但在开发过程中仍然会因为平台不一致导致一些莫名其妙的问题,最经典的当属CRLF(回车换行符)在Windows和Unix系统间造成的问题。而Windows糟糕的软件管理也一直被开发人员嫌弃,新机器装一个齐全的开发环境往往要重复经历打开浏览器-搜索软件-下载软件-手动安装的过程,这个过程在Linux下利用包管理器往往只需要一行命令搞定。
但在国内,想要将Linux当做主力系统困难重重,常用的微信,钉钉,企业微信都没有可用的第一方Linux客户端,Linux下deepin-wine的解决方案也不尽完美,Windows下开一个Linux虚拟机动辄几十G的大小又显得笨拙,这篇文章就介绍一下如何利用近年来火爆的容器技术搭建一个灵活,可复用,带版本控制的开发环境。
前置条件:
- Docker,Windows下则是Docker Desktop
- VSCode 或 JetBrains 全家桶
基于容器的开发本质上也就是远程开发,这方面VSCode 与 JetBrains IntelliJ 的实现有区别:VSCode 直接在远程环境运行,代码不保存在本地,JetBrains 则基于FTP/SFTP/FTPS协议在本地与远程代码同步,且配置有些繁琐。本文使用VSCode做演示
一、构建镜像
选择一个你熟悉的Linux发行版,基于基础镜像构建自己的开发环境,个人偏爱Arch Linux,以这个发行版为例,拉取镜像,并配置初始开发环境,我做了一个简单的Dockerfile:
FROM docker.io/library/archlinux:latest
RUN sed -i '1i Server = http://mirrors.aliyun.com/archlinux/$repo/os/$arch' /etc/pacman.d/mirrorlist \
&& sed -i '1i Server = https://mirrors.tencent.com/archlinux/$repo/os/$arch' /etc/pacman.d/mirrorlist \
&& sed -i '$i [archlinuxcn]' /etc/pacman.conf \
&& sed -i '$i SigLevel = TrustAll' /etc/pacman.conf \
&& sed -i '$i Server = https://repo.archlinuxcn.org/$arch' /etc/pacman.conf \
&& sed -i -r 's/^NoExtract\s*=\s*.*/# \0/g' /etc/pacman.conf \
&& pacman -Syyu --noconfirm \
&& pacman -Sy --noconfirm archlinuxcn-keyring && pacman -Su --noconfirm\
&& pacman -Syy --noconfirm git vim neovim zsh oh-my-zsh-git jdk-openjdk jdk8-openjdk jdk11-openjdk \
maven yay zsh python3 go nodejs npm yarn tmux python2 zsh-autosuggestions zsh-syntax-highlighting \
zsh-theme-powerlevel10k ranger python-pip python-neovim wl-clipboard fzf ripgrep man-db \
gcc clang base-devel wqy-zenhei noto-fonts-cjk wget unzip thefuck \
&& ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \
&& pacman -Scc --noconfirm \
&& rm -rf /var/lib/pacman/sync/* /var/cache/pacman/pkg/* \
&& echo "" > /var/log/pacman.log
pacman
是Arch Linux 下的包管理器,如果你清楚Dockerfile里的包都有什么作用,可以适当增删改,以上命令安装了jdk python go nodejs 和一些好用的命令行工具,配置了国内的时区,添加了包仓库的国内镜像源。
之后运行构建命令
docker build -t arch-test .
包含基础开发环境的镜像就构建好了
二、配置VSCode
VSCode做到容器内开发的核心就是Remote Development Pack插件,Docker插件能增强体验,搜索安装即可,而我们的核心是Remote Development Pack中的这个插件
如果你安装了Docker插件,可以在侧边栏直接管理Docker容器并将VSCode附加到容器
没有安装的话,则只能通过ctrl + shift + p
以命令的形式选择并附加到容器
附加后的窗口如图
前面提到,VSCode容器开发实际就是远程开发,而VSCode的服务是跑在容器里的,所以需要重新安装扩展,截图左侧位置的按钮点击即可在容器里同步本地的拓展
至此基于容器和VSCode的开发环境已经能用了,体验与Linux上的VSCode基本没有差别,但还有很多可以优化的地方
三、容器配置
容器的一般应用场景是为了跑一组服务,一般不会对用户权限做管理,VSCode容器开发默认连接到容器也是root用户,但对于一些强迫症用户(比如我),想要用非root用户开发当然也是支持的,ctrl + shift + p
打开命令面板输入remote container config
之后选择就可以编辑当前容器或已存在容器的配置
容器支持以下配置:
{
// 附加VSCode进程时打开的默认目录
"workspaceFolder": "/path/to/code/in/container/here",
// 进入容器时自动安装的扩展
"extensions": ["dbaeumer.vscode-eslint"],
// 容器配置,支持settings.json中的任意配置,设置后在当前容器中会覆盖settings.json中的配置
"settings": {
"terminal.integrated.shell.linux": "/bin/zsh"
},
// 自动转发的端口
"forwardPorts": [8000],
// 连接时登入的用户,不设置默认为root
"remoteUser": "vscode",
// VSCode和其子进程继承的环境变量
"remoteEnv": { "MY_VARIABLE": "some-value" }
}
remoteUser
项设置的前提当然是用户已创建,所以先在容器内执行或在Dockerfile里加上以下命令
useradd -d /home/vscode -m vscode && passwd vscode
之后设置一下新用户的密码即可
容器内开发,调试时跑服务的端口VSCode会自动检测并转发到本地,用localhost
即可访问,感知上与本地开发一样。实际使用时会自动检测,如果没有自动检测到,配置一下forwardPorts
即可
VSCode自身也支持直接创建开发容器,个人认为不如命令行操作直观,感兴趣的话可以看下微软官方文档Create a Dev Container
四、后续优化
大费周章去构建一个基于容器的开发环境只能做到统一开发和生产环境吗?当然不是,统一环境是基本需求,我们完全可以再花点心思用上Unix系才有的一些命令行神器,让终端好用到爱不释手,这里推荐一波本人在使用Linux过程中沉淀的工具:
- 丢掉默认难用的bash shell, 用zsh和插件打造一个好用的shell:
zsh & oh-my-zsh & powerlevel10k & zsh-autosuggestions & zsh-syntax-highlighting - 终端复用器,让你方便的管理终端,并在终端中断后可以随时继续你的上一次工作:
tmux & oh-my-tmux - 终端内文本编辑、文件浏览、文件/文件内容模糊搜索:
neovim & ranger & fzf & ripgrep - 优化终端显示效果,需要安装修补字体,推荐nerd-fonts,仓库中选择一个喜欢的字体本地安装,配置一下即可
- 直接启动容器的话代码是在容器里的,如果考虑到代码安全性,启动的时候就配置一下代码文件夹的映射吧
上述工具要想做到好用免不了一些配置,这里贴上我个人的vim zsh tmux配置以供参考,配置在github gist上长期维护,之后会专门写一篇文章介绍这些工具的用法
最终效果展示:
总结
构建好的容器开发环境,利用docker镜像的版本控制、迁移、上传等特性可以做到灵活、复用,从此换电脑只需要迁移镜像即可开发,告别Windows和Linux间莫名奇妙的环境问题。
参考文章:
【1】 https://code.visualstudio.com/docs/remote/remote-overview
【2】 https://docs.docker.com/desktop/