javascriptnode.jsdockerdockerode

dockerode imperative cli equivalent


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!


Solution

  • 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'
      }
    

    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'
      }
    )