I'm trying to build my app within docker and trying to start it. Below is my docker file,
FROM openjdk:11.0.7
MAINTAINER "Kannan Ramamoorthy"
RUN mkdir /var/myapp
WORKDIR /var/myapp
COPY . .
RUN ./gradlew build -x test
EXPOSE 8080
RUN ls /var/myapp/build/libs/myapp*.jar
RUN whoami
USER root
ENTRYPOINT ["java", "-jar", "build/libs/myapp*.jar"]
Some observations,
The whoami prints root.
And ls prints the file.
If I change the entry point to something else say "ping", "google.com", I'm able to get into server and start the jar.
I tried adding CMD ["-start"] at the end, as suggested here(Though I didn't get it why yet).
I tried giving the absolute path of the jar stillsame error.
None of those works. Any suggestion on fix and why its happening this way?
Found out the problem is that wildcard card doesn't work with the Entrypoint statement of Dockerfile, the solution and reason for the problem is discussed here
Related
I am new to Docker and I am following their official tutorial - https://docs.docker.com/get-started/.
I am trying to start my container with this command - docker run -dp 3000:3000 getting-started.
However, when I am trying to open my browser to http://localhost:3000 I get
I already did try to run it on different port - docker run -dp 3000:80 getting-started, however it redirects me to docker tutrial page and thats not what I want.
I have created a file app/Dockerfile with this content:
# syntax=docker/dockerfile:1
FROM node:12-alpine
RUN apk add --no-cache python3 g++ make
WORKDIR /app
COPY . .
RUN yarn install --production
CMD ["node", "src/index.js"]
I can't find the problem and I will be grateful for help.
Not sure if you ever solved this but I had a similar issue as I missed this all important line located in this section:
"If you haven't already done so, open a terminal and go to the app directory with the Dockerfile"
Your Dockerfile, as did mine in my http://localhost/tutorial/our-application/ does not have the
EXPOSE 3000
line at the end, whereas this line indeed appears in the Dockerfile in https://docs.docker.com/get-started/02_our_app/#build-the-apps-container-image (link provided in pbay's answer).
Without that line, the produced container does not expose port 3000, and docker start -dp 3000:(whatever) is bound to fail. [Edit: that's my understanding as a near-absolute beginner, but other people seem to have run that container successfully without that line. Go figure why/how. I'm ready to be enlightened.] In "Docker Desktop" on Windows, you can see in the dashboard that the container exits as soon as it starts.
I added that EXPOSE 3000 line, rebuild and rerun the using the same commands as first time:
docker build -t getting-started .
docker -dp 3000:3000 getting-started
and it now works fine.
(Rant: "If you've created Dockerfiles before, you might see a few flaws in the Dockerfile below" they say. Well this is not a minor flaw -- this is a beginner-discouraging trap. How come ?)
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
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.
Two things.
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
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.
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
I am trying to use ENTRYPOINT and whenever I do that I am getting an error as no such file or directory
Dockerfile:
FROM ubuntu:18.04
COPY . /home
COPY docker-entrypoint.sh /usr/local/bin/
RUN ln -s /usr/local/bin/docker-entrypoint.sh
WORKDIR /home
RUN chmod 777 /usr/local/bin/docker-entrypoint.sh
ENTRYPOINT ["docker-entrypoint.sh"]
CMD ["/bin/bash"]
I have tried giving it permission, tried running it with absolute path also tried this, tried it with #!/bin/bash & #!/bin/sh and in the end, I still get the file not found error.
I am not sure what the problem is.
The question you asked:
I don't remember exactly why, but the file isn't being found because you're calling it docker-entrypoint.sh rather than ./docker-entrypoint.sh.
The question you'll ask soon:
That doesn't entirely fix your problem. You've added execute privileges to the copy of docker-entrypoint.sh in /usr/local/bin, but there's another copy of the file in /home that gets found first and doesn't have execute privileges. You'll get a permissions error when you try to use it. An easy workaround (depending on what you want to do) consists of a modified entrypoint:
ENTRYPOINT ["/bin/bash", "docker-entrypoint.sh"]
Extra details if you'll be using Docker a lot:
Being able to enter a container or image to examine its contents is invaluable. For ubuntu-based images, write down the following line somewhere (replace bash with sh for basically every other linux OS):
docker run -it --rm --entrypoint=bash my_image_name
This will open up a shell in that image and let you play around in the same environment the Dockerfile is running in and debug whatever is causing you problems.
I would like to use a prod.conf file in production inside a Docker container. I added this to my Dockerfile:
ENTRYPOINT ["bin/myapp", "-D", "config.resource=prod.conf"]
But I got this error:
Bad root server path: /opt/docker/-D
I get the same error when I try to run the command manually as root
/opt/docker/bin/myapp -D config.resource=prod.conf
If I run
/opt/docker/bin/myapp
It works but using the default application.conf file.
I guess there is no permission issue.
Here is my full Dockerfile:
FROM openjdk:8u121-alpine
WORKDIR /opt/docker
ADD opt /opt
RUN ["chown", "-R", "daemon:daemon", "."]
EXPOSE 9000
USER daemon
ENTRYPOINT ["bin/myapp", "-D", "config.resource=prod.conf"]
CMD []
Edit:
I got the same error locally:
activator clean stage
target/universal/stage/bin/myapp -D config.resource=prod.conf
Bad root server path: /home/me/Documents/MyApp-D
There should be no space between the -D and the config value. Use this instead:
ENTRYPOINT ["bin/myapp", "-Dconfig.resource=prod.conf"]
JAVA_OPTS shall be used to avoid such errors.
JAVA_OPTS="-Dconfig.resource=prod.conf" bin/myapp
Worsk with command line, systemctl.
If you use sbt plugin "DockerPlugin" you can type
dockerEntrypoint := Seq("")
in your build.sbt file. It will cause
ENTRYPOINT [""]
in your Dockerfile. So, then you run docker with your image you should specify in run command the following
bin/myapp "-Dconfig.resource=prod.conf"
i.e.
docker run YOUR_DOCKER_IMAGE bin/myapp "-Dconfig.resource=prod.conf"
Pay attention to quotes on -D
I have a Dockerfile like:
FROM frolvlad/alpine-oraclejdk8:slim
ADD build/libs/zuul*.jar /app.jar
ADD src/main/script/startup.sh /startup.sh
EXPOSE 8080 8999
ENTRYPOINT ["/startup.sh"]
startup.sh looks like:
#!/bin/sh
set -e
if [ $# -eq 0 ]
then
echo "Environment value required"
exit 1
fi
java -jar -Xms400m -Xmx400m -Dlog4j.configurationFile=log4j2-qa2.xml -Djava.security.egd=file:/dev/./urandom -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=8999 -Dcom.sun.management.jmxremote.local.only=false -Dcom.sun.management.jmxremote.rmi.port=8999 app.jar
But when I run it with docker run, I got docker: Error response from daemon: Container command '/startup.sh' not found or does not exist... The shell script has execute permission.
I used the same way to run my other apps and they're all working fine. I wrote the files in Mac and tried to run the container in a Linux machine.
It turns out to be the ^M DOS-style line ending character that caused the issue. But since I'm editing in Mac and I checked several times with vim, I'm pretty sure the starting script in my local machine doesn't have that char. But when opened with vim inside the container, I can see ^M everywhere. So somehow that char gets added to startup.sh when copied into the image, which is weird. That prevents the script from being invoked.
The solution is to add dos2unix filename before the ENTRYPOINT in Dockerfile. But make sure that your base image has that utility.
The shell script has execute permission.
Are you sure though? (I mean within the container, onced ADDed)
To be sure, I would use the Dockerfile:
EXPOSE 8080 8999
COPY src/main/script/startup.sh /startup.sh
RUN chmod 755 /startup.sh
WORKDIR /
ENTRYPOINT ["/startup.sh"]
A container exits when its main process exits. So check that /startup.sh is not ending.
Particularly check that this java
java -jar -Xms400m -Xmx400m -Dlog4j.configurationFile=log4j2-qa2.xml \
-Djava.security.egd=file:/dev/./urandom \
-Dcom.sun.management.jmxremote \
-Dcom.sun.management.jmxremote.port=8999 \
-Dcom.sun.management.jmxremote.local.only=false \
-Dcom.sun.management.jmxremote.rmi.port=8999 \
app.jar
I think the trouble here is when you specify path like /app.jar, it is really difficult to make out where the current working directory actually is.
It can be any where and I suspect Docker must have accidentally copy your start.sh to a place whatever at that point ./ is.
You might want to ssh into the container and do a find to search and see where startup.sh is sitting.
docker ps -a - Find docker container ID
docker -i -t [CONTAINER_ID] /bin/bash - SSH inside
find . -name "startup.sh" - Look for file.
If you intend to copy the files through using ./ (current working directory), I think it would be better to specify where current is. And you can do this using the WORKDIR keyword.
Example:
WORKDIR /path/to/workdir
The WORKDIR instruction sets the working directory for any RUN, CMD,
ENTRYPOINT, COPY and ADD instructions that follow it in the
Dockerfile. If the WORKDIR doesn’t exist, it will be created even if
it’s not used in any subsequent Dockerfile instruction.
That way docker will not get confused.
See:
https://docs.docker.com/engine/reference/builder/#/workdir
I had a similar problem which led me to this thread, however my issue was not quite the exact same as yours. For me the problem was that I was using an alpine base image and my script was referencing #!/bin/bash, I just had to update mine to #!/bin/sh at the top of my script instead.