摘要:本文从容器技术应用的角度解构了HE2E项目的代码仓库配置、镜像构建、及docker-compose的部署方式。希望通过本篇文章分享可以使更多的开发者了解容器技术和华为云。
本文分享自华为云社区《解构华为云HE2E项目中的容器技术应用》,作者: 敏捷小智。
华为云DevCloud HE2E DevOps实践当中,项目采用Docker技术进行构建部署。
容器技术应用,其实说简单也很简单,其流程无外乎:制作镜像——上传镜像——拉取镜像——启动镜像。
今天,我们就带大家从容器技术应用的角度来解构HE2E项目。
HE2E技术架构图:
创建项目
在华为云DevCloud中创建项目时选择DevOps样例项目,即可创建出预置了代码仓库、编译构建、部署等任务的DevOps样例项目,此项目即HE2E项目。
代码仓库
HE2E项目中预置了代码仓库phoenix-sample。
在根目录下可以看到images、kompose、result、vote、worker五个文件夹,以及LICENSE、README.md和docker-compose-standalone、docker-compose两个yml文件。Images文件夹存了几张图片,LICENSE和README也与代码内容无关,docker-compose.yml文件是应用于本地开发时的测试文件,这些都无需理会。
配置Kubectl的kompose文件夹
我们先看一下kompose文件夹,此文件夹下有多个yaml文件,通过命名可以看出这些文件是针对于每个微服务应用的配置。当我们进行CCE部署时就读取这里的配置(在部署时进行配置)。本着由浅入深的精神,本文先对ECS部署时所需的配置进行讲解,大家不要心急噢。
功能模块与制作镜像的Dockerfile
result、vote、worker三个文件夹分别对应HE2E当中的三个功能模块:结果、投票、处理。
可以看到,三个文件夹下各自都有Dockerfile文件。制作镜像的时候就是靠这些Dockerfile文件来进行制作的。
我们以result下的Dockerfile进行举例说明:
FROM:定制的镜像都是基于 FROM 的镜像,这里的node:5.11.0-slim就是定制需要的基础镜像。后续的操作都是基于 node:5.11.0-slim。
WORKDIR /app:指定并创建工作目录/app。
RUN <命令>:执行<命令>。
ADD <文件> <目录>:复制<文件>至<目录>。
5-9行:执行npm安装操作,并将相关文件存放入相应目录。
ENV PORT 80:定义环境变量PORT=80
EXPOSE 80:声明端口80。
CMD <命令>:在docker run时运行<命令>。
在编译构建任务phoenix-sample-ci中,“制作Result镜像并推送到SWR仓库”步骤,通过“工作目录”、“Dockerfile路径”两个选项确定制作镜像时读取的Dockerfile:<工作目录>/<Dockerfile路径>,即./result/Dockerfile。
其余的vote和worker两个功能模块也是按此种办法制作镜像。值得一提的是,worker文件夹下有Dockerfile、Dockerfile.j和Dockerfile.j2三个文件,但是在构建任务中,我们只需选择一个文件进行镜像制作,选择的是Dockerfile.j2这个文件。
在Dockerfile.j2文件中,将target下的内容复制到code/target下,但是target文件夹又并不在代码当中。这是因为worker下的项目是Java项目,target文件夹是在Maven构建的过程产生的,所以在构建任务phoenix-sample-ci中,制作Worker镜像之前需要先通过Maven进行构建。
通过以上的Dockerfile文件已经可以制作出三大功能模块对应的容器镜像了。在部署主机中,直接使用docker login、docker pull和docker run命令就可以登录、拉取并启动相应的镜像。但是这种方式要求对每个镜像都进行拉取和启动,不能一次性配置全部镜像。故此,我们引入了docker compose,通过docker compose实现对 Docker 容器集群的快速编排。一键(一个配置文件)配置本项目所需的各个功能模块。
配置docker-compose的docker-compose-standalone.yml文件
当我们部署本项目到服务器时,采取docker-compose的方式启动。
在部署任务phoenix-sample-standalone中,最终通过执行shell命令启动本项目:
docker-compose -f docker-compose-standalone.yml up -d
这句shell命令中的docker-compose-standalone.yml正是我们代码仓库根目录的docker-compose-standalone.yml文件。
下面对docker-compose-standalone.yml文件进行解读。
version:指定本 yml 依从的 compose 哪个版本制定的。
services:包含的服务。
本yml中含有redis、db、vote、result、worker五个服务。其中db即数据库postgres。
image:镜像地址。
以redis和worker服务为例,其镜像为docker-server/docker-org/redis:alpine、docker-server/docker-org/worker:image-version,这里采用的是参数化替换的形式定义镜像地址的。
在构建任务phoenix-sample-ci中,“替换Docker-Compose部署文件镜像版本”步骤的shell命令正是将docker-compose-standalone.yml文件中的docker-server、docker-org、image-version三处替换为我们在该构建任务中定义的三个参数dockerServer、dockerOrg、BUILDNUMBER。
进行这样的替换以后,我们的docker-compose-standalone.yml中的镜像地址才会变成我们所需的最终地址。例:swr.cn-north-4.myhuaweicloud.com/devcloud-bhd/redis:alpine、swr.cn-north-4.myhuaweicloud.com/devcloud-bhd/worker:20220303.1。
五个服务中,vote、result、worker是本项目构建生成的,redis和db是采用第三方应用,所以在镜像版本方面会有区别。
ports:端口号。将容器和主机绑定到暴露的端口。
在vote当中ports: 5000:80就是将容器所使用的80端口号绑定到主机的5000端口号,这样我们就可以通过<主机ip>:5000来访问本项目的用户端界面了。
networks:配置容器连接的网络。这里使用的是最简单的两种声明网络名称。
frontend即前端,backend即后端。
environment:添加环境变量。POSTGRES_HOST_AUTH_METHOD: "trust",此变量防止访问postgres时无法登录。
volumes:将主机的数据卷或着文件挂载到容器里。db-data:/var/lib/postgresql/data下的内容即成为postgres当中的数据内容。
deploy:指定与服务的部署和运行有关的配置。placement:constraints: [node.role == manager]即:权限设置为管理员。
depends_on:设置依赖关系。vote依赖redis、result依赖db。
至此,整个HE2E项目的代码结构已经解构完毕。
编译构建
其实在完成代码解构之后,整个项目已经非常清晰了。代码中包括vote、result、worker三个功能模块,项目还用到了redis和postgres两个第三方应用。所以,我们在编译构建环节的主要目的就是把这些服务的镜像制作出来并上传到SWR容器镜像仓库中。
本项目中预置了5个构建任务。
我们仅分析phoenix-sample-ci任务即可。
三个功能模块的构建
在进行代码解构时,对构建任务的部分内容已经进行过分析了,其中就包括如何通过指定Dockerfile文件制作镜像,即docker build(制作)的操作。除此之外,制作XX镜像并推送到SWR的步骤中还包括了推送镜像所需的信息。这里设置了推送区域、组织、镜像名字、镜像标签,其实就是我们进行docker tag(打标签)和docker push(推送)的操作。
在vote、result、worker的镜像制作并推送的过程中,通过参数BUILDNUMBER定义镜像的版本号。BUILDNUMBER是系统预定义参数,随着构建日期及次数变化。
worker镜像在制作之前,需要先对worker目录下的工程进行Maven构建,这样就会生成Dockerfile.j2中(制作镜像时)所需的target文件。
Postgres和Redis的构建
在制作了三个功能模块镜像以后,接下来要做的是生成Postgres和Redis 镜像。这里选择的办法是,通过shell命令写出这两个应用的Dockerfile。
echo from postgres:9.4 > Dockerfile-postgres echo from redis:alpine > Dockerfile-redis
通过这段shell命令就会在当前的工作目录下生成Dockerfile-postgres和Dockerfile-redis两个文件。
Dockerfile-postgres:
FROM postgres:9.4
Dockerfile-redis:
FROM redis:alpine
在接下来的步骤当中,指定当前目录下的Dockerfile-postgres和Dockerfile-redis两个文件制作镜像并上传。
替换部署配置文件并打包
通过以上的步骤,镜像就已完全上传至SWR仓库了。后续的“替换Docker-Compose部署文件镜像版本”和“替换Kubernates部署文件镜像版本”两个步骤分别将代码仓根目录下的docker-compose-standalone.yml和kompose下的所有XX-deployment.yaml文件中的docker-server、docker-org、image-version替换为构建任务中的参数dockerServer、dockerOrg、BUILDNUMBER。这两步骤的意义就是将ECS部署(docker-compose/docker-compose-standalone.yml)和CCE部署(Kubernates/Kompose)所需的配置文件修改为可部署、可应用的版本。
这两个文件修改完毕后,都进行tar打包的操作。打包后的产物也通过接下来的两个“上传XX”步骤上传软件包到了软件发布库。
Tips
在本项目的帮助文档中,提到了“配置基础依赖镜像”。整个这一段落是由于构建任务中使用的基础镜像源DockerHub拉取受限,采取了一个折中的办法拉取镜像。简言之,整段操作即通过创建prebuild任务来实现基础镜像版本的替换,以避免开发者在进行构建phoenix-sample-ci任务时出现拉取镜像失败的情形。相应地,也在“配置并执行编译构建任务”中禁用了Postgres和Redis镜像的制作步骤。
部署
在编译构建环节,我们已经成功将三个功能模块镜像(vote、result、worker)和两个第三方镜像构建并上传至SWR(容器镜像仓库)中了。接下来需要做的就是将SWR中的镜像拉取到我们的部署主机并启动。
在整个实践中,提供了ECS部署和CCE部署两种方式,并且在项目中预置了3个部署任务。
我们仅分析phoenix-sample- standalone任务即可。
传输软件包至部署主机中
在构建环节,我们除了制成镜像并上传到SWR以外,还对配置文件进行了修改、压缩并上传到了软件发布库。在部署过程中,我们首先要做的,就是把配置文件从软件发布库中传到部署主机当中。
结合实际的部署任务来看,就是:向[主机组] group-bhd部署一个[软件包/构建任务(的产物)],我们选择了[构建任务] phoenix-sample-ci的最新版本([构建版本][Latest])构建产物,将其[下载到主机的部署目录]。
这一步骤执行完毕后,在部署主机的/root/phoenix-sample-standalone-deploy路径下,就会存在之前构建任务中压缩的docker-stack.tar.gz和phoenix-sample-k8s.tar.gz。ECS部署中,我们仅需要解压docker-stack.tar.gz,这个文件是docker-compose-standalone.yml的压缩包(回顾一下构建任务中的“替换部署配置文件并打包”)。
通过执行shell命令启动docker-compose
解压完成后,我们就可以通过执行docker-compose启动命令来启动项目了。
在这一步骤当中,前三行分别输出了三个参数docker-username、docker-password、docker-server。这三个参数是用以进行docker login操作的。因为我们在docker-compose-standalone.yml中涉及到拉取镜像的操作,需要在拉取镜像前先登录SWR镜像仓库。
登录完毕后,就可以进入/root/phoenix-sample-standalone-deploy目录下(cd /root/phoenix-sample-standalone-deploy)
启动docker-compose(docker-compose -f docker-compose-standalone.yml up -d)。
至此,项目已经部署至主机当中,在主机中,通过docker ps -a指令可以看到5个容器进程。
与此同时,访问http://{ip}:5000和http://{ip}:5001即可访问项目的用户端与管理端。
结语
本文从容器技术应用的角度解构了HE2E项目的代码仓库配置、镜像构建、及docker-compose的部署方式。希望通过本篇文章分享可以使更多的开发者了解容器技术和华为云。