Gitlab CI/CD非自托管Runner下如何访问当前容器API端点?
我正在搭建GitLab CI/CD流水线,用于测试多个Laravel微服务及前端。为验证前端是否正确展示API端点的返回结果,计划将API端点结果作为制品传递给前端。
原本尝试通过以下方式实现:
after_script: ... - wget --no-check-certificate 'https://localhost/api/product/' -O ./artifacts/product_api.json artifacts: when: always paths: - ./artifacts/product_api.json
但实际发现localhost指向的是启动容器的服务器,而非当前运行Laravel的容器,需要获取当前容器的主机名或IP地址。
曾看到有人称主机名是docker,但无法ping通该名称;另有方案建议用docker inspect获取容器IP,但该方法需要安装Docker,我不想这么做。
请问在非自托管Runner的GitLab CI/CD环境中,是否有方法访问当前运行的Laravel容器?
我的.gitlab-ci.yml配置大致如下:
Product-API: image: serversideup/php:8.2-fpm-nginx services: - name: mysql:8.0.33-debian alias: mysql entrypoint: ['/bin/sh', '-c', 'sed -i -e "/^skip-name-resolve/d" /etc/mysql/conf.d/docker.cnf && /usr/local/bin/docker-entrypoint.sh mysqld'] variables: GIT_SUBMODULE_STRATEGY: recursive GIT_SUBMODULE_FORCE_HTTPS: "true" #FF_NETWORK_PER_BUILD: 1 #mysql variables MYSQL_DATABASE: $MYSQL_DATABASE MYSQL_ROOT_PASSWORD: $MYSQL_ROOT_PASSWORD MYSQL_USER: $MYSQL_SHOP_ADMIN MYSQL_PASSWORD: $MYSQL_SHOP_ADMIN_PASSWORD #laravel variables APP_DEBUG: "true" DB_CONNECTION: mysql DB_HOST: $MYSQL_HOST DB_PORT: 3306 DB_USERNAME: '$PRODUCTAPI_DB_USER' DB_PASSWORD: '$PRODUCTAPI_DB_PASSWORD' DB_DATABASE: $MYSQL_DATABASE before_script: #download and unpack the product database - mkdir artifacts - 'curl --location --output ./artifacts/db_dump.zip --header "PRIVATE-TOKEN: $ARTIFACTS_TOKEN" "https://gitlab.com/api/v4/projects/test1/jobs/artifacts/develop/download?job=Database-Tables"' - 'curl --location --output ./artifacts/mysqlusersandgrants.zip --header "PRIVATE-TOKEN: $ARTIFACTS_TOKEN" "https://gitlab.com/api/v4/projects/test2/jobs/artifacts/develop/download?job=Database-Users"' - unzip ./artifacts/db_dump.zip - unzip ./artifacts/mysqlusersandgrants.zip #put the database in place - apt-get update - apt-get install -y mysql-client - mysql -uroot -p$MYSQL_ROOT_PASSWORD --host=$MYSQL_HOST "$MYSQL_DATABASE" < ./artifacts/db_dump.sql - mysql -uroot -p$MYSQL_ROOT_PASSWORD --host=$MYSQL_HOST mysql < ./artifacts/mysqlusersandgrants.sql #putting and .env file in place - mv .env.example .env #install Laravel - composer install - php artisan key:generate - php artisan config:cache - php artisan route:cache - php artisan view:cache #setting user and group rights - chown -R webuser:webgroup . script: - php artisan test --log-junit productapi_results.xml after_script: - 'curl -k --location --output ./artifacts/product_api.json "https://docker/api/product/"' - cat ./artifacts/product_api.json artifacts: when: always paths: - ./artifacts/product_api.json - productapi_results.xml reports: junit: productapi_results.xml
执行后出现如下错误:
Running after script... $ curl -k --location --output ./artifacts/product_api.json "https://docker/api/product/" % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0curl: (6) Could not resolve host: docker [18-Jan-2024 20:19:43] NOTICE: Terminating ... [18-Jan-2024 20:19:43] NOTICE: exiting, bye-bye! WARNING: after_script failed, but job will continue unaffected: exit code 1
解决方法
1. 修正localhost的使用方式
你之前对localhost的认知有误:在GitLab CI的Job容器中,localhost就是当前运行Laravel的容器本身。问题出在你使用了https协议,但serversideup/php:8.2-fpm-nginx镜像默认未配置HTTPS,直接改用HTTP访问即可(该镜像Nginx默认监听80端口):
# 修改after_script中的curl命令 - curl --location --output ./artifacts/product_api.json "http://localhost/api/product/"
2. 直接用Artisan命令生成API响应
不需要通过HTTP请求绕圈,直接调用Laravel控制器方法生成响应并写入文件,更高效且避免网络问题:
# 在after_script中执行 php artisan tinker --execute="echo json_encode(app(\App\Http\Controllers\ProductController::class)->index())" > ./artifacts/product_api.json
如果逻辑复杂,建议自定义Artisan命令专门处理API响应生成,灵活性更强。
3. 检查容器内服务状态
如果localhost仍无法访问,先在before_script或script阶段验证Nginx服务是否正常运行:
# 检查Nginx状态 service nginx status # 测试本地基础访问 curl http://localhost
同时确认/api/product/路由在Laravel中已正确定义且能正常响应。
4. 启用构建专属网络(可选)
取消注释变量FF_NETWORK_PER_BUILD: 1,让Job容器和服务容器处于同一网络,这主要用于服务间的访问,但如果API依赖其他服务,启用后可能解决潜在网络问题。
内容的提问来源于stack exchange,提问作者St. Jan

