How to run a dockerfile? - linux

Found a dockerfile that want to create image and run:
https://gist.github.com/matsuu/d5b4e83b3d591441f01b7be2ede774e2
Stored it in a new folder as centos-redhat-8-beta.dockerfile on my computer and tried:
docker build -t centos-redhat-8-beta .
unable to prepare context: unable to evaluate symlinks in Dockerfile path:
lstat /Users/dnk306/docker/centos-redhat-8-beta/Dockerfile: no such file or directory
What is exact command that need to run?

Dockerfile is not an extension, per default the file should be called Dockerfile for the build command to use it.
If you want to use a different name, though, the option -f or flag --file can help you achieve this.
docker build -t centos-redhat-8-beta -f centos-redhat-8-beta.dockerfile .
From the documentaion:
By default the docker build command will look for a Dockerfile at the root of the build context. The -f, --file, option lets you specify the path to an alternative file to use instead. This is useful in cases where the same set of files are used for multiple builds. The path must be to a file within the build context. If a relative path is specified then it is interpreted as relative to the root of the context.
Source: https://docs.docker.com/engine/reference/commandline/build/#text-files

Related

Build docker image jar file : COPY failed: no source files were specified

I have a leshan server jar file (to which I have made some changes) obtained by running the maven clean install. I specify that I work in linux and I put this jar file inside a "leshan_docker" folder contained in the desktop. within the same folder there is also a dockerfile to build the server image, and it is written as follows:
FROM openjdk:8-jre-alpine
COPY /Desktop/leshan_docker/leshan-server-demo-*.jar /Desktop/leshan_docker/
CMD ["java", "-jar", "/leshan-server-demo-2.0.0-SNAPSHOT.jar"]
but when I go to build through this command:
sudo docker build -f Dockerfile3 -t leshan-server3 .
It reports me the following error:
Sending build context to Docker daemon 12MB
Step 1/3 : FROM openjdk:8-jre-alpine
---> f7a292bbb70c
Step 2/3 : COPY /Desktop/leshan_docker/leshan-server-demo-*.jar /Desktop/leshan_docker/
COPY failed: no source files were specified
How can I go about solving the problem? Thanks in advance for your answers.
Your source path with the COPY command should be relative to the build context. Your build context is in the folder you're running sudo docker build in since the final argument you gave was .. I highly recommend taking a look at the docs.
The destination path for the COPY command should be relative to the path in your container. What may work now is to move your .jar to the root directory and run it from there.
So if your jar files are in the same directory you're running the command in, change it to:
COPY leshan-server-demo-*.jar /
It would be better practice to actually create a new directory in the container to hold your .jar file to keep your work more organized.

Dockerizing Node.js app - what does: ENV PATH /app/node_modules/.bin:$PATH

I went through one of very few good dockerizing Vue.js tutorials and there is one thing I don't understand why is mandatory in Dockerfile:
# add `/app/node_modules/.bin` to $PATH
ENV PATH /app/node_modules/.bin:$PATH
COPY package.json /usr/src/app/package.json #not sure though how it relates to PATH...
I found only one explanation here which says:
We expose all Node.js binaries to our PATH environment variable and
copy our projects package.json to the app directory. Copying the JSON
file rather than the whole working directory allows us to take
advantage of Docker’s cache layers.
Still, it doesn't made me any smarter. Anyone able to explain it in plain english?
Error prevention
I think this is just a simple method of preventing an error where Docker wasn't able to find the correct executables (or any executables at all). Besides adding another layer to your image, there is in general as far as I know no downside in adding that line to your Dockerfile.
How does it work?
Adding node_modules/bin to the PATH environment variable ensures that the executables created during the npm build or the yarn build processes can be found. You could also COPY your locally builded node_modules folder to the image but it's advised to build it inside the Docker container to ensure all binaries are adapted to the underlying OS running in the container. The best practice would be to use multistage builds.
Furthermore, adding the node_modules/bin at the beginning of the PATH environment variable ensures that exactly these executables (from the node_modules folder) are used instead of any other executables which might also be installed on the system inside the Docker image.
Do I need it?
Short answer: Usually no. It should be optional.
Long answer: It should be enough to set the WORKDIR to the path where the node_modules is located for the issued RUN, CMD or ENTRYPOINT commands in your Dockerfile to find the correct binaries and therefore to successfully get executed. But I for example had a case where Docker wasn't able to find the files (I had a pretty complex setup with a so called devcontainer in VSCode). Adding the line ENV PATH /app/node_modules/.bin:$PATH solved my problem.
So, if you want to increase the stability of your Docker setup in order to make sure that everything works as expected, just add the line.
So I think the benefit of this line is to add the node_modules path from the Docker container to the list of PATHs on the relevant container. If you're on a Mac (or Linux I think) and run:
$ echo $PATH
You should see a list of paths which are used to run global commands from your terminal i.e. gulp, husky, yarn and so on.
The above command will add node_modules path to the list of PATHs in your docker container so that such commands if needed can be run globally inside the container they will work.
.bin (short for 'binaries') is a hidden directory, the period before the bin indicates that it is hidden. This directory contains executable files of your app's modules.
PATH is just a collection of directories/folders that contains executable files.
When you try to do something that requires a specific executable file, the shell looks for it in the collection of directories in PATH.
ENV PATH /app/node_modules/.bin:$PATH adds the .bin directory to this collection, so that when node tries to do something that requires a specific module's executable, it will look for it in the .bin folder.
For each command, like FROM, COPY, RUN, CMD, ..., Docker creates a image with the result of this command, and this images are called as layers. The final image is the result of merge of all layers.
If you use the COPY command to store all the code in one layer, it will be greater than store a environment variable with path of the code.
That's why the cache layers is a benefit.
For more info about layers, take a look at this very good article.

docker image directory does not exist during build

I'm building a simple image from a Dockerfile: (note, pm3 is the name of the folder this Dockerfile lives in)
FROM continuumio/miniconda3
MINTAINER Jordan Miller
ENV PORT=5000
COPY . /opt/repos/
WORKDIR /opt/repos/pm3/
RUN ls -la
RUN python /opt/repos/pm3/lib/acquire_requirements.py
EXPOSE $PORT
ENTRYPOINT ["python","/opt/repos/pm3/src/web/api.py"]
I use docker build -f Dockerfile -t jm/pm3 . to build it. Now I thought this was working great last week, but I made some changes and it broke. so I ran docker system prune to clean everything out. But that didn't fix it so I think it's something wrong with the code.
At any rate, here's the error I get:
Step 7/9 : RUN python /opt/repos/pm3/lib/acquire_requirements.py
---> Running in f842a282a6a0
Invalid requirement: '/opt/repos/pm3/lib/acquire_requirements.py'
File '/opt/repos/pm3/lib/acquire_requirements.py' does not exist.
But it really is there, in my windows machine there's a lib folder in the pm3 folder and there is a acquire_requirements.py in the lib folder. should I not include the entire path to it on the linux box or something?
I included that line RUN ls -la after it gave me the error because I wanted to see if it copied over the folder correctly. but the output of that didn't show me anything had copied over, it showed an empty file. so I don't understand really what's going on. If the working directory really is /opt/repos/pm3 then shouldn't I see src when I run ls?
I'm hoping there's something obvious about linux or docker that I'm missing here. any ideas?
so I discovered by creating an image without the RUN python /opt/repos/pm3/lib/acquire_requirements.py that it doens't create a folder after the /opt/repos/ called pm3 like my root directory of the Dockerfile is in.
So I had to add that in manually to the command:
COPY . /opt/repos/ -> COPY . /opt/repos/pm3/

$(pwd) - one level up

I'm pretty new to the bash/shell script world, I'm trying to do the below and it could be pretty simple but I wasn't able to figure out the command, would be great if someone could help me out here and also point me to some documentation wrt to shell script topics. Thank you in advance.
My build.sh and Dockerfile resides under a folder called .settings and this folder lives directly under the app root. Now inside my build.sh and Dockerfile when I refer something like $(pwd) or COPY . /apps/ it might not work since my build.sh and Dockerfile does not live directly under the app root.
What command I can use in this scenario inside the files that I referenced above. Hope I made it clear. Once again this could be very simple since I'm a newbie in this arena I find it a little difficult.
inside build.sh, reference to $(pwd)
docker run \
-u root \
--rm \
-v $(pwd):/app \ ----> this $(pwd) references the application root, but if I
move this build.sh inside a folder called .settings then the $(pwd) context
would change and I still want to refer it to the root.
<MYIMAGE NAME FROM LOCAL REPO>
The last arg to docker build, often something like docker build . is the build context in docker. This directory is sent to the server where the build runs and all COPY and ADD commands are performed using this context. These commands do not run on the client, and docker is a client/server application, so anything not in that context simply doesn't exist for the purpose of building an image.
So in the above example, docker build . the current directory is the build context and if that's run while you're inside of the .settings directory, only those files are part of the build context. Therefore your build.sh script needs to pass a different directory, and also reference where the Dockerfile is inside of that build context. That would look like:
docker build -f .settings/Dockerfile ..
When you do this, all of the COPY and ADD commands will now be relevant to parent directory, so you may need to adjust your Dockerfile to compensate.
For your $(pwd) reference, you can either cd .. before running your docker run command or update the command to look like:
docker run \
-u root \
--rm \
-v $(pwd)/..:/app \
<your image>

'docker build' gives error that 'docker run' doesn't. How are they different?

My project is setup like this:
./ -
Dockerfile
package.json
build
compiled files from frontend and backend directories get put here
backend
app.js
frontend
frontend files...
scripts
startServer.sh
build.sh
startServer.sh:
docker build ../ --tag myImage
# The build script compiles all my assets and places
# them in the top level 'build' directory which i am
# trying to link to my docker image so I can recompile
# on each file change and have the changes show in the docker image.
./build.sh
docker run --volume /path/to/build/dir:/src/app myImage
Dockerfile:
FROM node:4.4.7
RUN ls src/app
The RUN command in the Dockerfile gives me this error when the build command from the startServer script is called:
ls: cannot access src/app: No such file or directory
If I change RUN to CMD it gives no error. Also, even after the build gives that error, it finishes the build and the docker run command gives no error.
Is the 'docker build' command actually trying to add the 'build' folder to the image from which containers are launched? Or is it just compiling some commands for the images to use when they are made?
If it is the later, how do you make one Dockerfile that is used for both building and running that works in both cases?
I feel like I might be missing a crucial concept with Docker, but I've gone through the tutorials and docs and couldn't solve this.
There is no src/app folder in the node image, so this is an expected error. The node image expects you to add your own /usr/src/app, either with a COPY step in your build, or with a volume mapping after the build is finished.
The RUN gives a step to run to add a layer to the resulting built image, so an ls makes little sense there since you didn't modify the image with new content.
The CMD gives a default command to run if one is not passed at the end of the docker run, so if you do a docker run node /bin/bash, the ls src/app CMD will never be run. This also runs after other steps in your build, and after any volume mounts you may be running on your container, which would create this folder.
When you run the docker image, you mount data volume to /src/app
But in docker script, you tried to access src/app
Because the default working directory is not a root. you cannot access src directory.
so, edit your docker file to
FROM node:4.4.7
RUN ls /src/app

Resources