如何在Ubuntu上配置docker和docker compose的连续集成测试环境

作者:无名 - 电脑 -

介绍

持续集成(ci )指开发人员尽可能多地集成代码,并且每个提交都在被合并到共享存储库之前进行测试。

ci 加速了开发过程,最大限度地减少了生产中关键问题的风险,但是建立起来并不简单,自动构建在不同的环境中运行,在该环境中,运行时依赖项的安装和外部服务的配置可能与本地环境和开发环境不同。

docker是一个集中化的平台,以简化环境标准化问题,使应用程序的部署成为标准化,对于开发人员,docker允许你在本地容器中运行应用程序组件来模拟本地机器上的生产环境,这些容器很容易使用docker compose自动化,独立于应用程序和底层操作系统。

本教程使用docker compose来演示ci工作流的自动化。

我们创建一个docker化的hello world类型的python应用程序和一个bash测试脚本,python应用程序将需要两个容器来运行: 一个用于应用程序本身,以及一个用于存储的redis容器,该容器是应用程序的依赖项。

然后,将测试脚本在它自己的容器中进行docker化,并将整个测试环境移至docker-compose.test.yml文件,以便我们确保在全新统一的应用程序环境中运行每个测试。

这种方法展示了如何在每次测试应用程序时为应用程序构建一个相同的,包括它的依赖的新测试环境。

前提条件

在开始之前,你需要:

带有sudo权限的非root用户的ubuntu 16.04服务器,使用ubuntu 16.04初始服务器设置配置这台服务器,按 在ubuntu 16.04上,如何安装和使用docker步骤1和2安装docker,按在ubuntu 16.04上如何安装docker compose步骤1安装docker compose

步骤1创建hello world python应用程序

在这个步骤中,我们创建一个简单的python应用程序,作为通过这个设置测试的应用程序类型的例子。

通过执行以下命令为我们的应用程序创建一个新目录:

cd ~

mkdir hello_world

cd hello_world

用nano编辑一个新文件app.py

nano app.py

添加以下内容:

app.py

from flask import flask

from redis import redis

app = flask(__name__)

redis = redis(host="redis")

@app.route("/")

def hello():

visits = redis.incr('counter')

html ="lt;h3gt;hello world!lt;/h3gt;"

"lt;bgt;visits:lt;/bgt; {visits}"

"lt;br/gt;"

return html.format(visits=visits)

if __name__ =="__main__":

app.run(host="0.0.0.0", port=80)

完成后,保存并退出文件。

app.py是一个基于 flask的web应用程序,它连接到一个redis数据服务,visits =redis.incr('counter')增加访问次数,并在redis中保持这个值,最后,在html中返回带有访问次数的hello world消息。

我们的应用程序有两个依赖项,flaskredis,在前两行中可以看到,在执行应用程序之前必须定义这些依赖项。

打开一个新文件:

nano requirements.txt

添加内容:

requirements.txt
 

flask

redis

完成后,保存并退出文件,现在我们已经定义了我们的需求,我们在后面的docker-compose.yml中进行定义,我们已经准备好下一步。

步骤2- docker化hello world应用程序

docker使用名为dockerfile的文件来指示为给定应用程序构建docker镜像所需的步骤,编辑一个新文件:

nano dockerfile

添加以下内容:

dockerfile

from python:2.7

workdir /app

add requirements.txt /app/requirements.txt

run pip install -r requirements.txt

add app.py /app/app.py

expose 80

cmd ["python","app.py"]

让我们分析每一行的含义:

from python:2.7 :表示我们的"hello world"应用程序镜像是由官方python:2.7 docker镜像构建
workdir /app :将docker镜像中的工作目录设置为/app
add requirements.txt /app/requirements.txt :将文件requirements.txt添加到我们的docker镜像
run pip install -r requirements.txt :安装应用程序依赖项的pip
add app.py /app/app.py :将我们的应用程序源代码添加到docker镜像
expose 80 :表明我们的应用程序可以在端口80 (标准公共端口端口)上到达
cmd ["python","app.py"] :启动应用程序的命令

保存并退出文件,这个dockerfile文件包含构建"hello world"应用程序的主要组件所需的所有信息。

依赖项

我们的应用程序需要redis作为外部服务,在传统的linux环境中,这种依赖性很难每次都以相同的方式设置,但是通过docker compose,我们可以每次都以可重复的方式设置它。

创建一个docker-compose.yml文件来开始使用docker compose 。

编辑一个新文件:

nano docker-compose.yml

添加以下内容:

docker-compose.yml

web:

build: .

dockerfile: dockerfile

links:

- redis

ports:

-"80:80"

redis:

image: redis

这个docker compose文件指出如何在两个docker容器中将"hello world"应用程序转到本地。

它定义了两个容器,webredis

web使用build上下文的当前目录,并从我们刚刚创建的dockerfile文件构建我们的python应用程序,这是我们为python应用程序创建的本地docker镜像,为redis容器定义一个链接,以便能够访问redis容器ip 。 它还可以使用ubuntu服务器的公共ip从internet上公开访问端口80

redis是从标准的公共docker映像执行的,名为redis

完成后,保存并退出文件。

步骤3部署hello world应用程序

在此步骤中,我们部署应用程序,最终它将通过互联网访问,对于部署工作流,可以考虑这是一个开发机,或者生产环境,因为可以用多次部署应用程序。

docker-compose.ymldockerfile文件允许你通过执行以下命令来自动化本地环境的部署:

docker-compose -f ~/hello_world/docker-compose.yml build

docker-compose -f ~/hello_world/docker-compose.yml up -d

第一行从dockerfile文件构建本地应用程序镜像,第二行在守护进程模式(-d )中运行webredis容器,在docker-compose.yml文件中指定。

检查应用程序容器是否已通过执行以下命令创建:

docker ps

这应该显示两个正在运行的容器,名为helloworld_web_1helloworld_redis_1

检查应用程序是否已启动,通过执行以下命令来获取helloworld_web_1容器的ip :

web_app_ip=$(docker inspect --format='{{range .networksettings.networks}}{{.ipaddress}}{{end}}' helloworld_web_1)

echo $web_app_ip

检查web应用程序是否返回正确的消息:

curl http://${web_app_ip}:80

这应该会返回如下内容:

输出

lt;h3gt;hello world!lt;/h3gt;lt;bgt;visits:lt;/bgt; 2lt;br/gt;

如何自定义你自己的应用程序

设置自己应用程序的关键是将应用程序放在自己的docker容器中,并从自己的容器中运行每个依赖项。

步骤4创建测试脚本

现在我们为python应用程序创建一个测试脚本,这将是一个简单的脚本,它检查应用程序输出的http ,这个脚本作为持续集成部署过程的测试类型的一个例子。

编辑一个新文件:

nano test.sh

添加以下内容:

test.sh

sleep 5

if curl web | grep -q 'lt;bgt;visits:lt;/bgt; '; then

echo"tests passed!"

exit 0

else

echo"tests failed!"

exit 1

fi

test.sh测试"hello world"应用程序的基本网络连接,它使用curl来检索访问次数来报告测试是否通过了。

步骤5创建测试环境

为了测试我们的应用程序,我们需要部署一个测试环境,我们要确保它与我们在步骤3中创建的动态应用程序环境是相同的。

首先,我们需要通过创建一个新的dockerfile文件来对接我们的测试脚本,编辑一个新文件:

nano dockerfile.test

添加以下内容:

dockerfile.test

from ubuntu:xenial

run apt-get update amp;amp; apt-get install -yq curl amp;amp; apt-get clean

workdir /app

add test.sh /app/test.sh

cmd ["bash","test.sh"]

dockerfile.test扩展官方ubuntu:xenial镜像来安装curl依赖,向镜像文件系统添加tests.sh,并指示使用bash执行测试脚本的cmd命令。

一旦我们的测试被dockerized,它们就可以用可复制方式执行。

下一步是将测试容器链接到"hello world"应用程序,这个是docker compose再次进入的地方,编辑一个新文件:

nano docker-compose.test.yml

添加以下内容:

docker-compose.test.yml

sut:

build: .

dockerfile: dockerfile.test

links:

- web

web:

build: .

dockerfile: dockerfile

links:

- redis

redis:

image: redis

docker-compose.test.yml文件还定义了一个sut容器(在测试下命名为系统),它负责执行集成测试,sut容器指定当前目录作为我们的build目录,并指定我们的dockerfile.test文件,它链接到web容器,以便test.sh脚本可以访问容器地址的应用程序ip 。

如何自定义你自己的应用程序

注意,docker-compose.test.yml可能包括数十个外部服务和多个测试容器,docker将能够在单个主机上运行所有这些依赖项,因为每个容器共享底层的操作系统。

如果你的应用程序有更多的测试,你可以为它们创建额外的dockerfiles,类似于上面所示的dockerfile.test文件。

然后,你可以在docker-compose.test.yml文件的sut容器下面添加额外的容器,引用附加的dockerfiles 。

步骤6测试hello world应用程序

最后,将docker想法从本地环境扩展到测试环境,我们有一种通过执行docker测试应用程序的方法:

docker-compose -f ~/hello_world/docker-compose.test.yml -p ci build

此命令生成docker-compose.test.yml所需的本地镜像,注意,使用-f来指向docker-compose.test.yml-p,以指示特定的项目名称。

现在,通过执行以下命令来提升你的新测试环境:

docker-compose -f ~/hello_world/docker-compose.test.yml -p ci up -d

outputcreating ci_redis_1

creating ci_web_1

creating ci_sut_1

通过执行以下命令检查sut容器的输出:

docker logs -f ci_sut_1

输出

% total % received % xferd average speed time time time current

dload upload total spent left speed

100 42 100 42 0 0 3902 0 --:--:-- --:--:-- --:--:-- 4200

tests passed!

最后,检查sut容器的退出代码以验证你的测试是否已通过:

docker wait ci_sut_1

输出
 

0

执行此命令后,如果通过测试,$的值为0 ,否则,我们的应用程序测试失败。

注意,其他ci工具可以克隆我们的代码存储库,并执行这些命令来验证测试是否与运行时相关。

就是这样,我们已经成功地在新构建的环境中运行了测试,该环境与生产环境相同,

结束语

由于docker和docker compose,我们能够对任何应用自动构建应用程序(dockerfile ),部署本地环境(docker-compose.yml ),构建测试镜像(dockerfile.test ) 。

特别是,使用docker-compose.test.yml文件进行测试的优点是:

自动化:工具执行docker-compose.test.yml的方式与被测试的应用程序无关
轻量:可以在单个主机上部署数百个外部服务,模拟复杂的(集成)测试环境
不可知:避免ci程序锁定,你的测试可以在任何支持docker的基础架构和任何操作系统上运行
不可变:测试通过本地机器传递你的ci工具

本教程展示了如何测试简单"hello world"应用程序的例子。



文章标签:comdocdocker整合测试envicontinuouscompose

正文

本文内容由IT人知识库(原文链接:http://www.itpeo.net/389619/4625352.html)本站为各位整理





使用matplotlib如何在python 3中绘制数据

介绍python非常适合处理数据,通常数据集将包括多个变量和多个实例,使得它难以理解所发生的事情,数据可视化是帮助你识别 ...

在Ubuntu 16.04上,如何使用Stunnel加密Redis的流量

介绍redis是一个开源key-value数据存储,使用了一个内存存储模型,有磁盘写入功能,它有事务,pub/sub消息 ...

如何在Ubuntu 16 04上用Spiped加密Redis的流量

介绍redis是一个开源key-value数据存储,使用了一个内存存储模型,有磁盘写入功能,redis有很多使用推荐的语 ...

我可以为新apt命令启用bash完成?

问题:自从 14.04年ubuntu中出现的新 apt 命令似乎是 apt-get 和 apt-cache 之间真正有用 ...

软件推荐如何从图像中提取文本?

问题:如何从图像中提取文本?我不是说扫描文件,但是花园的图像,比如当你在课堂上高清晰的画面。任何免费和开放的软件?我试过 ...

什么是Linux驱动器命名方案?

问题:在 windows 中,你有 c: 驱动器。 这是安装 windows的主驱动器。但是,linux使用了不同的命名 ...

bash如何从桌面快捷方式执行sh脚本?

问题:我正在尝试创建一个快捷方式来登录我的ssh服务器: ssh x.x.x.x 我做了以下的file: ssh_hom ...

在Ubuntu中,14.04 Having 问题安装和删除 MySQL

问题:在 ubuntu15.04. 中安装或者删除部分安装的mysql-server-5.6 时遇到麻烦我正在获取的错误 ...

命令行 为什么将目录移动到/dev/null 危险?

问题:当试图将 test_dir 目录移动到 /dev/null 时,我得到了消息mv: cannot overwrit ...

在我的服务器上,如何检查用户和访问SSH的访问权限?

问题:我有一些安全问题,我的一个服务器,一些ssh用户已经设置火灾,也许给出问题。我想:跟踪用户登录和注销跟踪这些ssh ...

在Ubuntu 16.04上,如何将gzip模块添加到Nginx

介绍网站加载的速度取决于浏览器必须下载的所有文件的大小。减少要传输的文件的大小可以使网站不仅加载速度更快,而且对于那些需 ...

在Ubuntu 16.04上,如何安装Discourse

一篇文章介绍安装discourse。前提条件在开始之前,我们需要先设置一些东西:ubuntu 16.04服务器至少有2g ...

如何在Debian8上安装Python3,并且建立本地编程环境

介绍通用编程语言python可以用于许多不同的编程项目,以英国喜剧团体monty python的名字为灵感,开发团队希望 ...

如何在CentOS 7上安装Mariadb

介绍mariadb是一个开源数据库管理系统,通常作为流行的lemp (linux,nginx,mysql/mariadb ...

如何在CentOS上安装MySQL 7

介绍mysql是一个开源数据库管理系统,通常作为流行的lemp (linux,nginx,mysql/mariadb,p ...

目录如何通过丛创建文件夹'seen'

问题:当我想将文件夹添加到丛时,我找不到它。我的电脑中有 2个 harddrives。 ubuntu安装在ssd上,另外 ...

如何保护我的SSH访问?

问题:我有一个 vps,我不知道如何管理它。 在 secure secure,我理解的第一件事是保护它,这个方向上我发现 ...

在多个硬盘上,脚本会发现&删除重复的文件

问题:我有 4个硬盘,想找出这四个硬盘上的文件是重复的。 它不仅应该在硬盘中检查,而且还要在所有其他的硬盘中。硬盘是大型 ...

rfedfre

在终端中,命令行 Ctrl+L

问题:我在终端中意外键入 ctrl + l,终端窗口跳了一个'屏幕'大小。 我查看了"编辑"-gt;"键盘快捷键"中的键 ...

multi内核为多核 CPU 优化?

问题:ubuntu是否使用多核 cpu ( 就像 windows 7所说的那样)?换句话说,of是优化的,使用户能够利用 ...