Building Micronaut docker image in GitlabRunner with docker executor - java

TLDR: How can one build docker images with Gradle inside a Openjdk container?
The problem
We are building a Micronaut based suite of microservices in a multi-module Gradle project using GitLab pipelines.
Currently our pipeline builds docker images in a separate pipeline stage using docker command line, but it is starting to become unwieldy and cumbersome to add new services that way.
So instead of having separate pipeline steps for building the executable and then building docker images for each executable, I am looking into building the docker images right along with the main build step using gradle.
Micronaut's gradle plugin includes and extends gradle-docker-plugin and allows building docker images using dockerBuild task.
The whole Gradle build step is executed from within openjdk:14 docker image by custom private gradle-runner instance, so that container doesn't have any docker related bits on it.
What I've tried so far
The naive approach
My first attempt was to simply add dockerBuild target to the Gradle command line. That one failed as expected with the following stacktrace (abbreviated for the sake of clarity):
Execution failed for task ':my-service:dockerBuild'.
> com.bmuschko.gradle.docker.shaded.org.apache.hc.client5.http.HttpHostConnectException: Connect to http://127.0.0.1:2375 [/127.0.0.1] failed: Connection refused
* Try:
Run with --info or --debug option to get more log output. Run with --scan to get full insights.
* Exception is:
org.gradle.api.tasks.TaskExecutionException: Execution failed for task ':my-service:dockerBuild'.
at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.lambda$executeIfValid$1(ExecuteActionsTaskExecuter.java:188)
at org.gradle.internal.Try$Failure.ifSuccessfulOrElse(Try.java:282)
/.../
at org.gradle.api.internal.tasks.execution.ResolveTaskExecutionModeExecuter.execute(ResolveTaskExecutionModeExecuter.java:51)
> Task :my-service:dockerBuild FAILED
Building image using context '/builds/my-group/my-project/my-service/build/docker'.
Using Dockerfile '/builds/my-group/my-project/my-service/build/docker/Dockerfile'
Using images 'registry.gitlab.com/my-group/my-project/my-service:1.0.1-SNAPSHOT+4b9f8460.179'.
at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:57)
/.../
at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:61)
Caused by: java.lang.RuntimeException: com.bmuschko.gradle.docker.shaded.org.apache.hc.client5.http.HttpHostConnectException: Connect to http://127.0.0.1:2375 [/127.0.0.1] failed: Connection refused
at com.github.dockerjava.httpclient5.ApacheDockerHttpClientImpl.execute(ApacheDockerHttpClientImpl.java:153)
at com.github.dockerjava.httpclient5.ApacheDockerHttpClient.execute(ApacheDockerHttpClient.java:8)
at com.github.dockerjava.core.DefaultInvocationBuilder.execute(DefaultInvocationBuilder.java:228)
at com.github.dockerjava.core.DefaultInvocationBuilder.lambda$executeAndStream$1(DefaultInvocationBuilder.java:269)
Caused by: com.bmuschko.gradle.docker.shaded.org.apache.hc.client5.http.HttpHostConnectException: Connect to http://127.0.0.1:2375 [/127.0.0.1] failed: Connection refused
at com.bmuschko.gradle.docker.shaded.org.apache.hc.client5.http.socket.PlainConnectionSocketFactory$1.run(PlainConnectionSocketFactory.java:87)
at com.bmuschko.gradle.docker.shaded.org.apache.hc.client5.http.socket.PlainConnectionSocketFactory.connectSocket(PlainConnectionSocketFactory.java:84)
/.../
at com.bmuschko.gradle.docker.shaded.org.apache.hc.client5.http.impl.classic.CloseableHttpClient.execute(CloseableHttpClient.java:67)
at com.github.dockerjava.httpclient5.ApacheDockerHttpClientImpl.execute(ApacheDockerHttpClientImpl.java:149)
... 3 more
After some initial headschratching I figured out that this was basically caused by the fact that a build running in a container simply did not have access to docker engine remote api.
Docker socket approach
Couple of mediocre applications of Google-Fu later, I found the recommendation to map /var/run/docker.sock into the container file system.
This prompted me to modify my gitlab-runner configuration:
[[runners]]
name = "gennet-elab jdk runner"
url = "https://gitlab.com/"
executor = "docker"
[runners.docker]
image = "openjdk:14.0.2-slim"
volumes = ["/var/run/docker.sock:/var/run/docker.sock", ...]
Running the pipeline with that configuration yielded me the following failure stacktrace:
Execution failed for task ':my-service:dockerBuild'.
> java.io.IOException: native write() failed : Connection reset by peer
org.gradle.api.tasks.TaskExecutionException: Execution failed for task ':my-service:dockerBuild'.
at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.lambda$executeIfValid$1(ExecuteActionsTaskExecuter.java:188)
at org.gradle.internal.Try$Failure.ifSuccessfulOrElse(Try.java:282)
at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeIfValid(ExecuteActionsTaskExecuter.java:186)
[...]
at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:61)
Caused by: java.lang.RuntimeException: java.io.IOException: native write() failed : Connection reset by peer
at com.github.dockerjava.httpclient5.ApacheDockerHttpClientImpl.execute(ApacheDockerHttpClientImpl.java:153)
at com.github.dockerjava.httpclient5.ApacheDockerHttpClient.execute(ApacheDockerHttpClient.java:8)
at com.github.dockerjava.core.DefaultInvocationBuilder.execute(DefaultInvocationBuilder.java:228)
at com.github.dockerjava.core.DefaultInvocationBuilder.lambda$executeAndStream$1(DefaultInvocationBuilder.java:269)
Caused by: java.io.IOException: native write() failed : Connection reset by peer
at com.github.dockerjava.httpclient5.UnixDomainSocket$UnixSocketOutputStream.write(UnixDomainSocket.java:319)
at com.bmuschko.gradle.docker.shaded.org.apache.hc.core5.http.impl.io.SessionOutputBufferImpl.flushBuffer(SessionOutputBufferImpl.java:117)
[...]
at com.bmuschko.gradle.docker.shaded.org.apache.hc.client5.http.impl.classic.CloseableHttpClient.execute(CloseableHttpClient.java:67)
at com.github.dockerjava.httpclient5.ApacheDockerHttpClientImpl.execute(ApacheDockerHttpClientImpl.java:149)
... 3 more
Suppressed: java.io.IOException: native write() failed : Broken pipe
at com.github.dockerjava.httpclient5.UnixDomainSocket$UnixSocketOutputStream.write(UnixDomainSocket.java:319)
at com.bmuschko.gradle.docker.shaded.org.apache.hc.core5.http.impl.io.SessionOutputBufferImpl.flushBuffer(SessionOutputBufferImpl.java:117)
at com.bmuschko.gradle.docker.shaded.org.apache.hc.core5.http.impl.io.SessionOutputBufferImpl.flush(SessionOutputBufferImpl.java:126)
[...]
at com.github.dockerjava.httpclient5.ApacheDockerHttpClient.execute(ApacheDockerHttpClient.java:8)
at com.github.dockerjava.core.DefaultInvocationBuilder.execute(DefaultInvocationBuilder.java:228)
at com.github.dockerjava.core.DefaultInvocationBuilder.lambda$executeAndStream$1(DefaultInvocationBuilder.java:269)
at java.base/java.lang.Thread.run(Thread.java:832)
This suggests to me, it tries to connect over the socket, but the connection is closed by docker API server. From reading the documentation it seems there is some sort of
From all that I can understand, the problem might have something to do with docker api security, but all of the tutorials out there show dind (Docker in Docker) usage and that does not really help my use case.
I've also tried running the container with privileged access and tried once with dind service attached to the build job, but none of these seemed to work.
The Question
So, the question for the Great and Powerful Internet is if there is a way to build docker images using Gradle inside openjdk container and leveraging Docker remote API?
If yes, what am I missing? If no, what are the alternatives (yes, I know I can probably just create a separate gitlab shell runner, but I'd like to explore the Docker option first)

Related

unable to install playwright as a maven dependancy

I'm trying to build my automation framework using playwright with java, however I'm running into below issue when running the tests. Please advice!
Failed to install browsers
Error: Failed to download chromium v1000, caused by
Error: unable to get local issuer certificate
at TLSSocket.onConnectSecure (node:_tls_wrap:1530:34)
at TLSSocket.emit (node:events:390:28)
at TLSSocket._finishInit (node:_tls_wrap:944:8)
at TLSWrap.ssl.onhandshakedone (node:_tls_wrap:725:12)
Exception in thread "main" java.lang.RuntimeException: Failed to create driver
at com.microsoft.playwright.impl.Driver.ensureDriverInstalled(Driver.java:61)
at com.microsoft.playwright.impl.PlaywrightImpl.create(PlaywrightImpl.java:40)
at com.microsoft.playwright.Playwright.create(Playwright.java:96)
at com.microsoft.playwright.Playwright.create(Playwright.java:100)
at Example.main(Example.java:5)
Caused by: java.lang.RuntimeException: Failed to install browsers, exit code: 1
at com.microsoft.playwright.impl.DriverJar.installBrowsers(DriverJar.java:76)
at com.microsoft.playwright.impl.DriverJar.initialize(DriverJar.java:48)
at com.microsoft.playwright.impl.Driver.ensureDriverInstalled(Driver.java:57)
... 4 more
I could solve it by disabling the download (as it was already installed with npx playwright install) by setting the env
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1
IntelliJ IDE Run Configuration
It's not a Playwright or Maven problem. You can fix it yourself. If you want just to avoid the problem, not fixing it, you can follow this recommendation: https://community.claris.com/en/s/question/0D53w00005GuQXxCAN/nodejs-fmsapiclient-unable-to-verify-the-first-certificate-local-server
namely by setting the system variable to zero

Azure DevOps Pipeline build failure

I am trying to build a Pipeline job in Azure DevOps. However, the build failed for the following reasons:
Failed tests: runCukes(cucumbertest.TestRunner_web): java.lang.IllegalStateException: The driver executable does not exist: C:\chromedriver.exe
The test is running successfully in my local machine. But it is not running in Azure DevOps due to the above error.
Please let me know how to fix that

How do I avoid java.lang.reflect.InvocationTargetException when using Gatling Frontline with compiled code?

I'm using Gatling Frontline to run load tests written in scala with sbt as the build tool. The project compiles, builds, and runs successfully locally. However, when running on a Frontline host, the host fails to connect to the injector pool because the injector process has crashed with an Exception in thread "main" java.lang.reflect.InvocationTargetException. The stack trace indicates that this exception is caused by
java.lang.NoClassDefFoundError: com/google/protobuf/ByteString$Output
and
java.lang.ClassNotFoundException: com.google.protobuf.ByteString$Output.
This error has never occurred locally, during development, as this google package is not used by my project. Could this problem be fixed by changing any of the jvm options supplied by Frontline, or by adding certain system properties or build properties.

Jenkins Pipeline error when building

We have been trying to get Pipeline working on Jenkins 2.107 however it keeps coming up with an error that i have struggled to locate online. We have a Windows 2008 R2 server with Jenkins running as a service.
I have installed the pipeline plugin and set up the Hello World provided to test it. As soon s it starts to build it throws this error to the console.
Running in Durability level: MAX_SURVIVABILITY [BFA] Scanning build
for known causes... [BFA] No failure causes found [BFA] Done. 0s
java.lang.ClassNotFoundException:
org.kohsuke.groovy.sandbox.GroovyInterceptor at
jenkins.util.AntClassLoader.findClassInComponents(AntClassLoader.java:1374)
at jenkins.util.AntClassLoader.findClass(AntClassLoader.java:1327)
at jenkins.util.AntClassLoader.loadClass(AntClassLoader.java:1080)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357) Caused:
java.lang.NoClassDefFoundError:
org/kohsuke/groovy/sandbox/GroovyInterceptor at
org.jenkinsci.plugins.workflow.cps.CpsGroovyShellFactory.makeClassLoader(CpsGroovyShellFactory.java:113)
at
org.jenkinsci.plugins.workflow.cps.CpsGroovyShellFactory.build(CpsGroovyShellFactory.java:119)
at
org.jenkinsci.plugins.workflow.cps.CpsFlowExecution.parseScript(CpsFlowExecution.java:556)
at
org.jenkinsci.plugins.workflow.cps.CpsFlowExecution.start(CpsFlowExecution.java:520)
at
org.jenkinsci.plugins.workflow.job.WorkflowRun.run(WorkflowRun.java:319)
at
hudson.model.ResourceController.execute(ResourceController.java:97)
at hudson.model.Executor.run(Executor.java:429) Finished: FAILURE
We are running Java 8 and i have set Jenkins to use Java 8 in the config file. I have researched this error but can't seem to find something similar.
We have another server which runs pipeline fine however the differences are that this is windows 2012 server and it is running an older version of Jenkins and Java. Other than the two differences all plugins and config match.
I had this error and resolved it by upgrading the Script Security plugin to version 1.44 (had 1.41).

Maven not able to download dependencies using eclipse, proxy not working

I am trying to build a maven project using eclipse. My overall problem is Maven will not connect to the online Maven repository to collect the necessary artifacts needed to build the project. I have tried using numerous proxies, but get the following errors:
Caused by: java.io.IOException: unexpected end of stream on Connection{repo.maven.apache.org:443, proxy=HTTP # /101.96.11.44:95 hostAddress=101.96.11.44 cipherSuite=none protocol=http/1.1} (recycle count=0)
at com.squareup.okhttp.internal.http.HttpConnection.readResponse(HttpConnection.java:210)
at com.squareup.okhttp.Connection.makeTunnel(Connection.java:400)
at com.squareup.okhttp.Connection.upgradeToTls(Connection.java:229)
at com.squareup.okhttp.Connection.connect(Connection.java:159)
at com.squareup.okhttp.Connection.connectAndSetOwner(Connection.java:175)
at com.squareup.okhttp.OkHttpClient$1.connectAndSetOwner(OkHttpClient.java:120)
at com.squareup.okhttp.internal.http.HttpEngine.nextConnection(HttpEngine.java:330)
at com.squareup.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:319)
at com.squareup.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:241)
at com.squareup.okhttp.Call.getResponse(Call.java:271)
at com.squareup.okhttp.Call$ApplicationInterceptorChain.proceed(Call.java:228)
at com.squareup.okhttp.Call.getResponseWithInterceptorChain(Call.java:199)
at com.squareup.okhttp.Call.execute(Call.java:79)
at io.takari.aether.okhttp.OkHttpAetherClient.execute(OkHttpAetherClient.java:154)
at io.takari.aether.okhttp.OkHttpAetherClient.get(OkHttpAetherClient.java:100)
at io.takari.aether.connector.AetherRepositoryConnector$GetTask.resumableGet(AetherRepositoryConnector.java:600)
at io.takari.aether.connector.AetherRepositoryConnector$GetTask.run(AetherRepositoryConnector.java:453)
at io.takari.aether.connector.AetherRepositoryConnector.get(AetherRepositoryConnector.java:304)
... 48 more
Caused by: java.io.EOFException: \n not found: size=0 content=...
at okio.RealBufferedSource.readUtf8LineStrict(RealBufferedSource.java:200)
at com.squareup.okhttp.internal.http.HttpConnection.readResponse(HttpConnection.java:190)
... 65 more
I have also tried connecting to another network that is not my own and have had no success.
When I do not use a proxy, I get the following errors:
Caused by: javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:980)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1363)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1391)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1375)
at com.squareup.okhttp.Connection.upgradeToTls(Connection.java:242)
at com.squareup.okhttp.Connection.connect(Connection.java:159)
at com.squareup.okhttp.Connection.connectAndSetOwner(Connection.java:175)
at com.squareup.okhttp.OkHttpClient$1.connectAndSetOwner(OkHttpClient.java:120)
at com.squareup.okhttp.internal.http.HttpEngine.nextConnection(HttpEngine.java:330)
at com.squareup.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:319)
at com.squareup.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:241)
at com.squareup.okhttp.Call.getResponse(Call.java:271)
at com.squareup.okhttp.Call$ApplicationInterceptorChain.proceed(Call.java:228)
at com.squareup.okhttp.Call.getResponseWithInterceptorChain(Call.java:199)
at com.squareup.okhttp.Call.execute(Call.java:79)
at io.takari.aether.okhttp.OkHttpAetherClient.execute(OkHttpAetherClient.java:154)
at io.takari.aether.okhttp.OkHttpAetherClient.get(OkHttpAetherClient.java:100)
at io.takari.aether.connector.AetherRepositoryConnector$GetTask.resumableGet(AetherRepositoryConnector.java:600)
at io.takari.aether.connector.AetherRepositoryConnector$GetTask.run(AetherRepositoryConnector.java:453)
at io.takari.aether.connector.AetherRepositoryConnector.get(AetherRepositoryConnector.java:304)
... 48 more
Caused by: java.io.EOFException: SSL peer shut down incorrectly
at sun.security.ssl.InputRecord.read(InputRecord.java:505)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:961)
... 67 more
The only solution that I have found is downloading the dependencies one by one from the Maven repository manually. Given that there are more than 100 dependencies left to install, I'd really prefer not to spend that much time getting this to work. If any other details need to be provided, I will be happy to do so.
Under Windows I resolved this problem by using mvn install in a command shell for my project.
Then I added/changed <localRepository> in the settings.xml of eclipse maven user settings to c:/users/ttt/.m2/repository where I found the downloaded dependencies.

Categories

Resources