0

I want to send some java code as a string to an API to then run it in a docker container and return the console output, I have managed to do it with Python but as java first needs to be compiled then ran I'm unsure how to implement the language.

currently using the python image but I am not too familiar with java and im unsure how to approach it.

my environment is node using typescript and im using the dockerode module.

let container = await docker.createContainer({
   Image: 'python',
   Tty: true,
   Cmd: ['/bin/bash'],
   StdinOnce: true
});

I'm able to pass the string directly to the container by adding it to the Cmd after running python but not sure how I would pass a string into a file then compile and run it.

var options = {
   Cmd: ['python', '-c'],
   AttachStdout: true,
   AttachStderr: true,
};

options.Cmd.push(code);

let exec = await container.exec(options);

I just have a listener to capture the output stream which can be used for later

stdout.on('data', (chunk: any) => {
   let data = chunk.toString('utf8').split(/\r?\n/).filter((str: string) => {return str.length});
   output = data;
})

any advice on which image to use along with how to pass the code through to get the output would be appreciated.

Codebling
  • 10,764
  • 2
  • 38
  • 66
Andrew Dean
  • 195
  • 1
  • 7
  • 23
  • That really depends how your could looks like. Java 11 introduced the "single class feature". Meaning: when you only have **one** self contained class, then you can directly do `java ThatClass.java` ... and the JVM will automatically compile it for you. But if you have multiple classes, yep, then you somehow have to trigger the compiler explicitly. – GhostCat Sep 11 '19 at 15:08
  • Andrew Dean could you post what you actually did to get this working? – cbutler Jan 01 '22 at 19:58
  • it was been a while since i looked at this code (this was a uni project) but here's the function https://pastebin.com/kPdMmZmC in short, you create a local .java file with the code and compress it to put it into the docker container as an archive – Andrew Dean Jan 13 '22 at 09:23

1 Answers1

0

Depending on what you're trying to achieve, you may want to compile your code inside the docker container or not, or bind mount or push the files into the container.

This example simply mounts (binds) the current working directory inside the container and calls javac (or java). The resulting .class file would appear in your current directory (only works on systems where your terminal is on the host). You could then re-run the same command with java and the class name to execute it.

docker.run(
  'java:8',
  ['javac', 'yourclass.java'],
  process.stdout,
  {
    HostConfig: {
      AutoRemove: true,
      Binds: [
          `${process.cwd()}:/app`
      ]
    },
    WorkingDir: '/app'
  }
)

Your question says that you "want to send some java code as a string to an API", although exactly what qualifies as "sending a string to an API" is not clear. Along the lines of what you did with Python, you could echo '${code}' > myclass.java, although you risk running into escaping issues with the quotation marks.

An alternative approach is to create the container and then container.putArchive('yourclass.java', options). I don't know if this qualifies as "sending a string".

Codebling
  • 10,764
  • 2
  • 38
  • 66
  • Andrew Dean could you post what you actually did to get this working? – cbutler Jan 01 '22 at 11:24
  • @cbutler since you replied to the answer which was written by me (and there are no other comments on it), I am the only one who gets a notification here. Normally you'd need to @ Andrew but I can't get that to work, but if you comment on the question Andrew will get a notification. Otherwise let me know if you have a more specific question – Codebling Jan 01 '22 at 17:25
  • Ahhhh Thanks Codebling! I'll try that. – cbutler Jan 01 '22 at 19:58