{"componentChunkName":"component---src-templates-blog-post-js","path":"/docker-training/","result":{"data":{"site":{"siteMetadata":{"title":"Nans' blogs"}},"markdownRemark":{"id":"8657fc98-1466-5474-bf13-e588e4bf0fd1","excerpt":"Docker Essentials: A developer introduction Lab 1 : Running a container  What are Containers ? A group of precesses, run in isolation. They run on a shared…","html":"<h1>Docker Essentials: A developer introduction</h1>\n<h2>Lab 1 : Running a container</h2>\n<h3> What are Containers ?</h3>\n<p>A group of precesses, run in isolation. They run on a shared kernel.\nThe isolation is provided by Linux <strong>namespaces</strong>.</p>\n<p>VM vs Container\nVMs are heavy and slow to start because they have a full OS.\n<span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 590px; \"\n    >\n      <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/d2e9c16aaa7c0f777b30fd7f7280fa15/e996b/2020-03-12-16-13-05.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 54.72972972972974%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAYAAAB/Ca1DAAAACXBIWXMAAAsTAAALEwEAmpwYAAAB1UlEQVQoz32Sb0/aUBTG+YB8iWXGb0HiC42JupckvnF7oVEzHWwzmmXTIqhsJgjY0jYCU2lLwZZWTfEP9M+ze6+tFjQ7ycm9vX3OL8+55yYcx4Esy2i32+j1elBVle01TUOr1YJpmgiCADToGmUU4/8SruuCQqO0LAsGgeidDoPRs3hBFI+DAYakNg6lkcBY/K3X8btwgMPcPjTilobv+yNAyzBQzOdxtJ+HTQyMOIwLPVJYqx6gcrKLP0fbEGt8CPSeNbSjM+kYYpUDT3QCXxkFxi37no+ps49415zHe3EORbE03gAC18dsYwUTFx8wKS+gQOCsNvDfAFKH4i7K1QzKlSx4oczO0+k0kskkUqkU+xYlDo3mDwjCFnj+JHT4BpCuez938G1zDV83VtFs1Nl5ndwrx3EolZ4cF3K/kP28gu9f1tEINVH9K6CiaKjyAnEqwyTPKD7BSHPZUlA5FcDXJHS7V+j3+yyfp/wylACLORUzmRqmMxKWi3p42T48jwyGXInrBVgqaJjOipjJSvh0qLNnZtv2ayBddfMGl7oBpdODce1Etp40oU4zbDQVHedqF9qV9f+WiQ0MHx/gDgdsH8Rgke7h/g63NzbJa9z3nZE3+g+C4DdLKQKZ1gAAAABJRU5ErkJggg=='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"2020 03 12 16 13 05\"\n        title=\"2020 03 12 16 13 05\"\n        src=\"/static/d2e9c16aaa7c0f777b30fd7f7280fa15/fcda8/2020-03-12-16-13-05.png\"\n        srcset=\"/static/d2e9c16aaa7c0f777b30fd7f7280fa15/12f09/2020-03-12-16-13-05.png 148w,\n/static/d2e9c16aaa7c0f777b30fd7f7280fa15/e4a3f/2020-03-12-16-13-05.png 295w,\n/static/d2e9c16aaa7c0f777b30fd7f7280fa15/fcda8/2020-03-12-16-13-05.png 590w,\n/static/d2e9c16aaa7c0f777b30fd7f7280fa15/efc66/2020-03-12-16-13-05.png 885w,\n/static/d2e9c16aaa7c0f777b30fd7f7280fa15/e996b/2020-03-12-16-13-05.png 1050w\"\n        sizes=\"(max-width: 590px) 100vw, 590px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n  </a>\n    </span>\ncontainers can be directly run on top of virtual machines.</p>\n<h3>What is Docker ?</h3>\n<p>Docker is tooling to manage containers.\n<em>“build once, run anywhere”</em></p>\n<h3>Why containers are appealing</h3>\n<ul>\n<li>no more “Works on my machine”</li>\n<li>lightweight and fast</li>\n<li>better resource utilization</li>\n</ul>\n<h3>Running a container</h3>\n<div class=\"gatsby-highlight\" data-language=\"bash\"><pre class=\"language-bash\"><code class=\"language-bash\">docker container run -t ubuntu <span class=\"token function\">top</span></code></pre></div>\n<p>The docker run command first starts a docker pull to download the Ubuntu image onto your host. After it is downloaded, it will start the container.</p>\n<p>Even though we are using the Ubuntu image, it is important to note that the container does not have its own kernel. It uses the kernel of the host and the Ubuntu image is used only to provide the file system and tools available on an Ubuntu system.</p>\n<div class=\"gatsby-highlight\" data-language=\"bash\"><pre class=\"language-bash\"><code class=\"language-bash\">docker container <span class=\"token function\">ls</span>\nCONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES\n\n        ubuntu              <span class=\"token string\">\"top\"</span>               <span class=\"token number\">58</span> seconds ago      Up <span class=\"token number\">58</span> seconds                           wizardly_germain</code></pre></div>\n<p>then</p>\n<div class=\"gatsby-highlight\" data-language=\"bash\"><pre class=\"language-bash\"><code class=\"language-bash\">$ docker container <span class=\"token builtin class-name\">exec</span> -it 7d1a9d47e601 <span class=\"token function\">bash</span>\nroot@7d1a9d47e601:/<span class=\"token comment\">#</span></code></pre></div>\n<p> Using docker container exec with bash is a common way to inspect a Docker container.</p>\n<blockquote>\n<p>Namespaces are a feature of the Linux kernel. However, Docker allows you to run containers on Windows and Mac. The secret is that embedded in the Docker product is a Linux subsystem.</p>\n</blockquote>\n<h3>2. Run multiple containers</h3>\n<p> running an nginx server :</p>\n<div class=\"gatsby-highlight\" data-language=\"bash\"><pre class=\"language-bash\"><code class=\"language-bash\">docker container run --detach --publish <span class=\"token number\">8080</span>:80 --name nginx nginx</code></pre></div>\n<p><code class=\"language-text\">--detach</code> flag will run this container in the background.\nthe <code class=\"language-text\">publish</code> flag publishes port 80 in the container by using port 8080 on your host.</p>\n<p>So here, go to localhost:8080 :\n<span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 558px; \"\n    >\n      <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/871db58906fc3a2c6832ff5ca5c68885/42a8d/2020-03-12-16-53-50.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 42.567567567567565%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAJCAYAAAAywQxIAAAACXBIWXMAAAsTAAALEwEAmpwYAAABU0lEQVQoz41SzY6CYAz01T34Eh5MPHryYHyOVURA+XdBMaKrggqCzjLd/W7uT5NJhyZMp+3X8n0f+/0eWZbhcrkgz3PhzEVRCD+dTjifz7jdbmA8n8+XYLQ6nQ663S76/b6AfDweYzgcYjQaod1uo9frYTAYiPBvQdFWVVXSmU6Yr9cryrKUzO80TYUTdKymULUsy6XGf8ShpmnQdR3T6RTkxGw2w2QykZpt28JN00QUReCKFosFXNcVGIYhmY1FcLVaYb1eS2Gz2WC32yEIArCeJAk+DgcEjch2m+CvkJFVFzqgG7olHMeR2nw+h+2FmJtLWEunqduI4whGeITmHREmGaXwUEfhCBT1PE9ECDq1LKsZXYPr+dC9A97sFMv3I+q6alCjrB4o7jXuTaYg9cQhXcVxLPthDsNQ9sQ1/De+zH075IXURdUV1cV/em+v3p/inzLpoZY0cwXHAAAAAElFTkSuQmCC'); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"2020 03 12 16 53 50\"\n        title=\"2020 03 12 16 53 50\"\n        src=\"/static/871db58906fc3a2c6832ff5ca5c68885/42a8d/2020-03-12-16-53-50.png\"\n        srcset=\"/static/871db58906fc3a2c6832ff5ca5c68885/12f09/2020-03-12-16-53-50.png 148w,\n/static/871db58906fc3a2c6832ff5ca5c68885/e4a3f/2020-03-12-16-53-50.png 295w,\n/static/871db58906fc3a2c6832ff5ca5c68885/42a8d/2020-03-12-16-53-50.png 558w\"\n        sizes=\"(max-width: 558px) 100vw, 558px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n  </a>\n    </span></p>\n<p>The <code class=\"language-text\">name</code> flag names the container.</p>\n<p>Then, we can run another container :</p>\n<div class=\"gatsby-highlight\" data-language=\"bash\"><pre class=\"language-bash\"><code class=\"language-bash\">docker container run --detach --publish <span class=\"token number\">8081</span>:27017 --name mongo mongo:3.4</code></pre></div>\n<p>We can see the containers by running <code class=\"language-text\">docker container ls</code>.</p>\n<h3>Removing containers</h3>\n<ol>\n<li>\n<p>Stop the containers :</p>\n<div class=\"gatsby-highlight\" data-language=\"bash\"><pre class=\"language-bash\"><code class=\"language-bash\">docker container stop <span class=\"token operator\">&lt;</span>container-id<span class=\"token operator\">></span></code></pre></div>\n</li>\n<li>\n<p>Remove the stopped containers :</p>\n<div class=\"gatsby-highlight\" data-language=\"bash\"><pre class=\"language-bash\"><code class=\"language-bash\">docker system prune</code></pre></div>\n</li>\n</ol>\n<p>⚠️ Note :\nYou should avoid using unverified content from the Docker Store when developing your own images because these images might contain security vulnerabilities or possibly even malicious software.</p>\n<h2>Lab 2 Add CI/CD value with Docker images</h2>\n<h3>Docker images</h3>\n<ul>\n<li>Docker image is a tar file containing a container’s filesystem + metadata</li>\n<li>for sharing and redistribution</li>\n</ul>\n<p><strong>Docker registry</strong> push and pull image from registry.\nDefault registry: Docker hub. Public and free for public images.</p>\n<p>You can also have a private registry, self-hosted, or cloud provider options.</p>\n<p>Creating a docker image - with Docker build</p>\n<ul>\n<li>\n<p>Create a “Dockerfile”</p>\n<ul>\n<li>It contains a List of instructions for how to construct the container</li>\n</ul>\n</li>\n<li><code class=\"language-text\">docker build -f Dockerfile</code></li>\n</ul>\n<p>Secret Sauce: Docker image layers</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 590px; \"\n    >\n      <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/8f362a809bd526391f0bf083d2690b56/d9199/2020-03-13-09-36-47.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 48.64864864864865%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAKCAYAAAC0VX7mAAAACXBIWXMAAAsTAAALEwEAmpwYAAAB5UlEQVQoz3VSTW/TQBT0f+PMz0AcOHBA6gm4UPELeqOckJB6qbghceDQKiRN2gYIUiKSxnbjrOO149Tr783aw+7aCSgST3p6O7Z2PDPPxvxuDs/14C5duMQF9SiIQ3Bv3WO1WsFxHMzncywWC1iWBUopttstyrJEIbuuBJY0wJOzr3h3MYTBUgb3gcBZOzBXpp4Kk3CpL2VZBsZYQ1AUEELgsDgvIbIEeRLDSIsYFh3D9ieYLUeYOT/1eeFPkRc5oihCmqb4X9V13cwWGzzzUSc3qOIbJPQbirCvsUhG2MovK3u7S0qpbdsIgkBHoKZ6V1WVnqqNMvexZX2U0QCMdpCuexIPULLvkkxaEdXepiIYj8eYTqeYTCZa/aFao8woOOtJwh6i1QXSoNNgNpS55To3pUDVZrPRRKZp6g7DNXyfwpFqs6yJpVEYDyTJAJGnFHY1FulIKngAIWSvYLcYzvn+mTQgu/6bYWNZEV5LdT3km6vW8o/Wstgr3GWp6vb2GtbslxRhwVvcIQkpfGLvCK/Aoz6Yd4ks7ELEEkvLaimHhLs8j148x9n7tzg5eopnjx/h97CLyy/ncsu8QC0SCM6wCQkS5rc43v/A/xJWLeGb1y9xenKMzsdTnB+/QrfXx+dPH/AHHhXtwSCnmMcAAAAASUVORK5CYII='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"2020 03 13 09 36 47\"\n        title=\"2020 03 13 09 36 47\"\n        src=\"/static/8f362a809bd526391f0bf083d2690b56/fcda8/2020-03-13-09-36-47.png\"\n        srcset=\"/static/8f362a809bd526391f0bf083d2690b56/12f09/2020-03-13-09-36-47.png 148w,\n/static/8f362a809bd526391f0bf083d2690b56/e4a3f/2020-03-13-09-36-47.png 295w,\n/static/8f362a809bd526391f0bf083d2690b56/fcda8/2020-03-13-09-36-47.png 590w,\n/static/8f362a809bd526391f0bf083d2690b56/efc66/2020-03-13-09-36-47.png 885w,\n/static/8f362a809bd526391f0bf083d2690b56/d9199/2020-03-13-09-36-47.png 960w\"\n        sizes=\"(max-width: 590px) 100vw, 590px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n  </a>\n    </span></p>\n<p>to make pushes faster, the lines in the docker file that change the most should be at the bottom of the file.\nBecause when you invalidate a layer, you automatically invalidate the layers after it.\nSo if it is the last layer, we optimize the caching system.</p>\n<ul>\n<li>\n<p>union file system</p>\n<ul>\n<li>merge image layers into single file system for each container</li>\n</ul>\n</li>\n<li>\n<p>copy-on-write</p>\n<ul>\n<li>copies files that are edited up to top writable layer</li>\n</ul>\n<p>Lab objectives :</p>\n<ul>\n<li>create custom image using a Dockerfile,</li>\n<li>build and run your image locally</li>\n<li>push your image to your account on DockerHub</li>\n<li>Update your image with a code change to see Docker image layering/caching in action</li>\n</ul>\n</li>\n</ul>\n<h3>Create a python app</h3>\n<p>Paste this in a file called app.py to create a simple Flask app :</p>\n<div class=\"gatsby-highlight\" data-language=\"python\"><pre class=\"language-python\"><code class=\"language-python\"><span class=\"token keyword\">from</span> flask <span class=\"token keyword\">import</span> Flask\n\napp <span class=\"token operator\">=</span> Flask<span class=\"token punctuation\">(</span>__name__<span class=\"token punctuation\">)</span>\n\n<span class=\"token decorator annotation punctuation\">@app<span class=\"token punctuation\">.</span>route</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"/\"</span><span class=\"token punctuation\">)</span>\n<span class=\"token keyword\">def</span> <span class=\"token function\">hello</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span>\n    <span class=\"token keyword\">return</span> <span class=\"token string\">\"hello world!\"</span>\n\n<span class=\"token keyword\">if</span> __name__ <span class=\"token operator\">==</span> <span class=\"token string\">\"__main__\"</span><span class=\"token punctuation\">:</span>\n    app<span class=\"token punctuation\">.</span>run<span class=\"token punctuation\">(</span>host<span class=\"token operator\">=</span><span class=\"token string\">\"0.0.0.0\"</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>then run</p>\n<div class=\"gatsby-highlight\" data-language=\"bash\"><pre class=\"language-bash\"><code class=\"language-bash\">pip3 <span class=\"token function\">install</span> flask\npython3 app.py</code></pre></div>\n<h3> Creating and building the docker image</h3>\n<p>Create a file named Dockerfile and add the following content:</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">FROM python:3.6.1-alpine\nRUN pip install flask\nCMD [&quot;python&quot;,&quot;app.py&quot;]\nCOPY app.py /app.py</code></pre></div>\n<p>The FROM line specifies the starting image to build your layers on top of it.\nIn this case, you are selecting the <code class=\"language-text\">python:3.6.1-alpine</code> base layer because it already has the version of Python and pip that you need to run your application.\nhe alpine version means that it uses the alpine distribution, which is significantly smaller than an alternative flavor of Linux. A smaller image means it will download (deploy) much faster.</p>\n<blockquote>\n<p>It is best practice to use a specific tag when inheriting a parent image so that changes to the parent dependency are controlled. If no tag is specified, the latest tag takes effect, which acts as a dynamic pointer that points to the latest version of an image.</p>\n</blockquote>\n<p> For security reasons, you must understand the layers that you build your docker image on top of.</p>\n<p> The RUN command executes commands needed to set up your image for your application, such as installing packages, editing files, or changing file permissions. In this case, you are installing Flask. The RUN commands are executed at build time and are added to the layers of your image.</p>\n<p> CMD is the command that is executed when you start a container. Here, you are using CMD to run your Python application.\nThere can be only one CMD per Dockerfile. If you specify more than one CMD, then the last CMD will take effect.</p>\n<p> This line copies the app.py file in the local directory (where you will run docker image build) into a new layer of the image.</p>\n<p> It seems counter-intuitive to put this line after the CMD [“python”,“app.py”] line. Remember, the CMD line is executed only when the container is started, so you won’t get a file not found error here.</p>\n<p>For full specifications about the Dockerfile :<a href=\"https://docs.docker.com/engine/reference/builder/\">documentation here</a>.</p>\n<p>Then, we can <strong>build the Docker image</strong>.</p>\n<div class=\"gatsby-highlight\" data-language=\"bash\"><pre class=\"language-bash\"><code class=\"language-bash\">docker image build -t python-hello-world ./</code></pre></div>\n<p>The <code class=\"language-text\">-t</code> parameter allows us to name the image.</p>\n<p>then we can run</p>\n<div class=\"gatsby-highlight\" data-language=\"bash\"><pre class=\"language-bash\"><code class=\"language-bash\">docker image <span class=\"token function\">ls</span></code></pre></div>\n<p>to see our image !</p>\n<h3>Run the docker image</h3>\n<div class=\"gatsby-highlight\" data-language=\"bash\"><pre class=\"language-bash\"><code class=\"language-bash\">docker run -p <span class=\"token number\">5001</span>:5000 -d python-hello-world</code></pre></div>\n<p>it returns > <code class=\"language-text\">0a8fa98d3b930c7b2d986c76fdeaf6b86cf041343be804a33585ccc9aedf5958</code></p>\n<p>Navigate to <a href=\"http://localhost:5001\">http://localhost:5001</a> => you see “hello world!“.</p>\n<p>To see the logs :</p>\n<div class=\"gatsby-highlight\" data-language=\"bash\"><pre class=\"language-bash\"><code class=\"language-bash\">docker container logs 0a8fa98d3b930c7b2d986c76fdeaf6b86cf041343be804a33585ccc9aedf5958</code></pre></div>\n<p>It returns :</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\"> * Serving Flask app &quot;app&quot; (lazy loading)\n * Environment: production\n   WARNING: This is a development server. Do not use it in a production deployment.\n   Use a production WSGI server instead.\n * Debug mode: off\n * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)\n172.17.0.1 - - [13/Mar/2020 09:10:34] &quot;GET / HTTP/1.1&quot; 200 -\n172.17.0.1 - - [13/Mar/2020 09:10:34] &quot;GET /favicon.ico HTTP/1.1&quot; 404 -</code></pre></div>\n<blockquote>\n<p>The Dockerfile is used to create reproducible builds for your application. A common workflow is to have your CI/CD automation run docker image build as part of its build process. After images are built, they will be sent to a central registry where they can be accessed by all environments (such as a test environment) that need to run instances of that application. In the next section, you will push your custom image to the public Docker registry, which is the Docker Hub, where it can be consumed by other developers and operators.</p>\n</blockquote>\n<h3>Push to a central registry</h3>\n<p>Login to the docker registry :</p>\n<div class=\"gatsby-highlight\" data-language=\"bash\"><pre class=\"language-bash\"><code class=\"language-bash\">docker login</code></pre></div>\n<p>Tag the image with you username.\nThe Docker Hub naming convention is to tag your image with <code class=\"language-text\">[dockerhub username]/[image name]</code>.</p>\n<div class=\"gatsby-highlight\" data-language=\"bash\"><pre class=\"language-bash\"><code class=\"language-bash\">docker tag python-hello-world nansdibm/python-hello-world</code></pre></div>\n<p>Use docker push :</p>\n<div class=\"gatsby-highlight\" data-language=\"bash\"><pre class=\"language-bash\"><code class=\"language-bash\">docker push nansdibm/python-hello-world</code></pre></div>\n<p>You can see your image on docker hub in the browser.</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 590px; \"\n    >\n      <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/848475263751cb22a46c233ab9f67ef0/d7abb/2020-03-13-10-57-10.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 18.91891891891892%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAECAYAAACOXx+WAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAbUlEQVQY05WPyQqAMBBD+///6FFcq+LaztI4LXjwpgMPJoeExIkImBkUI4jIsN90Sgmq+gtmgfPThGXbUfUz6t6jaTsMo8dxniX0610hFI/LphAJ60VQ82edyc3/BD4e91Rlm6ryniDynZJjgTdJfjuKe9G3WwAAAABJRU5ErkJggg=='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"2020 03 13 10 57 10\"\n        title=\"2020 03 13 10 57 10\"\n        src=\"/static/848475263751cb22a46c233ab9f67ef0/fcda8/2020-03-13-10-57-10.png\"\n        srcset=\"/static/848475263751cb22a46c233ab9f67ef0/12f09/2020-03-13-10-57-10.png 148w,\n/static/848475263751cb22a46c233ab9f67ef0/e4a3f/2020-03-13-10-57-10.png 295w,\n/static/848475263751cb22a46c233ab9f67ef0/fcda8/2020-03-13-10-57-10.png 590w,\n/static/848475263751cb22a46c233ab9f67ef0/efc66/2020-03-13-10-57-10.png 885w,\n/static/848475263751cb22a46c233ab9f67ef0/d7abb/2020-03-13-10-57-10.png 959w\"\n        sizes=\"(max-width: 590px) 100vw, 590px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n  </a>\n    </span></p>\n<h3>Deploy a change</h3>\n<p>Update app.py by changing “Hello World” with “Hello Beautiful World!“.</p>\n<p>Rebuild the image</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">docker image build -t nansdibm/python-hello-world .</code></pre></div>\n<p>Notice the “Using cache” for Steps 1 - 3. These layers of the Docker image have already been built, and the docker image build command will use these layers from the cache instead of rebuilding them.</p>\n<div class=\"gatsby-highlight\" data-language=\"bash\"><pre class=\"language-bash\"><code class=\"language-bash\">docker push nansdibm/python-hello-world</code></pre></div>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">The push refers to repository [docker.io/nansdibm/python-hello-world]\nbd3dadabc6d3: Pushed\n455874a92037: Layer already exists\n5f354b8b5dc0: Layer already exists\nf61107386c17: Layer already exists\ndb49993833a0: Layer already exists\n58c71ea40fb0: Layer already exists\n2b0fb280b60d: Layer already exists</code></pre></div>\n<p>There is a caching mechanism in place for pushing layers too. Docker Hub already has all but one of the layers from an earlier push, so it only pushes the one layer that has changed.</p>\n<h3> Understanding image layers</h3>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">FROM python:3.6.1-alpine\nRUN pip install flask\nCMD [&quot;python&quot;,&quot;app.py&quot;]\nCOPY app.py /app.py</code></pre></div>\n<p>Each of these lines is a layer. Each layer contains only the delta, or changes from the layers before it. To put these layers together into a single running container, Docker uses the union file system to overlay layers transparently into a single view.</p>\n<p>The “copy-on-write” function is very fast and in almost all cases, does not have a noticeable effect on performance. You can inspect which files have been pulled up to the container level with the docker diff command. For more information, see the command-line reference on the docker diff command.</p>\n<div class=\"gatsby-highlight\" data-language=\"bash\"><pre class=\"language-bash\"><code class=\"language-bash\">docker <span class=\"token function\">diff</span> 0a8fa98d3b93</code></pre></div>\n<p>Because image layers are read-only, <strong>they can be shared by images and by running containers</strong>.</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 513px; \"\n    >\n      <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/f47cc9b9642fc2111eda6de12919b63a/267f6/2020-03-13-11-20-10.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 67.56756756756756%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAOCAYAAAAvxDzwAAAACXBIWXMAAAsTAAALEwEAmpwYAAACGUlEQVQ4y5VSiZLaMAzl/7+rx3baGY5dlkIuEpJA7JCbxElsXmXDsj2gnWZG82RLepLzNOGco6oqZFmGsizRtq2xruvMuSgKSCmhv/P5jH99E8uy4Ps+4jhGEAQIwxBpmhp0HAd1Xf8foed5NwJNrCfmdNb3YRShaZpfCH+2e00mW88FZwlcx8Yu8On5JfytR4QuYiKU40BV6pr+Xvw7+RvxJG8GlKcBed2jIL8gP6sEykbQnUDdKdRCGWzEGVUr0XTy7nM16cRKJF62FT4/7/BlGWNmH+EwBY/1cNmIVdjh4zzA00tEOSHWcY91eEJR1oZECGFE7Pv+MmGUjYiyAbtUwDs0CHiHOJfYZwL7fDT+jgv4SWvi+hxnPU5th2Ggpq6L2WwGxtiFcLnNsbAZXtwU611pcOXnVDjCiirMrcTcfQ8KLL2j8e24RlnVUEohz3PoTblN+OoXpmhhcyIqLuRUqKe2o/oaY7fYwuHYUOO2E/f/ISsljs0Zaa3AK0koCUewogcrR3P/Hrv4R8q5Ls2fKluHkUQgS0a4XOHZK/Bp7pMIIT5MPYObvSCBpMnR5rEBo1QP9pAJBGlPYlwwyhV2Ry3SYM7aD0k4X8d5T9gjPApI9WCx7WSgjtSVS9iHHk96fWiqr68xphbHt9Ue0w3DNlVmjbRt+V8m1BNcVmekzgOssDBmRyXcfQ3nilp1LZTO2+fDwwl/ABZlK0pbHk1/AAAAAElFTkSuQmCC'); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"2020 03 13 11 20 10\"\n        title=\"2020 03 13 11 20 10\"\n        src=\"/static/f47cc9b9642fc2111eda6de12919b63a/267f6/2020-03-13-11-20-10.png\"\n        srcset=\"/static/f47cc9b9642fc2111eda6de12919b63a/12f09/2020-03-13-11-20-10.png 148w,\n/static/f47cc9b9642fc2111eda6de12919b63a/e4a3f/2020-03-13-11-20-10.png 295w,\n/static/f47cc9b9642fc2111eda6de12919b63a/267f6/2020-03-13-11-20-10.png 513w\"\n        sizes=\"(max-width: 513px) 100vw, 513px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n  </a>\n    </span></p>\n<blockquote>\n<p>Because the containers use the same read-only layers, you can imagine that starting containers is very fast and has a very low footprint on the host.</p>\n</blockquote>\n<h3> Remove the containers</h3>\n<div class=\"gatsby-highlight\" data-language=\"bash\"><pre class=\"language-bash\"><code class=\"language-bash\">docker container <span class=\"token function\">ls</span></code></pre></div>\n<div class=\"gatsby-highlight\" data-language=\"bash\"><pre class=\"language-bash\"><code class=\"language-bash\">docker container stop 0a8fa98d3b93</code></pre></div>\n<div class=\"gatsby-highlight\" data-language=\"bash\"><pre class=\"language-bash\"><code class=\"language-bash\">docker system prune</code></pre></div>\n<h2>Lab 3 Orchestrate applications with Docker Swarm</h2>\n<h3> Container orchestration</h3>\n<p>What about production ?\nAutomated scheduling and scaling, zero downtime deployments, high availability and fault tolerance…</p>\n<p>What is container orchestration ?</p>\n<ul>\n<li>Cluster management</li>\n<li>Scheduling</li>\n<li>Service discovery</li>\n<li>Health management</li>\n<li>\n<p>Declare desired state</p>\n<ul>\n<li>Active reconciliation</li>\n</ul>\n</li>\n</ul>\n<p>Docker swarm, Kubernetes, …\nWith hosted solutions :</p>\n<ul>\n<li>IBM Cloud Container Services</li>\n<li>Amazon ECS</li>\n<li>Azure Containers</li>\n<li>Google …</li>\n</ul>\n<p>Setup a 3 node cluster with container orchestration with Docker Swarm.</p>\n<ul>\n<li>Schedule and scale an application</li>\n<li>Expose the application</li>\n<li>Update with a rolling update</li>\n<li>Demonstrate node failure and reconciliation</li>\n</ul>\n<h3> Create your first swarm</h3>\n<p>Using <a href=\"https://labs.play-with-docker.com/\">https://labs.play-with-docker.com/</a>\nCreate a new instance</p>\n<div class=\"gatsby-highlight\" data-language=\"bash\"><pre class=\"language-bash\"><code class=\"language-bash\">docker swarm init --advertise-addr eth0</code></pre></div>\n<p>To add a worker in this swarm :</p>\n<div class=\"gatsby-highlight\" data-language=\"bash\"><pre class=\"language-bash\"><code class=\"language-bash\">docker swarm <span class=\"token function\">join</span> --token SWMTKN-1-61p9nb8opn3tg8lchklkbyjz7uhysj8krjexrlaxpr3kaprte8-ex2t37ry9f8ux0xu92u3jfsm8 <span class=\"token number\">192.168</span>.0.8:2377</code></pre></div>\n<p>To add a manager :</p>\n<div class=\"gatsby-highlight\" data-language=\"bash\"><pre class=\"language-bash\"><code class=\"language-bash\">docker swarm join-token manager</code></pre></div>\n<blockquote>\n<p>You can think of Docker Swarm as a special mode that is activated by the command: docker swarm init. The —advertise-addr option specifies the address in which the other nodes will use to join the swarm.</p>\n</blockquote>\n<p>With other instances, you can join the swarm by running</p>\n<div class=\"gatsby-highlight\" data-language=\"bash\"><pre class=\"language-bash\"><code class=\"language-bash\">docker swarm <span class=\"token function\">join</span> --token SWMTKN-1-61p9nb8opn3tg8lchklkbyjz7uhysj8krjexrlaxpr3kaprte8-ex2t37ry9f8ux0xu92u3jfsm8 <span class=\"token number\">192.168</span>.0.8:2377</code></pre></div>\n<p>Back on node1, run</p>\n<div class=\"gatsby-highlight\" data-language=\"bash\"><pre class=\"language-bash\"><code class=\"language-bash\">docker node <span class=\"token function\">ls</span></code></pre></div>\n<h3> Deploy your first service</h3>\n<p>To run containers on a Docker Swarm, you need to create a service. A service is an abstraction that represents multiple containers of the same image deployed across a distributed cluster.</p>\n<blockquote>\n<p>The —mount flag is useful to have NGINX print out the hostname of the node it’s running on. You will use this later in this lab when you start load balancing between multiple containers of NGINX that are distributed across different nodes in the cluster and you want to see which node in the swarm is serving the request.</p>\n</blockquote>\n<div class=\"gatsby-highlight\" data-language=\"bash\"><pre class=\"language-bash\"><code class=\"language-bash\">docker <span class=\"token function\">service</span> <span class=\"token function\">ls</span></code></pre></div>\n<div class=\"gatsby-highlight\" data-language=\"bash\"><pre class=\"language-bash\"><code class=\"language-bash\">docker <span class=\"token function\">service</span> <span class=\"token function\">ps</span> nginx1</code></pre></div>\n<h3>Scale your service</h3>\n<p>Update your service with an updated number of replicas.</p>\n<div class=\"gatsby-highlight\" data-language=\"bash\"><pre class=\"language-bash\"><code class=\"language-bash\">docker <span class=\"token function\">service</span> update --replicas<span class=\"token operator\">=</span><span class=\"token number\">5</span> --detach<span class=\"token operator\">=</span>true nginx1\nnginx1</code></pre></div>\n<ul>\n<li>The state of the service is updated to 5 replicas, which is stored in the swarm’s internal storage.</li>\n<li>Docker Swarm recognizes that the number of replicas that is scheduled now does not match the declared state of 5.</li>\n<li>Docker Swarm schedules 4 more tasks (containers) in an attempt to meet the declared state for the service.</li>\n</ul>\n<div class=\"gatsby-highlight\" data-language=\"bash\"><pre class=\"language-bash\"><code class=\"language-bash\">docker <span class=\"token function\">service</span> <span class=\"token function\">ps</span> nginx1</code></pre></div>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 590px; \"\n    >\n      <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/4ab19d0fde948f11ae1221935efcb148/318d8/2020-03-13-14-28-44.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 10.135135135135135%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAACCAYAAABYBvyLAAAACXBIWXMAABYlAAAWJQFJUiTwAAAAgUlEQVQI1z2LOwoDIQBEjRE/q9goSMJuIeKmEgvvIXiWkDZN9t6TrEWqGd68Ie/nC0oShO2G+xZxuTJIKaGUAiEExpiZjDE452ZqreG9hxACnPO/O8YA+RwH1nWDXhY89n0OIQTknEEpRUppMmstSimzxxhRa0VrDcvvd3on773jC8b4MxTCTXAjAAAAAElFTkSuQmCC'); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"2020 03 13 14 28 44\"\n        title=\"2020 03 13 14 28 44\"\n        src=\"/static/4ab19d0fde948f11ae1221935efcb148/fcda8/2020-03-13-14-28-44.png\"\n        srcset=\"/static/4ab19d0fde948f11ae1221935efcb148/12f09/2020-03-13-14-28-44.png 148w,\n/static/4ab19d0fde948f11ae1221935efcb148/e4a3f/2020-03-13-14-28-44.png 295w,\n/static/4ab19d0fde948f11ae1221935efcb148/fcda8/2020-03-13-14-28-44.png 590w,\n/static/4ab19d0fde948f11ae1221935efcb148/efc66/2020-03-13-14-28-44.png 885w,\n/static/4ab19d0fde948f11ae1221935efcb148/c83ae/2020-03-13-14-28-44.png 1180w,\n/static/4ab19d0fde948f11ae1221935efcb148/318d8/2020-03-13-14-28-44.png 2758w\"\n        sizes=\"(max-width: 590px) 100vw, 590px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n  </a>\n    </span></p>\n<div class=\"gatsby-highlight\" data-language=\"bash\"><pre class=\"language-bash\"><code class=\"language-bash\">docker <span class=\"token function\">service</span> logs nginx1</code></pre></div>\n<h3>Apply rolling updates</h3>\n<div class=\"gatsby-highlight\" data-language=\"bash\"><pre class=\"language-bash\"><code class=\"language-bash\">docker <span class=\"token function\">service</span> update --image nginx:1.13 --detach<span class=\"token operator\">=</span>true nginx1</code></pre></div>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 590px; \"\n    >\n      <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/a364151a1472cc7fdc3974f37cfca7ce/2d86d/2020-03-13-14-33-06.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 29.72972972972973%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAGCAYAAADDl76dAAAACXBIWXMAABYlAAAWJQFJUiTwAAAA20lEQVQY042RS5KDMAxEzR/MNwk2BiZVc4AMsJ37H0yhO+WUs8tCpZYlPcuy+n885GK1uPtd3M+vqCiRIs+lKApRStHHcUxd17U0TcMY3mvkqqp66b9jl1qfiSiS2/Uq0enRaIxh4TAMUpYl9TzP0nUd9bIsNNShJkkSnqtj36Xve9KNsZJlGW8bx5EFAHigtVa01tTTNDFe1/Wdp23bFgCNpGnKJg9EzjcAgum9hgGIIT6Abdty5G+A4YQwrMFf8nrycXAH2B2A+fkhIRBP9h8UTuicY4w9hk9+Am+siQHCjy44AAAAAElFTkSuQmCC'); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"2020 03 13 14 33 06\"\n        title=\"2020 03 13 14 33 06\"\n        src=\"/static/a364151a1472cc7fdc3974f37cfca7ce/fcda8/2020-03-13-14-33-06.png\"\n        srcset=\"/static/a364151a1472cc7fdc3974f37cfca7ce/12f09/2020-03-13-14-33-06.png 148w,\n/static/a364151a1472cc7fdc3974f37cfca7ce/e4a3f/2020-03-13-14-33-06.png 295w,\n/static/a364151a1472cc7fdc3974f37cfca7ce/fcda8/2020-03-13-14-33-06.png 590w,\n/static/a364151a1472cc7fdc3974f37cfca7ce/efc66/2020-03-13-14-33-06.png 885w,\n/static/a364151a1472cc7fdc3974f37cfca7ce/c83ae/2020-03-13-14-33-06.png 1180w,\n/static/a364151a1472cc7fdc3974f37cfca7ce/2d86d/2020-03-13-14-33-06.png 2578w\"\n        sizes=\"(max-width: 590px) 100vw, 590px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n  </a>\n    </span></p>\n<h3>Reconcile problems with containers</h3>\n<div class=\"gatsby-highlight\" data-language=\"bash\"><pre class=\"language-bash\"><code class=\"language-bash\">docker swarm leave</code></pre></div>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 590px; \"\n    >\n      <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/5474d319b64e887f614cfa02d3050641/81386/2020-03-13-14-37-27.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 17.567567567567565%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAECAYAAACOXx+WAAAACXBIWXMAABYlAAAWJQFJUiTwAAAAsUlEQVQY01WOTQtGUBSEiRIKSclVVhZWomTj7yifWcjCvx/vmbq33lvTPHeazjnW8zy47xvi13VhXVcsy4Jt2yj5az6OA+d5kvd9p8/zzOx9X86xfg9JkghQQRAY9jzPsOu6f700TRHHMRzHMRklxa7rUFUVbNtG27ZomoYsnuc5i3Vdo+97slIKwzBgHEdM0wTf981SXphlGaIogmZ9iVyhy5Lp4WEYkouiQFmWehD1AT+/ctCe23QgAAAAAElFTkSuQmCC'); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"2020 03 13 14 37 27\"\n        title=\"2020 03 13 14 37 27\"\n        src=\"/static/5474d319b64e887f614cfa02d3050641/fcda8/2020-03-13-14-37-27.png\"\n        srcset=\"/static/5474d319b64e887f614cfa02d3050641/12f09/2020-03-13-14-37-27.png 148w,\n/static/5474d319b64e887f614cfa02d3050641/e4a3f/2020-03-13-14-37-27.png 295w,\n/static/5474d319b64e887f614cfa02d3050641/fcda8/2020-03-13-14-37-27.png 590w,\n/static/5474d319b64e887f614cfa02d3050641/efc66/2020-03-13-14-37-27.png 885w,\n/static/5474d319b64e887f614cfa02d3050641/c83ae/2020-03-13-14-37-27.png 1180w,\n/static/5474d319b64e887f614cfa02d3050641/81386/2020-03-13-14-37-27.png 2640w\"\n        sizes=\"(max-width: 590px) 100vw, 590px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n  </a>\n    </span></p>\n<h3> Determine how many nodes you need</h3>\n<p>For a production application, you should provision a cluster with multiple manager nodes to allow for manager node failiures.\nAt least 3 manager nodes, but no more than 7.</p>\n<ul>\n<li>3 manager nodes tolerate 1 node failure</li>\n<li>5 manager nodes tolerate 2 node failures</li>\n<li>7 manager nodes tolerate 3 node failures</li>\n</ul>\n<p>Play with docker Templates :\n<span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 590px; \"\n    >\n      <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/093f44248b2756f022c1da03e8c9f2fe/229ad/2020-03-13-14-42-38.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 86.48648648648648%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAARCAYAAADdRIy+AAAACXBIWXMAABYlAAAWJQFJUiTwAAACQ0lEQVQ4y61STW8SURSdvX/BX1Hj0oUrky4bV5Vo3Fg1xp1uugIMpD+gLjRpYkggYFMD6cJFq0mrUGNLrEYqzJQMMEKnIwYYvgZm5vjug5kS6JjGeMMJ775357z7zj3Ck+WX8N1/g7uP1nH74TpuLb3+JywubeDx01cQfPfWcG0hg3nfB1y/uYO5G9u44oG5MWbPtnB1fhcLdxIQItFNHHzTkf6sInNwir3sCJ+yGscege/TP+2dnbk17Hz/sInkZgbC+3db+F9RyH+HsLr6nCcnJ6fI5Y5QKEgoFmXIcgmVigJJKiL3I49ftSpW0goW13YwGAxhmrYLg+UUyVQKQjAY5Em/32eFAxiGwTEcDl0YbB+wsfJRwoPUIQzTYqnNfiNQDUUsFoMQDoddQsuy2I2mJwCL11psTUQUk4SJBBtKKBTiSa/X4x3aEzeb4w/pIgKF2jY8CePx+FmHmqYhn89DFEWmYRHlcpmjWq1ClI5RlY+xcaTi8rO32Jdro04te5YwEAjwZMB1gtvNZKf0IcVXtYnQrghF77vdzRD6/X73yZPPm4E5dO1hs7VziSdhp9NBo9FAu93m6263y9ctXUeHoWmYSJcb6LHh2Q7xWMdzCVutFkqlEvOfzPxXgaqqqNfrUJiGv2sKXmQruLScxBdF4/WmZZ//ZEdDZ9MrfupdbMsa2gOTe3Lc3N81pMFMght7vGYiciLS0uJstvtkx1Lchw7htAenQSTm1PSdIZJcFNFodJbwouHUkvlJe/JxJBLBH6jhw28F8UqmAAAAAElFTkSuQmCC'); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"2020 03 13 14 42 38\"\n        title=\"2020 03 13 14 42 38\"\n        src=\"/static/093f44248b2756f022c1da03e8c9f2fe/fcda8/2020-03-13-14-42-38.png\"\n        srcset=\"/static/093f44248b2756f022c1da03e8c9f2fe/12f09/2020-03-13-14-42-38.png 148w,\n/static/093f44248b2756f022c1da03e8c9f2fe/e4a3f/2020-03-13-14-42-38.png 295w,\n/static/093f44248b2756f022c1da03e8c9f2fe/fcda8/2020-03-13-14-42-38.png 590w,\n/static/093f44248b2756f022c1da03e8c9f2fe/efc66/2020-03-13-14-42-38.png 885w,\n/static/093f44248b2756f022c1da03e8c9f2fe/c83ae/2020-03-13-14-42-38.png 1180w,\n/static/093f44248b2756f022c1da03e8c9f2fe/229ad/2020-03-13-14-42-38.png 1356w\"\n        sizes=\"(max-width: 590px) 100vw, 590px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n  </a>\n    </span></p>\n<h3>Summary</h3>\n<ul>\n<li>Docker Swarm schedules services by using a declarative language. You declare the state, and the swarm attempts to maintain and reconcile to make sure the actual state equals the desired state.</li>\n<li>Docker Swarm is composed of manager and worker nodes. Only managers can maintain the state of the swarm and accept commands to modify it. Workers have high scalability and are only used to run containers. By default, managers can also run containers.</li>\n<li>The routing mesh built into Docker Swarm means that any port that is published at the service level will be exposed on every node in the swarm. Requests to a published service port will be automatically routed to a container of the service that is running in the swarm.</li>\n</ul>","frontmatter":{"title":"Docker training","date":"March 13, 2020","description":"Notes taken during Docker training"}}},"pageContext":{"slug":"/docker-training/","previous":{"fields":{"slug":"/lambda-training/"},"frontmatter":{"title":"Lambda training","tags":["training","AWS"]}},"next":{"fields":{"slug":"/karbon/karbon/"},"frontmatter":{"title":"Karbon Editor","tags":["article","react"]}}}},"staticQueryHashes":["2841359383","3145232782"]}