Creating IMAGE BASE for REUSE in DOCKERFILE

Hello, good morning, I have a query about DOCKERFILE.

I understand that DOCKERFILE always starts from a base IMAGE (FATHER) , on which I add sentences, files, etc. to create a NEW IMAGE , with which I can create my CONTAINER.

In my case I want to create a base IMAGE (FATHER), to REUSE IT in my other CONTAINERS. This base IMAGE must have: UBUNTU + MAVEN + GRALVM. It would be nice if you create it like this:

FROM ubuntu:18.04

RUN apt-get update
RUN apt-get install maven -y
RUN mvn -version

RUN apt-get install sudo -y
RUN apt-get install nano -y
RUN apt-get install curl -y
RUN apt-get install wget -y
RUN apt-get install siege -y

WORKDIR /usr/jvm/

RUN wget https://github.com/graalvm/graalvm-ce-builds/releases/download/vm-21.0.0.2/graalvm-ce-java8-linux-amd64-21.0.0.2.tar.gz -P /usr/jvm/
RUN tar -xf /usr/jvm/graalvm-ce-java8-linux-amd64-21.0.0.2.tar.gz

RUN update-alternatives --install /usr/bin/java java /usr/jvm/graalvm-ce-java8-21.0.0.2/bin/java 1100
RUN update-alternatives --set java /usr/jvm/graalvm-ce-java8-21.0.0.2/bin/java
RUN update-alternatives --list java
RUN java -version

ENV JAVA_HOME=/usr/jvm/graalvm-ce-java8-21.0.0.2

RUN rm /usr/jvm/graalvm-ce-java8-linux-amd64-21.0.0.2.tar.gz
RUN rm -r /usr/jvm/graalvm-ce-java8-21.0.0.2
RUN rm -rf ~/.local/share/Trash/*

Luego, ejecuto para CREAR la IMAGEN:
$ docker build -t ubuntu-maven-graalvm:v1.0 .

What I want to know is if what I have done is going to work for me when I want to create a NEW DOCKERFILE, with my IMAGE as a base with EVERYTHING I need. Something like that:

FROM maktup/ubuntu-maven-graalvm:v1.0
RUN echo $JAVA_HOME
RUN java -version

Please comment to me, thank you.

Greetings.

I want to do it this way (in 2 parts), so as NOT to have to do only 1 DOCKERFILE that does EVERYTHING each time, since the download of: UBUNTU + MAVEN + GRALVM , I understand that it takes a long time to do it online Due to this, my idea is to have a base IMAGE that already has EVERYTHING inside & when I need to create a DOCKERFILE for my QUARKUS MICROSERVICE, simply have to refer to said NEW CUSTOM IMAGE from the FROM and add what is necessary to start the CONTAINER.

Thank you.

Yes, that’s possible.

You will have to ‘host’ the Dockerfile for your base image somewhere, if you want to use it on another machine without having to run the docker build for the base image separately. So you’ll need an account for something like docker hub or GitLab.

Does that answer your question?

Thanks for answering my friend.

If it is correct in my case I have created the BASE IMAGE as shown there and I have uploaded it to a SERVICE REGISTRY (DockerHub) with the name: maktup/ubuntu-maven-graalvm: v1.0 , it What I want to know is if my BASE IMAGE is well created. Since when I later want to deploy my MICROSERVICES in my CLUSTER based on a DOCKERFILE as is (based on my personalized BASE IMAGE, which is in my REPOSITORY), it DOES NOT work for me. This DOCKERFILE is just a piece that I have put here to verify if the JAVA should already be installed in my BASE IMAGE, so here I would no longer install any JAVA, but when I post this DOCKER FILE it does not recognize either the JAVA or the MAVEN:

FROM maktup/ubuntu-maven-graalvm:v1.0
RUN echo $JAVA_HOME
RUN java -version

I´ll have a look at your Dockerfile as well, maybe I can help figuring out what´s wrong. But before I do, I have some other questions:

Why are you adding maven to this image? Is it just a build image, or one to run code in production? In the first one it seems weird you´d need GraalVM, if it´s for running production code you wouldn´t need maven. Your image is getting really big, so it might be beneficial to remove some things, or make 2 containers with the same base.

Related to that, both Maven and GraalVM have their own container images. I guess you´re not using them because none of them have the combination of Maven + GraalVM. But why do you need the combination? Just reusing these standard containers can save you a lot of headaches (as you have right now).

Lastly, please reduce the amount of all-caps and bold text you use. It´s fine if you want to emphasize something, but right now it feels like you´re screaming.

It´s not working because you remove your java binaries:

FROM ubuntu:18.04

...

# Here you set your Java home
ENV JAVA_HOME=/usr/jvm/graalvm-ce-java8-21.0.0.2

...

# Here you remove the folder where your Java home is
RUN rm -r /usr/jvm/graalvm-ce-java8-21.0.0.2

Remove the line RUN rm -r /usr/jvm/graalvm-ce-java8-21.0.0.2 and it should work just fine.

Hello my friend, thanks for answering. I’ll tell you why.

I have been working for my Microservices that support: Jdk8 + Maven with the Image: maven:3-jdk-8-alpine , which is very good and only weighs: 122MB.

But right now we have been migrating to Microservices that support: Graalvm + Quarkus but we were using the Image: ghcr.io/graalvm/graalvm-ce which is good but weighs: 1.5GB which is too much. We also tried using other similar images:

- quay.io/quarkus/centos-quarkus-maven:21.0.0-java11 => 1.9GB
- quay.io/quarkus/centos-quarkus-maven:19.2.0 => 1.5GB
- jycr/maven-graalvm:3-jdk-11 => 1.81GB

And I see that they are really very heavy. Due to this my idea as explained above is to create a Base Image with a DockerFile that has those requirements: Ubuntu + Maven + Graalvm, and have it to reuse in my DockerHub. So when you need to create a Microservice, I only refer to said Image of my DockerHub from a DockeFile and add the Microservice to start it in the Container.

Thanks,

Allright, I hope it´s working like this :slight_smile:

Hi, I’m going to apply what you told me right now to see if it works. On the other hand, do you think the approach I’m trying to do is okay? My idea is to try to lower the size of the base IMAGE as low as possible, precisely for the reasons that I am explaining to you.

Thank you.

It looks like GraalVM is just what´s making these images so big. I´m not sure you can work around that.

When I build the Dockerfile from your first post, but don´t include that RUN rm -r /usr/jvm/graalvm-ce-java8-21.0.0.2 statement, the image is 1.64GB

Which makes sense, I guess. I downloaded GraalVM manually. The archive is already over 300MB. Unzipped, the size is almost 900MB:

$ du -hs graalvm-ce-java8-21.0.0.2/
884M    graalvm-ce-java8-21.0.0.2/

On top of that come all these other dependencies, so not sure you´ll manage to get below 1GB.

EDIT: you might not be able to get to a lower size for “build” containers. But ofc. you can generate native binaries with GraalVM and put them in their own containers: https://blog.softwaremill.com/small-fast-docker-images-using-graalvms-native-image-99c0bc92e70b?gi=58b1513a9f80.

That way the build containers will be big, but the production/runtime containers will be small. Or was that the plan all along?

EDIT2: also read this blogpost about large image sizes. It´s not necessarily a bad thing.