从零搭建符合自己需求的开发环境

本文长期持续更新中,保持和自己实际开发环境一致,欢迎关注交流讨论!

前言

这篇文章,一是总结自己,二是给新上道的小白一些思路,三是 何时能重组大学时的EXplosion工作组呢?

现状分析

个人自述

成长于一个有着IT背景的家庭,从小学到大学疯狂参加各种机器人比赛,曾多次获得国一等。

北京211本科,专业先后为 电子信息工程 -> 计算机科学与技术 -> 虚拟化与云基础设施,在法国巴黎留学过一年多,曾作为一个Java后端工程师就职于新疆某科技公司互联网部门。

个人的知识与技术主要是围绕Java的后端技术栈,其次是关于运维和软件工程方面,但前端、移动端以及游戏相关开发技术也密切关注。

已有的设备

笔记本电脑

我当前的笔记本时一台 华为 2020款 MateBook 13,CPU 为 Intel Core i5-10210U 1.6GHz (基准速度 2.11Ghz),内存 16GB 2133MHz,独显 MX250 2G,500GB 固态,十点2k触屏,1雷电口(充电口),1普通type-c口,开机按钮有指纹解锁,系统为 Windows 10 家庭中文版。

配置分析与选购的参考思维

作为一个开发,有必要有一台配置好一些的电脑,可以减少很多不必要的麻烦。

CPU:其实i5和i7没差多少,可以从这里省一部分钱。核心的数量,在一般软件使用中,由于通常没有基于多核的优化,讲道理双核就够。但考虑到系统自身的多核调用优化,以及最重要的,后端程序与本地运维模拟集群时,会用到多核,所以请尽量还是选购四核的cpu。至于台式8核的cpu,仔细想想自己用的到么?多的钱应当放在单核的速度上。

内存:在我的工作经验范畴内,内存是越多越好,但作为开发,请尽量内存至少16GB,不要低于8GB,如果有多的钱,先投资在内存存储量上,其次是速度上,但避免买杂牌,同品牌同参数内存条,没必要准求它是哪个更贵的系列,因为它说的系列优势你多半用不到或体验不明显。

独显:我是就这一台笔记本,平常还要打绝地求生呢…一般开发并不需要独显,如果涉及 3D 游戏开发,请配块高级显卡。

硬盘:2020年了,别再机械硬盘了,固态都好几代了…作为一个开发,打交道的永远不只是内存里的那点动态数据,把显卡和cpu剩的钱换一块1T的M.2固态吧,这带来的各方面体验提升,是硬件升级里最为明显的。

2k与触屏:2k和4k,用过了,再看回1080p,你会怀疑自己视力不良了…触屏,偶尔写个安卓app,不用接线连手机开开发者模式,直接第一时间在触屏上滑动模拟器,不爽么?平常浏览网页或图片,用习惯了,也比用鼠标滚轮和键盘快捷键操作方便。

type-c与雷电口:用过都说好,当然如果电脑还有别的口就更好了,单独买一个USB和雷电双口的U盘,太爽了。

系统生物解锁:原本我很喜欢摄像头window hello解锁,但用了一段时间开机键指纹解锁后,感觉更加稳定,二者速度通常都比敲密码快,越快越能保证临时打开电脑时不会忘记那一瞬间的灵感。

操作系统:我是因为目前就用这一台电脑,平常要和朋友玩绝地求生等游戏,自然还坚守着Windows阵营。但从开发经历上讲,Mac OS除了一开始让人觉得反人类,实在是太香了。个人仍然不推荐linux系统,比如有着很好UI的Ubuntu,因为所有linux和windows有的好工具,mac os基本都有,但linux如果开发者自己没有十足的功底,很容易被一些繁杂琐碎的事情耽误时间。mac os有和linux一样方便的文件管理结构,有和windows不分伯仲的ui(个人觉得甚至更胜一筹),和linux服务器交互也较windows方便。有些时候想做一些简单的服务端程序的本地模拟测试,windows经常因为各种原因很令开发者头疼,而mac os和linux凭借它们都是源于Unix的系统体系,会方便许多。Windows系统如果为Win 10,请尽量保持更新。

遇到过的设备配置坑点

诸如gitlab、nexus repository 3等,硬件推荐需求为4核8G及以上,当然稍微低一点配置也能运行,但是太低会出问题,低一点会很卡,总体配置越高越好。

又比如docker,windows 10 需要pro或者home的19000+的版本,因为牵扯到了虚拟化问题,兼容Hyper-V架构需要一些home低版本默认系统所没有的东西。

云服务器

一台阿里云1C2G轻量应用服务器,目前架设着个人网站和一个建设中的博客系统以及某私有商用计算器。

两台阿里云1C2G普通云服务器,用于日常实验折腾。

开发环境需求分析

一套完整软件项目开发流程,会从文档相关的需求分析做起,然后是代码的编写,接着进行验证测试,通过了进行部署,最后是运营维护。不论是传统的瀑布式,还是现在的敏捷与DevOps,需求+设计+代码+测试+部署,这个基本流程单元是没有彻底的完全变过的,在互联网模式下软件工程的演变,也仅仅是加快了这个流程的循环速度,并适当简化优化部分步骤,在部分过程中加入自动化,减小整体的花销并提高效率。

需求:首先,需求要被记录下来,并列入开发流程的时间线,在测试完成进行部署前可以再次核对验证。其次,需求要被拆分到细节,明确的需求分析可以大幅提高设计与代码甚至测试的效率,同时更容易做出优先级调整从而规划好时间项目周期。最后,需求最好能标记出版本,将不同部分拆分开,方便代码合并以及部署发版,对每一次迭代内容更加清晰。需求方面迫切需要一个公示板和一个能区分版本的日志。

设计:我目前选用Xmind画思维导图,滤清思路与将重要功能模块化,还可以表示成简单的类图与数据结构图从而搞清楚数据流向及关系,最重要的是,它免费且可以导出成很多格式。那么设计方面的需求便是,可以打标签进行细致分类收藏的,文件管理系统。

代码:我的主要开发语言是Java,但是也必然会去涉及其他语言,比如前端用到JavaScript和Html,安卓端用到Kotlin和Dart,运维和后端用到Golang和Shell,甚至游戏开发用到C#和C++等等。代码方面的需求主要是需要一个轻量级的私有代码仓库,同时最好有代码审查功能,方便以后万一呢,EXplosion工作组重组,我得确保团队代码质量。

测试:之前工作时,测试部分相对敷衍,后端会有手动单元测试,但目的其实只是验证编译不报错顺带生成接口文档,而前端的测试以及整体的测试,仅仅是唯一的测试工程师手动对着设计的测试用例进行测试,并自己手动书写测试报告,忙的时候或者太简单的代码更改,所有的测试都可能被跳过。测试相关需求说起来就很简单了,至少实现自动化。

部署:工作时的开发测试环境是提交代码自动部署的,这大大提高了和前端进行联调的效率。目前我个人的网站后端使用beego框架进行的简单开发,在通过手动交叉编译后,手动进行部署。现在想一了下,其实部署环境通常是固定不变的,部署的操作可以提炼出来写成脚本自动运行,所以部署方面的需求也是实现自动化。

技术选型

云服务器操作系统

我的云服务器安装的操作系统为Ubuntu 20.04 x86_64,推荐理由是apt使用方便且各种包更全更新。
真正最终确定操作系统的原因在于,ubuntu 20.04将持续维护到2030年,centos的研究方向改为了centos stream不再会有centos 9,而centos 7维护将结束于2024、centos 8维护将结束于2021。

我是长久以来一直用的CentOS,毕竟入门就是那本“黑色圣经”(《鸟哥的Linux私房菜》)。
有人说centos性能和稳定性比ubuntu更好,其实服务器端系统,同样是LTS长期支持版本,系统上的性能和稳定性都尚可且差不多,服务器运行的其它程序代码的性能及稳定性才是关键影响因素。

容器引擎

目前选择的Docker,但只是简单使用,未进行复杂容器编排,由于其安装配置使用,真的是相对太简单了,前期使用遇到各种奇葩问题的概率也相对较低,网上文章教程也多,配套工具也多(docker hub和docker compose不香么)。

未来可能会彻底改用Kubernetes(k8s),毕竟k8s宣布将要彻底放弃了dockershim,k8s和docker目前容器运行时都支持containerd,在之后对容器编排的需求变得更为重要时,相信转型也方便。

代码仓库

首先是版本控制服务,git都支持大文件(git lfs)了,SVN等其它工具,真的还那么香么?用过git的都说好,哪怕是Unreal Engine都集成git了。

再说下运行git的服务及代码存储仓库,我最终选择了gitea搭建私有代码仓库(存储采用mariadb)。

github、bitbucket、gitee、coding、teambition等等,私有仓库及团队合作相关的免费限制条件太多,虽然小规模开发肯定够用,但早晚会面临要缴费或为了免费而费神费力的情况。

gitlab、gogs、gitea等等,不选择gitlab纯粹只是因为现在国内个人能买到的极便宜云服务器难以很好运行(这玩意至少要求4C8G),gogs和gitea本是同根生,采用Golang开发,超级轻量级,功能完全够用,区别在于,前者是个人维护更新较慢,后者为社区维护更新较快。

最后看下代码的存储,我的gitea的数据存储选择的mariadb,理由很简单:我尽可能的少安装几种数据库,剩的之后万一没注意出现各种数据不兼容的情况,会处理起来很麻烦。mysql平常很常用,mysql和mariadb两者起初也是同一个东西,不过前者是商业产品,后者完全就是开源社区维护,mysql community version和mariadb都是免费的,但是mysql community version并不提供线程池(这部分在收费的企业版提供),而mariadb支持线程池,那么mariadb真香。

持续集成部署

也就是常说的CICD(Continuous Integration & Continuous Deployment)了,当然也有人说其中还包含着持续交付CD(Continuous Delivery),都对了,就是一套流程,从代码上传,到代码构建,接着运行测试、最后测试过了进行部署,让这一套流程自动化,就需要CICD工具了。

我最后选择的是Drone这个轻量级工具,而没有选择Jenkins和Gitlab CI,也没选择其它网络在线服务。Jenkins和Gitlab CI,两个都太重量级了,我的系统配置(1C2G)完全跟不上,外加Jenkins默认UI好丑。其它网络在线服务,多半也是重新封装了Jenkins,弄了套好看的可视化界面,不过,使用起来总觉得不自由。

开发环境安装

提示:以下安装过程中,所有下载地址均已改为国内地址无需***,所有参数为必填参数与建议填写参数,未填写的参数均为可选参数。

注意:以下内容均安装在同一台服务器内。但是docker设置了内部子网,且dockers内的不同容器分配了各自的内网ip,目的仅是为了模拟部署在不同的服务器上情况。以下使用内网ip的地方,均可以替换成等效的外网ip,但是使用外网ip的地方均不能被替换成内网ip(且应当被替换成域名路径),原因是这些外网ip是暴露给实际远端的终端客户的,如果使用内网ip,客户由于不处于同一子网故无法解析地址。

安装容器引擎

在云服务器上安装Docker

以ssh的方式连接上云服务器,比如Windows用户,这里推荐使用MobaXterm,个人使用免费、运行流畅、UI界面美观、各种功能多(我用过之后就再也没打开过PuTTY了)。

准备工作

更新apt包索引,并安装必要的一些系统工具包,以允许apt通过HTTPS使用存储库。

sudo apt-get update

sudo apt-get -y install \
    apt-transport-https \
    ca-certificates \
    curl \
    gnupg-agent \
    software-properties-common

安装GPG密钥。

curl -fsSL https://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | sudo apt-key add -

通过搜索正常的密钥后8位(0EBFCD88),验证GPG密钥安装成功。

sudo apt-key fingerprint 0EBFCD88

pub   rsa4096 2017-02-22 [SCEA]
      9DC8 5822 9FC7 DD38 854A  E2D8 8D81 803C 0EBF CD88
uid           [ unknown] Docker Release (CE deb) <docker@docker.com>
sub   rsa4096 2017-02-22 [S]

设置稳定存储库。

sudo add-apt-repository \
   "deb [arch=amd64] https://mirrors.aliyun.com/docker-ce/linux/ubuntu \
   $(lsb_release -cs) \
   stable"
安装并验证

更新apt包索引,安装最新版本的Docker Engine和containerd。

sudo apt-get -y install docker-ce docker-ce-cli containerd.io

运行一下hello-world这个官方远程库里的image,容器名设置为hi-docker。

sudo docker run --name hi-docker hello-world

如果你看到了“Hello from Docker!”,则说明Docker已经正常安装。

Hello from Docker!
This message shows that your installation appears to be working correctly.

删除这个成功完成运行的hi-docker容器,然后删除本地无用的hello-world镜像。

sudo docker rm hi-docker
sudo docker image rm hello-world
配置子网

为之后的Docker容器,使用docker network命令创建子网,默认是与宿主机桥接。

sudo docker network create --subnet 172.18.0.0/16 \
    --gateway 172.18.0.1 \
    ex-network

创建成功,会显示一个network的id号,可以通过id号或network名称查询子网详情。

sudo docker network inspect ex-network

搭建代码仓库

在云服务器上安装Gitea搭建Git服务和私有远程代码仓库

以容器形式安装mariadb用于gitea的数据存储
sudo mkdir -p /data/docker/mariadb
sudo docker run --name mariadb \
    --network ex-network \
    --ip 172.18.0.2 \
    -p 3306:3306 \
    -v /data/docker/mariadb/:/var/lib/mysql \
    --restart always \
    -e "MYSQL_ROOT_PASSWORD=root" \
    -e "MYSQL_DATABASE=gitea" \
    -e "MYSQL_USER=gitea" \
    -e "MYSQL_PASSWORD=gitea" \
    -itd \
    mariadb:latest
以容器形式安装gitea
sudo mkdir -p /data/docker/gitea
sudo docker run --name gitea \
    --network ex-network \
    --ip 172.18.0.3 \
    -p 3000:3000 \
    -p 3022:22 \
    -v /data/docker/gitea:/data \
    --restart always \
    -itd \
    gitea/gitea:latest
Gitea初始设置

打开一个web浏览器,地址栏输入 http://云服务器公网ip地址:3000,你将看到一个Gitea的初始化配置的UI界面。

提示:以下各种设置不说明则保持默认值。数据库主机、用户名数据库用户密码及数据库名称见上文。

数据库设置

数据库类型:MySQL
数据库主机:172.18.0.2:3306
用户名:gitea
数据库用户密码:gitea
数据库名称:gitea
字符集:utf8mb4

一般设置

站点名称:EXplosion

可选设置

管理员账号设置:自己的用户名、密码和邮箱。

修改Gitea地址

gitea默认的地址为localhost。如果所有操作都是本地内部的,那么无所谓了,可以跳过此步骤。如果你需要从别的地方与gitea产生交互,比如子网划分后不同地址的容器内程序想通过webhooks进行交互,又比如外网客户从远端克隆代码,都会发生localhost实际地址不一致无权限访问的问题,此时需要把localhost改为可访问的公网地址。

操作很简单,找到/data/docker/gitea/gitea/conf/app.ini这个文件,打开,并全文所有的localhost替换成 云服务器公网ip地址(最好是域名)。

配置持续集成部署工具

创建新的 OAuth2 应用程序

登录Gitea后,点击右上角头像,点击设置,选择”应用“分页。在管理OAuth2应用程序下的,创建新的 OAuth2 应用程序的里面,填写内容。

应用名称:drone

重定向URI:http://云服务器公网ip地址:3080/login

点击生成,将生成的客户端ID(DRONE_GITEA_CLIENT_ID)和客户端密钥(DRONE_GITEA_CLIENT_SECRET)记录保存下来,点击保存。

生成Shared Secret

生成Shared Secret(DRONE_RPC_SECRET)用于之后runners和central Drone server之间的通信。

openssl rand -hex 16

安装Drone Server

提示:目前drone的验证采用 oath2,不再需要设置DRONE_GIT_USERNAME和DRONE_GIT_PASSWORD。如果仓库的可见性并不是完全公开,drone默认只对github的私有仓进行授权克隆,其他情况需手动将DRONE_GIT_ALWAYS_AUTH设置为true。

sudo docker run --name=drone \
  --volume=/data/docker/drone:/data \
  --env=DRONE_GITEA_SERVER="http://云服务器公网ip地址:3000" \
  --env=DRONE_GITEA_CLIENT_ID="DRONE_GITEA_CLIENT_ID" \
  --env=DRONE_GITEA_CLIENT_SECRET="DRONE_GITEA_CLIENT_SECRET" \
  --env=DRONE_RPC_SECRET="DRONE_RPC_SECRET" \
  --env=DRONE_SERVER_HOST="云服务器公网ip地址:3080" \
  --env=DRONE_SERVER_PROTO="http" \
  --env=DRONE_GIT_ALWAYS_AUTH=true \
  --network ex-network \
  --ip 172.18.0.4 \
  -p 3080:80 \
  -p 443:443 \
  --restart=always \
  -itd \
  drone/drone:latest

安装Drone Runner

sudo docker run --name drone-runner \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -e DRONE_RPC_PROTO=http \
  -e DRONE_RPC_HOST="123.57.219.68:3080" \
  -e DRONE_RPC_SECRET="bc6b8c32f8513f7abbb1069262f1ebb7" \
  -e DRONE_RUNNER_CAPACITY=2 \
  -e DRONE_RUNNER_NAME="DroneRunner" \
  --network ex-network \
  --ip 172.18.0.5 \
  -p 6000:3000 \
  --restart always \
  -itd \
  drone/drone-runner-docker:latest

runner安装完成后,可以使用docker logs查看日志内容,从而验证是否安装成功。

sudo docker logs drone-runner