使用Docker为UI测试创建“可恢复的”MySQL数据库

时间:2017-01-31 19:22:12

标签: mysql selenium docker

我们有许多硒测试可以在我们的webapp的类似生产的设置上运行。问题是某些测试会影响数据库的应用程序。

是否可以拥有一个数据量或类似数据,我们可以在每次测试之前“克隆”并附加到容器上?

我们真的只需要一个可以在每次测试之前快速重新创建的MySQL数据库。偶尔我们会将模式迁移运行到该数据库。

还是有另一种更适合这种方法吗?

2 个答案:

答案 0 :(得分:4)

这是一个很好的问题,对于Docker来说可能是一个非常好的用例。有很多方法可以做到这一点,因为有办法备份MySQL数据库。我将在下面解释其中的几个。

但是,请注意,您正在进行权衡。这种方法的缺点是您的图像会变得非常大,并且需要更长的时间来

此外,您将遇到的一个问题是,大多数MySQL容器都使用/var/lib/mysql的卷(存储数据的位置)。因此,销毁容器不足以清除数据 - 您还需要清除卷。因此,当您执行docker rm清除旧容器时,请传递-v标记以删除卷。

选项1:将数据构建到容器中

可以将数据构建到容器中。这样做的好处是,您的容器在每次运行时都不会花费任何时间来设置数据。对于需要很长时间设置或拆除的大数据集,这种优势变得更加重要。换句话说,"重置"这个数据库几乎瞬时

在基本层面上,我们想要这样的东西:

ADD mysql_data.tar.gz /var/lib/mysql

这里棘手的部分是创建mysql_data.tar.gz文件(它只是/ var / lib / mysql的tar.gz备份)。我们可以这样做:

  1. 使用空数据库运行您的容器(我在这里使用mysql:latest)。请注意,我们正在使用指定的卷,并且我们正在转发端口3306。

    $ docker run -d --name my-mysql -v my-mysql-data:/var/lib/mysql -p 3306:3306 -e MYSQL_ROOT_PASSWORD=password mysql:latest

  2. 设置数据库。构建架构并插入所有测试数据。我们假设您有一个数据库备份backup.sql

    $ cat backup.sql | mysql -u root -ppassword -h 127.0.0.1

  3. 停止容器。我们不希望MySQL运行。数据将保留在指定的卷中。

    $ docker stop my-mysql

  4. 创建/var/lib/mysql的备份。请注意,我们使用相同的命名卷。

    $ docker run --rm -v my-mysql-data:/var/lib/mysql -v $(pwd):/backup mysql:latest tar czvf /backup/mysql_data.tar.gz /var/lib/mysql

  5. 现在您拥有来自/var/lib/mysql的gzip压缩数据,请在Dockerfile中使用它。请注意,由于我们对其进行压缩,我们需要在/复制它:

    ADD mysql_data.tar.gz /

    如果您还没有Dockerfile,请使用第一行创建一个

    FROM mysql:5.7

  6. (看工作)将Dockerfile构建到包含数据的容器映像中。然后运行容器。

    $ docker build -t my-data-image:latest .

    $ docker run -d -p 3306:3306 my-data-image:latest

  7. Docker会自动提取文件作为构建的一部分。你完成了。 Dockerfile中的容器将始终包含您的干净数据。到"重置"容器,只是停下来&删除/var/lib/mysql使用的卷。

    要编辑数据,请重复此过程,但在步骤1中替换现有容器。对于步骤2,请进行更改。您将生成一个新的mysql_data.tar.gz,如果您愿意,可以对其进行版本控制。重建Dockerfile后,如果愿意,可以在新标记下发布它。

    选项2:使用docker-entrypoint-initdb.d

    MySQL Docker镜像具有以下功能:当容器第一次运行时,它将在/docker-entrypoint-initdb.d中运行SQL文件。这样做的好处是它可以使用常规的MySQL转储来创建数据。缺点是数据库启动时较慢,因为它每次都会恢复所有数据。

    如果您在./backup.sql处拥有数据的mysqldump,则可以执行以下操作:

    $ docker run -e MYSQL_DATABASE=DB_NAME -e MYSQL_ROOT_PASSWORD=password -d --name my-mysql -v ./backup.sql:/docker-entrypoint-initdb.d/backup.sql -p 3306:3306 mysql:latest
    

    完成后,请移除容器及其卷。

    $ docker rm -v my-mysql
    

答案 1 :(得分:1)

我将使用golang应用程序服务器和mysql数据库的示例,因为这是我的主要用例:

version: '2'

services:
  app_test:
    image: golang:1.7-alpine
    volumes:
      - ./:/go/path/to/src
    links:
      - database_test
    environment:
      GOBIN: /go/bin
      APP_ENVIRONMENT: test
      APP_DB_HOST: database_test
      APP_DB_USERNAME: root
      APP_DB_DATABASE: app
    entrypoint:
      - /bin/sh
      - -c
      - /go/path/to/src/build_and_test.sh

  database_test:
    image: mysql:5.7
    volumes:
      - ./schema/test/auto_tests_structure.sql:/docker-entrypoint-initdb.d/a.sql
      - ./schema/test/auto_tests_data.sql:/docker-entrypoint-initdb.d/b.sql
    ports:
      - "3307:3306"
    environment:
      MYSQL_ALLOW_EMPTY_PASSWORD: "yes"
      MYSQL_DATABASE: app

重要的部分是将.sql文件挂载到mysql容器中,该容器自动填充选定的数据库(通过环境变量MYSQL_DATABASE - 这是在官方mysql图像的文档中),还有links项。

运行测试如下:

#!/bin/bash
PASSED_ARGS="${@}"

docker-compose -f docker-compose.test.yml stop database_test
docker-compose -f docker-compose.test.yml rm -vf database_test
docker-compose -f docker-compose.test.yml run -e PASSED_ARGS="${PASSED_ARGS}" app_test

重点是前两个docker-compose命令,它们停止并销毁具有相关卷的database-test容器。然后运行容器,重新创建它。

至于速度,我对它运行Docker for Mac不满意。但我团队中的一个人正在运行Linux,而且对他来说要快得多。