本 Chat 将分享作者近期接触到的一个项目,以实例分析的方式,讲解如何应用 Docker 对开发流程持续优化,提升开发效率和产品迭代速度,实现 CICD。
通过本 Chat 你将学到:
- 什么是 Docker?
- 开发中如何应用 Docker?
- 怎么实现 CICD,通过打通开发、测试、上线发布的自动化,提升整体研发效率和开发敏捷度?
背景
前一阵子,由于偶然的原因,接触到一个 WEB 项目,需求方期望能通过架构重构,大幅提升整体性能、稳定性和可维护性。
项目原始架构
这是一个典型的 LAMP 架构,部署在单机上面,一开始系统运行的很好,但随着用户量的上升,众多问题开始涌现出来。
由于项目本身年代久远,开发换了一波又一波,基本上已经没有人了解整个项目的全部,很多模块大家都是靠猜。整个系统长时间部署在同一台机器上,没人敢动这台机器。出了问题非常难定位,没人愿意维护这套东西。
改造后项目架构
主要将各子模块分离,Apache 做服务器,Memcache 做缓存,MySQL 做数据库,另外将附件等资源放置在 CDN 以提升用户的访问体验。
同时将各模块容器化, 并引入 CI/CD,以提升系统整体的可维护性和稳定性,由于系统的所有部分(包括环境)全部通过代码固化,就防止了后续由于开发人员变更导致的系统渐渐腐化的问题。
接下来将重点描述该项目如何实现 CI/CD,及 CI/CD 在该项目中起到的作用。
通过 CI/CD 提升效率
如何实现 CI/CD?
这里主要用到两个工具:Docker 和 Gitlab。
Docker 是一套轻量级的虚拟化技术,非常适合与开发集成,固化开发环境,提升开发效率,不必多说,大家应该都比较熟了。
Gitlab 是一个可以部署在私有云环境下的 Git 代码仓库管理系统,通过 Gitlab 自带的流水线功能,可以轻松实现 CI/CD。
通过 Docker 和 Gitlab 我们能轻松打通整个开发流程。
先看一下最终的效果:
在 Gitlab 上的效果:
整个流程包括:
构建 -> 推送 -> 部署到测试环境 -> 部署到生产环境
当然中途还会包含在测试环境的测试等步骤,我们可以看到整个过程都是持续和可视的,开发者只需要关注代码即可,代码一提交,后续过程都会自动化执行。
运行环境效果:
具体代码分析
下面贴一段 gitlab-ci 代码,通过代码我们可以轻松地知道上面过程是如何实现的。
这段代码包含了四个 stage,分别表示上图中的四个阶段,每个阶段会执行一些命令,来运行系统的各个组件。
variables:
TEST_IMAGE: "20.20.10.100:5000/test/test:latest"
TEST_URL: test.com
TEST_IP: 20.20.10.100
IMAGE_NAME: "20.20.10.100:5000/test/test:${CI_COMMIT_REF_SLUG}_${CI_COMMIT_SHA}"
PRODUCT_IP: 12.16.0.23
PRODUCT_URL: http://product.com
SvrDbIP: 12.16.0.5
# stage 定义运行的阶段
stages:
# 构建阶段
- build
# 发布阶段
- push
# 部署到测试环境
- deploy_test
# 部署到开发环境
- deploy_product
# 定义job(作业)
build:
# 必须指定该job运行的阶段
stage: build
# 要运行的shell命令
#image: docker:latest
script:
- echo "build"
- make
- docker build -t ${IMAGE_NAME} .
only:
- master
- test
push:
stage: push
script:
- docker push ${IMAGE_NAME}
only:
- master
- test
deploy_test:
stage: deploy_test
script:
- echo "Deploy to test server"
- ssh root@${TEST_IP} "docker kill ci;
docker rm -f ci;
docker run -d --cap-add=SYS_TIME --net=host --name=ci --restart=always
-p 80:80 -p 8889:8889 -e SvrDbIP=${TEST_IP} -e ${IMAGE_NAME} /start.sh
environment:
name: test
url: http://${TEST_IP}
only:
- master
- test
deploy_product:
stage: deploy_product
variables:
PRODUCT_IMAGE_NAME: "${PRODUCT_IP}:5000/product:${CI_COMMIT_REF_SLUG}_${CI_COMMIT_SHA}"
PRODUCTLOCAL_IMAGE_NAME: "localhost:5000/product:${CI_COMMIT_REF_SLUG}_${CI_COMMIT_SHA}"
script:
docker pull ${PRODUCTLOCAL_IMAGE_NAME}
docker commit ci ci:autobak-job${CI_JOB_ID}-$(date +%y%m%d%H%M%S)
docker rm -f cidel
docker rename ci cidel
docker kill cidel
docker run -d --cap-add=SYS_TIME --net=host --name=ci --restart=always -p 80:80 -p 8889:8889 -e SvrDbIP=${SvrDbIP} ${PRODUCTLOCAL_IMAGE_NAME} /start.sh
environment:
name: production
url: http://${PRODUCT_URL}
when: manual
only:
- master
- test
总结
项目通过上述方法重构后, 顺利地解决了性能、稳定性、可维护性等问题,并且通过 CI/CD 极大地降低了项目开发对人的依赖。后面的版本开发中,基本可以做的随便一个普通开发者都能快速上手。生产环境发现 Bug 也能快速回滚,从而减少整体影响。