Dante

通过利用镜像层的强大功能,针对 Docker 镜像构建测试。(Build tests against Docker images by harnessing the power of layers.)

  • Owner: retrohacker/dante
  • Platform: Linux, Windows, BSD
  • License::
  • Category::
  • Topic:
  • Like:
    0
      Compare:

Github stars Tracking Chart

此项目不再主动维护

Dante

通过利用镜像层的力量构建对 Docker 镜像的测试。

当我走过人生路的一半时, 我发现自己在一个阴影森林里, 因为我失去了不偏离的道路。

Dante 是一款用于构建和运行 Dockerfiles 验证测试的工具。通过 Dante,您可以确保您的 Dockerfiles 为您的应用程序创建安全稳定的环境。

Dante 是 CI 服务器和本地开发的理想工具。我们不建议在生产环境中使用此工具,其目的是在生产准备完成、达到生产之前验证镜像。

用法

设置

准备使用 Dante 只需3步。

  1. 当然,您需要将一个或多个环境定义为 Dockerfile s
  2. 使用 Dockerfile s 定义在您的环境中运行的测试
  3. 定义 inventory.yml 文件,它描述了您的项目目录的结构

命令

测试

示例: dante test

构建所有镜像,然后在其上运行测试。

Push

示例: dante push

将包含 inventoy.yml 中定义的标签的主机上的任何镜像推送到 Docker 注册表(不包括测试)。

标志

所有命令都支持这组标志:

  • -j COUNT 并行运行COUNT作业。
  • -r COUNT 重试失败的作业COUNT次。

inventory.yml File

该工具由名为 inventory.yml 的项目目录下的单个 yaml 文件驱动。

nventory.yml 可能如下所示:

images:
  - name: "wblankenship/dockeri.co:server"
    path: "./dockerico/server"
    test: ["./dockerico/tests/http","./dockerico/tests/badges"]
    alias: ["wblankenship/dockeri.co:latest"]
  - name: "wblankenship/dockeri.co:database"
    path: "./dockerico/database"
    test: "./dockerico/tests/db"

相应的项目目录如下所示:

.
├── dockerico
│   ├── db
│   │   └── Dockerfile
│   ├── server
│   │   └── Dockerfile
│   └── tests
│       ├── badges
│       │   └── Dockerfile
│       ├── db
│       │   ├── dependency.tar
│       │   └── Dockerfile
│       └── http
│           └── Dockerfile
└── inventory.yml

测试

使用 test 键在 inventory.yml 文件中定义测试,它可以接受单个字符串或字符串数组作为值。

测试仅仅是 Dockerfile ,看起来像这样:

WORKDIR /usr/src/app
ADD dependency.tar /
RUN tar -xvf dependency.tar
RUN this_will_fail
RUN echo "SUCCESS!"

当 Dante 运行时,它将在测试 Dockerfile 生成的镜像的顶部构建测试 Dockerfile 中定义的每个镜像层。如果任何命令不成功,Dante会将镜像标记为未通过测试。在此示例中, RUN this_will_fail 行会导致整个测试失败。

使用 ADD dependency.tar /. 演示的代码,通过 Dockerfile 包含依赖项是安全的。在构建镜像时,Dante 会将整个工作目录作为上下文上传到 docker 守护进程。

您可能已经注意到 Dockerfile 中缺少 FROM 命令。这是有意的,因为 Dante 将从它测试的镜像中构建这个 Dockerfile。如果您对这种工作方式感兴趣,或者为什么我们这样做,请参阅我们的哲学部分。

别名

别名用于用多个标签标记单个镜像。与重建镜像相比,这种风险可能会为应该使用别名的镜像创建不同的哈希值,而 alias 键将使用 docker 标记命令创建适当的别名键值数组中的每个值。

输出

Dante生成两个不同的输出

  1. Markdown
  2. Docker Images

运行时,该工具以 markdown 的形式将其状态输出到 stdout,以便与 GitHub 和Docker Registry 轻松集成。

它还生成标记有来自 inventory.yml 文件的 name 值的 docker 镜像,并且成功的测试镜像使用相同的标记构建,但是在末尾添加了 -test#,其中#是当前测试的数字。

例如,如果您有 inventory.yml 文件:

images:
  - name: "wblankenship/dockeri.co:server"
    path: "./dockerico/server"
    test: ["./dockerico/tests/http","./dockerico/tests/badges"]

您将最终得到以下 Docker 镜像(假设镜像构建和测试成功运行)

  • dockeri.co:server :基本镜像
  • dockeri.co:server-test1 :从 http 目录构建的镜像
  • dockeri.co:server-test2 :从 badge 目录构建的镜像

哲学

我们坚信工具应该自然地适应现有的生态系统。这种信念驱动着 Dante 开发的方方面面。我们充分利用 Docker 生态系统中现有的工具和格式,以产生一种不引人注目的方法来测试 Dockerfiles 和 docker 映像。

测试概念

我们的测试 docker 镜像的方法完全由镜像层驱动。现在快速了解我们的意思。

因此,假设你从一个 Dockerfile 构建一个镜像,它会产生如上图中的单个镜像层。 Dockerfile 中的每个命令都会生成一个镜像层。 FROM 命令是特殊的,它将在另一个镜像的镜像层的顶部构建 Dockerfile 镜像层。

这允许我们从 Dockerfile 构建镜像,然后将测试作为镜像顶层进行构建。假设测试中的所有命令都可以成功地在镜像上生成镜像层,那么您有足够的保证镜像内部的环境足够稳定,可以运行测试中表示的任务。然后,我们可以丢弃测试镜像层并发布基本镜像,现在我们知道它已处于稳定状态!

技术

在组合此工具时,我们仔细考虑了一些设计决策。主要是:

  • 测试为 Dockerfiles
  • 清单文件为 yaml
  • 输出为 Markdown

测试为 Dockerfiles

首先,我们希望所有的测试都是作为我们测试镜像的顶层进行构建的。这确保我们不仅捕获我们正在测试的环境,还捕获我们在该环境中运行的测试。假设您正在归档由 Dante 生成的镜像,那么当生产中发现应用程序应该已被捕获的错误时,您可以在任何镜像层重现测试环境,以检查测试通过的原因。

测试作为 Dockerfiles 也意味着用户不需要学习新工具来测试他们的镜像。他们只是简单地创建一个 Dockerfile,用于对他们正在测试的 Dockerfile 产生的环境进行断言。对于已经建立测试框架的用户,这些框架可以很容易地构建到 Dockerfile 中,并作为镜像本身的顶层运行。

清单文件为 yaml

我们在 docker-compose.yml 规范之后建立了库存文件。这种格式已经在社区中建立,并减少了生成文件的认知开销。

输出为 Markdown

将 Markdown 写入 stdout 的动机是为了方便地使用 Docker Registry 和 GitHub 上的结果。接下来,我们可能会包括改变这种行为的标志。

Overview

Name With Ownerretrohacker/dante
Primary LanguageGo
Program languageGo (Language Count: 3)
PlatformLinux, Windows, BSD
License:
Release Count5
Last Release Name2.2.0 (Posted on )
First Release Namev1.0.0 (Posted on )
Created At2015-07-23 17:12:42
Pushed At2019-01-31 19:01:54
Last Commit At2019-01-31 11:01:53
Stargazers Count44
Watchers Count6
Fork Count4
Commits Count27
Has Issues Enabled
Issues Count4
Issue Open Count4
Pull Requests Count2
Pull Requests Open Count0
Pull Requests Close Count0
Has Wiki Enabled
Is Archived
Is Fork
Is Locked
Is Mirror
Is Private

This project is no longer actively maintained ?

Dante

Build tests against Docker images by harnessing the power of layers

dante

When I had journeyed half of our life's way,
I found myself within a shadowed forest,
for I had lost the path that does not stray.

Dante is a tool for building and running validation tests against Dockerfiles. With Dante you can ensure your Dockerfiles produce a safe and stable environment for your applications.

Dante is the perfect tool for CI servers and local development. We do not recommend using this tool in a production environment, its purpose is to verify images are production ready before they reach production.

Usage

Setup

Getting ready to use Dante is a 3 step process.

  1. Naturally, you need to have one or more environments defined as Dockerfiles
  2. Define tests that run in your environment using Dockerfiles
  3. Define an inventory.yml file, which describes the structure of your project directory

Commands

test

Example: dante test

Builds all the images and subsequently runs tests on top of them.

push

Example: dante push

Pushes any images that exist on the host machine containing the tags defined in inventoy.yml to the Docker registry (not including tests).

Flags

All commands support this set of flags:

  • -j COUNT runs COUNT jobs in parallel.
  • -r COUNT retry failed jobs COUNT times.

inventory.yml File

The tool is driven by a single yaml file in the base of your project directory named inventory.yml.

An inventory.yml may look like this:

images:
  - name: "wblankenship/dockeri.co:server"
    path: "./dockerico/server"
    test: ["./dockerico/tests/http","./dockerico/tests/badges"]
    alias: ["wblankenship/dockeri.co:latest"]
  - name: "wblankenship/dockeri.co:database"
    path: "./dockerico/database"
    test: "./dockerico/tests/db"

Where the corresponding project directory would look like this:

.
├── dockerico
│   ├── db
│   │   └── Dockerfile
│   ├── server
│   │   └── Dockerfile
│   └── tests
│       ├── badges
│       │   └── Dockerfile
│       ├── db
│       │   ├── dependency.tar
│       │   └── Dockerfile
│       └── http
│           └── Dockerfile
└── inventory.yml

Tests

Tests are defined in the inventory.yml file using the test key, which can accept either a single string or an array of strings as a value.

A test is simply Dockerfile and looks like this:

WORKDIR /usr/src/app
ADD dependency.tar /
RUN tar -xvf dependency.tar
RUN this_will_fail
RUN echo "SUCCESS!"

When Dante runs, it will build each layer defined in the test Dockerfile on top of the image produced by the Dockerfile it is testing. If any command is unsuccesful, Dante will mark the image as having failed the test. In this example case the line RUN this_will_fail will result in the entire test failing.

It is safe to include dependencies in the directory with the Dockerfile as demonstrated with the line ADD dependency.tar /. Dante will upload the entire working directory as context to the docker daemon when building the image.

You may have noticed the missing FROM command in the Dockerfile. This is intentional as Dante will build this Dockerfile from the image it is a test for. If you are interested in how this works or why we do it this way, refer to our Philosophy section.

Aliases

Aliases are used to label a single image with mutliple tags. As opposed to rebuilding an image, which risks creating non-identical hashes for images that should be aliased, the alias key will use the docker tag command to create a proper alias for each value in the key's array.

Output

Dante generates two different outputs

  1. Markdown
  2. Docker Images

When running, the tool outputs its status to stdout in the form of markdown for easy integration with GitHub and the Docker Registry.

It also generates docker images tagged with the name value from the inventory.yml file, and successful test images are built with the same tag but with -test# append to the end, where # is the number of the current test

For example, if you have an inventory.yml file:

images:
  - name: "wblankenship/dockeri.co:server"
    path: "./dockerico/server"
    test: ["./dockerico/tests/http","./dockerico/tests/badges"]

You will end up with the following Docker images (assuming the image builds and the tests run succesfully)

  • dockeri.co:server: the base image
  • dockeri.co:server-test1: the image built from the http directory
  • dockeri.co:server-test2: the image built from the badges directory

Philosophy

We strongly believe that tooling should fit naturally into the existing ecosystem. This belief has driven every aspect of developing Dante. We have taken full advantage of existing tools and formats that exist within the docker ecosystem to produce an unobtrusive approach to testing Dockerfiles and docker images.

Testing Concept

Our approach to testing docker images is entirely driven by image layers. Now for a quick crash course into what we mean by that.

docker layers

So lets say you build an image from a Dockerfile, it produces individual layers like in the diagram above. Each command in a Dockerfile produces a layer. The FROM command is special, it will build your Dockerfile layers ontop of the layers from another image.

docker test

What this allows us to do is build your image from a Dockerfile, then build the tests as layers on top of your image. Assuming all of the commands in the tests can succesfully generate layers on top of your image, you have a guarentee that the environment inside of your image is stable enough to run the tasks represented in your tests. We can then throw away the test layers and ship the base image now that we know it is in a stable state!

Technologies

There were a few design decisions we took under careful consideration when putting together this tool. Primarily:

  • Tests as Dockerfiles
  • Inventory file as yaml
  • Output as Markdown

Tests as Dockerfiles

First and foremost, we wanted all tests to be built as layers ontop of the image we are testing. This ensures that we capture not only the environment we are testing, but the tests that we run inside of that environment. Assuming you are archiving the images generated by Dante, when a bug is found in production that the tests should have caught, you can reproduce the testing environment at any layer to inspect why exactly the test passed.

Tests as Dockerfiles also means that users do not need to learn new tools in order to test their images. They simply create a Dockerfile that makes assertions about the environment produced by the Dockerfile they are testing. For users with already established testing frameworks, these frameworks can easily be built into the Dockerfile and run as a layer ontop of the image itself.

Inventory file as yaml

We modeled our inventory file after the docker-compose.yml specification. This format is already established in the community, and reduces the congnitive overhead of producing the file.

Output as Markdown

The motivation for writting Markdown to stdout is to allow easy consumption of the results on both the Docker Registry and GitHub. Moving forward, we may include flags that change this behaviour.

Changlog

v2.1.0

  • alias key now supported in inventory.yml
  • test now tags aliases after successful build
  • push now pushes both images and their aliases

v2.0.0

  • Subcommands Added (test and push)
  • Dante can now push to repositories from an inventory.yml file
  • Implemented a -r flag for retrying failed tests, builds, and pushes.

v1.1.0

  • Added j flag for parallel builds
To the top