3

I am attempting to compile & execute a java program within a dockerode container in my node app. I am able to do this by first writing to a tmp.java file using basic javascript and then running the following shell commands:

docker run --rm -v $PWD:/app -w /app java:8 javac tmp.java

docker run --rm -v $PWD:/app -w /app java:8 java tmp

However, I am now trying to transition to using the dockerode module and am attempting to replicate this functionality as follows (based on the example on the dockerode github):

docker.run(
  'java:8',
  ['javac', 'tmp.java'],
  {
    Volumes: {
      '/': {}
    },
    WorkingDir: '/'
  },
  process.stdout
)
.then(data => {
  var output = data[0]
  console.log('OUTPUT: ', output)

  var container = data[1]
  console.log(output.StatusCode)
  return container.remove()
})      

However, this produces no output and does not generate tmp.class as expected when I specify Volumes and WorkingDir options, and when I leave out those options, I get the error: javac: file not found: tmp.java which I assume means my volume is not mounting correctly. Essentially, I am trying to create a temporary microcontainer, compile & run my java program in the container, and then destroy the container. Thus, I am unable to install a JDK and compile the program locally on my host system and have to essentially work exclusively within the container.

I am currently trying to use imperative Docker commands to achieve this use-case and am able to accomplish this using the cli commands above, however, I am unable to do the same thing using dockerode for node (whether through imperative commands or using a dockerfile).

I would really appreciate any help with this!

mlz7
  • 2,067
  • 3
  • 27
  • 51
  • I'd be very surprised to see a `javac` command produce a PNG file as its output. Is that actually the result you're getting, or are you getting some kind of text output or an exception? – David Maze Mar 11 '20 at 11:24
  • My first instinct reading through the question would be to install a JDK on the host and run the local `javac` command, instead of trying to run it via Docker; my second would be to run it in a Dockerfile instead of via imperative `docker run` commands. I think your Node code is mounting an anonymous volume on `/app` instead of bind-mounting the host directory. – David Maze Mar 11 '20 at 11:26
  • @DavidMaze I updated my question with some more details, let me know if I can clarify anything else. I see your point with regards to running `javac` locally, the problem is I am not sure installing a JDK on the host is a viable option for my use case given that I am essentially trying to handle the code execution completely remotely. – mlz7 Mar 11 '20 at 11:59

1 Answers1

1

The problem is that your directory is not mapped.

This options object is the equivalent of the options --rm -v $PWD:/app -w /app

  {
    HostConfig: {
      AutoRemove: true,
      Binds: [
          `${process.cwd()}:/app`
      ]
    },
    WorkingDir: '/app'
  }
  • AutoRemove: true is --rm
  • Binds: [ `${process.cwd()}:/app` ] is -v $PWD:/app, with process.cwd() as $PWD
  • WorkingDir: '/app' is -w /app

I also had to change the order of the arguments, as I was getting TypeError: dest.on is not a function. Running dockerode@3.1.0 I had to set the output stream as the 3rd argument and the option object as the 4th argument.

So the full command looked like this:

docker.run(
  'java:8',
  ['javac', 'tmp.java'],
  process.stdout,
  {
    HostConfig: {
      AutoRemove: true,
      Binds: [
          `${process.cwd()}:/app`
      ]
    },
    WorkingDir: '/app'
  }
)
Codebling
  • 10,764
  • 2
  • 38
  • 66