启动时使用静态数据进行 Docker 集成测试
Posted
技术标签:
【中文标题】启动时使用静态数据进行 Docker 集成测试【英文标题】:Docker integration test with static data at launch 【发布时间】:2017-03-07 13:57:05 【问题描述】:我已经为这个问题苦苦挣扎了一段时间。我想使用一组特定的数据进行性能测试。
为此,我使用了 Docker-compose,并导出了几个 .sql
文件。
当我第一次使用docker-compose build
和docker-compose up
构建和运行容器时,数据集很好。然后我运行我的测试(也插入)数据。运行测试后,我想再次执行它,所以我使用docker-compose up
重新启动容器。但是这一次,由于某种我不明白的原因,上次插入的数据(通过我的测试)仍然存在。我现在有不同的行为。
目前我有以下 Dockerfile:
FROM mysql:5.7
ENV MYSQL_DATABASE dev_munisense1\
MYSQL_ROOT_PASSWORD pass
EXPOSE 3306
ADD docker/data/ /docker-entrypoint-initdb.d/
因为我读到 mysql Docker 映像运行 /docker-entrypoint-initdb.d/
中的所有内容。第一次正常运行。
我也尝试过这些帖子的建议:
How do i migrate mysql data directory in docker container?
http://txt.fliglio.com/2013/11/creating-a-mysql-docker-container/
How to create populated MySQL Docker Image on build time
How to make a docker image with a populated database for automated tests?
还有一些相同的其他帖子。
它们目前似乎都不起作用。
如何确保每次启动容器时数据集都完全相同?无需每次都重建图像(由于数据集很大,这需要很长时间)。
提前致谢
编辑:
我还尝试使用不同的参数运行容器,例如:
docker-compose up --force-recreate --build mysql
但这没有成功。容器被重建并重新启动,但数据库仍然受到我的测试的影响。目前解决我的问题的唯一方法是删除整个容器和图像。
【问题讨论】:
这个答案可能对你有用:***.com/a/27572665/1856086 @StasMakarov 这与我想要的完全相反。我不想持久化数据库。我只是想从某个点开始一个容器,对它做一些事情,然后把它全部扔掉,这样我就可以从同一个起点重新开始...... 你可以尝试使用official Dockerfile创建你自己的mysql镜像,但没有VOLUME /var/lib/mysql
这一行(目前是#68)。这样它不应该在删除容器后保存任何数据。它可能远不是这个问题的最佳解决方案,但它可能会奏效。
您也可以尝试使用docker volume rm $volume_hash
删除包含mysql 数据的卷。或者使用docker volume rm $(docker volume ls -q)
删除所有卷。最后一个命令可以删除有用的东西。
@StasMakarov 当使用没有该行#68的确切Dockerfile时,我如何填充图像,以便每次启动容器时都预先填充?我不介意拥有更大的图像,只要创建的容器很短
【参考方案1】:
我通过执行以下操作设法解决了这个问题(使用 mysql 映像):
更改 sql 存储的挂载点(这实际上是导致问题的原因)我使用了此处建议的解决方案:How to create populated MySQL Docker Image on build time,但我通过运行 sed 命令做到了:RUN sed -i 's|/var/lib/mysql|/var/lib/mysql2|g' /etc/mysql/my.cnf
将我的脚本添加到容器内的文件夹中
运行使用守护进程插入数据的 import.sh 脚本(使用 wait-for-it.sh 脚本) 删除 sql 脚本 像普通一样暴露端口docker文件长这样(变量用来选择不同的SQL文件,我想要多个版本的镜像):
FROM mysql:5.5.54
ADD https://raw.githubusercontent.com/vishnubob/wait-for-it/master/wait-for-it.sh /utils/wait-for-it.sh
COPY docker/import.sh /usr/local/bin/
RUN sed -i 's|/var/lib/mysql|/var/lib/mysql2|g' /etc/mysql/my.cnf
ARG MYSQL_DATABASE
ARG MYSQL_USER
ARG MYSQL_PASSWORD
ARG MYSQL_ROOT_PASSWORD
ARG MYSQL_ALLOW_EMPTY_PASSWORD
ARG DEVICE_INFORMATION
ARG LAST_NODE_STATUS
ARG V_NODE
ARG NETWORKSTATUS_EVENTS
ENV MYSQL_DATABASE=$MYSQL_DATABASE \
MYSQL_USER=$MYSQL_USER \
MYSQL_PASSWORD=$MYSQL_PASSWORD \
MYSQL_ROOT_PASSWORD=$MYSQL_ROOT_PASSWORD \
DEVICE_INFORMATION=$DEVICE_INFORMATION \
LAST_NODE_STATUS=$LAST_NODE_STATUS \
V_NODE=$V_NODE \
MYSQL_ALLOW_EMPTY_PASSWORD=$MYSQL_ALLOW_EMPTY_PASSWORD
#Set up tables
COPY docker/data/$DEVICE_INFORMATION.sql /usr/local/bin/device_information.sql
COPY docker/data/$NETWORKSTATUS_EVENTS.sql /usr/local/bin/networkstatus_events.sql
COPY docker/data/$LAST_NODE_STATUS.sql /usr/local/bin/last_node_status.sql
COPY docker/data/$V_NODE.sql /usr/local/bin/v_node.sql
RUN chmod 777 /usr/local/bin/import.sh && chmod 777 /utils/wait-for-it.sh && \
/bin/bash /entrypoint.sh mysqld --user='root' & /bin/bash /utils/wait-for-it.sh -t 0 localhost:3306 -- /usr/local/bin/import.sh; exit
RUN rm -f /usr/local/bin/*.sql
ENTRYPOINT ["docker-entrypoint.sh"]
EXPOSE 3306
CMD ["mysqld"]
脚本如下所示:
#!/bin/bash
echo "Going to insert the device information"
mysql --user=$MYSQL_USER --password=$MYSQL_PASSWORD --database=$MYSQL_DATABASE < /usr/local/bin/device_information.sql
echo "Going to insert the last_node_status"
mysql --user=$MYSQL_USER --password=$MYSQL_PASSWORD --database=$MYSQL_DATABASE < /usr/local/bin/last_node_status.sql
echo "Going to insert the v_node"
mysql --user=$MYSQL_USER --password=$MYSQL_PASSWORD --database=$MYSQL_DATABASE < /usr/local/bin/v_node.sql
echo "Going to insert the networkstatus_events"
mysql --user=$MYSQL_USER --password=$MYSQL_PASSWORD --database=$MYSQL_DATABASE < /usr/local/bin/networkstatus_events.sql
echo "Database now has the following tables"
mysql --user=$MYSQL_USER --password=$MYSQL_PASSWORD --database=$MYSQL_DATABASE --execute="SHOW TABLES;"
所以现在我要做的就是开始我的性能测试了
#!/usr/bin/env bash
echo "Shutting down previous containers"
docker-compose -f docker-compose.yml down
docker-compose -f docker-compose-test-10k-half.yml down
docker-compose -f docker-compose-test-100k-half.yml down
docker-compose -f docker-compose-test-500k-half.yml down
docker-compose -f docker-compose-test-1m-half.yml down
echo "Launching rabbitmq container"
docker-compose up -d rabbitmq & sh wait-for-it.sh -t 0 -h localhost -p 5672 -- sleep 5;
echo "Going to execute 10k test"
docker-compose -f docker-compose-test-10k-half.yml up -d mysql_10k & sh wait-for-it.sh -t 0 -h localhost -p 3306 -- sleep 5 && ./networkstatus-event-service --env=performance-test --run-once=true;
docker-compose -f docker-compose-test-10k-half.yml stop mysql_10k
更多这些行(略有不同,导致不同的容器名称)
【讨论】:
【参考方案2】:在您的测试之后运行docker-compose down
将破坏与您的docker-compose.yml
相关的所有内容
Docker Compose 是一个容器生命周期管理器,默认情况下它会尝试在多次运行中保留所有内容。正如Stas Makarov 提到的,mysql
映像中定义了一个VOLUME
,它将数据保存在容器之外。
【讨论】:
这个“down”命令似乎确实破坏了容器,但现在我每次运行docker-compose up
它都必须重新插入所有测试数据。
@antonsteenvoorden 您可以将初始数据添加到图像中,而不是在启动后添加,以便下一次运行包含一些初始状态。
我通过执行以下操作设法解决了这个问题(使用 mysql 映像): 1. 更改 sql 存储的挂载点(这实际上是导致问题的原因)我使用了这里建议的解决方案: ***.com/questions/32482780/… 但我是通过运行 sed 命令完成的:RUN sed -i 's|/var/lib/mysql|/var/lib/mysql2|g' /etc/mysql/my.cnf
2. 将我的脚本添加到容器内的文件夹 3. 运行 import.sh 脚本,使用守护程序插入数据 4. 删除我刚刚制作的多个 sql 脚本具有不同数据的图像以上是关于启动时使用静态数据进行 Docker 集成测试的主要内容,如果未能解决你的问题,请参考以下文章
Spring启动在集成测试中使用PowerMock模拟静态方法