Extend docker container - java

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..

Related

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.

Alpine Linux, Non-Root User, Java 7, Setcap: libjli.so: No such file or directory (needed by java)

On an Alpine Linux docker container I have created. I have set up a non-root user to run my java (jboss) server. I am trying to give it access to run on ports < 1024. As a result, I have had to use setcap in order to provide Java with the permissions in order to run on ports < 1024.
Please note that authbind does not yet exist on Alpine Linux, so this is not an option. Setcap is the recommended approach. See the final comment: https://github.com/gliderlabs/docker-alpine/issues/166
$ setcap cap_net_bind_service=+eip /opt/jdk1.7.0_51/bin/java \
cap_net_bind_service=+eip /opt/jdk1.7.0_51/jre/bin/java
However, per Oracle, there is a known bug (and workaround) that resolves the setcap problem:
http://bugs.java.com/view_bug.do?bug_id=7157699
Basically, they recommend creating a file with the below contents. Please note that I have installed java into "/opt/jdk1.7.0_51", and this is a 64 bit version, so the directory paths are different.
$ mkdir -p /etc/ld.so.conf.d
$ echo "/opt/jdk1.7.0_51/jre/lib/amd64/jli" > /etc/ld.so.conf.d/java.conf
$ cat /etc/ld.so.conf.d/java.conf
/opt/jdk1.7.0_51/jre/lib/amd64/jli
However, this did not work. I have also tried creating links to the file:
$ ln -s /opt/jdk1.7.0_51/jre/lib/amd64/jli/libjli.so /lib64/
$ ls -al /lib64
...
... libjli.so -> /opt/jdk1.7.0_51/jre/lib/amd64/jli/libjli.so
...
$ ls /opt/jdk1.7.0_51/jre/lib/amd64/jli/
libjli.so
This also did not work. I have tried debugging the problem as recommended in the original post using ldconfig:
$ ldconfig | grep libjli
This doesn't work. Alpine runs a customer version of ldconfig with little documentation, so I haven't figured out exactly what to do.
Regardless, everytime I try to debug using ldd, I still get this error:
$ /opt/jdk1.7.0_51/jre/bin$ ldd java
/lib64/ld-linux-x86-64.so.2 (0x55901c23e000)
libpthread.so.0 => /lib64/ld-linux-x86-64.so.2 (0x55901c23e000)
Error loading shared library libjli.so: No such file or directory (needed by java)
libdl.so.2 => /lib64/ld-linux-x86-64.so.2 (0x55901c23e000)
libc.so.6 => /lib64/ld-linux-x86-64.so.2 (0x55901c23e000)
Error relocating java: JLI_Launch: symbol not found
I don't know what more I can possibly do at this point. I wanted to avoid changing our software again to get it to work under alpine, as that requires a release process and can potentially impact customers who are not yet on Docker. I don't really want to touch the ports again because they are working under root. I will have to go through another debug process to configure the load balancer, docker port redirection, customize recompile and debug our software, and then retest all of the above to make sure our automated scripts deploy it all correctly. This is something I'd perfer to avoid.
Anyone have suggestions?
The problem with libjli.so seems to be that the Oracle JDK are built using glibc whereas Alpine uses musl libc.
Issues for Java 8 have been opened for this, I guess they are also valid for Java 7:
Alpine libs not compatible with Java 8
libjli.so is missing for java:8-jre-alpine
There is this Docker image that provides glibc for Alpine, you may be able to use it as a base. It has been used to build a Oracle JDK 8 image.

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

Building a docker image doesnt stop because of minecraft server continuing to run

So I have been trying to learn docker for a few days now and set a first goal for me.
I want to run a spigot server inside a docker container and later on the road combine that with a BungeeCord network.
I have run into problem.
My dockerfile runs without problems but once it reaches the point where it starts the minecraft server, the images stops building.
I think this is due to the server continuing to run and not returning a code 0 to show docker to keep on running.
Am I wrong with my idea, and if not, how can I fix the problem?
Here is my Dockerfile:
FROM ubuntu:14.04
RUN apt-get update
RUN apt-get install openjdk-7-jre icedtea-7-plugin -y
RUN apt-get install wget -y
RUN mkdir mc_server && cd mc_server/
RUN wget http://getspigot.org/spigot18/spigot_server.jar
RUN java -Xms1536m -Xmx1536m -Dcom.mojang.eula.agree=true -jar spigot_server.jar nogui
This way the server starts up but docker never finishes building.
I hope I made my problem clear.
Greetings,
Joel
Replace that last RUN with CMD.
RUN / ADD / .. are used to build the static container environment where you want to run your application in. Everything that happens before running the actual application.
CMD and ENTRYPOINT define what's supposed to happen inside the container once you docker run it. This is where the startup script / call goes for the program.
The result of the Dockerfile is similar to a computer that's shut down but has everything installed on the harddrive including a script that autostarts the application. Turn it on and everything starts to run.
PS: https://hub.docker.com/search/?q=spigot&page=1&isAutomated=0&isOfficial=0&starCount=0&pullCount=0 there are several existing images

Docker: Combine multiple images

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

Categories