You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Jenkins Pipeline+Docker Compose部署RoR:容器正常但测试阶段不执行

解决Jenkins Pipeline中Docker Compose测试阶段无法执行的问题

看起来你碰到的核心问题是:直接在Docker Compose里启动rails s会让容器前台运行,Jenkins会一直卡在启动步骤,根本没机会进入测试阶段;而且就算容器起来了,Jenkins也不知道什么时候应用真正就绪,直接跑测试很容易失败。我之前部署RoR应用的时候也踩过这个坑,给你几个实用的解决思路:

第一步:调整Docker Compose配置,适配Pipeline流程

先把你的docker-compose.yml补全(假设你的应用服务叫app-test),同时加入数据库就绪等待的逻辑:

version: '3'
services:
  db-test:
    image: postgres
    environment:
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=secret
      - POSTGRES_DB=myapp_test
    volumes:
      - db-test-data:/var/lib/postgresql/data
    ports:
      - "5432:5432"
  app-test:
    build: .
    # 用wait-for-it先等数据库服务就绪,再启动rails(需要在Dockerfile安装该工具)
    command: sh -c "wait-for-it db-test:5432 -- rails s -b 0.0.0.0"
    environment:
      - RAILS_ENV=test
      - DATABASE_URL=postgres://postgres:secret@db-test:5432/myapp_test
    volumes:
      - .:/app
    ports:
      - "3000:3000"
    depends_on:
      - db-test
volumes:
  db-test-data:

要使用wait-for-it工具,需要在你的RoR应用Dockerfile中添加安装命令:

RUN apt-get update && apt-get install -y wait-for-it

第二步:修改Jenkinsfile,分阶段控制执行逻辑

把Pipeline拆成「拉取代码→启动服务→等待就绪→执行测试」几个核心阶段,避免Jenkins被阻塞,同时确保测试在服务就绪后执行:

pipeline {
  agent any

  stages {
    stage('拉取代码') {
      steps {
        checkout scm
      }
    }

    stage('启动测试环境服务') {
      steps {
        // 用-d参数后台启动所有服务,Jenkins不会被前台进程卡住
        sh 'docker-compose up -d'
      }
    }

    stage('等待应用就绪') {
      steps {
        script {
          // 轮询检查应用健康状态,最多等待5分钟
          def maxRetries = 30
          def retryCount = 0
          def isReady = false

          while (retryCount < maxRetries && !isReady) {
            try {
              // 调用应用的健康检查接口,需要提前在RoR路由中配置
              sh 'curl -f http://localhost:3000/healthcheck'
              isReady = true
              echo '应用服务已就绪,准备执行测试!'
            } catch (Exception e) {
              retryCount++
              sleep 10
              echo "等待服务就绪中... 第${retryCount}/${maxRetries}次尝试"
            }
          }

          if (!isReady) {
            error '服务超时未就绪,终止Pipeline'
          }
        }
      }
    }

    stage('执行测试') {
      steps {
        // 在运行中的app容器内执行测试,-T适配Jenkins非交互式环境
        sh 'docker-compose exec -T app-test bundle exec rspec'
        // 如果有其他测试(比如Cucumber),可以继续追加命令
        // sh 'docker-compose exec -T app-test bundle exec cucumber'
      }
    }

    stage('保持服务运行') {
      steps {
        echo '测试完成,服务将继续在后台运行'
      }
    }
  }

  post {
    always {
      // 若不需要长期保留容器,可在此添加清理命令
      // sh 'docker-compose down -v'
    }
  }
}

关键细节补充

  1. 健康检查路由配置:需要在RoR应用的config/routes.rb中添加一个简单的健康检查接口:
    Rails.application.routes.draw do
      get '/healthcheck', to: proc { [200, {}, ['OK']] }
      # 其他业务路由...
    end
    
    这样我们就能通过curl确认应用真正启动成功。
  2. 后台启动的意义docker-compose up -d让容器在后台运行,Jenkins不会被前台进程阻塞,能顺利进入后续测试阶段。
  3. 容器内执行测试:用docker-compose exec -T在已运行的容器中执行测试,既不影响容器持续运行,又能保证测试在正确的环境中执行。

这样调整后,你的Pipeline应该就能正常执行测试阶段,同时容器也会保持运行啦!

内容的提问来源于stack exchange,提问作者Xero

火山引擎 最新活动