How to run docker commands or shell scripts with docker commands from Java application

Viewed 927

I need to run some docker commands from a java application. So far I've searched and tried both runtime exec and processBuilder approaches but it doesn't work. My last try was with processBuilder trying to execute a bash script containing a docker pull command.

Nothing was printed to the eclipse IDE console, although when i modified the .sh file to do echo 'i am responding' it was printed to the console. To debug the code i modified the .sh script to redirect the stdout and stderr of the docker pull to a file. After opening the resulting file i got: line 11: docker: command not found whereas when i run it in my terminal the docker command works fine. Therefore i am assuming the problem is lies in the java code itself. Where am i going wrong?. Any help would be much appreciated.

Note: I also heard of and tried Spotify docker-client library but I guess my knowledge of Docker is not enough at the moment to set it up. I am using MacOS Big Sur. Here is the java code:

public static void main(String[] args) throws IOException {
    Common cm = new Common();
    String userDir = cm.getuserDirectory();
    String sp = cm.getfileSeparator();
    String filePath = userDir + sp + "src" + sp +  "data" + sp + "pull-and-run.sh";
    
    String[] cmd = {"sh", filePath};
    
    ProcessBuilder processBuilder = new ProcessBuilder(cmd);
    processBuilder.directory(new File(userDir + sp + "src" + sp +  "data"));
    
    Process process;
    
    try {
        process = processBuilder.start();
        BufferedReader br = new BufferedReader(new InputStreamReader(process.getInputStream()));
        
        String line;

        System.out.println("Output is: ");
        while ((line = br.readLine()) != null) {
            System.out.println(line);
        }
        
    } catch (IOException e) {
        e.printStackTrace();
    }

}
2 Answers

I tried to reproduce using a simplified version of your code creating a simple java project with a Main class and a show-docker-version.sh file (in the root of the project):

show-docker-version.sh

docker --version

Main.java

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;

public class Main {
    public static void main(String[] args) throws IOException {

        String filePath = "docker-container-list.sh";
        String[] cmd = {"sh", filePath};
        ProcessBuilder processBuilder = new ProcessBuilder(cmd);
        processBuilder.directory(new File("."));
        Process process;
        try {
            process = processBuilder.start();
            BufferedReader br = new BufferedReader(new InputStreamReader(process.getInputStream()));

            String line;

            System.out.println("Output is: ");
            while ((line = br.readLine()) != null) {
                System.out.println(line);
            }

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

The output is:

Output is: 
Docker version 20.10.3, build 48d30b5

Process finished with exit code 0

So the docker command worked here!

I've tried with at least two different JDKs (8 and 11) but not for all. So I am wondering if there is something to do with your JDK version. Another possibility is a lack of permissions due to docker installation. I don't know which OS you are using, assuming is Linux, consider to take a look at the Post-installation steps for Linux: https://docs.docker.com/engine/install/linux-postinstall/

The answer is "line 11: docker: command not found" :)

When launching a terminal, you're launching a shell, and its PATH is probably set in something like .bashrc (or the rc-file for whatever shell you're running).

I understand you launch your application from within Eclipse, and you probably launch Eclipse from your desktop, or a menu, or an application launcher: all of which won't have the settings your terminal has.

To validate this:

  • run your app from the terminal, rather than from within Eclipse or
  • add a "echo $PATH" line in the script you launch from within the application, and compare that to echo $PATH run in the terminal.

To fix it:

  • add docker to the "global" PATH used by your desktop session or
  • provide the full path to docker in the script or
  • launch eclipse from within a terminal; it will inherit the environment of the shell
Related