I tried to run this below command :
RUN if [ "$someargs" = "AAA" ]; then COPY from/ /usr/local/; fi
I got this error: This command returned a non-zero code: 127
You can't do, inside a
RUN
a Dockerfile
COPY
You need to find another way, you may have a script that creates different Dockerfile based on your test.
As the error states, COPY is not a shell command, it's a docker instruction which is supposed start with a newline.
Syntax -
INSTRUCTION arguments
You can use cp command in Dockerfile. However, you need to COPY the complete directory structure in your image to perform a cp operation. I haven't yet tried this yet but logically it should work.
You can apply the shell logic at your host & use docker cp to actually copy contents from/to host to/from container.
Ref - https://docs.docker.com/engine/reference/builder/
Related
What I want: i want to run a cpp file witch use opencv inside a container
What I've done:
installing an image of opencv:
docker pull spmallick/opencv-docker:opencv
create a docker file
FROM spmallick/opencv-docker:opencv
RUN ["g++ a.cpp -o a.out"]
COPY . .
CMD ["./a.out"]
bash command
sudo docker build -t project_opencv
OCI runtime create failed: container_linux.go:349: starting container process caused "exec: "g++ a.cpp -o a.out": executable file not found in $PATH": unknown
first I try this with cmd instead of RUN (how to use cmd inside a Dockerfile to compile a file). It couldn't find a.out although I've done COPY . .
Now it seems that there is a problem to create a.out
When you use the JSON-array form of RUN (or CMD or ENTRYPOINT), you explicitly provide the set of "words" that make up the command. As you've shown it, it is a single word, and Docker tries to run it as such, including the spaces in the command name it's looking up. You need to split it into its constituent words yourself.
RUN ["g++", "a.cpp", "-o", "a.out"]
The reverse side of this is that there is no splitting, expansion, or interpolation that happens in this command:
# Preserves both the literal $ and the spaces
RUN ["cp", "dollars-word-$word.txt", "file name with spaces.txt"]
Especially for RUN it's common to use the shell form. This wraps the command in sh -c so it works like an ordinary command. (There are technical reasons you might not want this for CMD and especially ENTRYPOINT.)
RUN g++ a.cpp -o a.out
RUN cp dollars-word-\$word.txt, 'file name with spaces.txt'
RUN tail env-var-$word.txt
First copy your a.cpp into docker image then your RUN command will work , I am not sure about your RUN ["g++ a.cpp -o a.out"] command this will work or not but try this:
FROM spmallick/opencv-docker:opencv
COPY . .
RUN ["g++ a.cpp -o a.out"]
CMD ["./a.out"]
I think you need to check the permissions for the files you have copied, from your host machine into the container.
You could also check the directory you are in, and if you need to change the directory, then you can use the WORKDIR command in your Dockerfile.
It would also be useful to start a bash session in the container, and run the commands manually. For each successful command, you can enter the command into the Dockerfile, or if you encounter an error, you can also troubleshoot more easily, rather than change the Dockerfile each time and run, and if you need to debug which is time consuming.
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'm confused about when should I use CMD vs RUN. For example, to execute bash/shell commands (i.e. ls -la) I would always use CMD or is there a situation where I would use RUN? Trying to understand the best practices about these two similar Dockerfile directives.
RUN is an image build step, the state of the container after a RUN command will be committed to the container image. A Dockerfile can have many RUN steps that layer on top of one another to build the image.
CMD is the command the container executes by default when you launch the built image. A Dockerfile will only use the final CMD defined. The CMD can be overridden when starting a container with docker run $image $other_command.
ENTRYPOINT is also closely related to CMD and can modify the way a container is started from an image.
RUN - command triggers while we build the docker image.
CMD - command triggers while we launch the created docker image.
I found this article very helpful to understand the difference between them:
RUN -
RUN instruction allows you to install your application and packages
required for it. It executes any commands on top of the current image
and creates a new layer by committing the results. Often you will find
multiple RUN instructions in a Dockerfile.
CMD -
CMD instruction allows you to set a default command, which will be
executed only when you run container without specifying a command.
If Docker container runs with a command, the default command will be
ignored. If Dockerfile has more than one CMD instruction, all but last
CMD instructions are ignored.
The existing answers cover most of what anyone looking at this question would need. So I'll just cover some niche areas for CMD and RUN.
CMD: Duplicates are Allowed but Wasteful
GingerBeer makes an important point: you won't get any errors if you put in more than one CMD - but it's wasteful to do so. I'd like to elaborate with an example:
FROM busybox
CMD echo "Executing CMD"
CMD echo "Executing CMD 2"
If you build this into an image and run a container in this image, then as GingerBeer states, only the last CMD will be heeded. So the output of that container will be:
Executing CMD 2
The way I think of it is that "CMD" is setting a single global variable for the entire image that is being built, so successive "CMD" statements simply overwrite any previous writes to that global variable, and in the final image that's built the last one to write wins. Since a Dockerfile executes in order from top to bottom, we know that the bottom-most CMD is the one gets this final "write" (metaphorically speaking).
RUN: Commands May not Execute if Images are Cached
A subtle point to notice about RUN is that it's treated as a pure function even if there are side-effects, and is thus cached. What this means is that if RUN had some side effects that don't change the resultant image, and that image has already been cached, the RUN won't be executed again and so the side effects won't happen on subsequent builds. For example, take this Dockerfile:
FROM busybox
RUN echo "Just echo while you work"
First time you run it, you'll get output such as this, with different alphanumeric IDs:
docker build -t example/run-echo .
Sending build context to Docker daemon 9.216kB
Step 1/2 : FROM busybox
---> be5888e67be6
Step 2/2 : RUN echo "Just echo while you work"
---> Running in ed37d558c505
Just echo while you work
Removing intermediate container ed37d558c505
---> 6f46f7a393d8
Successfully built 6f46f7a393d8
Successfully tagged example/run-echo:latest
Notice that the echo statement was executed in the above. Second time you run it, it uses the cache, and you won't see any echo in the output of the build:
docker build -t example/run-echo .
Sending build context to Docker daemon 9.216kB
Step 1/2 : FROM busybox
---> be5888e67be6
Step 2/2 : RUN echo "Just echo while you work"
---> Using cache
---> 6f46f7a393d8
Successfully built 6f46f7a393d8
Successfully tagged example/run-echo:latest
RUN - Install Python , your container now has python burnt into its image
CMD - python hello.py , run your favourite script
Note: Don’t confuse RUN with CMD. RUN actually runs a command and
commits the result; CMD does not execute anything at build time, but
specifies the intended command for the image.
from docker file reference
https://docs.docker.com/engine/reference/builder/#cmd
RUN Command:
RUN command will basically, execute the default command, when we are building the image. It also will commit the image changes for next step.
There can be more than 1 RUN command, to aid in process of building a new image.
CMD Command:
CMD commands will just set the default command for the new container. This will not be executed at build time.
If a docker file has more than 1 CMD commands then all of them are ignored except the last one. As this command will not execute anything but just set the default command.
RUN: Can be many, and it is used in build process, e.g. install multiple libraries
CMD: Can only have 1, which is your execute start point (e.g. ["npm", "start"], ["node", "app.js"])
There has been enough answers on RUN and CMD. I just want to add a few words on ENTRYPOINT. CMD arguments can be overwritten by command line arguments, while ENTRYPOINT arguments are always used.
This article is a good source of information.
I want to create new image from jdk, build it, it works; when I run my new imag, it return container id, but can't get the process-info when docker ps,this is my dockerfile:
# specified jdk version
FROM openjdk:7-jre
# env
ENV APP_HOME /usr/src/KOAL-OCSP
ENV PATH $APP_HOME:$PATH
# copy my app in .zip to /usr/src
COPY myapp.zip /usr/src/
# unzip copy file
RUN unzip /usr/src/myapp.zip
WORKDIR $APP_HOME
#port
expose 80
#run the setup script of my app when start container
CMD ["service.sh" "start"]
service.sh is a setup script is my app root-file, I wish the script can auto execuced when run the new self-build image.
I suspect that the container has executed and exited successfully. The container will stay alive as long as the processes that you have started using the services.sh script is still running.
In your case, the services.sh has executed and exited, thus causing the container to exit.
To view all containers, use docker ps -a
Update:
The error /bin/sh: 1: ./service.sh: not found indicates that the services.sh script is not found under $APP_HOME inside the Docker image. Make sure you add it under $APP_HOME using
ADD `service.sh` $APP_HOME
CMD ["service.sh" "start"]
The above is not valid json, it's missing a comma in the the array, so docker will execute it as a string which will fail since ["service.sh" will not be found as a command to run.
If you use docker ps -a you will see a list of all containers, including exited ones. From there, you can use docker logs $(docker ps -lq) to see the logs of the last container you tried to run. And you can docker inspect $(docker ps -lq) to see all the details about the last container it tried to run, including the exit code.
To get past your current error, correct your syntax with the missing comma:
CMD ["service.sh", "start"]
For the next problem you are seeing, a "not found" error can indicate:
The command doesn't exist inside your container (at the expected location). In your scenario, make sure it is included in /usr/src/KOAL-OCSP that you unzip in your image.
The shell script does exist, but calls a binary on the first line that doesn't exist in your image. E.g. if you call #!/bin/bash but only have /bin/sh in your container. This also happens when you edit the files on a Windows system and have ^M linefeeds that become part of the name of the binary that the container is looking for (/bin/sh^M instead of /bin/sh).
For binaries, this can happen if executable you are running has library dependencies that do not exist inside your container. For example, if you build on a glibc environment and run the container with a musl libc environment of Alpine, this same error message will appear.
I am trying to add a file from the host machine to the container into a hidden folder but it does not seem to be working. This is my Dockerfile:
FROM frekele/gradle:2.14.1-jdk8
MAINTAINER Fran Garcia <myemail#email.com>
ADD gradle.properties /root/.gradle/gradle.properties
# Run
CMD ["ls", "/root/.gradle/gradle.properties"]
But the file is not added. I can add this file to any other folder but not to a hidden one. Does anybody have any idea why this happens or how to fix it?
This is working as designed. Your error is in the way you use the CMD. Here's what's happening:
I created your Dockerfile, and then ran docker build . -t gr-foo
I started the container using docker run -it --rm gr-foo, which produced the following output line (among others):
exec: fatal: unable to exec ls /root/.gradle/gradle.properties: No such file or directory
I guess this is the error that you're seeing as well.
The CMD expects an array of values, where each entry is treated as one part of the command line. You need to change it to:
CMD ["ls", "/root/.gradle/gradle.properties"]
This will treat ls and the path as two different items, resulting in the desired output:
/root/.gradle/gradle.properties
ls exited 0