GitLab CI/CD中Playwright容器无法访问Web服务容器的问题
GitLab CI/CD中Playwright容器无法访问Docker容器内Web服务的问题解决
问题场景与现象
在GitLab CI/CD流水线中,尝试使用Playwright容器测试运行在Docker容器中的Web服务,当前gitlab-ci.yml配置如下:
stages: - test services: - docker:27-dind variables: DOCKER_HOST: tcp://docker:2375/ DOCKER_DRIVER: overlay2 DOCKER_TLS_CERTDIR: "" container-tests: stage: test when: always image: docker:27 script: - docker run -d --name app -p 8000:80 image-name - curl http://docker:8000 # 这可以正常访问! - > docker run --name tests -v "$(pwd)/tests:/tests" mcr.microsoft.com/playwright/python:v1.50.0-noble /bin/sh -c " pip install pytest-base-url pytest-playwright playwright && playwright install && pytest /tests --base-url='http://docker:8000'" # 这无法正常工作!
现象:Web服务容器启动后,Job容器内用curl http://docker:8000可正常访问,但Playwright容器执行测试时,报错无法解析主机名:
except Exception as error: > raise rewrite_error(error, f"{parsed_st['apiName']}: {error}") from None E playwright._impl._errors.Error: Page.goto: net::ERR_NAME_NOT_RESOLVED at http://docker:8000/ E Call log: E - navigating to "http://docker:8000/", waiting until "load"
核心问题分析
当前方案存在根本性错误:app容器与tests容器的网络环境不互通。
- Job容器能访问
http://docker:8000,是因为docker是GitLab CI服务的名称,Job容器的hosts文件已配置该名称指向dind服务的IP,且app容器把端口映射到了dind服务主机。 - 但
tests容器运行在dind服务的Docker环境中,其内部无法解析docker这个GitLab CI服务名称;同时两个容器默认处于同一bridge网络但未利用容器名通信,导致访问失败。
修正后的配置方案
1. 创建自定义Docker网络
先创建专属测试网络,确保容器间可通过名称直接通信:
docker network create test-network
2. 启动Web服务容器并加入自定义网络
修改app容器启动命令,加入自定义网络,保留端口映射以便Job容器验证:
docker run -d --name app --network test-network -p 8000:80 image-name
3. 启动Playwright容器并加入同一网络
修改tests容器启动命令,加入自定义网络,并直接用app容器名访问内部端口(无需依赖端口映射):
docker run --name tests --network test-network -v "$(pwd)/tests:/tests" \ mcr.microsoft.com/playwright/python:v1.50.0-noble /bin/sh -c " pip install pytest-base-url pytest-playwright playwright && playwright install && pytest /tests --base-url='http://app:80'"
完整修正后的gitlab-ci.yml
stages: - test services: - docker:27-dind variables: DOCKER_HOST: tcp://docker:2375/ DOCKER_DRIVER: overlay2 DOCKER_TLS_CERTDIR: "" container-tests: stage: test when: always image: docker:27 script: - docker network create test-network - docker run -d --name app --network test-network -p 8000:80 image-name # 轮询等待服务就绪,避免未启动完成就执行测试 - until curl -s http://docker:8000; do sleep 2; done - > docker run --name tests --network test-network -v "$(pwd)/tests:/tests" mcr.microsoft.com/playwright/python:v1.50.0-noble /bin/sh -c " pip install pytest-base-url pytest-playwright playwright && playwright install && pytest /tests --base-url='http://app:80'" # 清理资源 - docker stop app tests - docker network rm test-network
最佳实践建议
- 用自定义网络管理容器通信:避免默认
bridge网络的限制,容器间通过名称直接访问,无需依赖端口映射或外部主机名。 - 添加服务就绪检查:测试前通过轮询确保Web服务完全启动,避免因服务未就绪导致的测试失败。
- 预构建Playwright自定义镜像:将依赖包、浏览器预安装到自定义镜像中,避免每次流水线重复安装,缩短执行时间。
- 优先用GitLab CI Services启动服务:若Web服务可直接作为CI服务启动,无需手动
docker run,服务会自动与Job容器处于同一网络,配置更简洁。 - 清理流水线资源:在流水线结束后停止容器、删除网络,避免dind服务中残留无用资源。
内容的提问来源于stack exchange,提问作者Jasper
相关产品推荐
相关产品推荐

