Azure Pipelines: GraalVM Docker image build best practice - docker

I'm currently doing some research on how to use GraalVM in our project which by now contains an array of Micronaut apps.
I've followed this Micronaut article:
https://guides.micronaut.io/latest/micronaut-creating-first-graal-app-maven-kotlin.html
using Micronaut 3.5.2, JDK 17 and Kotlin.
Everything is working as expected on localhost (Ubuntu 20.04) when building the Docker image by using
mvn package -Dpackaging=docker-native and running the app using
docker run --publish 8080:8080 graal-test
Now I'm trying to figure out how to build GraalVM Docker images in Azure Pipelines without installing prerequisites for every build. There seems to be very little information about how to do this.
I'm able to run a successful build by adding these two script build steps. task.prependpath is in effect in next build step, hence two separate script steps.
- script: |
curl -Lo graalvm-archive.tar.gz https://github.com/graalvm/graalvm-ce-builds/releases/download/vm-22.1.0/graalvm-ce-java17-linux-amd64-22.1.0.tar.gz
tar -xzf graalvm-archive.tar.gz
echo '##vso[task.prependpath]$(System.DefaultWorkingDirectory)/graalvm-ce-java17-22.1.0/bin'
- script: |
gu install native-image
sudo apt-get install build-essential libz-dev zlib1g-dev
native-image --version
Docker image build step.
# Build Docker image
- task: Maven#3
displayName: 'Build Docker'
inputs:
goals: 'package'
options: '-Pgraalvm -Dpackaging=docker-native -Djib.to.image=$(yourImageNameVar):$(yourImageTagVar) -DskipTests=true -Dmaven.javadoc.skip=true --batch-mode'
javaHomeOption: 'JDKVersion'
The resulting image has approx. virtual size 30MiB in GCR, and app startup time is less than 40ms in GKE.
Closest so far is this
https://github.com/Azure/azure-sdk-for-java/issues/21735#issuecomment-867134666
The azure pipelines ubuntu 20.04 images recently added Graal CE
21.1.0: https://github.com/actions/virtual-environments/blob/main/images/linux/Ubuntu2004-README.md#graalvm
Unfortunately, the embedded link is broken.
Any hints on how to do this, will be highly appreciated.
Side-note
We managed to build 1 out of 5 Micronaut apps tested so far with GraalVM. There seems to be some issues with Kotlin and GraalVM.

Here's the non-broken link:
https://github.com/actions/virtual-environments/blob/main/images/linux/Ubuntu2004-Readme.md#graalvm
I hope this helps. I did notice on the issue that the CI pipeline support for GraalVM is not yet in place, but the VMs themselves are available on the Ubuntu image.

Related

Chaining Dockerfiles - after FROM, running npm no longer works?

I'm experimenting with docker. I have a simple dockerfile, which includes java and node.
https://github.com/Quafadas/scala-mill
https://github.com/Quafadas/scala-mill/blob/master/Dockerfile
It's published to dockerhub. Now, I'd like to build an application downstream
FROM quafadas/scala-mill:latest
RUN java -version
#This doesn't work :-(.
RUN npm --version
The command RUN npm --version works in the base image linked above, but apparently, not when I'm building on top of it using the FROM directive. Is anyone able to help me understand why?
/bin/sh: npm: command not found
15:15:19
The command '/bin/sh -c npm --version' returned a non-zero code: 127
enter code here
``
There seem to have been a few recent commits to the repo which has apparently fixed the issue! I was able to build and run the Dockerfile to get the npm version without any issues!
In case you need additional modules (such as npm) to be installed on a base image that doesn't provide it, use a multi-stage Dockerfile with different FROM commands to get your necessary dependencies onto a single Dockerfile and a docker image later. Reference.

How to run selenium java testcases and copy test framework from Mac host to Ubutnu Docker container

I have a selenium java test automation framework in my Mac os . Now , I want to execute my automation testcases in Ubuntu Docker container using a docker file which should automatically install java, selenium , TestNG, Maven in ubuntu docker container .
Docker require shell commands so, before thinking on docker, you need to be able to run your selenium tests using the shell. If your test cannot be executed using the shell on your mac, it will be difficult to execute it with docker.
If you are able to run the tests using the shell and al of your reports are well generated, you are ready to docker.
Selenium tests are not live applications, so your docker container will be use just to run the tests and after that, you should destroy it.
As you using java, is there an option to run your tests as a single jar, instead maven. If you achieve this, your flow will be more easy or light.
If you achieve the dockerization of your test, you could run your tests developed in you mac on any machine on-premise or cloud with this line:
docker run --name tests -d \
-e PARAM1=FOO \
-e PARAM2=BAR \
tests:1.0.0
Running tests with maven (source code level)
If you pom.xml is well configured, you could run your the testng test with : mvn clean test
So you docker file will be
FROM maven:3.3-jdk-8
RUN mkdir /usr/test
COPY . /usr/test
WORKDIR /usr/test
CMD["mvn","clean", "test"]
Note: I'm not tested this Dockerfile yet
The execution will be a little slower because compilation is performed at docker run phase.
Run tests using jar
According to this you can run testng with pure java:
java -cp F:\Selenium\SampleTestNG\lib\*;F:\Selenium\SampleTestNG\bin org.testng.TestNG testng.xml
As you can see, you need the testng framework jars. That will complicate the dockerization.
If you are able to use the maven-assembly-plugin, maven will merge all the jars in just one. If you achieve this, your automation flow will be:
mvn clean package
java -jar selenium-test.jar org.testng.TestNG testng.xml
If you achieve this, your Dockerfile could be:
FROM maven:3.3-jdk-8
RUN mkdir /usr/test
COPY . /usr/test
WORKDIR /usr/test
RUN mvn clean package
CMD["java","-jar", "selenium-test.jar","org.testng.TestNG","testng.xml"]
Note: I'm not tested this Dockerfile yet
In this approach, the compilation is done at docker build phase, so it is more fast than previous approach
Common mistake
If your selenium tests opens a browser in you developer machine, you could not achieve this with a single docker container.
Selenium needs a operative system with desktop interface and a browser installed. At developer phase, all of this is performed on you developer machine. On real environments, you have these options
- ubuntu with desktop
Is not common but it is possible. If you choose this, you will need to install many browsers (and its selenium drivers) as much as you can test. As this approach is not a shell solution, you will need to install an agent to be executed remotely. Also you will need emulators to be able to launch browser of specific os like safari or microsoft edge. This will be a nigthmare
So basically this is the same of your developer machine but in another network or in a cloud.
- Selenium grid server
Similar to the previous option, but more elegantly. Check:
https://digital.ai/catalyst-blog/set-up-cross-browser-testing-with-our-selenium-grid-tutorial
https://github.com/SeleniumHQ/docker-selenium
You are not saved of browser installation, but it is free.
Your test code will be the same, just the configuration change a little bit:
https://www.mstsolutions.com/technical/execution-of-test-in-remote-machine-using-selenium-grid/
- BrowserStack ($)
Basically, is a Selenium grid server private service ready to use which needs a payment (Sometime the time is worthier than money). Just need to point your selenium test to its url. You just pick your browsers and run:
https://www.browserstack.com/docs/automate/selenium/getting-started/java#run-your-first-test
Also with this service, docker may not necessary because you just need a simple mvn test or java -jar. These commands could be launched with a Jenkins or a simple shell script in your devops server.
- headless browser
Basically are browsers that run in background mode in your shell using your ram. This is perfect if you cannot pay browserstack o configure your own selenium grid server.
The only disadvantage is that some latest javascript features may not be work in this kind of virtual browsers. Also don't support features like printers, camera, or another low level requirement or in which a real UI is required.
Here some options:
https://phantomjs.org/
https://hacks.mozilla.org/2017/12/using-headless-mode-in-firefox/
https://developers.google.com/web/updates/2017/04/headless-chrome

configuration JMeter wtth Jenkins by Docker container

I did functional tests in JMeter (backend application).
I have in Jmeter 42 functional tests and I launch this in one docker container
Now I configuration JMeter with Jenkins by docker container -
My dockerfile is following:
[https://pastebin.com/Aq9A9eqh][1]
To automatically run these tests regullary,
I created docker - container and when I run build execution on Jenkins, I had a following error:
https://pastebin.com/365kLWXB
What is wrong?
How is the best way to improve this?
What can I improve further?
I know that I must add a java jdk, but I don't know how to add to my dockerfile?
https://pastebin.com/Aq9A9eqh
When I added:
FROM openjdk:8u162-jre-slim-stretch
ARG GITHUB_OAUTH_TOKEN
it didn't run.
With regards to your current setup your Docker image doesn't have Java installed therefore you cannot launch JMeter.
You can fix it by replacing these line:
RUN apt-get install -y git
with this one:
RUN apt-get install -y git default-jre
With regards to "improve further" be aware that according to JMeter Best Practices you should always be using the latest version of JMeter so consider replacing JMeter version 3.3 with somethine more recent, as of now it's JMeter 5.0, you can always check JMeter Downloads page for current release details.

Installing Git Release in Docker

If I want to install code from a release version in Github in Docker, how can I do that taking up the least space possible in the image? Currently, I've done something like:
RUN wget https://github.com/some/repo/archive/v1.5.1.tar.gz¬
RUN tar -xvzf v1.5.1.tar.gz¬
WORKDIR /unzipped-1.5.1/¬
RUN make; make install
Issue here is the final image will have the downloaded tar, the unzipped version, and everything that gets created during make. I don't need the vast majority of this. How do I install my library in my image without keeping all of this extra data?
This is the textbook definition of the problem that the docker multi-stage build aims to solve.
The idea is to use a separate build with the dependencies and use that docker image to build the final product.
Note that this is available only in the new versions of Docker (17.05 onwards).

Aurelia build using cli produces different results on different platforms

I'm trying to setup a jenkins job to automate builds of our aurelia app. When I build the app locally it works 100%, but when I build it on jenkins using the same process, then the files in the script directory is different.
I'm running Debian testing on my laptop. The Jenkins is a docker image running on Rancher.
When I test the build with jenkins, I get the following error:
http://localhost/src/main.js Failed to load resource: the server responded with a status of 404 (Not Found)
vendor-bundle.js:2 Error: Script error for "main"(…)r # vendor-bundle.js:2
Both my local environment and jenkins have the following tools and versions:
node: 6.9.1
npm: 3.10.8
aurelia: 0.22.0
The app is written in typescript.
we are also using aurelia-cli to build the app using : "au build --env prod"
The process we use to build the app:
npm install aurelia-cli
npm install
typings install
au build --env prod
Any help appreciated

Resources