I am trying to learn Docker from other DockerFiles and and set up a customised development environment for my projects.
But from other DockerFiles, I don't understand - where are those src files coming from for ADD and COPY? How do I create them myself? What code should I put inside them?
For instance, fauria/lamp:
COPY run-lamp.sh /usr/sbin/
Where can I get this file or create it? What are the lines inside that file?
again, nickistre/ubuntu-lamp:
ADD supervisord.conf /etc/
Where can I get a copy of it?
Another one, linuxconfig/lamp:
# Include supervisor configuration
ADD supervisor-lamp.conf /etc/supervisor/conf.d/
ADD supervisord.conf /etc/supervisor/
supervisor-lamp.conf and supervisord.conf?
Any ideas?
When you run a docker build ., files in the folder . that are not included inside the .dockerignore file are sent to the Docker engine. From this context of files, docker performs the COPY or ADD commands.
With your first example, the Dockerfile is located in a github repo (linked on the right side of the page on the Docker hub), and inside that repo is the run-lamp.sh script. Therefore if you're trying to reproduce the image, you would checkout the linked github repo and perform your build from within that folder.
Related
In my Dockerfile, I have the following:
COPY . /var/task
...which copies my app code into the image.
I need to exclude the vendor/ directory when performing this copy.
I cannot add vendor/ to .dockerignore, because that directory needs to be part of the image when it gets built within the image with a RUN composer install.
I cannot specify every file and directory that should be copied, because they may change and I can't rely on other developers to keep the list updated.
I've tried the following, with the following errors:
COPY [^vendor$]* /var/task
When using COPY with more than one source file, the destination must be a directory and end with a /
COPY [^vendor$]*/ /var/task
COPY failed: no source files were specified
It is actually enough to add the vendor directory to the .dockerignore file.
You can broadly follow the flow of files through docker build in three phases:
docker build reads files from the directory you name, ignoring things in the .dockerignore file, and sends them to the Docker daemon as the build context.
The COPY instruction copies files from the build context into the container filesystem.
RUN instructions do further transformation or processing.
If you put vendor in the .dockerignore file, it prevents the directory from being included in the build context. The build will go somewhat faster, and COPY won't have the files to copy into the image. It won't prevent a RUN composer install step later on from creating its own vendor directory in the image.
I don't think there is an easy solution to this problem.
If you need vendor for RUN composer install and you're not using a multistage build then it doesn't matter if you remove the vendor folder in the copy command. If you've copied it into the build earlier then it's going to be present in your final image, even if you don't copy it over in your COPY step.
One way to get around this is with multi-stage builds, like so:
FROM debian as base
COPY . /var/task/
RUN rm -rf /var/task/vendor
FROM debian
COPY --from=base /var/task /var/task
If you can use this pattern in your larger build file then the final image will contain all the files in your working directory except vendor.
There's still a performance hit though. You're still going to have to copy the entire vendor directory into the build, and depending on what docker features you're using that will still take a long time. But if you need it for composer install then there's really no way around this.
I have folder with files common for multiple docker images. How can I COPY these files to the image referencing the parent directory in Dockerfile? Obviously I don't want to duplicate this folder to all Docker projects.
When you run docker build the latest parameter is called PATH. Here is a description of it taken from here:
The docker build command builds Docker images from a Dockerfile and a “context”. A build’s context is the set of files located in the specified PATH [omissis]. The build process can refer to any of the files in the context. For example, your build can use a COPY instruction to reference a file in the context.
That means you have to specify a PATH that contains all of the files you need in your Dockerfile. Please be aware that changing the PATH to a different directory will require changing all of your COPY and ADD instructions to reflect the new directory structure.
I have one Rockerfile that builds 4 images; I also have one central .dockerignore file. For one of the images I require assets that are blocked by the .dockerignore file -- is there a way when doing ADD or COPY to force add / ignore this list?
It'll be a lot easier to do this in one file as opposed to three separate...!
In a simple way no.
The .dockerignore file is used to filter what will be used in the build before even reading the Dockerfile.
The docker daemon does not see your build folder, when the build starts, all the files in the context build folder are compressed (or just packed) and send to the daemon and only then it will read your Dockerfile to build the container with the files it received.
More content about .dockerignore: https://docs.docker.com/engine/reference/builder/#/dockerignore-file
In a normal Docker build the .dockerignore file affects the "build context" that is packaged up and sent to the docker server at the beginning of the build. If the "build context" doesn't contain the files then you can't reference them, so this is how the files are excluded. They don't "exist" for the build.
Rocker claims to run differently by not sending a build context to the server. The code looks like each ADD/COPY step is composed into a tar file that ignores the files. Also, the .dockerignore is read once at startup and cached.
As Rocker is not sending the build context before each build, only filtering for each ADD/COPY command, there is hope. But due to the ignore data being read only once at startup you can't do anything funky like copying different .dockerignore files at different stages of the build though.
Use MOUNT
One option is to continue using the .dockerignore as is and use a Rocker MOUNT command to manually copy the ignored directories. Their last example in the mount section demonstrates:
FROM debian:jessie
ADD . /app # assets/ in .dockerignore
WORKDIR /app
MOUNT .:/context
RUN cp -r /context/assets /app # include assets/
Change App Structure
The only other useful option I can think of is to split out your ADD or COPY into multiple commands so that you don't rely on the the .dockerignore to filter files to the other 3 images. This would probably require your assets directory to be stored outside of your application root.
I was trying to dockerize a nodejs application. I am adding code files to container using ADD command in Dockerfile. But i just noticed that folders named branches, objects, config, hooks are created automatically. Anybody out there know if its docker?
Found the issue. Using ADD ./* ./folder name/ instead of ADD . ./folder name created the extra folders.
But still wonder where those folders came from.
If your code file is in a git repo, you would have a .git subfolder that could be included by your ADD command.
That would explain the branches, hooks, ... folders.
As mentioned in "How to ADD all files/directories except hidden directory like .git in Dockerfile", you can exclude that folder with a .dockerignore file.
I don't really understand how .dockerignore works.
Is it intended to be used like the following:
First I add somethings in it such as *.md
Then I put this .dockerignore into the container.
After that I run and enter the container.
I create a new file named test.md and commit this container to the new image.
The new image will ignore this file so it will not be in the new container.
Before explaining the use of the .dockerignore file we must spend a little time understanding what docker build does.
Docker build. What does happen when I build an image ?
When you build an image from a Dockerfile using the docker build command the daemon will create a context. That context contains everything in the directory you executed the command in.
What does .dockerignore do and why use it?
The .dockerignore file allows you to exclude files from the context like a .gitignore file allow you to exclude files from your git repository.
It helps to make build faster and lighter by excluding from the context big files or repository that are not used in the build.
docker build has a step where it tars up the CONTEXT directory and sends it to the docker daemon. This is because the daemon and client might not exist on the same server.
The tar and network send is why unused files can slow down the build. These happen even if the daemon runs locally.
Then I put this .dockerignore in container.
nope, don't do that. The .dockerignore file is meant to be in the same directory as your Dockerfile and is intended to speed up the docker build command by excluding at build time some of the files that won't be used to build the docker image.