如何在Travis构建Docker容器时运行Symfony5项目的PHPUnit测试并配置测试数据库
解决方案:在Travis CI中为容器化Symfony项目配置MariaDB测试数据库
你遇到的核心问题是Docker容器内的PHP应用无法访问Travis环境中的测试数据库——默认情况下,容器和主机/其他容器不在同一网络环境,导致PHPUnit、Doctrine无法连接到数据库。下面提供两种可行的方案,你可以根据项目需求选择:
方案一:利用Travis内置MariaDB服务
这种方法直接使用Travis提供的MariaDB服务,无需额外维护Docker Compose配置,只需让PHP容器能访问主机上的数据库即可。
1. 配置.travis.yml
language: minimal services: - docker - mariadb # 启动Travis内置的MariaDB服务 env: global: - IMAGE=your-php-image-name # 替换为你的PHP镜像名 - TEST_DB_HOST=host.docker.internal # 容器内访问主机的别名 - TEST_DB_NAME=symfony_test # 测试数据库名 - TEST_DB_USER=root - TEST_DB_PASSWORD=travis # 可根据Travis MariaDB默认配置调整 before_install: # 构建你的PHP镜像(如果Travis上没有预构建的镜像) - docker build -t $IMAGE:$TRAVIS_COMMIT . before_script: # 在Travis主机上创建测试数据库(如果需要) - mysql -h 127.0.0.1 -u $TEST_DB_USER -p$TEST_DB_PASSWORD -e "CREATE DATABASE IF NOT EXISTS $TEST_DB_NAME;" script: # 运行无需数据库的代码检查(原有命令可直接复用) - docker run $IMAGE:$TRAVIS_COMMIT /bin/sh -c "bin/phpcs" - docker run $IMAGE:$TRAVIS_COMMIT /bin/sh -c "bin/phpstan analyze -c phpstan.neon.dist --memory-limit=1G" # 运行数据库相关命令:添加主机映射+传递数据库连接参数 - docker run --add-host=host.docker.internal:host-gateway \ -e DATABASE_URL="mysql://$TEST_DB_USER:$TEST_DB_PASSWORD@$TEST_DB_HOST:3306/$TEST_DB_NAME?serverVersion=mariadb-10.5" \ $IMAGE:$TRAVIS_COMMIT /bin/sh -c "bin/console do:mi:mi -n" - docker run --add-host=host.docker.internal:host-gateway \ -e DATABASE_URL="mysql://$TEST_DB_USER:$TEST_DB_PASSWORD@$TEST_DB_HOST:3306/$TEST_DB_NAME?serverVersion=mariadb-10.5" \ $IMAGE:$TRAVIS_COMMIT /bin/sh -c "bin/console do:fi:lo -n" - docker run --add-host=host.docker.internal:host-gateway \ -e DATABASE_URL="mysql://$TEST_DB_USER:$TEST_DB_PASSWORD@$TEST_DB_HOST:3306/$TEST_DB_NAME?serverVersion=mariadb-10.5" \ $IMAGE:$TRAVIS_COMMIT /bin/sh -c "bin/phpunit --configuration=phpunit.xml.dist"
关键说明
--add-host=host.docker.internal:host-gateway:让容器能解析host.docker.internal到Travis主机的IP,这样容器内的Symfony就能通过这个地址访问主机上的MariaDB。DATABASE_URL环境变量:直接覆盖Symfony的数据库配置,确保Doctrine和PHPUnit使用测试数据库的连接参数。- Travis内置MariaDB默认配置:通常root用户无密码,你可以根据实际情况通过
env设置MYSQL_ROOT_PASSWORD调整。
方案二:使用Docker Compose启动完整测试栈
这种方法和本地开发环境完全一致,通过Docker Compose同时启动PHP容器和测试MariaDB容器,两者自动处于同一Docker网络,直接通过服务名访问数据库。
1. 创建测试专用docker-compose.test.yml
version: '3.8' services: php: build: . # 基于当前目录的Dockerfile构建PHP镜像 environment: # 直接用服务名`test_db`访问数据库,无需IP DATABASE_URL: mysql://root:root@test_db:3306/symfony_test?serverVersion=mariadb-10.5 depends_on: - test_db test_db: image: mariadb:10.5 # 选择和业务数据库一致的MariaDB版本 environment: MYSQL_ROOT_PASSWORD: root MYSQL_DATABASE: symfony_test # 自动创建测试数据库 ports: - "3306:3306"
2. 配置.travis.yml
language: minimal services: - docker env: global: - COMPOSE_FILE=docker-compose.test.yml # 指定测试用的Compose文件 before_install: # 在Travis中安装Docker Compose - sudo apt-get update - sudo apt-get install -y docker-compose before_script: # 启动测试容器栈 - docker-compose up -d # 等待数据库启动就绪(避免因数据库未启动导致迁移失败) - until docker-compose exec -T test_db mysql -u root -proot -e "SELECT 1"; do sleep 1; done script: # 运行代码检查 - docker-compose exec -T php bin/phpcs - docker-compose exec -T php bin/phpstan analyze -c phpstan.neon.dist --memory-limit=1G # 运行数据库迁移、数据填充和单元测试 - docker-compose exec -T php bin/console do:mi:mi -n - docker-compose exec -T php bin/console do:fi:lo -n - docker-compose exec -T php bin/phpunit --configuration=phpunit.xml.dist after_script: # 停止并清理容器 - docker-compose down
关键说明
docker-compose exec -T:以非交互式方式在PHP容器内执行命令,适配Travis的CI环境。- 等待数据库就绪:通过循环检查数据库连接,确保数据库完全启动后再执行迁移和测试,避免报错。
- 环境一致性:和本地开发使用相同的容器配置,减少环境差异带来的问题。
额外注意事项
- PHPUnit配置:确保
phpunit.xml.dist中使用env(DATABASE_URL)来获取数据库连接参数,这样才能通过环境变量覆盖配置:
<php> <env name="DATABASE_URL" value="mysql://root:root@localhost:3306/symfony_test?serverVersion=mariadb-10.5" /> </php>
- 数据库版本匹配:测试数据库的MariaDB版本尽量和业务数据库保持一致,避免因版本差异导致的SQL兼容性问题。
- 镜像缓存:如果Travis构建镜像耗时较长,可以配置Docker镜像缓存(比如使用Travis的cache功能或推送镜像到Docker Hub),加快构建速度。
内容的提问来源于stack exchange,提问作者Calamity Jane
相关产品推荐
相关产品推荐

