Using docker Container links in Jenkins Using docker Container links in Jenkins postgresql postgresql

Using docker Container links in Jenkins


A possible root cause, assuming you are using the official postgres docker image, is that the container's entrypoint's script is failing.

From the image's Docker page:

Warning: scripts in /docker-entrypoint-initdb.d are only run if you start the container with a data directory that is empty; [...] One common problem is that if one of your /docker-entrypoint-initdb.d scripts fails (which will cause the entrypoint script to exit) and your orchestrator restarts the container with the already initialized data directory, it will not continue on with your scripts

Solution

Assuming that the entrypoint process is indeed failing (probably because it sees a DB that is not owned and is designed by entrypoint to override it, since it's linked to another postgres container), you can overcome this by setting your own entrypoint and cmd, thus preventing the image from trying to create a db that you are not going to use anyway, i.e.:

FROM postgres#Switch back to default entrypointENTRYPOINT ["/bin/sh"]#Let the container start and do nothing until the pipeline kicks inCMD ["-c","sleep infinity"]

Create a new image based on above Dockerfile, push it, and define it in Jenkin's pipeline instead of the current (only for the sidecar). You should then have a stable container, linked to the actual db container, that the pipeline can jump into.

Finally, regarding the command launched in the sidecar, I'd suggest to use localhost instead of db as the target host, on command question's pg_isready -h db -p 5432, reulting in: pg_isready -h localhost -p 5432


After some trial and errors, here is what worked for us. Although it is very similar to the initial set up, the key change is at the choice of using inside and withRun. The final Jenkinsfile looks like this.

// credentialsdef docker_user_credentialsId = '<DOCKER-USER>'def docker_repository = '<CUSTOM-REGISTRY>'// docker imagesdef pg = docker.image('postgres:12-alpine')def flyway = docker.image('flyway/flyway:7-alpine')pipeline {    agent none    options {        buildDiscarder(logRotator(daysToKeepStr: '90', numToKeepStr: '20', artifactDaysToKeepStr: '90', artifactNumToKeepStr: '20'))        timeout(time: 120, unit: 'MINUTES')     }    stages {        stage('db migration test') {            agent {                 label 'docker && linux'            }            environment {                PGHOST = 'db'                PGPORT = '5432'                PGDATABASE = 'postgres'                PGUSER = 'postgres'                PGPASSWORD = 'postgres'            }            steps {                script {                    docker.withRegistry(docker_repository, docker_user_credentialsId) {                        def db = pg.withRun(                            "-v ${WORKSPACE}/docker/init-user-db.sh:/docker-entrypoint-initdb.d/init-user-db.sh -e POSTGRES_USER=${env.PGUSER} -e POSTGRES_PASSWORD=${env.PGPASSWORD} -e POSTGRES_DB=${env.PGDATABASE}"                        ) { db ->                            pg.inside("--link ${db.id}:${env.PGHOST}") {                                                                sh '''                                    echo "$(date) - waiting for database to start"                                    while ! pg_isready                                    do                                        sleep 10                                    done                                '''                            }                            flyway.withRun("-e FLYWAY_LOCATIONS=filesystem:/tmp/database/server,filesystem:/tmp/database/local -e FLYWAY_URL=jdbc:postgresql://${PGHOST}:${env.PGPORT}/${env.PGDATABASE} -e FLYWAY_USER=${env.PGUSER} -e FLYWAY_PASSWORD=${env.PGPASSWORD} -v ${WORKSPACE}/database/local:/tmp/database/local -v ${WORKSPACE}/database/server:/tmp/database/server --link ${db.id}:db", "migrate") { f ->                                sh "docker logs -f ${f.id}"                                def output = sh script: "docker inspect ${f.id} --format='{{.State.ExitCode}}'", returnStdout: true                                sh "exit ${output}"                            }                        }                    }                }            }        }    } }