{"id":7735,"date":"2018-10-03T08:05:29","date_gmt":"2018-10-03T00:05:29","guid":{"rendered":"http:\/\/rmohan.com\/?p=7735"},"modified":"2018-10-03T08:05:58","modified_gmt":"2018-10-03T00:05:58","slug":"copy-and-add-commands-in-dockerfile","status":"publish","type":"post","link":"https:\/\/mohan.sg\/?p=7735","title":{"rendered":"COPY and ADD commands in Dockerfile"},"content":{"rendered":"<p><strong>COPY and ADD commands in Dockerfile<\/strong><\/p>\n<p>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.<\/p>\n<p>Build context concept<br \/>\nWhen 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.<\/p>\n<p>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:<\/p>\n<p>$ docker build -t testx \/home\/mohan\/hc<\/p>\n<p>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.<\/p>\n<p>The COPY and ADD commands cannot copy local files outside the context.<br \/>\nFor 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.<br \/>\nIn 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,<\/p>\n<p>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:<\/p>\n<p>Work with WORKDIR<\/p>\n<p>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:<\/p>\n<p>WORKDIR \/app<br \/>\nCOPY checkredis.py .<\/p>\n<p>Then build a container image named testx and run a container to view the file path:<\/p>\n<p>The checkredis.py file is copied to the WORKDIR \/app directory.<\/p>\n<p>The simplicity of the COPY command<br \/>\nIf you just copy the local file to the container image, the COPY command is the most appropriate. The format of the command is:<br \/>\nCOPY &lt;src&gt; &lt;dest&gt;<\/p>\n<p>In addition to specifying the full file name, the COPY command also supports Go-style wildcards, such as:<\/p>\n<p>COPY check* \/testdir\/ # Copy all files at the beginning of<br \/>\ncheck COPY check?.log \/testdir\/ # ? is a placeholder for a single character, such as matching file check1.log<\/p>\n<p>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:<\/p>\n<p>WORKDIR \/app<br \/>\nCOPY mohandir .<\/p>\n<p>The structure of the mohandir directory is as follows:<\/p>\n<p>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:<\/p>\n<p>WORKDIR \/app<br \/>\nCOPY mohandir .\/mohandir<\/p>\n<p>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&#8217;s article &#8221; multi-stage in Dockerfile &#8220;. In the multistage usage, you can use the COPY command to copy the product from the previous stage to another image, such as:<\/p>\n<p>FROM golang: 1.7.3<br \/>\nWORKDIR \/go\/src\/github.com\/sparkdevo\/href-counter\/<br \/>\nRUN go get -d -v golang.org\/x\/net\/html<br \/>\nCOPY app.go .<br \/>\nRUN CGO_ENABLED=0 GOOS=linux Go build -a -installsuffix cgo -o app .<\/p>\n<p>FROM alpine:latest<br \/>\nRUN apk &#8211;no-cache add ca-certificates<br \/>\nWORKDIR \/root\/<br \/>\nCOPY &#8211;from=0 \/go\/src\/github.com\/sparkdevo\/href-counter\/app .<br \/>\nCMD [&#8220;.\/app&#8221;]<\/p>\n<p>This code is referenced in the article &#8221; multi-stage in Dockerfile &#8220;, where the COPY command copies the product of the previous stage build into the current image by specifying the &#8211;from=0 parameter.<\/p>\n<p>The ADD command can also do other things.<br \/>\nThe format of the ADD command is the same as the COPY command, which is also:<br \/>\nADD &lt;src&gt; &lt;dest&gt;<\/p>\n<p>In addition to the fact that it can&#8217;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:<\/p>\n<p>Extract the compressed files and add them to the image<br \/>\nCopy files from url to image<br \/>\nOf course, these features also make the ADD command more complicated and less intuitive than the COPY command.<\/p>\n<p>Extract the compressed files and add them to the image.<br \/>\nIf 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:<\/p>\n<p>WORKDIR \/app<br \/>\nADD mohandir.tar.gz .<\/p>\n<p>This should be the best use case for the ADD command!<\/p>\n<p>Copying files from url to images<br \/>\nis 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):<\/p>\n<p>ADD http:\/\/example.com\/big.tar.xz \/usr\/src\/things\/<br \/>\nRUN tar -xJf \/usr\/src\/things\/big.tar.xz -C \/usr\/src\/things<br \/>\nRUN make -C \/ Usr\/src\/things all<\/p>\n<p>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:<\/p>\n<p>RUN mkdir -p \/usr\/src\/things \\<br \/>\n&amp;&amp; curl -SL http:\/\/example.com\/big.tar.xz \\<br \/>\n| tar -xJC \/usr\/src\/things \\<br \/>\n&amp;&amp; make -C \/usr\/src\/things All<\/p>\n<p>Well, it seems that the ADD command is only needed when extracting compressed files and adding them to the image!<\/p>\n<p>Tips for speeding up image construction<br \/>\nWhen 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:<\/p>\n<p>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.<\/p>\n<p>to sum up<br \/>\nWhen you first see the COPY and ADD commands, you can&#8217;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&#8217;s doubts about the COPY and ADD commands in the Dockerfile<\/p>\n","protected":false},"excerpt":{"rendered":"<p>COPY and ADD commands in Dockerfile<\/p>\n<p>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.<\/p>\n<p>Build context concept When you create a mirror from a [&#8230;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[82],"tags":[],"_links":{"self":[{"href":"https:\/\/mohan.sg\/index.php?rest_route=\/wp\/v2\/posts\/7735"}],"collection":[{"href":"https:\/\/mohan.sg\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/mohan.sg\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/mohan.sg\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/mohan.sg\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=7735"}],"version-history":[{"count":2,"href":"https:\/\/mohan.sg\/index.php?rest_route=\/wp\/v2\/posts\/7735\/revisions"}],"predecessor-version":[{"id":7737,"href":"https:\/\/mohan.sg\/index.php?rest_route=\/wp\/v2\/posts\/7735\/revisions\/7737"}],"wp:attachment":[{"href":"https:\/\/mohan.sg\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=7735"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/mohan.sg\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=7735"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/mohan.sg\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=7735"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}