<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Getting-Started | Haobin Tan</title><link>https://haobin-tan.netlify.app/tags/getting-started/</link><atom:link href="https://haobin-tan.netlify.app/tags/getting-started/index.xml" rel="self" type="application/rss+xml"/><description>Getting-Started</description><generator>Hugo Blox Builder (https://hugoblox.com)</generator><language>en-us</language><lastBuildDate>Sun, 13 Dec 2020 00:00:00 +0000</lastBuildDate><image><url>https://haobin-tan.netlify.app/media/icon_hu7d15bc7db65c8eaf7a4f66f5447d0b42_15095_512x512_fill_lanczos_center_3.png</url><title>Getting-Started</title><link>https://haobin-tan.netlify.app/tags/getting-started/</link></image><item><title>Getting Started</title><link>https://haobin-tan.netlify.app/docs/coding/docker/docker-getting-started/</link><pubDate>Thu, 06 Feb 2020 00:00:00 +0000</pubDate><guid>https://haobin-tan.netlify.app/docs/coding/docker/docker-getting-started/</guid><description/></item><item><title>What is Docker?</title><link>https://haobin-tan.netlify.app/docs/coding/docker/docker-getting-started/what-is-docker/</link><pubDate>Sat, 12 Dec 2020 00:00:00 +0000</pubDate><guid>https://haobin-tan.netlify.app/docs/coding/docker/docker-getting-started/what-is-docker/</guid><description>&lt;h2 id="overview">Overview&lt;/h2>
&lt;ul>
&lt;li>Docker is an open platform for developing, shipping, and running applications.&lt;/li>
&lt;li>Docker enables you to &lt;strong>separate your applications from your infrastructure&lt;/strong> so you can deliver software quickly.&lt;/li>
&lt;li>With Docker, you can manage your infrastructure in the same ways you manage your applications. By taking advantage of Docker’s methodologies for shipping, testing, and deploying code quickly, you can significantly reduce the delay between writing code and running it in production. &amp;#x1f44f;&lt;/li>
&lt;/ul>
&lt;img src="https://raw.githubusercontent.com/EckoTan0804/upic-repo/master/uPic/1*NXZYK4_f0lFJ8gpgcE5tHA.png" alt="Docker for Dummies, Literally. Yes, those days are long gone when you… | by Saad A Akash | Medium" style="zoom: 67%;" />
&lt;h2 id="docker-architecture">Docker architecture&lt;/h2>
&lt;h3 id="docker-engine">Docker engine&lt;/h3>
&lt;p>&lt;em>Docker Engine&lt;/em> is a client-server application with these major components:&lt;/p>
&lt;ul>
&lt;li>A server which is a type of long-running program called a &lt;strong>daemon&lt;/strong> process (the &lt;code>dockerd&lt;/code> command).&lt;/li>
&lt;li>A REST API which specifies interfaces that programs can use to talk to the daemon and instruct it what to do.&lt;/li>
&lt;li>A command line interface (CLI) client (the &lt;code>docker&lt;/code> command).&lt;/li>
&lt;/ul>
&lt;p>&lt;img src="https://raw.githubusercontent.com/EckoTan0804/upic-repo/master/uPic/engine-components-flow.png" alt="Docker Engine Components Flow">&lt;/p>
&lt;h3 id="docker-images">Docker images&lt;/h3>
&lt;ul>
&lt;li>An &lt;em>image&lt;/em> is a read-only template with instructions for creating a Docker container.&lt;/li>
&lt;li>Often, an image is &lt;em>based on&lt;/em> another image, with some additional customization.
&lt;ul>
&lt;li>For example, you may build an image which is based on the &lt;code>ubuntu&lt;/code> image, but installs the Apache web server and your application, as well as the configuration details needed to make your application run.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>You might create your own images or you might only use those created by others and published in a registry.
&lt;ul>
&lt;li>To build your own image, you create a &lt;em>&lt;strong>Dockerfile&lt;/strong>&lt;/em> with a simple syntax for defining the steps needed to create the image and run it.
&lt;ul>
&lt;li>Each instruction in a Dockerfile creates a layer in the image.&lt;/li>
&lt;li>When you change the Dockerfile and rebuild the image, only those layers which have changed are rebuilt.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;h3 id="docker-containers">Docker containers&lt;/h3>
&lt;ul>
&lt;li>A container is a &lt;strong>runnable instance of an image&lt;/strong>.&lt;/li>
&lt;li>You can create, start, stop, move, or delete a container using the Docker API or CLI. You can connect a container to one or more networks, attach storage to it, or even create a new image based on its current state.&lt;/li>
&lt;li>Containerization is increasingly popular because containers are:
&lt;ul>
&lt;li>&lt;strong>Flexible&lt;/strong>: Even the most complex applications can be containerized.&lt;/li>
&lt;li>&lt;strong>Lightweight&lt;/strong>: Containers leverage and share the host kernel, making them much more efficient in terms of system resources than virtual machines.&lt;/li>
&lt;li>&lt;strong>Portable&lt;/strong>: You can build locally, deploy to the cloud, and run anywhere.&lt;/li>
&lt;li>&lt;strong>Loosely coupled&lt;/strong>: Containers are highly self sufficient and encapsulated, allowing you to replace or upgrade one without disrupting others.&lt;/li>
&lt;li>&lt;strong>Scalable&lt;/strong>: You can increase and automatically distribute container replicas across a datacenter.&lt;/li>
&lt;li>&lt;strong>Secure&lt;/strong>: Containers apply aggressive constraints and isolations to processes without any configuration required on the part of the user.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;h3 id="registries">Registries&lt;/h3>
&lt;ul>
&lt;li>A Docker &lt;em>registry&lt;/em> stores Docker images. Docker Hub is a public registry that anyone can use, and Docker is configured to look for images on Docker Hub by default. You can even run your own private registry.&lt;/li>
&lt;li>When you use the &lt;code>docker pull&lt;/code> or &lt;code>docker run&lt;/code> commands, the required images are pulled from your configured registry. When you use the &lt;code>docker push&lt;/code> command, your image is pushed to your configured registry.&lt;/li>
&lt;/ul>
&lt;h2 id="docker-vs-virtual-machines-vms">Docker Vs. Virtual Machines (VMs)&lt;/h2>
&lt;p>A container runs &lt;em>natively&lt;/em> on Linux and shares the kernel of the host machine with other containers. It runs a discrete process, taking no more memory than any other executable, making it lightweight.&lt;/p>
&lt;p>By contrast, a &lt;strong>virtual machine&lt;/strong> (VM) runs a full-blown “guest” operating system with &lt;em>virtual&lt;/em> access to host resources through a hypervisor. In general, VMs incur a lot of overhead beyond what is being consumed by your application logic.&lt;/p>
&lt;p>&lt;img src="https://raw.githubusercontent.com/EckoTan0804/upic-repo/master/uPic/%E6%88%AA%E5%B1%8F2020-12-12%2022.34.09.png" alt="截屏2020-12-12 22.34.09">&lt;/p>
&lt;h2 id="get-docker">Get Docker&lt;/h2>
&lt;p>See: &lt;a href="https://docs.docker.com/get-docker/">Get Docker&lt;/a>&lt;/p>
&lt;h2 id="workflow-overview">Workflow overview&lt;/h2>
&lt;img src="https://raw.githubusercontent.com/EckoTan0804/upic-repo/master/uPic/docker-stages.png" alt="Docker for the busy researcher · Erick Matsen" style="zoom:67%;" />
&lt;h2 id="tutorials">Tutorials&lt;/h2>
&lt;ul>
&lt;li>
&lt;p>🔥 &lt;a href="https://www.guru99.com/docker-tutorial.html">Docker Tutorial for Beginners&lt;/a>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;a href="https://juejin.cn/post/6844903815729119245">30 分钟快速入门 Docker 教程&lt;/a>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;a href="https://takacsmark.com/getting-started-with-docker-in-your-project-step-by-step-tutorial/">Docker tutorial for beginners through examples - a step by step tutorial&lt;/a>&lt;/p>
&lt;/li>
&lt;/ul>
&lt;h2 id="reference">Reference&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="https://docs.docker.com/get-started/overview/">Docker overview&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>Container</title><link>https://haobin-tan.netlify.app/docs/coding/docker/docker-getting-started/docker-container/</link><pubDate>Sat, 12 Dec 2020 00:00:00 +0000</pubDate><guid>https://haobin-tan.netlify.app/docs/coding/docker/docker-getting-started/docker-container/</guid><description>&lt;h2 id="tldr">TL;DR&lt;/h2>
&lt;p>&lt;strong>Lifecycle&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>&lt;a href="https://docs.docker.com/engine/reference/commandline/create">&lt;code>docker create&lt;/code>&lt;/a> creates a container but does not start it.&lt;/li>
&lt;li>&lt;a href="https://docs.docker.com/engine/reference/commandline/rename/">&lt;code>docker rename&lt;/code>&lt;/a> allows the container to be renamed.&lt;/li>
&lt;li>&lt;a href="https://docs.docker.com/engine/reference/commandline/run">&lt;code>docker run&lt;/code>&lt;/a> creates and starts a container in one operation.&lt;/li>
&lt;li>&lt;a href="https://docs.docker.com/engine/reference/commandline/rm">&lt;code>docker rm&lt;/code>&lt;/a> deletes a container.&lt;/li>
&lt;li>&lt;a href="https://docs.docker.com/engine/reference/commandline/update/">&lt;code>docker update&lt;/code>&lt;/a> updates a container&amp;rsquo;s resource limits.&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>Starting and stpping&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>&lt;a href="https://docs.docker.com/engine/reference/commandline/start">&lt;code>docker start&lt;/code>&lt;/a> starts a container so it is running.&lt;/li>
&lt;li>&lt;a href="https://docs.docker.com/engine/reference/commandline/stop">&lt;code>docker stop&lt;/code>&lt;/a> stops a running container.&lt;/li>
&lt;li>&lt;a href="https://docs.docker.com/engine/reference/commandline/restart">&lt;code>docker restart&lt;/code>&lt;/a> stops and starts a container.&lt;/li>
&lt;li>&lt;a href="https://docs.docker.com/engine/reference/commandline/pause/">&lt;code>docker pause&lt;/code>&lt;/a> pauses a running container, &amp;ldquo;freezing&amp;rdquo; it in place.&lt;/li>
&lt;li>&lt;a href="https://docs.docker.com/engine/reference/commandline/unpause/">&lt;code>docker unpause&lt;/code>&lt;/a> will unpause a running container.&lt;/li>
&lt;li>&lt;a href="https://docs.docker.com/engine/reference/commandline/wait">&lt;code>docker wait&lt;/code>&lt;/a> blocks until running container stops.&lt;/li>
&lt;li>&lt;a href="https://docs.docker.com/engine/reference/commandline/kill">&lt;code>docker kill&lt;/code>&lt;/a> sends a SIGKILL to a running container.&lt;/li>
&lt;li>&lt;a href="https://docs.docker.com/engine/reference/commandline/attach">&lt;code>docker attach&lt;/code>&lt;/a> will connect to a running container.&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>Info&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>&lt;a href="https://docs.docker.com/engine/reference/commandline/ps">&lt;code>docker ps&lt;/code>&lt;/a> shows running containers.
&lt;ul>
&lt;li>&lt;code>docker ps -a&lt;/code> shows running and stopped containers.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;a href="https://docs.docker.com/engine/reference/commandline/logs">&lt;code>docker logs&lt;/code>&lt;/a> gets logs from container. (You can use a custom log driver, but logs is only available for &lt;code>json-file&lt;/code> and &lt;code>journald&lt;/code> in 1.10).&lt;/li>
&lt;li>&lt;a href="https://docs.docker.com/engine/reference/commandline/inspect">&lt;code>docker inspect&lt;/code>&lt;/a> looks at all the info on a container (including IP address).&lt;/li>
&lt;li>&lt;a href="https://docs.docker.com/engine/reference/commandline/events">&lt;code>docker events&lt;/code>&lt;/a> gets events from container.&lt;/li>
&lt;li>&lt;a href="https://docs.docker.com/engine/reference/commandline/port">&lt;code>docker port&lt;/code>&lt;/a> shows public facing port of container.&lt;/li>
&lt;li>&lt;a href="https://docs.docker.com/engine/reference/commandline/top">&lt;code>docker top&lt;/code>&lt;/a> shows running processes in container.&lt;/li>
&lt;li>&lt;a href="https://docs.docker.com/engine/reference/commandline/stats">&lt;code>docker stats&lt;/code>&lt;/a> shows containers&amp;rsquo; resource usage statistics.
&lt;ul>
&lt;li>&lt;code>docker stats --all&lt;/code> shows a list of all containers, default shows just running.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;a href="https://docs.docker.com/engine/reference/commandline/diff">&lt;code>docker diff&lt;/code>&lt;/a> shows changed files in the container&amp;rsquo;s FS.&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>Import/Export&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>&lt;a href="https://docs.docker.com/engine/reference/commandline/cp">&lt;code>docker cp&lt;/code>&lt;/a> copies files or folders between a container and the local filesystem.&lt;/li>
&lt;li>&lt;a href="https://docs.docker.com/engine/reference/commandline/export">&lt;code>docker export&lt;/code>&lt;/a> turns container filesystem into tarball archive stream to STDOUT.&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>Executing commands&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>&lt;a href="https://docs.docker.com/engine/reference/commandline/exec">&lt;code>docker exec&lt;/code>&lt;/a> to execute a command in container.&lt;/li>
&lt;/ul>
&lt;h2 id="what-is-docker-container">What is Docker container?&lt;/h2>
&lt;img src="https://raw.githubusercontent.com/EckoTan0804/upic-repo/master/uPic/docker-containerized-appliction-blue-border_2.png" alt="img" style="zoom: 40%;" />
&lt;ul>
&lt;li>Containers are an abstraction at the app layer that packages code and dependencies together.&lt;/li>
&lt;li>Multiple containers can run on the same machine and share the OS kernel with other containers, each running as isolated processes in user space.&lt;/li>
&lt;li>Containers take up less space than VMs (container images are typically tens of MBs in size), can handle more applications and require fewer VMs and Operating systems.&lt;/li>
&lt;/ul>
&lt;h2 id="basic-usages">Basic Usages&lt;/h2>
&lt;h3 id="pulling-image">Pulling image&lt;/h3>
&lt;p>We can use &lt;code>docker pull&lt;/code> to pull images from registry&lt;/p>
&lt;p>E.g.: Pull &lt;code>ubuntu&lt;/code> image&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">docker pull ubuntu
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="running-a-container">Running a container&lt;/h3>
&lt;p>Running of containers is managed with the Docker &lt;code>run&lt;/code> command.&lt;/p>
&lt;p>For example, we creat a container using an &lt;code>ubuntu:15.10&lt;/code> image and start it:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">docker run -it ubuntu:15.10 /bin/bash
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;ul>
&lt;li>&lt;code>-i&lt;/code> : interactive&lt;/li>
&lt;li>&lt;code>-t &lt;/code> : terminal&lt;/li>
&lt;li>&lt;code>ubuntu:15.10&lt;/code>: ubuntu image (version tag &lt;code>15.10&lt;/code>)&lt;/li>
&lt;li>&lt;code>/bin/bash&lt;/code> : command behind image&lt;/li>
&lt;/ul>
&lt;p>If we want our docker service to run in background, we can use argument &lt;code>-d&lt;/code>. For example:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">docker run -itd --name ubuntu-test-1 ubuntu /bin/bash
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;ul>
&lt;li>&lt;code>--name&lt;/code>: assign a name &lt;code>ubuntu-test-1&lt;/code> to this container&lt;/li>
&lt;li>&lt;code>-d&lt;/code>: If we add this argument, it won&amp;rsquo;t enter the container by default&lt;/li>
&lt;/ul>
&lt;h3 id="listing-containers">Listing containers&lt;/h3>
&lt;p>Listing running containers:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">docker ps
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Listing all containers&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">docker ps -a
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="starting-a-container">Starting a container&lt;/h3>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">docker start &amp;lt;stopped-container-ID&amp;gt;&lt;span class="o">=&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="ruuning-a-command-in-a-running-container">Ruuning a command in a running container&lt;/h3>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">docker &lt;span class="nb">exec&lt;/span> &amp;lt;container-name&amp;gt; &amp;lt;command&amp;gt;
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>For example, we run a container firstly in background&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">docker run -itd --name ubuntu-test-1 ubuntu /bin/bash
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Check the running container:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">docker ps
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">67cbb5de95c2 ubuntu &amp;#34;/bin/bash&amp;#34; 10 minutes ago Up 10 minutes ubuntu-test-1
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Now we want to print &lt;code>Hello world&lt;/code> in the terminal of container &lt;code>ubuntu-test-1&lt;/code> :&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">docker &lt;span class="nb">exec&lt;/span> -it ubuntu-test-1 &lt;span class="nb">echo&lt;/span> &lt;span class="s2">&amp;#34;Hello World&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">Hello World
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="stopping-a-container">Stopping a container&lt;/h3>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">docker stop &amp;lt;container-ID&amp;gt;
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="removing-a-container">Removing a container&lt;/h3>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">docker rm -f &amp;lt;container-ID&amp;gt;
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="reference">Reference&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="https://github.com/wsargent">wsargent&lt;/a>/&lt;strong>&lt;a href="https://github.com/wsargent/docker-cheat-sheet">docker-cheat-sheet&lt;/a>&lt;/strong>&lt;/li>
&lt;li>&lt;a href="https://www.runoob.com/docker/docker-container-usage.html">Docker容器使用&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>Image</title><link>https://haobin-tan.netlify.app/docs/coding/docker/docker-getting-started/docker-image/</link><pubDate>Sun, 13 Dec 2020 00:00:00 +0000</pubDate><guid>https://haobin-tan.netlify.app/docs/coding/docker/docker-getting-started/docker-image/</guid><description>&lt;h2 id="tldr">TL;DR&lt;/h2>
&lt;p>&lt;strong>Lifecycle&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>&lt;a href="https://docs.docker.com/engine/reference/commandline/images">&lt;code>docker images&lt;/code>&lt;/a> shows all images.&lt;/li>
&lt;li>&lt;a href="https://docs.docker.com/engine/reference/commandline/import">&lt;code>docker import&lt;/code>&lt;/a> creates an image from a tarball.&lt;/li>
&lt;li>&lt;a href="https://docs.docker.com/engine/reference/commandline/build">&lt;code>docker build&lt;/code>&lt;/a> creates image from Dockerfile.&lt;/li>
&lt;li>&lt;a href="https://docs.docker.com/engine/reference/commandline/commit">&lt;code>docker commit&lt;/code>&lt;/a> creates image from a container, pausing it temporarily if it is running.&lt;/li>
&lt;li>&lt;a href="https://docs.docker.com/engine/reference/commandline/rmi">&lt;code>docker rmi&lt;/code>&lt;/a> removes an image.&lt;/li>
&lt;li>&lt;a href="https://docs.docker.com/engine/reference/commandline/load">&lt;code>docker load&lt;/code>&lt;/a> loads an image from a tar archive as STDIN, including images and tags (as of 0.7).&lt;/li>
&lt;li>&lt;a href="https://docs.docker.com/engine/reference/commandline/save">&lt;code>docker save&lt;/code>&lt;/a> saves an image to a tar archive stream to STDOUT with all parent layers, tags &amp;amp; versions (as of 0.7).&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>Info&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>&lt;a href="https://docs.docker.com/engine/reference/commandline/history">&lt;code>docker history&lt;/code>&lt;/a> shows history of image.&lt;/li>
&lt;li>&lt;a href="https://docs.docker.com/engine/reference/commandline/tag">&lt;code>docker tag&lt;/code>&lt;/a> tags an image to a name (local or registry).&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>Cleaning up&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>&lt;code>docker image prune&lt;/code> is also available for removing unused images. (See &lt;a href="https://github.com/wsargent/docker-cheat-sheet#prune">Prune&lt;/a>).&lt;/li>
&lt;/ul>
&lt;h2 id="basic-usages">Basic usages&lt;/h2>
&lt;p>In Docker, everything is based on Images. Images are &lt;strong>templates&lt;/strong> for creating docker containers.&lt;/p>
&lt;h3 id="listing-images">Listing images&lt;/h3>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">docker images
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">REPOSITORY TAG IMAGE ID CREATED SIZE
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">docker-hello-world_web latest 85f9e3024e99 14 hours ago 196MB
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">my_image 0.0.1 9f3378bbf7e4 36 hours ago 133MB
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">nginx v3 6ed4b5e97df7 37 hours ago 133MB
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">python 3.7-alpine 0ce5215b0b31 43 hours ago 41.1MB
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">nginx latest 7baf28ea91eb 2 days ago 133MB
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">ubuntu latest f643c72bc252 2 weeks ago 72.9MB
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;ul>
&lt;li>
&lt;p>&lt;code>REPOSITORY&lt;/code> : repository source of image&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;code>TAG&lt;/code> : tag of image&lt;/p>
&lt;ul>
&lt;li>
&lt;p>There could be a number of tags in the same repository source, representing different version of this repository source. For example, in &lt;code>ubuntu&lt;/code> repository source, there are many different versions such as 15.10, 14.04, etc. We use &lt;code>REPOSITORY:TAG&lt;/code> to specify different images&lt;/p>
&lt;/li>
&lt;li>
&lt;p>For example, if we want to run container with &lt;code>ubuntu&lt;/code> version 15.10:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">docker run -t -i ubuntu:15.10 /bin/bash
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>
&lt;p>&lt;code>IMAGE ID&lt;/code> : ID of image&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;code>CREATED&lt;/code>: creation time of image&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;code>SIZE&lt;/code> : size of image&lt;/p>
&lt;/li>
&lt;/ul>
&lt;h3 id="downloading-images">Downloading images&lt;/h3>
&lt;p>Docker automatically downloads a non-existent image when we use it on the local host. If we want to pre-download the image, we can use the &lt;code>docker pull&lt;/code> command to download it.&lt;/p>
&lt;p>For example, we download &lt;code>ubuntu:13.10&lt;/code>, which doesn&amp;rsquo;t exist in the local machine:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">docker pull ubuntu:13.10
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="searching-images">Searching images&lt;/h3>
&lt;p>We can search images in &lt;a href="https://hub.docker.com/">Docker Hub&lt;/a>.&lt;/p>
&lt;h3 id="removing-images">Removing images&lt;/h3>
&lt;p>Removing image using image ID:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">docker rmi &amp;lt;image-ID&amp;gt;
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Removing image using image name&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">docker rmi &amp;lt;image-name&amp;gt;
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="building-image">Building image&lt;/h3>
&lt;p>We use the command &lt;code>docker build&lt;/code> to create a new image from scratch. To do this, we need to create a &lt;code>Dockerfile&lt;/code> file that contains a set of instructions to tell Docker how to build our image. (More see &lt;a href="https://haobin-tan.netlify.app/docs/coding/docker/docker-getting-started/learn-dockerfile/">Dockerfile&lt;/a>)&lt;/p>
&lt;h3 id="tagging-image">Tagging image&lt;/h3>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">docker tag &amp;lt;image-ID&amp;gt; &amp;lt;image-tag&amp;gt;
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="reference">Reference&lt;/h2>
&lt;ul>
&lt;li>
&lt;p>&lt;a href="https://www.runoob.com/docker/docker-image-usage.html">Docker 镜像使用&lt;/a>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;a href="https://www.tutorialspoint.com/docker/docker_images.htm">Docker - Images&lt;/a>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;a href="https://github.com/wsargent">wsargent&lt;/a>/&lt;strong>&lt;a href="https://github.com/wsargent/docker-cheat-sheet">docker-cheat-sheet&lt;/a>&lt;/strong>&lt;/p>
&lt;/li>
&lt;/ul></description></item><item><title>Dockerfile</title><link>https://haobin-tan.netlify.app/docs/coding/docker/docker-getting-started/learn-dockerfile/</link><pubDate>Sun, 13 Dec 2020 00:00:00 +0000</pubDate><guid>https://haobin-tan.netlify.app/docs/coding/docker/docker-getting-started/learn-dockerfile/</guid><description>&lt;h2 id="tldr">TL;DR&lt;/h2>
&lt;h2 id="what-is-dockerfile">What is Dockerfile?&lt;/h2>
&lt;p>&lt;strong>A Dockerfile is a text file that defines a Docker &lt;a href="https://haobin-tan.netlify.app/docs/coding/docker/docker-getting-started/docker-image/">image&lt;/a>. You’ll use a Dockerfile to create your own custom Docker image, in other words to define your custom environment to be used in a Docker &lt;a href="https://haobin-tan.netlify.app/docs/coding/docker/docker-getting-started/docker-container/">container&lt;/a>.&lt;/strong>&lt;/p>
&lt;p>&lt;img src="https://raw.githubusercontent.com/EckoTan0804/upic-repo/master/uPic/1*p8k1b2DZTQEW_yf0hYniXw.png" alt="Build a Docker Image just like how you would configure a VM | by Nilesh Jayanandana | Platformer Cloud | Medium">&lt;/p>
&lt;p>A Dockerfile is a step by step definition of building up a Docker image. The Dockerfile contains a list of instructions that Docker will execute when you issue the &lt;code>docker build&lt;/code> command. Your workflow is like this:&lt;/p>
&lt;ol>
&lt;li>Create the &lt;strong>Dockerfile&lt;/strong> and define the steps that build up your images&lt;/li>
&lt;li>Issue the &lt;code>docker build&lt;/code> command which will build a Docker image from your Dockerfile&lt;/li>
&lt;li>Use this image to start containers with the &lt;code>docker run&lt;/code> command&lt;/li>
&lt;/ol>
&lt;h2 id="dockerfile-commands">Dockerfile commands&lt;/h2>
&lt;h3 id="from">FROM&lt;/h3>
&lt;ul>
&lt;li>
&lt;p>The &lt;code>FROM&lt;/code> instruction initializes a new build stage and sets the &lt;a href="https://docs.docker.com/glossary/#base_image">&lt;em>Base Image&lt;/em>&lt;/a> for subsequent instructions.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>As such, a valid &lt;code>Dockerfile&lt;/code> must start with a &lt;code>FROM&lt;/code> instruction.&lt;/p>
&lt;ul>
&lt;li>Note: &lt;code>ARG&lt;/code> is the only instruction that may precede &lt;code>FROM&lt;/code> in the &lt;code>Dockerfile&lt;/code>.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>
&lt;p>The image can be any valid image – it is especially easy to start by &lt;strong>pulling an image&lt;/strong> from the &lt;a href="https://docs.docker.com/docker-hub/repos/">&lt;em>Public Repositories&lt;/em>&lt;/a>.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Syntax:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-dockerfile" data-lang="dockerfile">&lt;span class="line">&lt;span class="cl">&lt;span class="k">FROM&lt;/span>&lt;span class="s"> [--platform=&amp;lt;platform&amp;gt;] &amp;lt;image&amp;gt;[:&amp;lt;tag&amp;gt;] [AS &amp;lt;name&amp;gt;]&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;li>
&lt;p>Example:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-dockerfile" data-lang="dockerfile">&lt;span class="line">&lt;span class="cl">&lt;span class="k">FROM&lt;/span>&lt;span class="s"> ubuntu:18.04&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;/ul>
&lt;h3 id="run">RUN&lt;/h3>
&lt;ul>
&lt;li>
&lt;p>Execute a command in a shell or exec form.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>The RUN instruction &lt;strong>adds a new layer&lt;/strong> on top of the newly created image.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>The committed results are then used for the next instruction in the DockerFile.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Syntax&lt;/p>
&lt;ul>
&lt;li>
&lt;p>Shell form (the command is run in a shell, which by default is &lt;code>/bin/sh -c&lt;/code> on Linux)&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-dockerfile" data-lang="dockerfile">&lt;span class="line">&lt;span class="cl">&lt;span class="k">RUN&lt;/span> &amp;lt;command&amp;gt;&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>In the &lt;em>shell&lt;/em> form you can use a &lt;code>\&lt;/code> (backslash) to continue a single RUN instruction onto the next line.&lt;/p>
&lt;p>E.g.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-dockerfile" data-lang="dockerfile">&lt;span class="line">&lt;span class="cl">&lt;span class="k">RUN&lt;/span> /bin/bash -c &lt;span class="s1">&amp;#39;source $HOME/.bashrc; \
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s1">echo $HOME&amp;#39;&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Together they are equivalent to this single line:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-dockerfile" data-lang="dockerfile">&lt;span class="line">&lt;span class="cl">&lt;span class="k">RUN&lt;/span> /bin/bash -c &lt;span class="s1">&amp;#39;source $HOME/.bashrc; echo $HOME&amp;#39;&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;li>
&lt;p>Exec form&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-dockerfile" data-lang="dockerfile">&lt;span class="line">&lt;span class="cl">&lt;span class="k">RUN&lt;/span> &lt;span class="o">[&lt;/span>&lt;span class="s2">&amp;#34;executable&amp;#34;&lt;/span>, &lt;span class="s2">&amp;#34;param1&amp;#34;&lt;/span>, &lt;span class="s2">&amp;#34;param2&amp;#34;&lt;/span>&lt;span class="o">]&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>E.g.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-dockerfile" data-lang="dockerfile">&lt;span class="line">&lt;span class="cl">&lt;span class="k">RUN&lt;/span> &lt;span class="o">[&lt;/span>&lt;span class="s2">&amp;#34;/bin/bash&amp;#34;&lt;/span>, &lt;span class="s2">&amp;#34;-c&amp;#34;&lt;/span>, &lt;span class="s2">&amp;#34;echo hello&amp;#34;&lt;/span>&lt;span class="o">]&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;h3 id="cmd">CMD&lt;/h3>
&lt;ul>
&lt;li>
&lt;p>Give the default commands &lt;strong>when the image is instantiated&lt;/strong>, it doesn’t execute while build stage.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>The &lt;code>CMD&lt;/code> instruction has three forms:&lt;/p>
&lt;ul>
&lt;li>
&lt;p>&lt;code>CMD [&amp;quot;executable&amp;quot;,&amp;quot;param1&amp;quot;,&amp;quot;param2&amp;quot;]&lt;/code> (&lt;em>&lt;strong>exec&lt;/strong>&lt;/em> form, this is the &lt;strong>preferred&lt;/strong> form)&lt;/p>
&lt;ul>
&lt;li>It will NOT involke a command shell. This means that normal shell processing does NOT happen.&lt;/li>
&lt;/ul>
&lt;p>E.g&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-dockerfile" data-lang="dockerfile">&lt;span class="line">&lt;span class="cl">&lt;span class="k">CMD&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;echo&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="s2">&amp;#34;hello&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;world&amp;#34;&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;li>
&lt;p>&lt;code>CMD [&amp;quot;param1&amp;quot;,&amp;quot;param2&amp;quot;]&lt;/code> (as &lt;em>default parameters to ENTRYPOINT&lt;/em>)&lt;/p>
&lt;ul>
&lt;li>If you would like your container to run the same executable every time, then you should consider using &lt;code>ENTRYPOINT&lt;/code> in combination with &lt;code>CMD&lt;/code>. See &lt;a href="https://docs.docker.com/engine/reference/builder/#entrypoint">&lt;em>ENTRYPOINT&lt;/em>&lt;/a>.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>
&lt;p>&lt;code>CMD command param1 param2&lt;/code> (&lt;em>&lt;strong>shell&lt;/strong>&lt;/em> form)&lt;/p>
&lt;ul>
&lt;li>
&lt;p>The &lt;code>&amp;lt;command&amp;gt;&lt;/code> will execute in &lt;code>/bin/sh -c&lt;/code>.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>E.g.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-dockerfile" data-lang="dockerfile">&lt;span class="line">&lt;span class="cl">&lt;span class="k">CMD&lt;/span> &lt;span class="nb">echo&lt;/span> &lt;span class="nv">$HW&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>It will execute the command &lt;code>/bin/sh -c echo $HW&lt;/code>&lt;/p>
&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>
&lt;p>There can only be &lt;strong>ONE&lt;/strong> &lt;code>CMD&lt;/code> instruction in a &lt;code>Dockerfile&lt;/code>. If you list more than one &lt;code>CMD&lt;/code> then only the last &lt;code>CMD&lt;/code> will take effect.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>The main purpose of a &lt;code>CMD&lt;/code> is to provide defaults for an executing container.&lt;/strong> These defaults can include&lt;/p>
&lt;ul>
&lt;li>an executable, or&lt;/li>
&lt;li>they can omit the executable, in which case you must specify an &lt;code>ENTRYPOINT&lt;/code> instruction as well.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;div class="flex px-4 py-3 mb-6 rounded-md bg-yellow-100 dark:bg-yellow-900">
&lt;span class="pr-3 pt-1 text-red-400">
&lt;svg height="24" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">&lt;path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M12 9v3.75m-9.303 3.376c-.866 1.5.217 3.374 1.948 3.374h14.71c1.73 0 2.813-1.874 1.948-3.374L13.949 3.378c-.866-1.5-3.032-1.5-3.898 0zM12 15.75h.007v.008H12z"/>&lt;/svg>
&lt;/span>
&lt;span class="dark:text-neutral-300">If the user specifies arguments to &lt;code>docker run&lt;/code> then they will override the default specified in &lt;code>CMD&lt;/code>.&lt;/span>
&lt;/div>
&lt;h3 id="entrypoint">ENTRYPOINT&lt;/h3>
&lt;ul>
&lt;li>
&lt;p>Configures a container that will run as an executable. I.e., a specific application can be set as default and run every time a container is created using the image.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;code>ENTRYPOINT&lt;/code> has two forms:&lt;/p>
&lt;ul>
&lt;li>
&lt;p>&lt;em>exec&lt;/em> form (the preferred form)&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-dockerfile" data-lang="dockerfile">&lt;span class="line">&lt;span class="cl">&lt;span class="k">ENTRYPOINT&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;executable&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;param1&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;param2&amp;#34;&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;li>
&lt;p>&lt;em>shell&lt;/em> form:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-dockerfile" data-lang="dockerfile">&lt;span class="line">&lt;span class="cl">&lt;span class="k">ENTRYPOINT&lt;/span> &lt;span class="nb">command&lt;/span> param1 param2&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>
&lt;p>Unlike &lt;code>CMD&lt;/code>, command line arguments to &lt;code>docker run &amp;lt;image&amp;gt;&lt;/code> will NOT override the default specified in &lt;code>CMD&lt;/code>. Instead, they will be &lt;strong>appended&lt;/strong> after all elements in an &lt;em>exec&lt;/em> form &lt;code>ENTRYPOINT&lt;/code>, and will override all elements specified using &lt;code>CMD&lt;/code>.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Only the last &lt;code>ENTRYPOINT&lt;/code> instruction in the &lt;code>Dockerfile&lt;/code> will have an effect.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>You can override the &lt;code>ENTRYPOINT&lt;/code> instruction using the &lt;code>docker run --entrypoint&lt;/code> flag.&lt;/p>
&lt;/li>
&lt;/ul>
&lt;h4 id="understand-how-cmd-and-entrypoint-interact">Understand how CMD and ENTRYPOINT interact&lt;/h4>
&lt;p>Both &lt;code>CMD&lt;/code> and &lt;code>ENTRYPOINT&lt;/code> instructions define what command gets executed when running a container. There are few rules that describe their co-operation.&lt;/p>
&lt;ol>
&lt;li>Dockerfile should specify at least one of &lt;code>CMD&lt;/code> or &lt;code>ENTRYPOINT&lt;/code> commands.&lt;/li>
&lt;li>&lt;code>ENTRYPOINT&lt;/code> should be defined when using the container as an executable.&lt;/li>
&lt;li>&lt;code>CMD&lt;/code> should be used as a way of defining default arguments for an &lt;code>ENTRYPOINT&lt;/code> command or for executing an ad-hoc command in a container.&lt;/li>
&lt;li>&lt;code>CMD&lt;/code> will be overridden when running the container with alternative arguments.&lt;/li>
&lt;/ol>
&lt;p>The table below shows what command is executed for different &lt;code>ENTRYPOINT&lt;/code> / &lt;code>CMD&lt;/code> combinations:&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th style="text-align:left">&lt;/th>
&lt;th style="text-align:left">No ENTRYPOINT&lt;/th>
&lt;th style="text-align:left">ENTRYPOINT exec_entry p1_entry&lt;/th>
&lt;th style="text-align:left">ENTRYPOINT [“exec_entry”, “p1_entry”]&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td style="text-align:left">&lt;strong>No CMD&lt;/strong>&lt;/td>
&lt;td style="text-align:left">&lt;em>error, not allowed&lt;/em>&lt;/td>
&lt;td style="text-align:left">&lt;code>/bin/sh -c exec_entry p1_entry&lt;/code>&lt;/td>
&lt;td style="text-align:left">&lt;code>exec_entry p1_entry&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:left">&lt;strong>CMD [“exec_cmd”, “p1_cmd”]&lt;/strong>&lt;/td>
&lt;td style="text-align:left">&lt;code>exec_cmd p1_cmd&lt;/code>&lt;/td>
&lt;td style="text-align:left">&lt;code>/bin/sh -c exec_entry p1_entry&lt;/code>&lt;/td>
&lt;td style="text-align:left">&lt;code>exec_entry p1_entry exec_cmd p1_cmd&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:left">&lt;strong>CMD [“p1_cmd”, “p2_cmd”]&lt;/strong>&lt;/td>
&lt;td style="text-align:left">&lt;code>p1_cmd p2_cmd&lt;/code>&lt;/td>
&lt;td style="text-align:left">&lt;code>/bin/sh -c exec_entry p1_entry&lt;/code>&lt;/td>
&lt;td style="text-align:left">&lt;code>exec_entry p1_entry p1_cmd p2_cmd&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:left">&lt;strong>CMD exec_cmd p1_cmd&lt;/strong>&lt;/td>
&lt;td style="text-align:left">&lt;code>/bin/sh -c exec_cmd p1_cmd&lt;/code>&lt;/td>
&lt;td style="text-align:left">&lt;code>/bin/sh -c exec_entry p1_entry&lt;/code>&lt;/td>
&lt;td style="text-align:left">&lt;code>exec_entry p1_entry /bin/sh -c exec_cmd p1_cmd&lt;/code>&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>A common use case is: the &lt;strong>executable is defined with ENTRYPOINT&lt;/strong>, while &lt;strong>CMD specifies the default parameter&lt;/strong>.&lt;/p>
&lt;p>Example:&lt;/p>
&lt;p>&lt;em>Dockerfile&lt;/em>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-dockerfile" data-lang="dockerfile">&lt;span class="line">&lt;span class="cl">&lt;span class="k">FROM&lt;/span>&lt;span class="s"> node:8.11-slim&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="k">CMD&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;world&amp;#34;&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="k">ENTRYPOINT&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;echo&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;Hello&amp;#34;&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Build image:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">docker built -t my-docker-image .
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Run container:&lt;/p>
&lt;ul>
&lt;li>
&lt;p>without argument&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">docker run -it my-docker-image
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>output:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">Hello world
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;blockquote>
&lt;p>If we run &lt;code>docker run&lt;/code> without argument, the default argument &lt;code>world&lt;/code> defined in &lt;code>CMD&lt;/code> will be used. I.e, the command &lt;code>echo Hello World&lt;/code> will be executed.&lt;/p>
&lt;/blockquote>
&lt;/li>
&lt;li>
&lt;p>with argument&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">docker run -it my-docker-image James Bond
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>output:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">Hello James Bond
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;blockquote>
&lt;p>If we specify arguments when running &lt;code>docker run&lt;/code>, &lt;code>CMD&lt;/code> will be overriden by our given arguments. In our case, &lt;code>CMD [&amp;quot;World&amp;quot;]&lt;/code> is overriden to &lt;code>CMD [&amp;quot;James&amp;quot;, &amp;quot;Bond&amp;quot;]&lt;/code> and then applied to &lt;code>echo&lt;/code>. Thus, the command &lt;code>echo Hello James Bond&lt;/code> will be executed.&lt;/p>
&lt;/blockquote>
&lt;/li>
&lt;/ul>
&lt;blockquote>
&lt;p>Summary of &lt;code>CMD&lt;/code> and &lt;code>ENTRYPOINT&lt;/code> see: &lt;a href="https://phoenixnap.com/kb/docker-cmd-vs-entrypoint">Docker CMD Vs Entrypoint Commands: What&amp;rsquo;s The Difference?&lt;/a>&lt;/p>
&lt;/blockquote>
&lt;h3 id="expose">EXPOSE&lt;/h3>
&lt;ul>
&lt;li>
&lt;p>Specify the port on which the container will be listening at runtime by running the EXPOSE instruction.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Syntax&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-dockerfile" data-lang="dockerfile">&lt;span class="line">&lt;span class="cl">&lt;span class="k">EXPOSE&lt;/span>&lt;span class="s"> &amp;lt;port&amp;gt;&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;/ul>
&lt;h3 id="env">ENV&lt;/h3>
&lt;ul>
&lt;li>
&lt;p>Set environment variables using the ENV instruction.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>This value will be in the environment for all subsequent instructions in the build stage and can be &lt;a href="https://docs.docker.com/engine/reference/builder/#environment-replacement">replaced inline&lt;/a> in many as well.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>They come as key value pairs and increases the flexibility of running programs.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Syntax&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-dockerfile" data-lang="dockerfile">&lt;span class="line">&lt;span class="cl">&lt;span class="k">ENV&lt;/span> &amp;lt;key&amp;gt;&lt;span class="o">=&lt;/span>&amp;lt;value&amp;gt; ...&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>e.g.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-dockerfile" data-lang="dockerfile">&lt;span class="line">&lt;span class="cl">&lt;span class="k">ENV&lt;/span> &lt;span class="nv">PATH&lt;/span>&lt;span class="o">=&lt;/span>usr/node&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>or&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-dockerfile" data-lang="dockerfile">&lt;span class="line">&lt;span class="cl">&lt;span class="k">ENV&lt;/span> &amp;lt;key&amp;gt; &amp;lt;value&amp;gt;&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>e.g.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-dockerfile" data-lang="dockerfile">&lt;span class="line">&lt;span class="cl">&lt;span class="k">ENV&lt;/span> PATH usr/node&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;/ul>
&lt;h3 id="add">ADD&lt;/h3>
&lt;ul>
&lt;li>
&lt;p>&lt;code>ADD&lt;/code> has two forms:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-dockerfile" data-lang="dockerfile">&lt;span class="line">&lt;span class="cl">&lt;span class="k">ADD&lt;/span> &lt;span class="o">[&lt;/span>--chown&lt;span class="o">=&lt;/span>&amp;lt;user&amp;gt;:&amp;lt;group&amp;gt;&lt;span class="o">]&lt;/span> &amp;lt;src&amp;gt;... &amp;lt;dest&amp;gt;&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>or&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-dockerfile" data-lang="dockerfile">&lt;span class="line">&lt;span class="cl">&lt;span class="k">ADD&lt;/span> &lt;span class="o">[&lt;/span>--chown&lt;span class="o">=&lt;/span>&amp;lt;user&amp;gt;:&amp;lt;group&amp;gt;&lt;span class="o">]&lt;/span> &lt;span class="o">[&lt;/span>&lt;span class="s2">&amp;#34;&amp;lt;src&amp;gt;&amp;#34;&lt;/span>,... &lt;span class="s2">&amp;#34;&amp;lt;dest&amp;gt;&amp;#34;&lt;/span>&lt;span class="o">]&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;li>
&lt;p>Copies new files, directories or remote file URLs from &lt;code>&amp;lt;src&amp;gt;&lt;/code> and adds them to the filesystem of the image at the path &lt;code>&amp;lt;dest&amp;gt;&lt;/code>.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Invalidates caches. &lt;strong>Avoid &lt;code>ADD&lt;/code> and use &lt;code>COPY&lt;/code> instead.&lt;/strong>&lt;/p>
&lt;/li>
&lt;/ul>
&lt;h3 id="copy">COPY&lt;/h3>
&lt;ul>
&lt;li>
&lt;p>Syntax&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-dockerfile" data-lang="dockerfile">&lt;span class="line">&lt;span class="cl">&lt;span class="k">COPY&lt;/span> &lt;span class="o">[&lt;/span>--chown&lt;span class="o">=&lt;/span>&amp;lt;user&amp;gt;:&amp;lt;group&amp;gt;&lt;span class="o">]&lt;/span> &amp;lt;src&amp;gt;... &amp;lt;dest&amp;gt;&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>or&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-dockerfile" data-lang="dockerfile">&lt;span class="line">&lt;span class="cl">&lt;span class="k">COPY&lt;/span> &lt;span class="o">[&lt;/span>--chown&lt;span class="o">=&lt;/span>&amp;lt;user&amp;gt;:&amp;lt;group&amp;gt;&lt;span class="o">]&lt;/span> &lt;span class="o">[&lt;/span>&lt;span class="s2">&amp;#34;&amp;lt;src&amp;gt;&amp;#34;&lt;/span>,... &lt;span class="s2">&amp;#34;&amp;lt;dest&amp;gt;&amp;#34;&lt;/span>&lt;span class="o">]&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;li>
&lt;p>Copy new files or directories from &lt;code>&amp;lt;src&amp;gt;&lt;/code> and adds them to the filesystem of the container at the path &lt;code>&amp;lt;dest&amp;gt;&lt;/code>.&lt;/p>
&lt;ul>
&lt;li>Each &lt;code>&amp;lt;src&amp;gt;&lt;/code> may contain wildcards and matching will be done using Go’s &lt;a href="http://golang.org/pkg/path/filepath#Match">filepath.Match&lt;/a> rules.&lt;code>COPY&lt;/code> obeys the following rules:&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>
&lt;p>Example: copy &lt;code>test.txt&lt;/code> to &lt;code>&amp;lt;WORKDIR&amp;gt;/relativeDir/&lt;/code>:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-dockerfile" data-lang="dockerfile">&lt;span class="line">&lt;span class="cl">&lt;span class="k">COPY&lt;/span> test.txt relativeDir/&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;li>
&lt;p>&lt;code>COPY&lt;/code> obeys the following rules:&lt;/p>
&lt;ul>
&lt;li>
&lt;p>The &lt;code>&amp;lt;src&amp;gt;&lt;/code> path must be inside the &lt;em>context&lt;/em> of the build&lt;/p>
&lt;/li>
&lt;li>
&lt;p>If &lt;code>&amp;lt;src&amp;gt;&lt;/code> is a directory, the entire contents of the directory are copied, including filesystem metadata.&lt;/p>
&lt;p>(The directory itself is not copied, just its contents.)&lt;/p>
&lt;/li>
&lt;li>
&lt;p>If &lt;code>&amp;lt;src&amp;gt;&lt;/code> is any other kind of file, it is copied individually along with its metadata. In this case, if &lt;code>&amp;lt;dest&amp;gt;&lt;/code> ends with a trailing slash &lt;code>/&lt;/code>, it will be considered a directory and the contents of &lt;code>&amp;lt;src&amp;gt;&lt;/code> will be written at &lt;code>&amp;lt;dest&amp;gt;/base(&amp;lt;src&amp;gt;)&lt;/code>.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>If multiple &lt;code>&amp;lt;src&amp;gt;&lt;/code> resources are specified, either directly or due to the use of a wildcard, then &lt;code>&amp;lt;dest&amp;gt;&lt;/code> must be a directory, and it must end with a slash &lt;code>/&lt;/code>.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>If &lt;code>&amp;lt;dest&amp;gt;&lt;/code> does not end with a trailing slash, it will be considered a regular file and the contents of &lt;code>&amp;lt;src&amp;gt;&lt;/code> will be written at &lt;code>&amp;lt;dest&amp;gt;&lt;/code>.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>If &lt;code>&amp;lt;dest&amp;gt;&lt;/code> doesn’t exist, it is created along with all missing directories in its path.&lt;/p>
&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;h3 id="volumn">VOLUMN&lt;/h3>
&lt;ul>
&lt;li>Creates a mount point for externally mounted volumes or other containers&lt;/li>
&lt;/ul>
&lt;h3 id="workdir">WORKDIR&lt;/h3>
&lt;ul>
&lt;li>
&lt;p>Sets the working directory for any &lt;code>RUN&lt;/code>, &lt;code>CMD&lt;/code>, &lt;code>ENTRYPOINT&lt;/code>, &lt;code>COPY&lt;/code> and &lt;code>ADD&lt;/code> instructions that follow it in the &lt;code>Dockerfile&lt;/code>.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>The &lt;code>WORKDIR&lt;/code> instruction can be used multiple times in a &lt;code>Dockerfile&lt;/code>. If a relative path is provided, it will be relative to the path of the previous &lt;code>WORKDIR&lt;/code> instruction. E.g.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-dockerfile" data-lang="dockerfile">&lt;span class="line">&lt;span class="cl">&lt;span class="k">WORKDIR&lt;/span>&lt;span class="s"> /usr/node&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="k">WORKDIR&lt;/span>&lt;span class="s"> app&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>The resulted work directory will be &lt;code>/usr/mode/app&lt;/code>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>The &lt;code>WORKDIR&lt;/code> instruction can resolve environment variables previously set using &lt;code>ENV&lt;/code>. E.g.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-dockerfile" data-lang="dockerfile">&lt;span class="line">&lt;span class="cl">&lt;span class="k">ENV&lt;/span> &lt;span class="nv">WORK_DIR&lt;/span>&lt;span class="o">=&lt;/span>/usr/node/app&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="k">WORKDIR&lt;/span>&lt;span class="s"> ${WORK_DIR}&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;/ul>
&lt;h3 id="arg">ARG&lt;/h3>
&lt;ul>
&lt;li>
&lt;p>Defines a build-time variable&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Syntax&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-dockerfile" data-lang="dockerfile">&lt;span class="line">&lt;span class="cl">&lt;span class="k">ARG&lt;/span> &amp;lt;name&amp;gt;&lt;span class="o">[=&lt;/span>&amp;lt;default value&amp;gt;&lt;span class="o">]&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;li>
&lt;p>&lt;code>ARG&lt;/code> is the only instruction that can occur before the &lt;code>FROM&lt;/code>.&lt;/p>
&lt;p>E.g. we can use &lt;code>ARG&lt;/code> to specify the version of base image&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-dockerfile" data-lang="dockerfile">&lt;span class="line">&lt;span class="cl">&lt;span class="k">ARG&lt;/span> &lt;span class="nv">NODE_VERSION&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="m">8&lt;/span>.11-slim&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="k">FROM&lt;/span>&lt;span class="s"> node:${NODE_VERSION}&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;/ul>
&lt;h3 id="onbuild">ONBUILD&lt;/h3>
&lt;ul>
&lt;li>Adds a trigger instruction when the image is used as the base for another build&lt;/li>
&lt;/ul>
&lt;h3 id="stopsignal">STOPSIGNAL&lt;/h3>
&lt;ul>
&lt;li>Sets the system call signal that will be sent to the container to exit.&lt;/li>
&lt;/ul>
&lt;h3 id="label">LABEL&lt;/h3>
&lt;ul>
&lt;li>
&lt;p>Add key/value metadata to your images, containers, or daemons.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Syntax&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-dockerfile" data-lang="dockerfile">&lt;span class="line">&lt;span class="cl">&lt;span class="k">LABEL&lt;/span> &amp;lt;key&amp;gt;&lt;span class="o">=&lt;/span>&amp;lt;value&amp;gt; &amp;lt;key&amp;gt;&lt;span class="o">=&lt;/span>&amp;lt;value&amp;gt; &amp;lt;key&amp;gt;&lt;span class="o">=&lt;/span>&amp;lt;value&amp;gt; ...&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;li>
&lt;p>Example&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-dockerfile" data-lang="dockerfile">&lt;span class="line">&lt;span class="cl">&lt;span class="k">LABEL&lt;/span> &lt;span class="nv">version&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;1.0&amp;#34;&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="k">LABEL&lt;/span> &lt;span class="nv">description&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;Just a demo&amp;#34;&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;li>
&lt;p>If a label already exists but with a different value, the most-recently-applied value overrides any previously-set value.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>To view an image’s labels, use the &lt;code>docker image inspect&lt;/code> command. You can use the &lt;code>--format&lt;/code> option to show just the labels&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">docker image inspect --format&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;&amp;#39;&lt;/span> &amp;lt;image&amp;gt;
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;/ul>
&lt;h3 id="shell">SHELL&lt;/h3>
&lt;ul>
&lt;li>Override default shell is used by docker to run commands.&lt;/li>
&lt;/ul>
&lt;h3 id="healthcheck">HEALTHCHECK&lt;/h3>
&lt;ul>
&lt;li>Tells docker how to test a container to check that it is still working.&lt;/li>
&lt;/ul>
&lt;h2 id="example-with-common-commands">Example with common commands&lt;/h2>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-dockerfile" data-lang="dockerfile">&lt;span class="line">&lt;span class="cl">&lt;span class="c"># ARG is used to pass some arguments to consecutive instructions&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="c"># this is only command other than a comment can be used before FROM.&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="k">ARG&lt;/span> &lt;span class="nv">NODE_VERSION&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="m">8&lt;/span>.11-slim&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="c"># from base image node&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="k">FROM&lt;/span>&lt;span class="s"> node:${NODE_VERSION}&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="c"># LABEL add metadata to your images, containers, or daemons&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="k">LABEL&lt;/span> &lt;span class="s2">&amp;#34;about&amp;#34;&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;This file is just an example to demostrate the basic usage of dockerfile commands&amp;#34;&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="c"># ENV sets the environment variables for the subsequent instructions in the build stage&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="k">ENV&lt;/span> WORK_DIR /usr/node&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="c"># WORKDIR sets the working directory for all the consecutive commands.&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="c"># We can have multiple WORKDIR commands and will be appended with a relative path.&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="c"># E.g. we have two WORKDIR commands leads to /usr/node/app&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="k">WORKDIR&lt;/span>&lt;span class="s"> ${WORK_DIR}&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="k">WORKDIR&lt;/span>&lt;span class="s"> app&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="c"># VOLUME is used to create a mount point with the specified name&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="k">RUN&lt;/span> mkdir /dockerexample&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="k">VOLUME&lt;/span>&lt;span class="s"> /dockerexample&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="c"># COPY is used to copy files or directories &lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="c"># from source host filesystem to a destination in the container file system.&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="c"># Here we&amp;#39;re gonna copy package.json from our system to container file system&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="k">COPY&lt;/span> package.json .&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="c"># RUN executes the instructions in a new layer on top of the existing image and commit those layers&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="c"># The resulted layer will be used for the next instructions in the Dockerfile&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="k">RUN&lt;/span> ls -ll &lt;span class="o">&amp;amp;&amp;amp;&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> npm install&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="c"># USER instruction sets the user name and optionally the user group to use&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="c"># when running the image and for any instructions that follow it in the Dockerfile&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="k">RUN&lt;/span> useradd ecko&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="k">USER&lt;/span>&lt;span class="s"> ecko&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="c"># ADD is used to add files or directories and remote files &lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="c"># from URL from source host filesystem to a destination in the container file system.&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="c"># Avoid ADD and use COPY instead!&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="k">ADD&lt;/span> index.js .&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="c"># CMD command is used to give the default commands when the image is instantiated, &lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="c"># it doesn’t execute while build stage. &lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="c"># There should be only ONE CMD per Dockerfile, &lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="c"># you can list multiple but the last one will be executed.&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="k">CMD&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;echo&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;Hello World&amp;#34;&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="c"># EXPOSE informs Docker that &lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="c"># the container listens on the specified network ports at runtime. &lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="k">EXPOSE&lt;/span>&lt;span class="s"> 3070&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="c"># ENTRYPOINT is used as an executable for the container.&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="c"># We can use ENTRYPOINT for executable command &lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="c"># and use CMD command to pass some default commands to the executable.&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="k">ENTRYPOINT&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;echo&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;Hello&amp;#34;&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="reference">Reference&lt;/h2>
&lt;ul>
&lt;li>Tutorials
&lt;ul>
&lt;li>&amp;#x1f525; Step by step tutorial with example: &lt;a href="https://medium.com/bb-tutorials-and-thoughts/docker-a-beginners-guide-to-dockerfile-with-a-sample-project-6c1ac1f17490">Docker — A Beginner’s guide to Dockerfile with a sample project&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://takacsmark.com/dockerfile-tutorial-by-example-dockerfile-best-practices-2018/#overview">Dockerfile tutorial by example - basics and best practices [2018]&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://www.runoob.com/docker/docker-dockerfile.html">Docker Dockerfile&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://www.flux7.com/tutorial/docker-tutorial-series-part-3-automation-is-the-word-using-dockerfile/">Docker Tutorial Series, Part 3: Automation is the Word Using DockerFile&lt;/a>&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>
&lt;span class="inline-block pr-1">
&lt;svg style="height: 1em; transform: translateY(0.1em);" viewBox="0 0 370 391" xmlns="http://www.w3.org/2000/svg">&lt;g clip-rule="evenodd" fill-rule="evenodd">&lt;path d="m207.5 22.4 114.4 66.6c13.5 7.9 21.9 22.4 21.9 38v136.4c0 17.3-9.3 33.3-24.5 41.8l-113.5 63.9a49.06 49.06 0 0 1 -48.5-.2l-104.5-60.1c-16.4-9.5-26.6-27-26.6-45.9v-129.5c0-19.1 9.9-36.8 26.1-46.8l102.8-63.5c16-9.9 36.2-10.1 52.4-.7z" fill="#ff4088" stroke="#c9177e" stroke-width="27" />&lt;path d="m105.6 298.2v-207.2h43.4v75.5h71.9v-75.5h43.5v207.2h-43.5v-90.6h-71.9v90.6z" fill="#fff" />&lt;/g>&lt;/svg>
&lt;/span> Reference: &lt;a href="https://docs.docker.com/engine/reference/builder/#entrypoint">Dockerfile reference&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/wsargent/docker-cheat-sheet#dockerfile">Cheatsheet&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>Dockerfile Best Practice</title><link>https://haobin-tan.netlify.app/docs/coding/docker/docker-getting-started/dockerfile-best-practice/</link><pubDate>Sun, 13 Dec 2020 00:00:00 +0000</pubDate><guid>https://haobin-tan.netlify.app/docs/coding/docker/docker-getting-started/dockerfile-best-practice/</guid><description>&lt;h2 id="general-guidelines">General Guidelines&lt;/h2>
&lt;h3 id="write-dockerignore">Write &lt;code>.dockerignore&lt;/code>&lt;/h3>
&lt;ul>
&lt;li>
&lt;p>When building an image, Docker has to prepare &lt;code>context&lt;/code> first - gather all files that may be used in a process.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Default context contains all files in a Dockerfile directory. Usually &lt;strong>we don&amp;rsquo;t want to include there &lt;code>.git&lt;/code> directory, downloaded libraries, and compiled files&lt;/strong>.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Similar to &lt;code>.gitignore&lt;/code>, &lt;code>.dockerignore&lt;/code> can look like followings:&lt;/p>
&lt;p>&lt;em>.dockerignore&lt;/em>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">.git/
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">node_modules/
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">dist/
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;/ul>
&lt;h3 id="container-should-do-one-thing-decouple-applications">Container should do one thing (Decouple applications)&lt;/h3>
&lt;p>Technically, you can start multiple processes (such as database, frontend, backend applications) inside Docker container. However, such a big container will bite you&lt;/p>
&lt;ul>
&lt;li>long build times (change in e.g. frontend will force the whole backend to rebuild)&lt;/li>
&lt;li>very large images&lt;/li>
&lt;li>hard logging from many applications (no more simple stdout)&lt;/li>
&lt;li>wasteful horizontal scaling&lt;/li>
&lt;li>problems with zombie processes - you have to remember about proper init process&lt;/li>
&lt;/ul>
&lt;p>The proper way is&lt;/p>
&lt;ul>
&lt;li>prepare separate Docker image for each component&lt;/li>
&lt;li>use &lt;a href="https://docs.docker.com/compose/">Docker Compose&lt;/a> to easily start multiple containers at the same time.&lt;/li>
&lt;/ul>
&lt;h3 id="minimize-the-number-of-layers">Minimize the number of layers&lt;/h3>
&lt;p>Docker is all about &lt;strong>layers&lt;/strong>.&lt;/p>
&lt;ul>
&lt;li>Each command in Dockerfile creates so-called &lt;em>layer&lt;/em>&lt;/li>
&lt;li>Layers are cached and reused&lt;/li>
&lt;li>Invalidating cache of a single layer invalidates all subsequent layers&lt;/li>
&lt;li>Invalidation occurs after command change, if copied files are different, or build variable is other than previously&lt;/li>
&lt;li>Layers are immutable, so if we add a file in one layer, and remove it in the next one, image STILL contains that file (it&amp;rsquo;s just not available in the container)!&lt;/li>
&lt;/ul>
&lt;p>Minimizing the number of steps in your image may improve build and pull performance. Therefore it’s a cool best practice to combine several steps into one line, so that they’ll create only one intermediary image.&lt;/p>
&lt;div class="flex px-4 py-3 mb-6 rounded-md bg-primary-100 dark:bg-primary-900">
&lt;span class="pr-3 pt-1 text-primary-600 dark:text-primary-300">
&lt;svg height="24" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">&lt;path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="m11.25 11.25l.041-.02a.75.75 0 0 1 1.063.852l-.708 2.836a.75.75 0 0 0 1.063.853l.041-.021M21 12a9 9 0 1 1-18 0a9 9 0 0 1 18 0m-9-3.75h.008v.008H12z"/>&lt;/svg>
&lt;/span>
&lt;span class="dark:text-neutral-300">Only &lt;code>RUN&lt;/code>, &lt;code>COPY&lt;/code> and &lt;code>ADD&lt;/code> instructions create layers to improve build performance. Other instructions create temporary intermediate images, and do not increase the size of the build.&lt;/span>
&lt;/div>
&lt;h3 id="example">Example&lt;/h3>
&lt;p>❌&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-dockerfile" data-lang="dockerfile">&lt;span class="line">&lt;span class="cl">&lt;span class="k">FROM&lt;/span>&lt;span class="s"> alpine:3.4&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="k">RUN&lt;/span> apk update&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="k">RUN&lt;/span> apk add curl&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="k">RUN&lt;/span> apk add vim&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="k">RUN&lt;/span> apk add git&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>✅&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-dockerfile" data-lang="dockerfile">&lt;span class="line">&lt;span class="cl">&lt;span class="k">FROM&lt;/span>&lt;span class="s"> alpine:3.4&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="k">RUN&lt;/span> apk update &lt;span class="o">&amp;amp;&amp;amp;&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> apk add curl &lt;span class="o">&amp;amp;&amp;amp;&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> apk add vim &lt;span class="o">&amp;amp;&amp;amp;&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> apk add git&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>After building this Dockerfile the usual way you’ll find that this time it has only taken 2 steps instead of 5.&lt;/p>
&lt;h3 id="sort-multi-line-arguments">Sort multi-line arguments&lt;/h3>
&lt;ul>
&lt;li>
&lt;p>Whenever possible, ease later changes by &lt;strong>sorting multi-line arguments alphanumerically&lt;/strong>.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>This helps to avoid duplication of packages and make the list much easier to update. This also makes PRs a lot easier to read and review. Adding a space before a backslash (&lt;code>\&lt;/code>) helps as well.&lt;/p>
&lt;/li>
&lt;/ul>
&lt;p>Example&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-dockerfile" data-lang="dockerfile">&lt;span class="line">&lt;span class="cl">&lt;span class="k">RUN&lt;/span> apt-get update &lt;span class="o">&amp;amp;&amp;amp;&lt;/span> apt-get install -y &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> bzr &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> cvs &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> git &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> mercurial &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> subversion &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> &lt;span class="o">&amp;amp;&amp;amp;&lt;/span> rm -rf /var/lib/apt/lists/*&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="do-not-use-latest-base-image-tag">Do not use &amp;rsquo;latest&amp;rsquo; base image tag&lt;/h3>
&lt;ul>
&lt;li>
&lt;p>&lt;code>latest&lt;/code> tag is a default one, used when no other tag is specified. E.g. our instruction &lt;code>FROM ubuntu&lt;/code> in reality does exactly the same as &lt;code>FROM ubuntu:latest&lt;/code>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>But &amp;rsquo;latest&amp;rsquo; tag will point to a different image when a new version will be released, and your build may break. &amp;#x1f622;&lt;/p>
&lt;/li>
&lt;li>
&lt;p>So, unless you are creating a generic Dockerfile that must stay up-to-date with the base image, &lt;strong>provide specific tag&lt;/strong>!!!&lt;/p>
&lt;/li>
&lt;/ul>
&lt;h3 id="remove-unneeded-files-after-each-run-step">Remove unneeded files after each RUN step&lt;/h3>
&lt;p>Let&amp;rsquo;s assume we updated apt-get sources, installed few packages required for compiling others, downloaded and extracted archives. We obviously don&amp;rsquo;t need them in our final images, so better let&amp;rsquo;s make a cleanup.&lt;/p>
&lt;p>E.g. we can remove apt-get lists (created by &lt;code>apt-get update&lt;/code>):&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-dockerfile" data-lang="dockerfile">&lt;span class="line">&lt;span class="cl">&lt;span class="k">FROM&lt;/span>&lt;span class="s"> ubuntu:16.04&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="k">RUN&lt;/span> apt-get update &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> &lt;span class="o">&amp;amp;&amp;amp;&lt;/span> apt-get install -y nodejs &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> &lt;span class="c1"># added lines&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span> &lt;span class="o">&amp;amp;&amp;amp;&lt;/span> rm -rf /var/lib/apt/lists/*&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="k">ADD&lt;/span> . /app&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="k">RUN&lt;/span> &lt;span class="nb">cd&lt;/span> /app &lt;span class="o">&amp;amp;&amp;amp;&lt;/span> npm install&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="k">CMD&lt;/span> npm start&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="use-proper-base-image">Use proper base image&lt;/h3>
&lt;p>Use specilaized image instead of general-purpose base image. For example, if we just want to run node application, instead of using &lt;code>ubuntu&lt;/code> as our base image, we should use &lt;code>node&lt;/code> (or even alpine version).&lt;/p>
&lt;h3 id="set-workdir-and-cmd">Set &lt;code>WORKDIR&lt;/code> and &lt;code>CMD&lt;/code>&lt;/h3>
&lt;ul>
&lt;li>&lt;code>WORKDIR&lt;/code> command changes default directory, where we run our &lt;code>RUN&lt;/code> / &lt;code>CMD&lt;/code> / &lt;code>ENTRYPOINT&lt;/code> commands.&lt;/li>
&lt;li>&lt;code>CMD&lt;/code> is a default command run after creating container without other command specified. It&amp;rsquo;s usually the most frequently performed action.&lt;/li>
&lt;/ul>
&lt;p>Example&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-dockerfile" data-lang="dockerfile">&lt;span class="line">&lt;span class="cl">&lt;span class="k">FROM&lt;/span>&lt;span class="s"> node:7-alpine&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="k">WORKDIR&lt;/span>&lt;span class="s"> /app&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="k">ADD&lt;/span> . /app&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="k">RUN&lt;/span> npm install&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="k">CMD&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;npm&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;start&amp;#34;&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="use-entrypoint-optional">Use &lt;code>ENTRYPOINT&lt;/code> (optional)&lt;/h3>
&lt;h3 id="use-exec-inside-entrypoint-script">Use &amp;ldquo;exec&amp;rdquo; inside entrypoint script&lt;/h3>
&lt;h3 id="prefer-copy-over-add">Prefer &lt;code>COPY&lt;/code> over &lt;code>ADD&lt;/code>&lt;/h3>
&lt;ul>
&lt;li>&lt;code>COPY&lt;/code> is simpler.&lt;/li>
&lt;li>&lt;code>ADD&lt;/code> has some logic for downloading remote files and extracting archives (more see &lt;a href="https://docs.docker.com/engine/userguide/eng-image/dockerfile_best-practices/#add-or-copy">official documentation&lt;/a>)&lt;/li>
&lt;li>&lt;strong>Just stick with &lt;code>COPY&lt;/code>&lt;/strong> !&amp;#x1f4aa;&lt;/li>
&lt;/ul>
&lt;h3 id="use-multi-stage-builds">Use multi-stage builds&lt;/h3>
&lt;ul>
&lt;li>&lt;a href="https://docs.docker.com/develop/develop-images/multistage-build/">Multi-stage builds&lt;/a> allow you to drastically reduce the size of your final image, without struggling to reduce the number of intermediate layers and files.&lt;/li>
&lt;li>Because an image is built during the final stage of the build process, you can minimize image layers by &lt;a href="https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#leverage-build-cache">leveraging build cache&lt;/a>.&lt;/li>
&lt;li>If your build contains several layers, you can order them &lt;strong>from the less frequently changed&lt;/strong> (to ensure the build cache is reusable) &lt;strong>to the more frequently changed&lt;/strong>:
&lt;ul>
&lt;li>Install tools you need to build your application&lt;/li>
&lt;li>Install or update library dependencies&lt;/li>
&lt;li>Generate your application&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;h3 id="leverage-build-cache">Leverage build cache&lt;/h3>
&lt;ul>
&lt;li>When building an image, Docker steps through the instructions in your &lt;code>Dockerfile&lt;/code>, executing each in the order specified. As each instruction is examined, Docker looks for an existing image in its cache that it can reuse, rather than creating a new (duplicate) image.&lt;/li>
&lt;li>The basic rules that Docker follows are outlined below:
&lt;ul>
&lt;li>Starting with a parent image that is already in the cache, the next instruction is compared against all child images derived from that base image to see if one of them was built using the exact same instruction. If not, the cache is invalidated.&lt;/li>
&lt;li>In most cases, simply comparing the instruction in the &lt;code>Dockerfile&lt;/code> with one of the child images is sufficient.&lt;/li>
&lt;li>For the &lt;code>ADD&lt;/code> and &lt;code>COPY&lt;/code> instructions, the contents of the file(s) in the image are examined and a checksum is calculated for each file. The last-modified and last-accessed times of the file(s) are not considered in these checksums. During the cache lookup, the checksum is compared against the checksum in the existing images. If anything has changed in the file(s), such as the contents and metadata, then the cache is invalidated.&lt;/li>
&lt;li>Aside from the &lt;code>ADD&lt;/code> and &lt;code>COPY&lt;/code> commands, cache checking does not look at the files in the container to determine a cache match.&lt;/li>
&lt;li>Once the cache is invalidated, all subsequent &lt;code>Dockerfile&lt;/code> commands generate new images and the cache is not used.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;h3 id="specify-default-environment-variables-ports-and-volumes">Specify default environment variables, ports and volumes&lt;/h3>
&lt;p>It&amp;rsquo;s a good practice to set default values in Dockerfile, which can make our dockerfile more consistent and flexible.&lt;/p>
&lt;p>Example&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-dockerfile" data-lang="dockerfile">&lt;span class="line">&lt;span class="cl">&lt;span class="k">FROM&lt;/span>&lt;span class="s"> node:7-alpine&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="c"># ENV variables required during build&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="k">ENV&lt;/span> &lt;span class="nv">PROJECT_DIR&lt;/span>&lt;span class="o">=&lt;/span>/app&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="k">WORKDIR&lt;/span>&lt;span class="s"> $PROJECT_DIR&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="k">COPY&lt;/span> package.json &lt;span class="nv">$PROJECT_DIR&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="k">RUN&lt;/span> npm install&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="k">COPY&lt;/span> . &lt;span class="nv">$PROJECT_DIR&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="k">ENV&lt;/span> &lt;span class="nv">MEDIA_DIR&lt;/span>&lt;span class="o">=&lt;/span>/media &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> &lt;span class="nv">NODE_ENV&lt;/span>&lt;span class="o">=&lt;/span>production &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> &lt;span class="nv">APP_PORT&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="m">3000&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span> &lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="k">VOLUME&lt;/span>&lt;span class="s"> $MEDIA_DIR&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="k">EXPOSE&lt;/span>&lt;span class="s"> $APP_PORT&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="add-metadata-to-image-using-label">Add metadata to image using LABEL&lt;/h3>
&lt;h3 id="create-ephemeral-containers">Create ephemeral containers&lt;/h3>
&lt;p>The image defined by your &lt;code>Dockerfile&lt;/code> should generate containers that are as ephemeral as possible. By “ephemeral”, we mean that the container can be stopped and destroyed, then rebuilt and replaced with an absolute minimum set up and configuration.&lt;/p>
&lt;h3 id="dont-install-unnecessary-packages">Don’t install unnecessary packages&lt;/h3>
&lt;p>To reduce complexity, dependencies, file sizes, and build times, avoid installing extra or unnecessary packages just because they might be “nice to have.”&lt;/p>
&lt;h2 id="dockerfile-instructions">Dockerfile instructions&lt;/h2>
&lt;h3 id="from">FROM&lt;/h3>
&lt;ul>
&lt;li>Whenever possible, use current official images as the basis for your images.&lt;/li>
&lt;li>We recommend the &lt;a href="https://hub.docker.com/_/alpine/">Alpine image&lt;/a> as it is tightly controlled and small in size (currently under 5 MB), while still being a full Linux distribution.&lt;/li>
&lt;/ul>
&lt;h3 id="label">LABEL&lt;/h3>
&lt;ul>
&lt;li>
&lt;p>You can add labels to your image to help organize images by project, record licensing information, to aid in automation, or for other reasons. (More see: &lt;a href="https://docs.docker.com/config/labels-custom-metadata/">Understanding object labels&lt;/a>)&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Acceptable formats&lt;/p>
&lt;ul>
&lt;li>
&lt;p>One label per line&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-dockerfile" data-lang="dockerfile">&lt;span class="line">&lt;span class="cl">&lt;span class="k">LABEL&lt;/span> com.example.version&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;0.0.1-beta&amp;#34;&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="k">LABEL&lt;/span> com.example.release-date&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;2015-02-12&amp;#34;&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;li>
&lt;p>Multiple labels on one line&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-dockerfile" data-lang="dockerfile">&lt;span class="line">&lt;span class="cl">&lt;span class="k">LABEL&lt;/span> com.example.version&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;0.0.1-beta&amp;#34;&lt;/span> com.example.release-date&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;2015-02-12&amp;#34;&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;li>
&lt;p>Set multiple labels at once, using line-continuation characters to break long lines&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-dockerfile" data-lang="dockerfile">&lt;span class="line">&lt;span class="cl">&lt;span class="k">LABEL&lt;/span> com.example.version&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;0.0.1-beta&amp;#34;&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> com.example.release-date&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;2015-02-12&amp;#34;&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;h3 id="run">RUN&lt;/h3>
&lt;p>Split long or complex &lt;code>RUN&lt;/code> statements on multiple lines separated with backslashes to make your &lt;code>Dockerfile&lt;/code> more readable, understandable, and maintainable.&lt;/p>
&lt;h4 id="apt-get">&lt;code>apt-get&lt;/code>&lt;/h4>
&lt;ul>
&lt;li>
&lt;p>Avoid &lt;code>RUN apt-get upgrade&lt;/code> and &lt;code>dist-upgrade&lt;/code>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Always combine &lt;code>RUN apt-get update&lt;/code> with &lt;code>apt-get install&lt;/code> in the same &lt;code>RUN&lt;/code> statement. This ensures your Dockerfile installs the latest package versions with no further coding or manual intervention. (“cache busting”)&lt;/p>
&lt;p>E.g.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-dockerfile" data-lang="dockerfile">&lt;span class="line">&lt;span class="cl">&lt;span class="k">RUN&lt;/span> apt-get update &lt;span class="o">&amp;amp;&amp;amp;&lt;/span> apt-get install -y &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> package-bar &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> package-baz &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> package-foo &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> &lt;span class="o">&amp;amp;&amp;amp;&lt;/span> rm -rf /var/lib/apt/lists/*&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;li>
&lt;p>You can also achieve cache-busting by specifying a package version. (&amp;ldquo;cache busting&amp;rdquo;)&lt;/p>
&lt;p>E.g.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-dockerfile" data-lang="dockerfile">&lt;span class="line">&lt;span class="cl">&lt;span class="k">RUN&lt;/span> apt-get update &lt;span class="o">&amp;amp;&amp;amp;&lt;/span> apt-get install -y &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> package-bar &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> package-baz &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> package-foo&lt;span class="o">=&lt;/span>1.3.*&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;/ul>
&lt;p>Below is a well-formed &lt;code>RUN&lt;/code> instruction that demonstrates all the &lt;code>apt-get&lt;/code> recommendations.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-dockerfile" data-lang="dockerfile">&lt;span class="line">&lt;span class="cl">&lt;span class="k">RUN&lt;/span> apt-get update &lt;span class="o">&amp;amp;&amp;amp;&lt;/span> apt-get install -y &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> aufs-tools &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> automake &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> build-essential &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> curl &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> dpkg-sig &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> libcap-dev &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> libsqlite3-dev &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> mercurial &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> reprepro &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> ruby1.9.1 &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> ruby1.9.1-dev &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> &lt;span class="nv">s3cmd&lt;/span>&lt;span class="o">=&lt;/span>1.1.* &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> &lt;span class="o">&amp;amp;&amp;amp;&lt;/span> rm -rf /var/lib/apt/lists/*&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="cmd">CMD&lt;/h3>
&lt;ul>
&lt;li>The &lt;code>CMD&lt;/code> instruction should be used to run the software contained in your image, along with any arguments.&lt;/li>
&lt;li>&lt;code>CMD&lt;/code> should almost always be used in the form of &lt;code>CMD [&amp;quot;executable&amp;quot;, &amp;quot;param1&amp;quot;, &amp;quot;param2&amp;quot;…]&lt;/code>.&lt;/li>
&lt;li>&lt;code>CMD&lt;/code> should rarely be used in the manner of &lt;code>CMD [&amp;quot;param&amp;quot;, &amp;quot;param&amp;quot;]&lt;/code> in conjunction with &lt;a href="https://docs.docker.com/engine/reference/builder/#entrypoint">&lt;code>ENTRYPOINT&lt;/code>&lt;/a>, unless you and your expected users are already quite familiar with how &lt;code>ENTRYPOINT&lt;/code> works.&lt;/li>
&lt;/ul>
&lt;h3 id="expose">EXPOSE&lt;/h3>
&lt;ul>
&lt;li>The &lt;code>EXPOSE&lt;/code> instruction indicates the ports on which a container listens for connections.&lt;/li>
&lt;li>You should use the common, traditional port for your application. E.g.
&lt;ul>
&lt;li>an image containing the Apache web server would use &lt;code>EXPOSE 80&lt;/code>&lt;/li>
&lt;li>an image containing MongoDB would use &lt;code>EXPOSE 27017&lt;/code>&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;h3 id="env">ENV&lt;/h3>
&lt;ul>
&lt;li>
&lt;p>To make new software easier to run, you can use &lt;code>ENV&lt;/code> to update the &lt;code>PATH&lt;/code> environment variable for the software your container installs.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;code>ENV&lt;/code> instruction is also useful for providing required environment variables specific to services you wish to containerize&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;code>ENV&lt;/code> can also be used to set commonly used version numbers so that version bumps are easier to maintain&lt;/p>
&lt;p>E.g.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-dockerfile" data-lang="dockerfile">&lt;span class="line">&lt;span class="cl">&lt;span class="k">ENV&lt;/span> &lt;span class="nv">PG_MAJOR&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="m">9&lt;/span>.3&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="k">ENV&lt;/span> &lt;span class="nv">PG_VERSION&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="m">9&lt;/span>.3.4&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="k">RUN&lt;/span> curl -SL https://example.com/postgres-&lt;span class="nv">$PG_VERSION&lt;/span>.tar.xz &lt;span class="p">|&lt;/span> tar -xJC /usr/src/postgress &lt;span class="o">&amp;amp;&amp;amp;&lt;/span> …&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="k">ENV&lt;/span> &lt;span class="nv">PATH&lt;/span>&lt;span class="o">=&lt;/span>/usr/local/postgres-&lt;span class="nv">$PG_MAJOR&lt;/span>/bin:&lt;span class="nv">$PATH&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;li>
&lt;p>Each &lt;code>ENV&lt;/code> line creates a new intermediate layer, just like &lt;code>RUN&lt;/code> commands&lt;/p>
&lt;ul>
&lt;li>This means that even if you unset the environment variable in a future layer, it still persists in this layer and its value can’t be dumped.&lt;/li>
&lt;li>You can separate your commands with &lt;code>;&lt;/code> or &lt;code>&amp;amp;&amp;amp;&lt;/code>. Using &lt;code>\&lt;/code> as a line continuation character for Linux Dockerfiles improves readability.&lt;/li>
&lt;li>Or you could also put all of the commands into a shell script and have the &lt;code>RUN&lt;/code> command just run that shell script.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;h3 id="add-or-copy">ADD or COPY&lt;/h3>
&lt;ul>
&lt;li>
&lt;p>&lt;strong>&lt;code>COPY&lt;/code> is preferred.&lt;/strong>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>If you have multiple &lt;code>Dockerfile&lt;/code> steps that use different files from your context, &lt;strong>&lt;code>COPY&lt;/code> them individually, rather than all at once.&lt;/strong> This ensures that each step’s build cache is only invalidated (forcing the step to be re-run) if the specifically required files change.&lt;/p>
&lt;p>E.g.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-dockerfile" data-lang="dockerfile">&lt;span class="line">&lt;span class="cl">&lt;span class="k">COPY&lt;/span> requirements.txt /tmp/&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="k">RUN&lt;/span> pip install --requirement /tmp/requirements.txt&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="k">COPY&lt;/span> . /tmp/&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>This results in fewer cache invalidations for the &lt;code>RUN&lt;/code> step, than if you put the &lt;code>COPY . /tmp/&lt;/code> before it.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Using &lt;code>ADD&lt;/code> to fetch packages from remote URLs is &lt;strong>strongly discouraged&lt;/strong> 🙅‍♂️; you should use &lt;code>curl&lt;/code> or &lt;code>wget&lt;/code> instead.&lt;/p>
&lt;ul>
&lt;li>
&lt;p>That way you can delete the files you no longer need after they’ve been extracted and you don’t have to add another layer in your image.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>E.g.&lt;/p>
&lt;p>❌&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-dockerfile" data-lang="dockerfile">&lt;span class="line">&lt;span class="cl">&lt;span class="k">ADD&lt;/span> https://example.com/big.tar.xz /usr/src/things/&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="k">RUN&lt;/span> tar -xJf /usr/src/things/big.tar.xz -C /usr/src/things&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="k">RUN&lt;/span> make -C /usr/src/things all&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>✅&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-dockerfile" data-lang="dockerfile">&lt;span class="line">&lt;span class="cl">&lt;span class="k">RUN&lt;/span> mkdir -p /usr/src/things &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> &lt;span class="o">&amp;amp;&amp;amp;&lt;/span> curl -SL https://example.com/big.tar.xz &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> &lt;span class="p">|&lt;/span> tar -xJC /usr/src/things &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> &lt;span class="o">&amp;amp;&amp;amp;&lt;/span> make -C /usr/src/things all&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>
&lt;p>For other items (files, directories) that do not require &lt;code>ADD&lt;/code>’s tar auto-extraction capability, you should always use &lt;code>COPY&lt;/code>.&lt;/p>
&lt;/li>
&lt;/ul>
&lt;h3 id="entrypoint">ENTRYPOINT&lt;/h3>
&lt;ul>
&lt;li>
&lt;p>The best use for &lt;code>ENTRYPOINT&lt;/code> is to set the image’s main command, allowing that image to be run as though it was that command (and then use &lt;code>CMD&lt;/code> as the default flags).&lt;/p>
&lt;ul>
&lt;li>
&lt;p>Example: image for the command line tool &lt;code>s3cmd&lt;/code>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-dockerfile" data-lang="dockerfile">&lt;span class="line">&lt;span class="cl">&lt;span class="k">ENTRYPOINT&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;s3cmd&amp;#34;&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="k">CMD&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;--help&amp;#34;&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Now the image can be run like this to show the command’s help:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">docker run s3cmd
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>or use the right parameters to execute a command:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">docker run s3cmd ls s3://mybucket
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>
&lt;p>The &lt;code>ENTRYPOINT&lt;/code> instruction can also be used in combination with a helper script, allowing it to function in a similar way to the command above, even when starting the tool may require more than one step.&lt;/p>
&lt;/li>
&lt;/ul>
&lt;h3 id="workdir">WORKDIR&lt;/h3>
&lt;ul>
&lt;li>For clarity and reliability, you should always use absolute paths for your &lt;code>WORKDIR&lt;/code>.&lt;/li>
&lt;li>You should use &lt;code>WORKDIR&lt;/code> instead of proliferating instructions like &lt;code>RUN cd … &amp;amp;&amp;amp; do-something&lt;/code>, which are hard to read, troubleshoot, and maintain.&lt;/li>
&lt;/ul>
&lt;h2 id="reference">Reference&lt;/h2>
&lt;ul>
&lt;li>
&lt;span class="inline-block pr-1">
&lt;svg style="height: 1em; transform: translateY(0.1em);" viewBox="0 0 370 391" xmlns="http://www.w3.org/2000/svg">&lt;g clip-rule="evenodd" fill-rule="evenodd">&lt;path d="m207.5 22.4 114.4 66.6c13.5 7.9 21.9 22.4 21.9 38v136.4c0 17.3-9.3 33.3-24.5 41.8l-113.5 63.9a49.06 49.06 0 0 1 -48.5-.2l-104.5-60.1c-16.4-9.5-26.6-27-26.6-45.9v-129.5c0-19.1 9.9-36.8 26.1-46.8l102.8-63.5c16-9.9 36.2-10.1 52.4-.7z" fill="#ff4088" stroke="#c9177e" stroke-width="27" />&lt;path d="m105.6 298.2v-207.2h43.4v75.5h71.9v-75.5h43.5v207.2h-43.5v-90.6h-71.9v90.6z" fill="#fff" />&lt;/g>&lt;/svg>
&lt;/span> Official guide: &lt;a href="https://docs.docker.com/develop/develop-images/dockerfile_best-practices/">Best practices for writing Dockerfiles&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://rock-it.pl/how-to-write-excellent-dockerfiles/">How to write excellent Dockerfiles&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>Docker Volume</title><link>https://haobin-tan.netlify.app/docs/coding/docker/docker-getting-started/docker-volume/</link><pubDate>Thu, 06 Feb 2020 00:00:00 +0000</pubDate><guid>https://haobin-tan.netlify.app/docs/coding/docker/docker-getting-started/docker-volume/</guid><description>&lt;p>In general, Docker containers are &lt;strong>ephemeral&lt;/strong>, running just as long as it takes for the command issued in the container to complete. By default, any data created inside the container is ONLY available from within the container and only while the container is running.&lt;/p>
&lt;p>Docker &lt;strong>volumes&lt;/strong> can be used to share files between a host system and the Docker container.&lt;/p>
&lt;h2 id="bindmounting-a-volume">Bindmounting a Volume&lt;/h2>
&lt;p>We can use &lt;code>-v&lt;/code> flag in &lt;code>docker run&lt;/code> to bind mount a volume. Let&amp;rsquo;s take a look at an example, which will create a directory called &lt;code>nginxlogs&lt;/code> in your current user’s home directory and bindmount it to &lt;code>/var/log/nginx&lt;/code> in the container:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">docker run --name&lt;span class="o">=&lt;/span>nginx -d -v ~/nginxlogs:/var/log/nginx -p 5000:80 nginx
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;code>-v ~/nginxlogs:/var/log/nginx&lt;/code> sets up a bindmount volume that links the &lt;code>/var/log/nginx&lt;/code> directory from inside the Nginx container to the &lt;code>~/nginxlogs&lt;/code> directory on the host machine. Docker uses a &lt;code>:&lt;/code> to split the host’s path from the container path, and the &lt;strong>host path always comes first&lt;/strong>.&lt;/p>
&lt;div class="flex px-4 py-3 mb-6 rounded-md bg-primary-100 dark:bg-primary-900">
&lt;span class="pr-3 pt-1 text-primary-600 dark:text-primary-300">
&lt;svg height="24" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">&lt;path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="m11.25 11.25l.041-.02a.75.75 0 0 1 1.063.852l-.708 2.836a.75.75 0 0 0 1.063.853l.041-.021M21 12a9 9 0 1 1-18 0a9 9 0 0 1 18 0m-9-3.75h.008v.008H12z"/>&lt;/svg>
&lt;/span>
&lt;span class="dark:text-neutral-300">&lt;p>If the first argument of &lt;code>-v&lt;/code> begins with a &lt;code>/&lt;/code> or &lt;code>~/&lt;/code>, you’re creating a bindmount. Remove that, and you’re naming the volume.&lt;/p>
&lt;ul>
&lt;li>&lt;code>-v /path:/path/in/container&lt;/code> mounts the host directory, &lt;code>/path&lt;/code> at the &lt;code>/path/in/container&lt;/code>&lt;/li>
&lt;li>&lt;code>-v path:/path/in/container&lt;/code> creates a volume named &lt;code>path&lt;/code> with no relationship to the host.&lt;/li>
&lt;/ul>&lt;/span>
&lt;/div>
&lt;p>If you make any changes to the &lt;code>~/nginxlogs&lt;/code> folder, you’ll be able to see them from inside the Docker container in real time as well. In other words, the content of &lt;code>~/nginxlogs&lt;/code> and &lt;code>/var/log/nginx&lt;/code> are synchronous.&lt;/p>
&lt;h2 id="reference">Reference&lt;/h2>
&lt;ul>
&lt;li>
&lt;p>&lt;a href="https://docs.docker.com/storage/bind-mounts/">Use bind mounts&lt;/a>: Docker official documentation&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;a href="https://www.digitalocean.com/community/tutorials/how-to-share-data-between-the-docker-container-and-the-host">How To Share Data Between the Docker Container and the Host&lt;/a>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;a href="https://thenewstack.io/docker-basics-how-to-share-data-between-a-docker-container-and-host/">Docker Basics: How to Share Data Between a Docker Container and Host&lt;/a>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;a href="https://kebingzao.com/2019/02/25/docker-volume/">Docker Volume - 目录挂载以及文件共享&lt;/a>&lt;/p>
&lt;/li>
&lt;/ul></description></item></channel></rss>