I have a Java program that runs inside a Docker container. This program needs to execute a shell command that should be run by the host system, but just calling Runtime.getRuntime().exec(...) executes it inside the Docker container (as it should be).
Is there a way I can start a process from inside a container so the process runs outside? I suspect that the exec command should go via Docker to tell it that the command itself needs to be run on the host, but I'm not sure how to do that.
The idea how to do it can be based on how docker comand line client communicates with docker service. It is just a client, that uses unix socket (i.e. just file) to stream commands to the service. Thus you may connect 1) the service on the host machine via tcp (google for docker TCP socket) 2) may make volumes of docker host machine with docker utility to make them availdable on the docker container like those parameters of docker run on Ubuntu
-v /var/run/docker.sock:/var/run/docker.sock -v /usr/bin/docker:/usr/bin/docker -v /usr/lib/x86_64-linux-gnu/libltdl.so.7:/usr/lib/x86_64-linux-gnu/libltdl.so.7
that make you possible to exectude docker utility in container and actually all commands will be done in host service
Related
I want to build an application. For testing it uses testcontainers. The build will run on CI and on the developers' machines. The Dockerfile is more or less:
FROM amazoncorretto:17-alpine as builder
add . .
run ./gradlew build
from amazoncorretto:17-alpine
copy --from=builder build/libs/*.jar app.jar
ENTRYPOINT ["java","-jar","/app.jar"]
And I run the build using docker build .
Part of the ./gradlew build runs tests with Testscontainers and uses
val sftpDocker = GenericContainer(DockerImageName.parse("atmoz/sftp:alpine"))
And it returns
java.lang.IllegalStateException: Could not find a valid Docker environment. Please see logs and check configuration
I know that:
Testcontainers has its own docker API client and doesn't requires installed docker inside the Alpine container 3
Someone made it using "docker:20.10.14-dind" image. But I don't know how it fits in my problem 4
I can mount the /var/run/docker.sock during docker run ... but I'm using RUN command inside dockerfile and docker build ... instead
I can expose DOCKER_HOST and testcontainers should use the default gateway's IP address. But it's way less secure than using socket
So is there a way to use a socket in this setup? If not, how should I run my host Docker to expose TCP instead of a socket?
I'm trying to install/run jenkins manually without pulling the Jenkins image from the docker-hub
for this exercise I have used the ubuntu image container and I did the following:
Install jdk-11 on the container
Set up the JAVA_HOME env variable
Install jenkins with apt-get
Run jenkins with the command service jenkins start
then status output is the following
root#42024442b87b:/# service jenkins status
Correct java version found
Jenkins Automation Server is running with the pid 89
Now I don't now how to access the jenkins server running in the container from my host.
thanks in advance
Docker containers are not reachable using the network from the host system by default. You need to expose a container's host, meaning that the port will be opened on the host machine and all traffic forwarded to the container.
Running docker with -p 8080:8080 forwards 8080. Take a look at the syntax here.
You can also specify which port on the host machine is supposed to be mapped to a container's port with something like -p 1234:8080.
You can also use the EXPOSE keyword in your Dockerfile.
I have a Java server application running in Docker Container. The container runs in a Linux server (Ubuntu 18.04 LTS), with a static IP address. Another Java application, running in a PC, has to connect to the Java server application.
The server app listens for TCP connection requests and the PC App can open a TCP connection, knowing port and static IP address of Server App.
Let me say that the app server listens on port 5000 for TCP connection requests; then, when a TCP connection arrives from external, the TCP server releases a connection assigning a port in the range 5000-20000. So first question is if this range 5000-20000 to be exposed?
Before, the Java server application runned in a linux server, without container, and it worked.
Now, with the Server App inside the Docker container, the connection is refused; I guess that there is a problem of ports.
The Java application is configured by a dockerfile like that:
FROM openjdk:8-oraclelinux8
WORKDIR /mydir
# VOLUME . /
COPY ["./My_name_Java_app.jar", "./My_name_Java_app.properties", "./"]
EXPOSE 80
EXPOSE 8080
EXPOSE 5000-20000
ENTRYPOINT ["/bin/java", "-Djava.awt.headless=true", "-jar", "My_name_Java_app.jar"]
I have read that I have to publish the ports on Docker run command, but when I run the container by:
docker run -d --name my_container -p 5000-20000:5000-20000/tcp -p 80:80 -p 8080:8080 -v /root/my_app/volume:/mydir my_image
I get the following error (in Linux terminal - note that the final full stop is exactly whay I get):
linux docker: Error response from daemon xxxxxxxxx: driver failed programming external connectivity on endpoint Error starting userland proxy:.
So finally my target is that the PC app can connect to Server app using the port 5000 and opening a connection in the range of port (5001-20000).
I also exposed ports 80 and 8080 because the Server App must perform some http requests to a website, so I suppose that I have to expose the ports 80 and 8080; other question is if do I have also to expose and publish 80 and 8080 by -p option?
By the way, if I delete (see below) the -p option with 80 and 8080, I get always the same error.
docker run -d --name my_container -p 5000-20000:5000-20000/tcp -v /root/my_app/volume:/mydir my_image
Moreover, if I eliminate at all the -p option, the container starts without errors.
SOLVED:
AT the end of the story nothing was really wrong, simply I had to expose (inside the dockerfile) and publish with -p option (in docker run command) only the only port that I really need (that is the 5000), and not the big range of ports I considered at beginning.
How do I run the ps command from Java code? I know how to execute commands when the application is running locally, but I want to execute the command for a remote Linux operating system. For example, a Java client running on Windows. The Java client needs to connect with the remote Linux system and needs to execute the ps command of Linux and get all process details.
You can run commands using Runtime.exec
https://docs.oracle.com/javase/8/docs/api/java/lang/Runtime.html#exec-java.lang.String-
Also, if you have key based authentication enabled you can run commands in remote systems using a ssh connection like this:
ssh user#remote.host ps -eaf
So, you can use something like:
Runtime.getRuntime().exec("ssh admin#example.com ps -eaf");
I wrote a simple microservice in Java using nanohttpd for the HTTP server. I am able to run it from the jar file directly from the Windows 10 command prompt like this:
D:\Docker\JoeMicroserviceTest\src>java -jar JoeMicroserviceTest-1.0-SNAPSHOT.jar
The server starts fine and displays:
Server started, Hit Enter to stop.
I can then make HTTP requests against the server, and everything works great.
I then put it in a Docker image, and when I run it, the container starts, the nanohttpd server starts, then immediately stops. This is what I see:
Server started, Hit Enter to stop.
Server stopped.
There is pretty much no delay between the starting and stopping. And then of course my container exits because the server process stopped.
Here is my dockerfile:
FROM openjdk:8
COPY ./src/ /usr/src/JoeMicroserviceTest
WORKDIR /usr/src/JoeMicroserviceTest
CMD ["java","-jar","JoeMicroserviceTest-1.0-SNAPSHOT.jar"]
EXPOSE 8080
I build it like this:
docker build -t joe-microservice-test .
I run it like this:
docker run -p 8080:8080 joe-microservice-test
Why could this be happening?
Ok, I got this working by adding "-dit" to the run command. Here is the working run command:
docker run -dit -p 8080:8080 joe-microservice-test
Here's another question that helps explain why it's needed.