我们有许多硒测试可以在我们的webapp的类似生产的设置上运行。问题是某些测试会影响数据库的应用程序。
是否可以拥有一个数据量或类似数据,我们可以在每次测试之前“克隆”并附加到容器上?
我们真的只需要一个可以在每次测试之前快速重新创建的MySQL数据库。偶尔我们会将模式迁移运行到该数据库。
还是有另一种更适合这种方法吗?
答案 0 :(得分:4)
这是一个很好的问题,对于Docker来说可能是一个非常好的用例。有很多方法可以做到这一点,因为有办法备份MySQL数据库。我将在下面解释其中的几个。
但是,请注意,您正在进行权衡。这种方法的缺点是您的图像会变得非常大,并且需要更长的时间来拉。
此外,您将遇到的一个问题是,大多数MySQL容器都使用/var/lib/mysql
的卷(存储数据的位置)。因此,销毁容器不足以清除数据 - 您还需要清除卷。因此,当您执行docker rm
清除旧容器时,请传递-v
标记以删除卷。
可以将数据构建到容器中。这样做的好处是,您的容器在每次运行时都不会花费任何时间来设置数据。对于需要很长时间设置或拆除的大数据集,这种优势变得更加重要。换句话说,"重置"这个数据库几乎瞬时。
在基本层面上,我们想要这样的东西:
ADD mysql_data.tar.gz /var/lib/mysql
这里棘手的部分是创建mysql_data.tar.gz
文件(它只是/ var / lib / mysql的tar.gz备份)。我们可以这样做:
使用空数据库运行您的容器(我在这里使用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
设置数据库。构建架构并插入所有测试数据。我们假设您有一个数据库备份backup.sql
。
$ cat backup.sql | mysql -u root -ppassword -h 127.0.0.1
停止容器。我们不希望MySQL运行。数据将保留在指定的卷中。
$ docker stop my-mysql
创建/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
现在您拥有来自/var/lib/mysql
的gzip压缩数据,请在Dockerfile中使用它。请注意,由于我们对其进行压缩,我们需要在/
复制它:
ADD mysql_data.tar.gz /
如果您还没有Dockerfile,请使用第一行创建一个
FROM mysql:5.7
(看工作)将Dockerfile构建到包含数据的容器映像中。然后运行容器。
$ docker build -t my-data-image:latest .
$ docker run -d -p 3306:3306 my-data-image:latest
Docker会自动提取文件作为构建的一部分。你完成了。 Dockerfile中的容器将始终包含您的干净数据。到"重置"容器,只是停下来&删除/var/lib/mysql
使用的卷。
要编辑数据,请重复此过程,但在步骤1中替换现有容器。对于步骤2,请进行更改。您将生成一个新的mysql_data.tar.gz,如果您愿意,可以对其进行版本控制。重建Dockerfile后,如果愿意,可以在新标记下发布它。
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,而且对他来说要快得多。