web-dev-qa-db-ja.com

jenkins内のDockerコンテナーからログを取得する

統合テストを実行できる完全なテスト環境をDockerにセットアップしようとしていますが、これまでのところ、実際には機能しておらず、ログの取得に問題があります。

パイプラインとして実行し、jenkinsfileを使用したいと思います。これは私がこれまでに得たものです:

pipeline {
    agent any
    stages {
        stage('build war') {
            agent {
                docker { 
                    image 'gradle:latest'
                    reuseNode true 
                }
            }
            steps {
                sh 'gradle war -b oven/build.gradle'
            }
        }
        stage('test') {
            steps {
                script {
                    docker.image('mysql:latest').withRun('-e "MYSQL_ROOT_PASSWORD=password" -e "MYSQL_USER=root" -e "MYSQL_DATABASE=highlygroceries"') { c -> 
                        docker.image('munhunger/highly-oven').withRun('-e "test=test"') { h -> 
                            docker.image('mysql:latest').inside("--link ${c.id}:db") {
                                sh 'while ! mysqladmin ping -hdb --silent; do sleep 1; done'
                            }
                            docker.image('munhunger/highly-oven').inside("--link ${c.id}:db -e 'DB_URL=db:3306' -e 'DB_PASS=password' -e 'DB_USER=root'") {
                                sh 'sleep 5'
                            }
                            docker.image('gradle:latest').inside("--link ${h.id}:backend -e 'OVEN_URL=http://backend:8080'") {
                                sh 'gradle test -b oven/build.gradle'
                            }
                            sh "docker logs ${h.id}"
                        }
                    }
                }
            }
        }
        stage('build dockerimage') {
            steps {
                script {
                    dir('oven') {
                        def image = docker.build("munhunger/highly-oven")

                        docker.withRegistry('https://registry.hub.docker.com', 'docker-hub-credentials') {
                            image.Push("${env.BUILD_NUMBER}")
                            image.Push("latest")
                        }
                    }
                }
            }
        }
    }
}

しかし、私のバックエンドとデータベースの間の接続に問題があるようです...

私がビルドログから得るすべてはこれです:

se.munhunger.oven.rest.UserTest > System is up and running, Creating a user, it returns 204 upon creation FAILED
    Java.lang.AssertionError at UserTest.Java:38

これは次を指し示します:

                Assert.assertEquals("non 204 from backend", 204,
                                    client.target(baseURL + "/api/user")
                                        .request()
                                        .header("email", "[email protected]")
                                        .post(Entity.json(null))
                                        .getStatus());

次のテストが成功したため、テスターとバックエンド間の接続が機能していると思います

            Assert.assertEquals(200,
                                client.target(baseURL + "/swagger")
                                    .request()
                                    .get()
                                    .getStatus());

これは、バックエンドのDockerイメージからログを取得する方法の主な質問だと思います。私はそれなしで感じている、何が悪いのかデバッグすることはほとんど不可能です

編集いくつかのログを取得しましたが、間違ったタイミングで。次のように変更した場合:

                docker.image('mysql:latest').withRun('-e "MYSQL_ROOT_PASSWORD=password" -e "MYSQL_USER=root" -e "MYSQL_DATABASE=highlygroceries"') { c -> 
                    docker.image('munhunger/highly-oven').withRun('-e "test=test"') { h -> 
                        docker.image('mysql:latest').inside("--link ${c.id}:db") {
                            sh 'while ! mysqladmin ping -hdb --silent; do sleep 1; done'
                        }
                        docker.image('munhunger/highly-oven').inside("--link ${c.id}:db -e 'DB_URL=db:3306' -e 'DB_PASS=password' -e 'DB_USER=root'") {
                            sh 'sleep 5'
                        }
                        sh "docker logs ${h.id}"
                        docker.image('gradle:latest').inside("--link ${h.id}:backend -e 'OVEN_URL=http://backend:8080'") {
                            sh 'gradle test -b oven/build.gradle'
                        }
                        sh "docker logs ${h.id}"
                    }
                }

起動時にすべてのログを取得します。しかし、テスト失敗後のログは出力されません

6
munHunger

Jenkinsファイルを使用せずに統合テストを実行できる場合に役立ちます。したがって、これらのネストされたdocker.imageステートメントを使用する代わりに、docker-composeを使用する必要があります。

私はこのような統合テストをします:

stage('Run integration tests') {
  steps {
    script {
      try {
        timeout(30) {
          // Tear up integration test environment
          sh "docker-compose up -d"
          // Wait until it is ready
          waitUntil {
            "healthy" == sh(returnStdout: true,
              script: "docker inspect CONTAINER_NAME --format=\"{{ .State.Health.Status }}\"").trim()
          }

          docker.image('IMAGENAME').inside('--network projectname_default') {
            sh "gradle integrationTest"
          }
        }
      } finally {
        try {
          step([$class: 'JUnitResultArchiver', testResults: '**/build/integrationTest-results/TEST-*.xml'])
        } catch (Exception e) {
          // Ignore exception when there are no test results
        }
        sh "docker-compose logs >integration-test.log"
        sh "docker-compose down --rmi local --volumes --remove-orphans"
        archive 'integration-test.log'
      }
    }
  }
}

ご覧のとおり、Gradleテストコンテナーをdocker-composeによってセットアップされたネットワークに接続します。これにより、テストだけでなくコンポーズを再利用できます。

ここで、使用するすべてのコンテナーがstdoutにログを記録することを確認する必要があります。最後に、すべてのログをアーカイブ統合-test.logに取得します。もちろん、これを拡張して、コンテナーごとに個別のログファイルを取得することもできます。

5

あなたはそのたわごとをまっすぐにキャッチできることがわかりました:

pipeline {
    agent any
    stages {
        stage('build war') {
            agent {
                docker { 
                    image 'gradle:latest'
                    reuseNode true 
                }
            }
            steps {
                sh 'gradle war -b oven/build.gradle'
            }
        }
        stage('test') {
            steps {
                script {
                    docker.image('mysql:latest').withRun('-e "MYSQL_ROOT_PASSWORD=password" -e "MYSQL_USER=root" -e "MYSQL_DATABASE=highlygroceries"') { c -> 
                        docker.image('munhunger/highly-oven').withRun('-e "test=test"') { h -> 
                            docker.image('mysql:latest').inside("--link ${c.id}:db") {
                                sh 'while ! mysqladmin ping -hdb --silent; do sleep 1; done'
                            }
                            docker.image('munhunger/highly-oven').inside("--link ${c.id}:db -e 'DB_URL=db:3306' -e 'DB_PASS=password' -e 'DB_USER=root'") {
                                sh 'sleep 5'
                            }
                            try {
                                docker.image('gradle:latest').inside("--link ${h.id}:backend -e 'OVEN_URL=http://backend:8080'") {
                                        sh 'gradle test -b oven/build.gradle'

                                }
                            }
                            catch (exc) {
                                sh "docker logs ${h.id}"
                                throw exc
                            }
                        }
                    }
                }
            }
        }
        stage('build dockerimage') {
            steps {
                script {
                    dir('oven') {
                        def image = docker.build("munhunger/highly-oven")

                        docker.withRegistry('https://registry.hub.docker.com', 'docker-hub-credentials') {
                            image.Push("${env.BUILD_NUMBER}")
                            image.Push("latest")
                        }
                    }
                }
            }
        }
    }
}
3
munHunger