Docker: Combine multiple images - java

Is it possible with Docker to combine two images into one?
Like this here:
genericA --
\
---> specificAB
/
genericB --
For example there's an image for Java and an image for MySQL.
I'd like to have an image with Java and MySQL.

No, you can only inherit from one image.
You probably don't want Java and MySQL in the same image as it's more idiomatic to have a single component in a container i.e. create a separate MySQL container and link it to the Java container rather than put both into the same container.
However, if you really must have them in the same image, write a Dockerfile with Java as the base image (FROM statement) and install MySQL in the Dockerfile. You should be able to largely copy the statements from the official MySQL Dockerfile.

Docker doesn't directly support this, but you can use DockerMake (full disclosure: I wrote it) to manage this sort of "inheritance". It uses a YAML file to set up the individual pieces of the image, then drives the build by generating the appropriate Dockerfiles.
Here's how you would build this slightly more complicated example:
--> genericA --
/ \
debian:jessie --> customBase ---> specificAB
\ /
--> genericB --
You would use this DockerMake.yml file:
specificAB:
requires:
- genericA
- genericB
genericA:
requires:
- customBase
build_directory: [some local directory]
build: |
#Dockerfile commands go here, such as
ADD installA.sh
RUN ./installA.sh
genericB:
requires:
- customBase
build: |
#Here are some other commands you could run
RUN apt-get install -y genericB
ENV PATH=$PATH:something
customBase:
FROM: debian:jessie
build: |
RUN apt-get update && apt-get install -y buildessentials
After installing the docker-make CLI tool (pip install dockermake), you can then build the specificAB image just by running
docker-make specificAB

If you do docker commit, it is not handy to see what commands were used in order to build your container, you have to issue a docker history image
If you have a Dockerfile, just look at it and you see how it was built and what it contains.
Docker commit is 'by hand', so prone to errors, docker build using a Dockerfile that works is much better.

You can put multiple FROM commands in a single Dockerfile.
https://docs.docker.com/reference/builder/#from

Related

How can I deploy two versions of a microservice at the same time in OpenShift?

I am following the ISTIO tutorial for Service Mesh, and I am having problems to copy one of the steps they do.
https://docs.huihoo.com/microservices/introducing-istio-service-mesh-for-microservices.pdf
They have a java application called Recommendation, which they deploy twice.
docker build -t example/recommendation:v1 .
docker build -t example/recommendation:v2 .
I have a Java application, TEST, deployed in OpenShift which I want to copy and change the version, so I have TEST-V1 and TEST-V2. How can I do it? Do I need to deploy the application twice with different Deployment.yaml?
Thanks in advance.
How can I do it? Do I need to deploy the application twice with different Deployment.yaml?
Basically - yes. At the end, what you need, are two service endpoints pointing to different pods. You may place the service endpoints into the same deployment file, but for sake of robustness I'd use complete different deployment.
First of all, your commands:
docker build -t example/recommendation:v1 .
docker build -t example/recommendation:v2 .
are not deployment.
What you do is building docker image.
This is the line to deploy your service for the first example:
oc apply -f <(istioctl kube-inject -f \ src/main/kubernetes/Deployment.yml) -n tutorial
and second:
Finally, inject the Istio sidecar proxy and deploy this into Kubernetes:
oc apply -f <(istioctl kube-inject -f \ src/main/kubernetes/Deployment-v2.yml) -n tutorial
You ask if you need to deploy 2 times if you change version. First of all, you need to know that you are operating on containers. The docker build command creates a container for you that you will use later. If you create a new version of the application, you should create a new container. They are similar but not identical. That means, that are completely diffent docker images from the OpenShift / Kubernetes point of view. Every time you change the container image, you need to do deploy to Kubernetes / OpenShift. You need to do it one time for each docker image change.

Need to pass different environment variable values for each docker container while run docker image

I am new to docker and i worked in one small scenario. Situation is, i need to pass different values during each docker container creation using docker run command.
FROM nginx:alpine
ARG files
ENV files=$files
COPY $files /usr/share/nginx/html
For building docker image using docker build . -t sample-ui command.
while running the docker container, i am passing one html file like below.
docker run -p 8090:80 -e files=sample1.html sample-ui
Now i just checked in browser, http://localhost:8090/sample1.html and it works fine and i am able to see the sample1.html web page.
Now i am going to create another container on top of same docker image with different html page as environment value.
docker run -d -p 8091:80 -e files=sample2.html sample-ui
But now the second container also have sample1.html only but not sample2.html. Means http://localhost:8091/sample2.html is not working. http://localhost:8091/sample1.html is working.
Anyone help me to resolve this issue.
From Dockerfile
COPY $files /usr/share/nginx/html
This COPY command will execute while building the docker image using the Dockerfile.
While I build docker image using above Dockerfile It copied all files and directory of my current folder into /user/share/nginx/html folder.
To ensure run following:
docker exec -it <container id> sh
/ # ls /user/share/nginx/html
Now i just checked in browser, http://localhost:8090/sample1.html and it works fine and i am able to see the sample1.html web page.
So, In your case there might be sample1.html filed present while you are building image. That's why above url working.
sample2.html was not present, so it's not working
Now I am successfully pass environmental variable values during docker container creation( docker run Image name).
docker run -d -p 8091:80 -e "files=sample2.html" sample-ui
Actually we need to give double quote as mentioned above.
By this way, I am able to create different docker container with dynamic html files

Add specific JRE to .Net Dockerfile

I'm setting up a .net Docker image, with some .net code within it. The code, however, needs access to a very specific version of Java Runtime (jre-7u9-windowsx64.exe).
I don't know exactly where to start in adding this executable into my dotnet Dockerfile.
The current Dockerfile for dotnet
FROM mcr.microsoft.com/dotnet/core/sdk:2.2 AS build-env
WORKDIR /name
# Copy csproj and restore as distinct layers
COPY *.csproj ./
RUN dotnet restore
# Copy everything else and build
COPY . ./
RUN dotnet publish -c Release -o out
# Build runtime image
FROM mcr.microsoft.com/dotnet/core/aspnet:2.2
WORKDIR /app
COPY --from=build-env /app/out .
ENTRYPOINT ["dotnet", "name.dll"]
I would just like to get the JRE added to the Dockerfile so it is installed or available when Docker spins up.
Because the JRE forms part of your runtime environment, you're going to want to install it into your # Build runtime image.
Your ideal goal is to find the lowest common multiple, sufficient to run both ASP.NET and your .NET code and the JRE and your Java code.
Option #1: Find a (trusted) container image that runs both ASP.NET and JRE
Presumably, you've pursued this approach and been unsuccessful.
Option #1: Start from your currently working solution and add
I'm unfamiliar with mcr.microsoft.com/dotnet/core/aspnet but this may well continue to suffice as your baseline and it has the advantage that you know it will run your .NET app.
So, your process will be to determine what additionally -- if anything -- you'll need to install to be able to run jre-7u9-windowsx64.exe.
A hacky way to determine this would be to insert whatever the installer is for this binary (between lines 13-14). This will take the form RUN the jre-7u9-windowsx64.exe installer. Then, try to build your container and see what errors arise.
A more considered approach would be to identify whether you need to install additional packages to support jre-7u9-windowx64.exe and, if you do, you'll need to install those (using further RUN ...) commands beforehand.
Option #2: Start from a minimal baseline and add
Alternatively, you could start from a more foundational baseline. I assume the OS here is Windows rather than Linux. Presumably there's a minimal Windows container image?
Then you'd need to add whatever is needed to:
Get ASP.NET and your .NET code working
Get JRE and your Java code working
This would provide a more considered foundation for your image but at the cost of requiring you to solve two puzzles.
Option #3: Start from a working JRE image and add
Included for completeness but not-recommended in this case.

How to add external folder into docker and then set environment variable

My Java code expects GATE_HOME to be set on the system. It works perfectly fine in my desktop. While add that to docker, I have the following code:
FROM gliderlabs/alpine:3.4
FROM openjdk:8-jre-alpine
ADD test.jar test.jar
ADD GATE /usr/local/GATE
ENV GATE_HOME /usr/local/GATE
I am trying to copy the GATE folder to the docker image and set GATE_HOME. Is this the correct approach. If I do this, then will my Java code understand System.getProperty("GATE_HOME")?
As of now, I am getting null for getProperty.
I think you should take a look to Docker "Manage data in containers" documentation (link) :
Manage data in containers
In this section you’re going to learn how you can manage data inside
and between your Docker containers.
You’re going to look at the two primary ways you can manage data with
Docker Engine.
Data volumes
Data volume containers
Example :
Add a data volume
You can add a data volume to a container using the -v flag with the
docker create and docker run command. You can use the -v
multiple times to mount multiple data volumes. Now, mount a single
volume in your web application container.
$ docker run -d -P --name web -v /webapp training/webapp python app.py
Volume with Dockerfile (link)
FROM ubuntu
RUN mkdir /myvol
RUN echo "hello world" > /myvol/greeting
VOLUME /myvol

Extend docker container

I am new to Docker and I have a question regarding possibility to extend docker image after pulling it from docker repository. I need specifically docker image with ubuntu 14.04, java and R. I see there are images separately with the three of them. My question is where is the Dockerfile of newly pulled images so I can extend them?
docker pull command just pull a pre-built image. There isn't Dockerfile on your local machine. But you can find the original Dockerfile from Docker Hub. If you use itzg/ubuntu-openjdk-7 image you can access it's online repository.
https://registry.hub.docker.com/u/itzg/ubuntu-openjdk-7/
Dockerfile is available on Dockerfile tab(Only "Automated Build" repositories have Dockefile tab on Docker Hub).
FROM ubuntu:trusty
MAINTAINER itzg
ENV APT_GET_UPDATE 2014-07-19
RUN apt-get update
RUN apt-get install -y openjdk-7-jre-headless
ENV JAVA_HOME /usr/lib/jvm/java-7-openjdk-amd64
Below is another Dockerfile from edwindj/docker-r.
FROM ubuntu:trusty
MAINTAINER Edwin de Jonge
RUN apt-get update
RUN apt-get install -y r-base
There is no method to automatically merge two or more Dockerfiles, but you can combine these two Dockerfile like below.
FROM ubuntu:trusty
RUN apt-get update
# Install java
RUN apt-get install -y openjdk-7-jre-headless
ENV JAVA_HOME /usr/lib/jvm/java-7-openjdk-amd64
# Install R
RUN apt-get install -y r-base
And build it with docker build command.
$ docker build nacyot/ubuntu-java-r .
Try to java and R command on the container which based on nacyot/ubuntu-java-r image.
$ docker run -it nacyot/ubuntu-java-r cat /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=14.04
DISTRIB_CODENAME=trusty
DISTRIB_DESCRIPTION="Ubuntu 14.04.1 LTS"
$ docker run -it nacyot/ubuntu-java-r java -version
java version "1.7.0_55"
OpenJDK Runtime Environment (IcedTea 2.4.7) (7u55-2.4.7-1ubuntu1)
OpenJDK 64-Bit Server VM (build 24.51-b03, mixed mode)
$ docker run -it nacyot/ubuntu-java-r R --version
R version 3.0.2 (2013-09-25) -- "Frisbee Sailing"
Copyright (C) 2013 The R Foundation for Statistical Computing
Platform: x86_64-pc-linux-gnu (64-bit)
R is free software and comes with ABSOLUTELY NO WARRANTY.
You are welcome to redistribute it under the terms of the
GNU General Public License versions 2 or 3.
For more information about these matters see
http://www.gnu.org/licenses/.
It works fine.
There is no magic, but you can extend and bulid (almost) any images which have packages you need at first hand by referencing Dockerfiles on Docker Hub.
Dockerfiles are made to build image but you the inverse operation isn't possible.
If you want to extend an existing image you have 2 solution.
Run your image in a container, do the change and then commit to a new image. https://docs.docker.com/reference/commandline/cli/
Write a Dockerfile with the image you want as base. (1st line of Dockerfile should be FROM myimage) https://docs.docker.com/reference/builder/
The Repository is your namespace, essentially. So you need to pull the image, which you did. The file is located in the container, if you think about it.
List all the images--sudo docker images --Will show you the location of the file.
List item -- run a shell within a docker container. $ sudo docker run "your filename"
Now we are inside Docker container. We can list all the files using ls command.
Create your own directory if needed, but to answer your question you can stop at #3.
From here you could add the image to your own registry, and then pull it from there which honestly makes like easier.
For simplicity you honestly would only need to do numbers 1 and possibly 2 for
sure. When I tried it, #2 was also one I did but that lists the files
to add to your own registry when you create your own directory.
Check out this "tutorial" if needed: Docker Repository Tutorial
Also check out the documentation! Docker Documentation
Sure you can.
You can download a docker image, change it and generate (AKA commit) a new image with a new name (and tag).
To change the container you can either do it manually or with Dockerfile.
I not sure that I can give you all steps in a single answer, but if you follow this little guide I believe that you can get the idea in 10 minutes or less: https://docs.docker.com/userguide/dockerimages/#creating-our-own-images
Merging several images is not possible automatic, but often, the Dockerfiles are easy to follow to create your own version with both R and Java (if thats what you want).
Some upstream containers also uses the ONBUILD https://docs.docker.com/reference/builder/#onbuild entry in their dockerfiles to have something run only when their image is included in another via the FROM entry.
If you find one java container you are happy with, just create your own image with a dockerfile and FROM java-something on top. Then add R. All the docker run ... parameters that you use (entrypoints and cmd) will still work even if you include the container via FROM.
If you need to hack on the existing container thats also possible. Take a look at something I created to enable oauth on the gitlab container (before they officially did it) # https://github.com/xeor/dockerfiles/tree/master/gitlab. There I'm expanding the original image and adding my own set of config tweeks..

Categories