Moving files onto docker container and running them - docker

I'm pretty new to docker, so I apologize if this is a simple question. I need to create a script of some sort that will start a docker image in ubuntu:16.04, copy files from a directory onto the container, and run some of the code that was just copied in.
From what I understand, the first step would be to start up the container with something like this:
docker run --name test_container my_image
Then, I need to copy over the files. From what I have found, this is conventionally done on the host with a command like so:
docker cp src/. test_container:/code/src
Lastly, lets say I want to run some code from my container, that I just put on it. If I started my container with the -it tag, I could probably just do something like the following (assuming there was a makefile and hello_world.c in the src folder that was copied):
cd code/src/
make
./hello_world
But is there some way I can have this automated. For example, I want to put the following lines in my docker file:
WORKDIR code/src/
RUN make
RUN ./hello_world
But the main problem is that if I run my dockerfile right at the beginning, I will not have my copied files on the container by the time I get to these commands at the bottom.
I was looking to see if there is a way to copy files onto the container by running commands inside the container. For example:
RUN docker cp src/. test_container:/code/src
But that doesn't seem to work, which kind of makes sense. So I was wondering if there is another good way to automate a process like this.

If you want to bake your files into the image the command is
COPY src /code/src/
WORKDIR /code/src
RUN make
CMD ["./hello_world"]
If you want to use files at runtime, you'd do it with something like
docker run -v $CWD/src:/code/src myimage make

Related

How does to download and extract .tar files in a container for Dockerfile?

Over here is a use case - I want to download and extract all files from a particular website and allow users to specify from which workweek it might be done. Please, imagine using one docker command and specifying only the variable which tells where to go, download and extract files.
The problem is I want to allow a user to manipulate variables that refer to a particular workweek.
Now it is only my idea, not sure If I am thinking right before I start to design my Dockerfile.
Dockerfile:
...
ENV TARGET="$WW_DIR"
...
Now you can imagine that the first user wants to download files from WW17 so he can type:
docker container run -e TARGET=WW17 <image_name>
The second one wants to download files from WW25:
docker container run -e TARGET=WW25 <image_name>
Etc.
Underhood Dockerfile knows that it must go to the directory from WW17 (in the first scenario) or WW25 (in the second scenario). My imagination is that a new container is created then using for example "curl" files are downloaded from an external server and extracted.
Can you recommend to me the best methods with some examples of how to solve it? Apply bash script inside of the container?
Thanks.
There is no Dockerfile at docker container run, it just runs the command. So write a command that does what you want or add the data to the image when building it with Dockerfile.
# Dockerfile
FROM your_favourite_image
COPY your_script /
RUN chmod +x /your_script
CMD /your_script
# your_script
#!/usr/bin/env your_favourite_langauge_like_python_or_bash_or_perl
# download the $TARGET or whatever you want to do
And then
docker build -t image .
docker run -r TARGET=WW1 image
Reading: https://docs.docker.com/engine/reference/builder/#cmd https://docs.docker.com/engine/reference/builder/#entrypoint https://docs.docker.com/get-started/overview/ https://btholt.github.io/complete-intro-to-containers/dockerfile

How can I reproduce docker commands seen in docker hub image layers?

I am wondering how it is possible to reproduce the docker commands seen in this docker image. The image copies certain versions of clang and gcc, which is something I wish to do in my own dockerfile. I cannot use the linked docker image, as it contains many commands that are unnecessary for the work I want to do.
The very first command is
ADD file:2cddee716e84c40540a69c48051bd2dcf6cd3bd02a3e399334e97f20a77126ff in /
Further down, there are many similar COPY commands. I wish to reproduce the following command in my own dockerfile:
COPY dir:49371ba683da700cabfad7284da39bd2144aa0c46086c3015a74737d7be6b51e in /compilers/clang/3.4.2
The command copies clang-3.4.2 into the given folder. I am unsure how I can do the same, or even what the hash is/means.
I tried looking, but I couldn't find the Dockerfile used to create the image. There is another way though.
It's quite a large image and I'm on a terrible internet connection, so I haven't tested this myself, but one thing you can do is copy the things you need from the image into a new one of your own like this
FROM cnsun/perses:perses_part_54_name_clang_trunk AS original
FROM ubuntu:latest
COPY --from=original /compilers/clang/3.4.2 /compilers/clang/3.4.2
You can also copy the files from the image to your computer. Then you can copy them from there into new images without referencing the cnsun image:
docker run --rm -v $(pwd):/dest --entrypoint /bin/bash cnsun/perses:perses_part_54_name_clang_trunk -c "cp -r /compilers/clang/3.4.2 /dest"
This will copy the /compilers/clang/3.4.2 directory into the current directory on the host. If your host is Windows, replace $(pwd) with %cd%.

Lifecycle of Files copied to a docker container

I'm a Docker newbie and I fired the following command which successfully copied the file to a running container.
sudo docker cp app.py 943395e93d1d:/app/app.py
Note : The container was already contains a app.py and so my guess was that because app.py is running inside the container it will not allow the copy .
I did another thing now
sudo docker cp sample.txt 943395e93d1d:/app/sample.txt
Now this also went successfully .
My question : Will the sample.txt file continue to exist within the container even after I stop the container ? So that if I start it again the updated files are there .
Because that means I don't build the docker file again and again but just copy the files if there are changes in some assets of my application ?
Anything you copy in with docker cp will be lost as soon as the container exits. I'd use this command sparingly. It's certainly not a way to update your code; re-run docker build when your application changes.
(In typical use, with an interpreted language where just copying in source code is enough, re-running docker build should be very quick. It will generally know to skip over time-consuming dependency installation and just COPY in the new source code. Even if you only have a single container using Docker Compose to drive things will give you a single place to list out the options you need to run it.)

How to copy a file from the host into a container while starting?

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

Is it possible to persist a file in a docker image?

I want to prepare a base docker image that executes a command and produces a report. I want this to be persisted within the image for the next docker file. Is this possible?
What you can do is to set a WORKDIR within your dockerfile e.g.
WORKDIR /data
and use a volume with the run command for the built image.
docker run -v /users/home/your_user/use_case_folder:/data -it your_image_tag /bin/bash
When you run your reports/predictions you have to write them to /data, then your files will be placed on your local system. You now can use the next
Dockerfile and use the same volume mount, which is defined as WORKDIR within the new Dockerfile. Sharing the results within the image itself for another image is not possible as far as I know. You will always have to use an outside mounted File System or Database or sth. similar.
Maybe here you can find some infos too:
https://docs.docker.com/storage/volumes/#restore-container-from-backup

Resources