-1

I am trying to build a docker image using the dockerfile, my purpose is to copy a file into a specific folder when i run the "docker run" command!

this my dockerfile code:

    FROM openjdk:7

    MAINTAINER MyPerson

    WORKDIR /usr/src/myapp

    ENTRYPOINT ["cp"]

    CMD ["/usr/src/myapp"]

    CMD ls /usr/src/myapp

After building my image without any error (using the docker build command), i tried to run my new image:

    docker run myjavaimage MainClass.java

i got this error: ** cp: missing destination file operand after ‘MainClass.java’ **

How can i resolve this? thx

user1444393
  • 213
  • 1
  • 4
  • 17
  • your command is cp MainClass.java because of the ENTRYPOINT. what are you trying to do with this ? – LinPy Nov 12 '19 at 09:20
  • i try to copy the MainClass.java file from the host to the container when it start to run (I want to specify each time the file which will be copied on each docker run command) – user1444393 Nov 12 '19 at 09:32
  • that will not work you need to use volumes or `docker cp` see this for example https://stackoverflow.com/questions/57771529/copy-a-file-to-a-docker-container-just-before-starting-it/57771688#57771688 – LinPy Nov 12 '19 at 09:34
  • I don't think that volumes will help (**because my goal is to copy file from the Host... not the inverse**)! ... and i don't want to execute manually the docker cp command! ... – user1444393 Nov 12 '19 at 09:47
  • 1
    you are wrong , volumes will copy the files from your host to the container – LinPy Nov 12 '19 at 09:50
  • @LinPy I'm not sure about that. I have mounted a 1TB Filestore to my docker container (which def doesn't have 1TB space). Doesn't it simply makes the volume (on the host machine) accessible from within the container, no? Similarly when using `--privileged` makes evth on the host machine accessible. – DUDANF Nov 12 '19 at 12:11

3 Answers3

1

I think you want this Dockerfile:

FROM openjdk:7
WORKDIR /usr/src/myapp
COPY MainClass.java .
RUN javac MainClass.java
ENV CLASSPATH=/usr/src/myapp
CMD java MainClass

When you docker build this image, it COPYs your Java source file from your local directory into the image, compiles it, and sets some metadata telling the JVM where to find the resulting .class files. Then when you launch the container, it will run the single application you've packaged there.

It's common enough to use a higher-level build tool like Maven or Gradle to compile multiple files into a single .jar file. Make sure to COPY all of the source files you need in before running the build. In Java it seems to be common to build the .jar file outside of Docker and just COPY that in without needing a JDK, and that's a reasonable path too.

In the Dockerfile you show, Docker combines ENTRYPOINT and CMD into a single command and runs that command as the single main process of the container. If you provide a command of some sort at the docker run command, that overrides CMD but does not override ENTRYPOINT. You only get one ENTRYPOINT and one CMD, and the last one in the Dockerfile wins. So you're trying to run container processes like

# What's in the Dockerfile
cp /bin/sh -c "ls /usr/src/myapp"

# Via your docker run command
cp MainClass.java

As @QuintenScheppermans suggests in their answer you can use a docker run -v option to inject the file at run time, but this will happen after commands like RUN javac have already happened. You don't really want a workflow where the entire application gets rebuilt every time you docker run the container. Build the image during docker build time, or before.

David Maze
  • 130,717
  • 29
  • 175
  • 215
  • Thank you for your clear explanation, but i would like to make it automatically, it means that i want to pass the file name (MainClass.java) as an argument in the docker run command... (not like that: COPY MainClass.java . ) ... I hope you understood me :) – user1444393 Nov 14 '19 at 09:49
1

Two things.

  1. You have used CMD twice.

CMD can only be used once, think of it as the purpose of your docker image. Every time a container is run, it will always execute CMD if you want multiple commands, you should use RUN and then lastly, used CMD

FROM openjdk:
MAINTAINER MyPerson
WORKDIR /usr/src/
ENTRYPOINT ["cp"]
RUN /usr/src/myapp
RUN ls /usr/src/myapp
  1. Copying stuff into image There is a simple command COPY the syntax being COPY <from-here> <to-here>

Seems like you want to run myjavaimage so what you will do is

COPY /path/to/myjavaimage /myjavaimage
CMD myjavaimage MainClass.java

Where you see the arrows, I've just written dummy code. Replace that with the correct code.

Also, your Dockerfile is badly created.

ENTRYPOINT -> not sure why you'd do "cp", but it's an actual entrypoint. Could point to the root dir of your project or to an app that will be run. Don't understand why you want to do ls /usr/src/myapp but if you do want to do it, use RUN and not CMD

Lastly, Best way to debug docker containers are in interactive mode. That means ssh'ing in to your container, have a look around, run code, and see what is the problem.

Run this: docker run -it <image-name> /bin/bash and then have a look inside and it's usually the best way to see what causes issues.

DUDANF
  • 2,618
  • 1
  • 12
  • 42
0

This stackoverflow page perfectly answers your question.

COPY foo.txt /data/foo.txt
# where foo.txt is the relative path on host
# and /data/foo.txt is the absolute path in the image

If you need to mount a file when running the command:

docker run --name=foo -d -v ~/foo.txt:/data/foo.txt -p 80:80 image_name
Quinten Scheppermans
  • 954
  • 1
  • 10
  • 29