Say I set ENV VAR=foo while building image1.
Can I access this VAR from another Dockerfile, like the COPY --from synthax?
I need to do this without building "FROM image1"
Related
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
I find that if I implement my own CMD, when I run a container with my derived image, I lost all the functionality provided by the base image.
Inclusive, my container doesn't keep running if I put a CMD in the derived Dockerfile....
How to reuse the same ENTRYPOINT and CMD from a base image, just adding more commands?
I want to do that because I want to run certain commands every time I run a new container.
(That sounds right?)
Example:
php:7.4.7-apache
ENTRYPOINT ["docker-php-entrypoint"]
CMD ["apache2-foreground"]
https://github.com/docker-library/php/tree/b6fd2f70018163227f0f18f3ba1fa4d70e6d929e/7.4/buster/apache
Docker only runs one command when a container is starting and if you have a base image and a derived image, it will run the command from the derived image. Or if you override the command while using docker run command / use a different command in docker-compose, it will take priority over the command defined inside the image.
You can create a shell file or any executable file (like python file if python is available in the container) to execute any number of commands and run this file during container startup using a bash shell (or any other shell that's available in the container).
I have a very simple Dockerfile like the below :-
FROM my-base-image
COPY abc.properties /opt/conf/
Now my base-image has a docker entrypoint (at the end of its Dockerfile) but this resulting image as you can see has none. Does this work or do we need to have a docker entrypoint/CMD in any given Dockerfile. Also what would be the order of execution for the COPY instruction in the resulting image. With this i mean since this Dockerfile has no entrypoint it would execute one from the base image but will that be executed after the COPY instruction or will the base image entrypoint be executed first and then execute this COPY instruction when the container starts
Just looking for concepts in docker.
Several of the Dockerfile directives (notably ENTRYPOINT and CMD, but also EXPOSE, LABEL, and MAINTAINER) just set metadata in the image; they don't really do anything themselves. Within a single Dockerfile this will work just fine:
FROM ubuntu:18.04
WORKDIR /app
# Just remembers this in the image metadata; doesn't actually run it
CMD ["/app/main.sh"]
# ...we should actually copy the file in too
COPY main.sh /app
When you have one Dockerfile built FROM another image it acts almost entirely like you ran all of the commands in the first Dockerfile, then all of the commands in the second Dockerfile. Since CMD and ENTRYPOINT just set metadata, the second image inherits this metadata.
Building and running an image are two separate steps. In the example you show, the COPY directive happens during the docker build step, and the base image's command doesn't take effect until the later docker run step. (This is also true in Docker Compose; a common question is about why Dockerfile steps can't connect to other containers declared in the Compose YAML file.)
There is one exception, and it's around ENTRYPOINT. If you have a base image that declares an ENTRYPOINT and a CMD both, and you redeclare the ENTRYPOINT in a derived image, it resets the CMD as well (very last paragraph in this section). This usually isn't a practical problem.
When you build an image, the Dockerfiles are merged as per their instructions. Building an image doesnt mean it runs. So ideally your instructions from your Base Dockerfile and your current Dockerfile will be packed. Since you have mentioned CMD entrypoint in the Base Dockerfile, that will be used for execution of your image inside the container, when you use docker run.
So when you build your image, the COPY statement from your child Dockerfile will also get set. and your image must be built fine.
Execute your docker build and docker run and let us know
I have a Dockerfile that creates the build image I want to use here: ~/build/Dockerfile then I use a standard image to deploy
The image built from ~/build/Dockerfile is not Published anywhere, I know I can simply copy paste the one Dockerfile into the other, however it would be better if I could simply reference it so..
Is it possible to somehow reference the Dockerfile itself when deploying?
like so:
FROM [insert something that creates an image using ~/build/Dockerfile] as build-env
... build operations ....
FROM some-image
COPY --from=build-env /built .
ENTRYPOINT [blah]
This won't work but is there some other way to accomplish this?
No you can't do it because you have to provide an image to FROM.
Change the COPY line to
COPY --from=step1 /built .
And write a script to build your image:
cd path1
docker build -t step1 .
cd path2
docker build -t final_image .
(if you don't want to hard code step1 in the Dockerfile, replace it with a var and call with ARG)
Generally things in Docker space like the docker run command and the FROM directive will use a local image if it exists; it doesn't need to be pushed to a repository. That means you can build your first image and refer to it in the later Dockerfile by name. (There's no way to refer to the other Dockerfile per se.)
Newer versions of Docker have an extended form of the Dockerfile COPY command which
accepts a flag --from=<name|index>.... In case a build stage with a specified name can’t be found an image with the same name is attempted to be used instead.
So if you ahead of time run
docker build -t build-env ~/build
then the exact syntax you show in your proposed Dockerfile will work
FROM some-image
COPY --from=build-env /built .
and it doesn't matter that the intermediate build image isn't actually pushed anywhere.
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