{"id":4965,"date":"2020-12-08T11:58:33","date_gmt":"2020-12-08T06:28:33","guid":{"rendered":"https:\/\/opstree.com\/blog\/\/?p=4965"},"modified":"2020-12-08T15:57:55","modified_gmt":"2020-12-08T10:27:55","slug":"dockerfile-hidden-secrets","status":"publish","type":"post","link":"https:\/\/opstree.com\/blog\/2020\/12\/08\/dockerfile-hidden-secrets\/","title":{"rendered":"Hidden Secrets of Dockerfile"},"content":{"rendered":"\r\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-5114\" src=\"https:\/\/opstree.com\/blog\/\/wp-content\/uploads\/2020\/12\/lfvwbmiw_400x400.png?w=400\" alt=\"\" width=\"387\" height=\"387\" \/><\/figure>\r\n\r\n\r\n\r\n<p class=\"has-text-align-justify\">Have you ever faced an issue in which while building the docker image, even though you have mentioned &#8220;apt-get -y update&#8221; the package you are trying to install is not found in the repository?<br \/><br \/>Here, in this blog, we are going to discuss two common scenarios that I faced along with the root cause of this problem. Let&#8217;s take a look.<br \/><br \/>First, it&#8217;s important to remember that valid intermediate images are not built again. They are loaded from cache. Dockerfile cache is considered valid if the build command gives a 0 return code.<\/p>\r\n<p><!--more--><\/p>\r\n<p class=\"has-text-align-justify\"><br \/>1. Consider the following Dockerfile.<\/p>\r\n<p class=\"has-text-align-justify\">\r\n\r\n<\/p>\r\n<pre><code>From ubuntu\r\n<code>RUN apt-get -y update<\/code> <code>RUN apt-get install -y python-pip<\/code><\/code><\/pre>\r\n<p class=\"has-text-align-justify\">\r\n\r\n<\/p>\r\n<p>Now when we build it:<\/p>\r\n<p class=\"has-text-align-justify\">\r\n\r\n<\/p>\r\n<pre class=\"wp-block-code\"><code>docker build -t test:image1 .<\/code><\/pre>\r\n<p class=\"has-text-align-justify\">\r\n\r\n<\/p>\r\n<p class=\"has-text-align-justify\">Suppose while building the above Dockerfile we created an intermediary image with the directive \u201cRUN apt-get update\u201d.<\/p>\r\n<p class=\"has-text-align-justify\">\r\n\r\n<\/p>\r\n<p class=\"has-text-align-justify\">This intermediate image will be used for all the subsequent docker builds.<br \/><br \/>Let&#8217;s say a couple of months down the line, there is a new package-manager release of python-pip which is required by the application. Now, even though in Dockerfile we have mentioned &#8220;RUN apt-get update&#8221;, the apt repo will not get updated because that image will be taken from the cache. Hence the latest version of python-pip won\u2019t be installed.<\/p>\r\n<p class=\"has-text-align-justify\">\r\n\r\n<\/p>\r\n<p>2. Our story is not over yet, consider the following.<br \/><br \/>Before building the below Dockerfile, turn your internet connection off.<\/p>\r\n<p class=\"has-text-align-justify\">\r\n\r\n<\/p>\r\n<pre><code>From ubuntu<br \/>RUN apt-get -y update ; echo \"status is: $?\" \r\nRUN apt-get install -y python-pip<\/code><\/pre>\r\n<p class=\"has-text-align-justify\">\r\n\r\n<\/p>\r\n<p>Now when we build it:<\/p>\r\n<p class=\"has-text-align-justify\">\r\n\r\n<\/p>\r\n<pre class=\"wp-block-code\"><code>Docker build -t test:image2 .\r\n<\/code><\/pre>\r\n<p class=\"has-text-align-justify\">\r\n\r\n<\/p>\r\n<p>Output:<\/p>\r\n<p class=\"has-text-align-justify\">\r\n\r\n<\/p>\r\n<pre><code>Err http:\/\/security.debian.org stable\/updates Release.gpg\u00a0\r\nCould not resolve 'security.debian.org'\u00a0\r\nHit http:\/\/192.168.1.100 stable Release.gpg\u00a0\r\nHit http:\/\/192.168.1.100 stable Release\r\nHit http:\/\/192.168.1.100 stable\/main i386 Packages\u00a0\r\nHit http:\/\/192.168.1.100 stable\/contrib i386 Packages\r\nHit http:\/\/192.168.1.100 stable\/non-free i386 Packages\r\nIgn http:\/\/192.168.1.100 stable\/contrib Translation-en\r\nIgn http:\/\/192.168.1.100 stable\/main Translation-en\r\nIgn http:\/\/192.168.1.100 stable\/non-free Translation-en\r\nReading package lists... Done\u00a0\r\nW: Failed to fetch http:\/\/security.debian.org\/dists\/stable\/updates\/Release.gpg \r\nW: Some index files failed to download. They have been ignored, or old ones used instead.\r\n\r\n\r\n<code>status is: 0<\/code><\/code><\/pre>\r\n<p class=\"has-text-align-justify\">\r\n\r\n<\/p>\r\n<p><br \/>\u00a0Aside from the\u00a0<code>ADD<\/code>\u00a0and\u00a0<code>COPY<\/code>\u00a0commands, cache checking does not look at any other file in the container to determine a cache match. For example, when processing a\u00a0<code>RUN apt-get -y update<\/code>\u00a0command, the files updated in the container are not examined to determine if a cache hit exists. In such a case, just the command string itself is used to find a match.<\/p>\r\n<p class=\"has-text-align-justify\">\r\n\r\n<\/p>\r\n<p class=\"has-text-align-justify\">As we can see above, \u201capt-get update\u201d throws a \u201cWARN\u201d and not an \u201cERROR\u201d and the return code is 0, which is a successful response. Since the response code is zero hence this image will get cached.<\/p>\r\n<p class=\"has-text-align-justify\">\r\n\r\n<\/p>\r\n<p class=\"has-text-align-justify\">The problem comes when we re-build the Dockerfile with our internet connection on, <strong>Docker will still take the &#8220;apt-get -y update&#8221; image from the cache and subsequent &#8220;RUN apt-get install -y python-pip&#8221; will fail <\/strong>because \u201capt-get -y update&#8221; didn&#8217;t trigger successfully in the last run.<\/p>\r\n<p class=\"has-text-align-justify\">\r\n\r\n<\/p>\r\n<p><strong>Solution<\/strong>:<\/p>\r\n<p class=\"has-text-align-justify\">\r\n\r\n<\/p>\r\n<p class=\"has-text-align-justify\">Try building the image again with the &#8220;no-cache&#8221; option. \u00a0This will force the rebuilding of layers already available.<\/p>\r\n<p class=\"has-text-align-justify\">\r\n\r\n<\/p>\r\n<pre><code>Docker build --no-cache -t test:image3 . <\/code><\/pre>\r\n<p class=\"has-text-align-justify\">\r\n\r\n<\/p>\r\n<p class=\"has-text-align-justify\"><strong>Conclusion<\/strong> :<br \/>Once an image is successfully built, all the intermediate images will be kept and reused. A valid docker intermediate image will not be built again unless we pass the &#8220;no-cache&#8221; option or delete the existing image.<\/p>\r\n<p class=\"has-text-align-justify\">\r\n\r\n<\/p>\r\n<p><a href=\"https:\/\/twitter.com\/Docker\/photo\" target=\"_blank\" rel=\"noopener\">Image Resource<\/a><\/p>\r\n<p class=\"has-text-align-justify\"><\/p>\r\n<p>Opstree is an End to End DevOps solution provider<\/p>\r\n<p><!-- \/wp:paragraph -->\r\n\r\n<!-- wp:paragraph --><\/p>\r\n<p><a href=\"https:\/\/www.opstree.com\/contact-us\" target=\"_blank\" rel=\"noreferrer noopener\">CONTACT US<\/a><\/p>\r\n<p class=\"has-text-align-justify\"><!-- wp:paragraph --><\/p>\r\n<p>&nbsp;<\/p>\r\n<p class=\"has-text-align-justify\"><!-- \/wp:paragraph --><\/p>","protected":false},"excerpt":{"rendered":"<p>Have you ever faced an issue in which while building the docker image, even though you have mentioned &#8220;apt-get -y update&#8221; the package you are trying to install is not found in the repository? Here, in this blog, we are going to discuss two common scenarios that I faced along with the root cause of &hellip; <a href=\"https:\/\/opstree.com\/blog\/2020\/12\/08\/dockerfile-hidden-secrets\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;Hidden Secrets of Dockerfile&#8221;<\/span><\/a><\/p>\n","protected":false},"author":197176204,"featured_media":29900,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_coblocks_attr":"","_coblocks_dimensions":"","_coblocks_responsive_height":"","_coblocks_accordion_ie_support":"","jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":false,"jetpack_social_options":{"image_generator_settings":{"template":"highway","enabled":false},"version":2}},"categories":[28070474,4504191],"tags":[768739308,768739305,255138070,206669118,3801184],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"https:\/\/opstree.com\/blog\/wp-content\/uploads\/2025\/11\/DevSecOps-1.jpg","jetpack_likes_enabled":true,"jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/pfDBOm-1i5","jetpack-related-posts":[],"_links":{"self":[{"href":"https:\/\/opstree.com\/blog\/wp-json\/wp\/v2\/posts\/4965"}],"collection":[{"href":"https:\/\/opstree.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/opstree.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/opstree.com\/blog\/wp-json\/wp\/v2\/users\/197176204"}],"replies":[{"embeddable":true,"href":"https:\/\/opstree.com\/blog\/wp-json\/wp\/v2\/comments?post=4965"}],"version-history":[{"count":24,"href":"https:\/\/opstree.com\/blog\/wp-json\/wp\/v2\/posts\/4965\/revisions"}],"predecessor-version":[{"id":5128,"href":"https:\/\/opstree.com\/blog\/wp-json\/wp\/v2\/posts\/4965\/revisions\/5128"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/opstree.com\/blog\/wp-json\/wp\/v2\/media\/29900"}],"wp:attachment":[{"href":"https:\/\/opstree.com\/blog\/wp-json\/wp\/v2\/media?parent=4965"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/opstree.com\/blog\/wp-json\/wp\/v2\/categories?post=4965"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/opstree.com\/blog\/wp-json\/wp\/v2\/tags?post=4965"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}