COPY and ADD commands in Dockerfile
Two very similar commands COPY and ADD are provided in the Dockerfile. This article attempts to explain the basic functions of these two commands, as well as their similarities and differences, and then summarize their respective suitable application scenarios.
Build context concept
When you create a mirror from a Dockerfile using the docker build command, a build context is generated. The so-called build context is the collection of files in the path specified by the PATH or URL of the docker build command. Any file in the context can be referenced during the image build process, such as the COPY and ADD commands we will introduce, to reference the files in the context.
By default, the docker build -t testx . command in the command indicates that the build context is the current directory. Of course we can specify a directory as the context, such as the following command:
$ docker build -t testx /home/mohan/hc
We specify the /home/mohan/hc directory as the build context. By default, docker will use the Dockerfile found in the root of the context.
The COPY and ADD commands cannot copy local files outside the context.
For COPY and ADD commands, if you want to copy a local file to an image, the local file must be a file in the context directory.
In fact, this is a good explanation, because when the build command is executed, the docker client will send all the files in the context to the docker daemon . Considering that the docker client and the docker daemon are not on the same machine,
the build command can only get the file from the context. If we reference a file that is not in the context in the COPY and ADD commands of the Dockerfile, we receive an error similar to the following:
Work with WORKDIR
The WORKDIR command configures the working directory for subsequent commands such as RUN, CMD, COPY, and ADD. After the WORKDIR command is set, the relative path in the next COPY and ADD commands is the path specified relative to WORKDIR. For example, we add the following command to the Dockerfile:
COPY checkredis.py .
Then build a container image named testx and run a container to view the file path:
The checkredis.py file is copied to the WORKDIR /app directory.
The simplicity of the COPY command
If you just copy the local file to the container image, the COPY command is the most appropriate. The format of the command is:
COPY <src> <dest>
In addition to specifying the full file name, the COPY command also supports Go-style wildcards, such as:
COPY check* /testdir/ # Copy all files at the beginning of
check COPY check?.log /testdir/ # ? is a placeholder for a single character, such as matching file check1.log
For directories, the COPY and ADD commands have the same characteristics: only copy the contents of the directory and not the directory itself. For example, we add the following command to the Dockerfile:
COPY mohandir .
The structure of the mohandir directory is as follows:
There are only file1 and file2, and there is one less directory mohandir. If you want file1 and file2 to be saved in the mohandir directory, you need to specify the name of the directory in the target path, for example:
COPY mohandir ./mohandir
One use of the COPY command from the ADD command is in a multistage scenario. For an introduction and usage of multistage, please refer to the author’s article ” multi-stage in Dockerfile “. In the multistage usage, you can use the COPY command to copy the product from the previous stage to another image, such as:
FROM golang: 1.7.3
RUN go get -d -v golang.org/x/net/html
COPY app.go .
RUN CGO_ENABLED=0 GOOS=linux Go build -a -installsuffix cgo -o app .
RUN apk –no-cache add ca-certificates
COPY –from=0 /go/src/github.com/sparkdevo/href-counter/app .
This code is referenced in the article ” multi-stage in Dockerfile “, where the COPY command copies the product of the previous stage build into the current image by specifying the –from=0 parameter.
The ADD command can also do other things.
The format of the ADD command is the same as the COPY command, which is also:
ADD <src> <dest>
In addition to the fact that it can’t be used in multistage scenarios, the ADD command can do all the functions of the COPY command, and it can also do two cool features:
Extract the compressed files and add them to the image
Copy files from url to image
Of course, these features also make the ADD command more complicated and less intuitive than the COPY command.
Extract the compressed files and add them to the image.
If we have a compressed file package, we need to add the files from this compressed package to the image. Do you need to unpack the package and then execute the COPY command? Of course not needed! We can do this once with the ADD command:
ADD mohandir.tar.gz .
This should be the best use case for the ADD command!
Copying files from url to images
is a much more cool usage! However, in the best practices of the official documentation of docker , it is strongly recommended not to use this! ! The docker officially recommends that when we need to copy files from a remote location, it is best to use the curl or wget commands instead of the ADD command. The reason is that when using the ADD command, more mirror layers are created, and of course the size of the image will be larger (the two pieces of code below are from the docker official documentation):
ADD http://example.com/big.tar.xz /usr/src/things/
RUN tar -xJf /usr/src/things/big.tar.xz -C /usr/src/things
RUN make -C / Usr/src/things all
If you use the following command, not only does the number of layers in the image decrease, but the big.tar.xz file is also not included in the image:
RUN mkdir -p /usr/src/things \
&& curl -SL http://example.com/big.tar.xz \
| tar -xJC /usr/src/things \
&& make -C /usr/src/things All
Well, it seems that the ADD command is only needed when extracting compressed files and adding them to the image!
Tips for speeding up image construction
When using the COPY and ADD commands, we can use some tricks to speed up the mirror build process. For example, put the copy operation of the files that are least likely to change in the lower mirror layer, so that the cache generated by the previous build will be used when rebuilding the image. For example, the author needs to use the following files when building a mirror:
As shown in the figure above, the second step and the third step do not rebuild the mirror layer, but use the previous cache. From the fourth step, the mirror layer is rebuilt. When the file size is large and the number of files is large, especially when you need to perform operations such as installation, such a design is still very obvious for the speed of the build. So we should try to choose the Dockerfile method that can use the cache.
to sum up
When you first see the COPY and ADD commands, you can’t help wondering. But after analysis, you will find that the COPY command is designed for the most basic usage, with clear concepts and simple operation. The ADD command is basically a superset of the COPY command (except for the multistage scenario), which allows for some convenient and cool copy operations. The ADD command adds complexity to its use, such as copying compressed files from urls. I hope this article can solve everyone’s doubts about the COPY and ADD commands in the Dockerfile