如何在Ubuntu 14.04上使用Docker和Docker Compose配置持续集成测试环境

介绍

持续集成(CI)指的是开发人员尽可能频繁地集成代码,并且在自动化构建将每个提交合并到共享存储库之前和之后都要进行测试的实践。

CI加快了您的开发过程,并最大限度地降低了生产中关键问题的风险,但设置并非易事; 自动构建在不同的环境中运行,其中运行时依赖项的安装和外部服务的配置可能与本地和开发环境中的不同。

Docker是一个容器化平台,旨在简化环境标准化问题,因此应用程序的部署也可以标准化。对于开发人员,Docker允许您通过在本地容器中运行应用程序组件来模拟本地计算机上的生产环境。使用Docker Compose可以轻松自动化这些容器,而与应用程序和底层操作系统无关。

同时,您也可以选择使用腾讯云容器服务,腾讯云容器服务基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务。

本教程使用Docker Compose演示CI工作流的自动化。

我们将创建一个Dockerized“Hello world”类型的Python应用程序和一个Bash测试脚本。Python应用程序需要运行两个容器:一个用于应用程序本身,一个用于存储的Redis容器,作为应用程序的依赖项。

然后,测试脚本将在其自己的容器中进行Docker化,整个测试环境转移到docker-compose.test.yml文件,这样我们就可以确保在新的统一应用程序环境中运行每个测试执行。

此方法显示了每次测试时如何为应用程序构建相同的,全新的测试环境,包括其依赖关系。

因此,我们将CI工作流的自动化独立于测试中的应用程序和底层基础架构。

要求

在开始之前,您将需要:

  • 一个Ubuntu 14.04服务器,没有服务器的同学可以在这里购买,不过我个人更推荐您使用免费的腾讯云开发者实验室进行试验,学会安装后在购买服务器
  • 具有sudo权限的非root用户。
  • 熟悉Docker和Docker Compose

第1步 - 安装Docker

如果您的服务器上尚未提供Docker,最简单的方法是下载并执行官方Docker安装脚本,该脚本会提示输入sudo密码:

wget -qO- https://get.docker.com/ | sh

为了更容易使用Docker,请使用以下命令将用户添加到docker组:

sudo usermod -aG docker $(whoami)

注销然后登录到您的服务器以激活用户的docker组。

第2步 - 安装Docker Compose

Docker Compose是一个开源工具,用于使用声明式方法定义和运行多容器应用程序。要安装Docker Compose,请执行以下命令:

sudo apt-get update
sudo apt-get -y install python-pip
sudo pip install docker-compose

执行以下命令验证docker-compose是否已正确安装:

docker-compose --version

你应该看到类似的东西:

docker-compose version 1.6.2, build 4d72027

这应该告诉您已安装的docker-compose的版本。

第3步 - 创建“Hello World”Python应用程序

在这一步中,我们将创建一个简单的Python应用程序,作为您可以使用此设置测试的应用程序类型的示例。

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

cd ~
mkdir hello_world
cd hello_world

使用nano编辑新文件app.py

nano 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 = "<h3>Hello World!</h3>" \
           "<b>Visits:</b> {visits}" \
           "<br/>"
    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中保留了此值。最后,Hello World消息以及访问次数以HTML格式返回。

我们的应用有两个依赖,FlaskRedis,你可以在头两行看到他们。我们必须先定义这些依赖项,然后才能执行应用程序。编辑新文件:

nano requirements.txt

添加内容:

Flask
Redis

第4步 - 对“Hello World”应用程序进行Docker化

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

nano 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.7Docker镜像构建的
  • 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(标准公共Web端口)访问
  • CMD ["python", "app.py"]:启动我们的应用程序的命令

Dockerfile文件包含构建“Hello World”应用程序主要组件所需的所有信息。

依赖性

现在我们来看一个更复杂的例子。我们的应用程序需要Redis作为外部服务。这种依赖类型在传统的Linux环境中每次都很难以相同的方式设置,但是使用Docker Compose,我们每次都可以以可重复的方式进行设置。

让我们创建一个docker-compose.yml文件来开始使用Docker Compose。

编辑新文件:

nano 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

第5步 - 部署“Hello World”应用程序

在此步骤中,我们将部署应用程序,最后它将可通过Internet访问。从部署工作流程的目的来看,您可以将其视为开发,登台或生产环境,因为您可以多次以相同的方式部署应用程序。

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 '{{ .NetworkSettings.IPAddress }}' helloworld_web_1)
echo $WEB_APP_IP

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

curl http://${WEB_APP_IP}:80

这应该返回如下信息:

<h3>Hello World!</h3><b>Visits:</b> 1<br/>

每次点击此端点时,访问次数都会增加。您还可以通过访问Ubuntu服务器的公共IP地址从浏览器访问“Hello World”应用程序。

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

设置自己的应用程序的关键是将您的应用程序放在自己的Docker容器中,并从自己的容器中运行每个依赖项。然后,您可以使用Docker Compose定义容器之间的关系。

第6步 - 创建测试脚本

现在我们将为Python应用程序创建一个测试脚本。这将是一个检查应用程序HTTP输出的简单脚本。该脚本是您可能希望作为持续集成部署过程的一部分运行的测试类型的示例。

编辑新文件:

nano test.sh

添加以下内容:

sleep 5
if curl web | grep -q '<b>Visits:</b> '; then
  echo "Tests passed!"
  exit 0
else
  echo "Tests failed!"
  exit 1
fi

test.sh测试我们的“Hello World”应用程序的基本Web连接。它使用cURL来检索访问次数并报告测试是否通过。

第7步 - 创建测试环境

为了测试我们的应用程序,我们需要部署一个测试环境。而且,我们希望确保它与我们在步骤5中创建的实时应用程序环境完全相同。

首先,我们需要通过创建一个新的Dockerfile文件来Docker化我们的测试脚本。编辑新文件:

nano Dockerfile.test

添加以下内容:

FROM ubuntu:trusty
​
RUN apt-get update && apt-get install -yq curl && apt-get clean
​
WORKDIR /app
​
ADD test.sh /app/test.sh
​
CMD ["bash", "test.sh"]

Dockerfile.test扩展官方ubuntu:trusty映像以安装curl 依赖项,添加tests.sh到映像文件系统,并指示CMD使用Bash执行测试脚本的命令。

一旦我们的测试进行了Docker化,它们就可以以可复制和不可知的方式执行。

下一步是将我们的测试容器链接到我们的“Hello World”应用程序。这是Docker Compose再次可以帮助到我们的地方。编辑新文件:

nano docker-compose.test.yml

添加以下内容:

sut:
  build: .
  dockerfile: Dockerfile.test
  links:
    - web
web:
  build: .
  dockerfile: Dockerfile
  links:
    - redis
redis:
  image: redis

Docker Compose文件的后半部分以与前一个文件相同的方式部署主web应用程序及其redis依赖项docker-compose.yml。这是指定webredis容器的文件的一部分。唯一的区别是web容器不再暴露端口80,因此在测试期间应用程序将无法通过公共Internet访问。因此,您可以看到我们正在构建应用程序及其依赖项,与在实时部署中完全相同。

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。

第8步 - 测试“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

执行以下命令检查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文件进行测试的优点是该测试过程:

  • 自动化:工具执行docker-compose.test.yml的方式独立于被测应用程序
  • 轻量级:可以在单个主机上部署数百个外部服务,模拟复杂(集成)测试环境
  • 不可知:避免CI提供程序锁定,并且您的测试可以在任何基础结构和支持Docker的任何操作系统上运行
  • 不可变:在本地计算机上传递的测试将传递给您的CI工具

本教程展示了如何测试简单的“Hello World”应用程序的示例。

现在是时候使用您自己的应用程序文件,Docker化您自己的应用程序测试脚本,并创建自己docker-compose.test.yml的应用程序以在新的和不可变的环境中测试您的应用程序。

更多Ubuntu教程请前往腾讯云+社区学习更多知识。


参考文献:《How To Configure a Continuous Integration Testing Environment with Docker and Docker Compose on Ubuntu 14.04》

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

编辑于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏宝哥的专栏

Docker系列学习文章 - docker基本使用(四)

| 导语通过上一篇文章的学习,我们把docker安装好了,那么安装好docker后该怎么使用呢?本篇文章通过一两个例子跟大家讲述下docker的基本使用。然后,...

1.5K21
来自专栏云计算教程系列

如何在Ubuntu 16.04上使用Docker和Docker Compose配置持续集成测试环境

持续集成(CI)是指开发人员尽可能经常集成代码并在每个提交在通过自动构建合并到共享存储库之前和之后进行测试的实践。

950

Docker – 清理磁盘占用

最近,我们开始对一些应用进行 docker 化,不得不说,我已经爱上 Docker 了!这是一个非常棒的工程,在 AWS EC2 上,它让我们的生活变得更加轻松...

4319
来自专栏崔庆才的专栏

Docker 入门教程

1673
来自专栏编程坑太多

跟我一起学docker(七)--网络

1726
来自专栏编程坑太多

『中级篇』构建自己的Docker镜像(16)

PS:为啥推荐用Dockerfile的方式,因为文件可以随便编辑,如果你用容器的话,你发给别人如何发麻烦不?还是单文件方便吧。

2036
来自专栏finleyMa

docker学习系列3 提交并分享自己的镜像

docker有个类似 github的平台,叫 https://hub.docker.com 可以 pull 官方或第三方提供的镜像,当然也可以发布自己的镜像供...

1735
来自专栏阮一峰的网络日志

Docker 入门教程

2013年发布至今, Docker 一直广受瞩目,被认为可能会改变软件行业。 但是,许多人并不清楚 Docker 到底是什么,要解决什么问题,好处又在哪里?本文...

3493
来自专栏应用案例

docker搭建私有仓库

序言 黄金指,一不小心就弄出一个故障。。。好可怕好可怕,我的小心脏。。。我的小心眼。。。 我这么信任你,你居然欺骗我。。。。****,这么大的坑,填不满啊。。。...

4507
来自专栏吴伟祥

Docker学习——Docker 三剑客(七) 顶

1591

扫码关注云+社区

领取腾讯云代金券