首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

怎样用Jenkins、Docker和CI/CD构建无服务器应用程序?

我正在用AWS lambda开发一个无服务器架构的自由职业项目。

用Jenkins和Docker实现CI/CD,并在Docker容器上运行Jenkins pipelines。我会向你展示如何一步步设置环境。

由于是苹果电脑,我首先在电脑上安装Docker软件。还需Jenkins软件。我选择在Docker容器中运行Jenkins,因为这样的运行环境更简单干净。于是,我为Jenkins找到一个Docker镜像版本(image)。

简而言之,Docker把容器当作独立的计算机来操作。

Docker会利用镜像文件创建容器。例如,在使用的这个Docker镜像中,包含了Linux操作系统和Jenkins软件。当Docker用这个镜像创建一个容器时,就相当于我们有一台计算机已经预先安装了Linux和Jenkins。

一、设置容器

接下来,让我们看看如何设置这个容器。一开始,我们从Docker镜像的线上资源库Docker hub中提取镜像文件。

代码语言:javascript
复制
docker pull jenkins/jenkins:lts
代码语言:javascript
复制
lts: Pulling from jenkins/jenkins
844c33c7e6ea: Pull complete 
ada5d61ae65d: Pull complete 
f8427fdf4292: Pull complete 
f025bafc4ab8: Pull complete 
67b8714e1225: Pull complete 
64b12da521a3: Pull complete 
2e38df533772: Pull complete 
b1842c00e465: Pull complete 
b08450b01d3d: Pull complete 
2c6efeb9f289: Pull complete 
0805b9b9cdc4: Pull complete 
f129619fc383: Pull complete 
cd27f3a82cdf: Pull complete 
f31251f493ed: Pull complete 
2c902f1f4dfa: Pull complete 
2fe1d2cb7aab: Pull complete 
908723de775f: Pull complete 
54aa3899e429: Pull complete 
f48cf8764dc1: Pull complete 
Digest: sha256:d5069c543e80454279caacd13457d012fb32c5229b5037a163d8bf61ffa6b80b
Status: Downloaded newer image for jenkins/jenkins:lts

Docker软件下载镜像文件并对之解压。现在,我们可以在自己的目录下看到该镜像文件。

代码语言:javascript
复制
alis-MBP:scms aliyuksel$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
jenkins/jenkins     lts                 a3f949e5ebfd        2 weeks ago         582MB

然后,我们可以用这个镜像构建一个容器并运行。使用以下命令:

代码语言:javascript
复制
docker run -p 8080:8080 -p 50000:50000 jenkins/jenkins:lts

一旦这个容器正常启动,我们就能使用Jenkins软件,直到该容器关闭。但在容器关闭后会有一个问题:在下一次运行中,我们找不到之前已创建的任何pipeline或配置。

这是因为,Docker是在镜像文件上运行容器,而镜像文件本身是不可更改的。这就意味着,当我们在Jenkins中定义一个pipeline时,Jenkins会将它保存到容器文件系统中而不是镜像文件中。当关闭容器时,这些信息就丢失了。

因此,我们必须使用“Volumes”来解决这个问题。

Volumes用于将虚拟容器的文件系统固化到我们的实际物理计算机文件系统中。为此,我们必须定义新的Volume以保留容器中的Jenkins_home目录。这并不难,我们需要更改run命令如下:

代码语言:javascript
复制
docker run -p 8080:8080 -p 50000:50000 -v jenkins_home:/var/jenkins_home jenkins/jenkins:lts

这里-v代表“Volume”。如果没有Volume,它将自动创建一个Volume。你可以查看Docker相关文档以了解更多信息。

简而言之,我们用这种方法定义了名为jenkins_home的新卷,并挂载容器文件系统中的路径至:/var/jenkins_home。之后,即使关闭容器,我们的更改也不会丢失。因为/var/jenkins_home文件夹下的所有文件都保存在Volume中。

现在,我们可以在浏览器上调用Jenkins的url了。这时应开启Jenkins。我们需要初始密码initialAdminPassword。当执行以上命令时,我们可以看到日志,并在日志中找到需要的initialAdminPassword

代码语言:javascript
复制
*************************************************************
*************************************************************
*************************************************************
Jenkins initial setup is required. An admin user has been created and a password generated.
Please use the following password to proceed to installation:
fb7b0666b23f40db985817700d1d0821
This may also be found at: /var/jenkins_home/secrets/initialAdminPassword
*************************************************************
*************************************************************
*************************************************************

我们在Jenkins的页面中输入十六进制的密码。之后,我们会完成以下步骤:

  • 安装建议的插件
  • 创建第一个管理员用户
  • Jenkins实例配置
  • 开始使用Jenkins

到这里,我们完成本教程的第一部分。

二、实现pipeline

我们已经得到一个Jenkins的实例(instance)。

然后,开始实现pipeline。该pipeline将执行以下步骤:

  • 下面的所有步骤都将在另一个Docker容器上运行
  • 从Git(bitbucket)中提取我的项目代码,这是用nodejs编写的一个lambda项目。
  • 使用无服务器架构将该lambda项目部署到AWS云上。

我们需要这个新容器的镜像文件。这个镜像其实是一台简单的linux计算机。我们从Docker hub提取这个新容器的镜像文件。

代码语言:javascript
复制
docker pull alpine

此时,我们在本地机器上已经有这个Docker镜像文件了。但是Jenkin运行在另一个容器中。所以Jenkins需要连接这个新的Docker镜像。

我们必须在容器和Docker之间建立一座桥梁,用“Volume”定义来解决这个问题。

代码语言:javascript
复制
-v /var/run/docker.sock:/var/run/docker.sock  -v $(which docker):$(which docker) 

分析一下上面的命令。其中,docke.sock文件用于侦听套接字(socket)。在将这些Volume添加到命令行之后,docker.sock会挂载到本地计算机(localmachine)里的docker.sock文件中。

如果我们使用-v,并在之后指定本地计算机的真实路径,这条命令的意思就是执行“挂载(mount)”。如果我们在-v之后使用$(),则表示运行命令。-v $(which docker):$(which docker) 语句表示,如果“which docker”在容器上运行,Docker也会在本地计算机上运行“which container”,并将执行结果返回给容器。

必须在以上命令中添加这个参数,因为Jenkins通过运行“which docker”来查找具体运行的Docker。

我们还须改变这个文件的权限,因为缺省情况下,Jenkins用户无法访问这个文件。我们需要用根用户权限(root user)连接到该容器。

执行这个命令,并运行容器。

代码语言:javascript
复制
 docker run -p 8080:8080 -p 50000:50000 --name jenkins  -v jenkins_home:/var/jenkins_home -v /var/run/docker.sock:/var/run/docker.sock  -v $(which docker):$(which docker)  jenkins/jenkins:lts

我们使用以下命令打开容器的终端窗口。简单而言,使用根用户权限在容器上运行bash命令,我们然后用chmod更改文件权限。

这里强调的一个重点是,同一个容器名不能被使用两次。当关闭容器时,你必须删除该容器。

代码语言:javascript
复制
docker container rm jenkins

在此之后,下次可以用–name命令来使用Jenkins。

我们现在可以构建pipeline了。

点击容器终端窗口菜单下的“New Item”。为这个Item输入一个名称。选择PipeLine类型并单击OK。

在屏幕上选择PipeLine。首先,pipeline创建一个新容器,并执行容器上的所有命令。

代码语言:javascript
复制
pipeline {
   agent {
        docker { image 'alpine' }
    }
   stages {
      stage('pull project') {
         steps {
             sh 'pwd'
         }
      }
   }
}

现在可以通过Jenkins查看日志,看到的应该类似下图:

接下来,我们需要从bitbucket中提取项目。

首先,我们应该在Jenkins上定义一个可以访问bitbucket的用户。

单击菜单上的Credentials/System(证书/系统)。然后单击屏幕上的Global Credentials(全局证书)。这时菜单会发生改变,我们可以看到Add Credentials(添加证书)的新菜单。单击Add Credentials并定义你已经在bitbucket上预先建立的用户。

这时要重点关注的是ID字段。当从bitbucket中提取出该项目时,我们将使用这个字段的值。

这时进入pipeline.的配置页面。我们通过编写pipeline.脚本来从bitbucket中提取出该项目。

代码语言:javascript
复制
pipeline {
   agent {
        docker { image 'alpine' }
    }
   stages {
      stage('pull project') {
         steps {
             git credentialsId : 'aliyksel', url:'https://aliyksel@bitbucket.org/allscms/scms.git'
         }
      }
   }
}

保存,并运行pipeline。点击“Build Now”。

然后,该pipeline开始运行,并从bitbucket提取项目。

三、运行单元测试

接下来,就需要使用npm。通常可以使用npm plug-in插件。但既然需要为无服务器创建一个新的镜像文件,我更倾向于使用新镜像文件中的npm,而不是npm plug-in。因此,我们将创建一个包含npm和无服务器架构的镜像文件。

首先,提取包含节点的镜像文件。

代码语言:javascript
复制
docker pull node

之后,我们会把无服务器架构添加到这个镜像中。

从节点运行容器。

代码语言:javascript
复制
docker run -it --name node  node bash

现在已经进入容器。我们安装无服务器架构。

代码语言:javascript
复制
npm install serverless -g

现在我可以从这个容器创建一个新的镜像文件。于是在本地机器上运行以下命令。

代码语言:javascript
复制
docker commit node  serverlessimg

退出该Docker容器。

代码语言:javascript
复制
exit

此时,我们已经有了一个新的无服务器镜像,能在Jenkins中使用这个镜像。我们也可以使用pipeline,该pipeline能将无服务器应用程序部署到AWS云端。

你需要更改镜像文件的名称,并向pipeline添加以下步骤。

代码语言:javascript
复制
  agent {
        docker { image 'serverlessimg' }
    }
...
stage('pull and deploy project : scms') {
         steps {
               git credentialsId : 'aliyksel', url:'https://aliyksel@bitbucket.org/allscms/scms.git'
               sh 'npm install'
               sh 'serverless config credentials --provider aws --key AKIAIOSFODNN7EXAMPLE --secret wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY'
               sh 'serverless deploy'
             }
         }
      }

我们还需定义用户信息以实现对AWS服务的访问。如果你还没建立自己的AWS用户账户,可以查看该文档。鉴于我已有一个AWS用户名了。我将以如下方式设置自己的用户证书(credentials)。

代码语言:javascript
复制
serverless config credentials --provider aws --key AKIAIOSFODNN7EXAMPLE --secret wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY

至此,所有步骤完成,我们为无服务器架构创建了一个新镜像,并部署了一个AWS应用程序。

英文原文:

Using Jenkins, Docker and CI/CD for Serverless Applications

  • 发表于:
  • 本文为 InfoQ 中文站特供稿件
  • 首发地址https://www.infoq.cn/article/0sueQNsY9tLDVi79UZms
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券