{"id":236,"date":"2015-12-29T05:56:27","date_gmt":"2015-12-29T05:56:27","guid":{"rendered":"https:\/\/carson.fenimorefamily.com\/?p=236"},"modified":"2016-01-01T17:27:58","modified_gmt":"2016-01-01T17:27:58","slug":"containers-for-fun-and-profit","status":"publish","type":"post","link":"https:\/\/carson.fenimorefamily.com\/?p=236","title":{"rendered":"Containers for Fun and Profit"},"content":{"rendered":"<p>With all the whirl about containers I decided I could wait no longer to join the fray.  Here is a log of some of the things I learned.<\/p>\n<p><strong><a href=\"https:\/\/docs.docker.com\/linux\/step_one\/\">Basic test<\/a>, e.g. what the heck is this?<\/strong><\/p>\n<p>I spun up a cent7 vm several months back. Apparently my repos were a tad old and things didnt work until i did a yum update first, then reboot.  Then I could systemctl enable docker, systemctl start docker<\/p>\n<p>Note you MUST sudo in for docker commands to work<\/p>\n<p>Also note: cent7 has docker in it natively &#8211; no need to wget install it (unless you want to use some of the new features like the networking module)<\/p>\n<p>The following is your smoke test:<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nsudo docker run hello-world \r\n<\/pre>\n<p><strong><a href=\"https:\/\/docs.docker.com\/linux\/step_three\/\">Test 2: Expanded sample<\/a><\/strong><\/p>\n<p>This worked flawlessly\u2026<\/p>\n<p><strong><a href=\"https:\/\/docs.docker.com\/linux\/step_four\/\">Test 3: Interactive sample<\/a><\/strong><\/p>\n<p>Ditto, worked perfectly<\/p>\n<p><strong>Test 4: Do my own thing<\/strong><\/p>\n<p>I made a \u201clooper.py\u201d app with the following code:<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\n#!\/usr\/bin\/python\r\nimport time\r\nwhile True:\r\n\tprint &quot;Hi! &quot;, time.time()\r\n\ttime.sleep(1)\r\n<\/pre>\n<p>I then made the following Dockerfile<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nFROM docker.io\/centos:latest\r\nRUN yum install python -y\r\nCOPY looper.py \/\r\nCMD \/looper.py\r\n<\/pre>\n<p>And create the image with <\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\n\tdocker build -t looper .\r\n<\/pre>\n<p>When i ran the build one of the things I noticed is that python was already installed in the centos image.  I modified the Dockerfile by removing the RUN line, and one cool thing is that when i re-ran the build command, the python install layer was automatically removed, and everything else was basically a noop.  In other words docker appears to do a good job at being efficient.<\/p>\n<p>I then ran my looper:<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\n\tdocker run looper\r\n<\/pre>\n<p>Nothing happened\u2026 So i thought\u2026and though\u2026 and eventually decided to try and attach.  Ubeknowest to me, by doing docker run i WAS attached, but nonetheless I learned a few things:<\/p>\n<ul>\n<li>To attach you need your container id<\/li>\n<li>To get your container id you run \u201cdocker ps\u201d<\/li>\n<\/ul>\n<p>Once I did a docker attach to my container id, i saw nothing, still.  I did a Ctrl-C and viola, my looper output appeared!  I suspected buffering, which turned out to be the case.  I modified looper as follows:<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\n#!\/usr\/bin\/python\r\nimport time\r\nimport sys\r\nwhile True:\r\n\tprint &quot;Hi! &quot;, time.time()\r\n\tsys.stdout.flush()\r\n\ttime.sleep(1)\r\n<\/pre>\n<p>Then rebuilt, and re-ran, and it all worked.<\/p>\n<p>Note that this only runs the command in the foreground.  To run it in the background:<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\n\tdocker run -d looper\r\n<\/pre>\n<p>You can then docker ps, find the cid, docker attach to it.   But\u2026 you cannot detach (without sending a SIGKILL)!  The docks say Ctrl-P + Ctrl+Q will detach, but this appears to only work if you use the following command when running it:<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\n\tdocker run -tdi looper\r\n<\/pre>\n<p>Where <strong>t<\/strong> means create a tty, and <strong>i<\/strong> means \u201ckeep stdin open even if not attached\u201d.  This works well.<\/p>\n<p>Note that each time i make changes to looper, when i rebuild it takes at most 20 seconds.. if no changes, docker takes milliseconds\u2026<\/p>\n<p><strong>Test 5: layers<\/strong><\/p>\n<p>What if the container modifies a file?<\/p>\n<p>I modified looper.py to write to stdout and a file:<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\n#!\/usr\/bin\/python\r\nimport time\r\nimport sys\r\nwhile True:\r\n\tmsg = &quot;Hi! &quot; + str(time.time())\r\n\tprint msg\r\n\twith open('myfile','a') as f:\r\n\t\tf.write(msg + '\\n')\r\n\tsys.stdout.flush()\r\n\ttime.sleep(1)\r\n<\/pre>\n<p>For fun i created a file named \u201cmyfile\u201d, then build the image, then ran the container. When it runs i can do a docker diff:<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\n# docker diff f04849645523\r\nA \/myfile\r\n<\/pre>\n<p>And to be clear, this means the file was added in the image. Docker wont let the app reach into my own version of \u201cmyfile\u201d.<\/p>\n<p>What if i want to see the file?  In older versions of docker, apparently you had a few options, such as running ssh, or making a snapshot, but now its easy:<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\n\tdocker exec -t -i &lt;cid&gt; \/bin\/bash\r\n<\/pre>\n<p>You can then just cat the file, etc.  If you actually want to copy the files out,<br \/>\nyou can export the whole filesystem (docker export <cid>) as a tar, but this seems nuts. If you just want a single file, use docker cp:<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\ndocker cp &lt;cid&gt;:&lt;src&gt; &lt;dest&gt;\r\n<\/pre>\n<p><strong>Test 6: CPU limit<\/strong><\/p>\n<p>You can do a couple things:<\/p>\n<p>1) Limit the share of cpu usage across multiple containers. This is done by specifying a relative weighting (with -c)<\/p>\n<p>2) Pin the process to certain cpus with \u2014cpuset-cpus=<cpuset><\/p>\n<p>I havent been able to find an equivalent to the simple \u201climit to N processors\u201d idea on virtual machines.  The weighting is fairly close.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>With all the whirl about containers I decided I could wait no longer to join the fray. Here is a log of some of the things I learned. Basic test, e.g. what the heck is this? I spun up a cent7 vm several months back. Apparently my repos were a tad old and things didnt &hellip; <a href=\"https:\/\/carson.fenimorefamily.com\/?p=236\" class=\"more-link\">Continue reading <span class=\"screen-reader-text\">Containers for Fun and Profit<\/span> <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4],"tags":[],"class_list":["post-236","post","type-post","status-publish","format-standard","hentry","category-containers"],"_links":{"self":[{"href":"https:\/\/carson.fenimorefamily.com\/index.php?rest_route=\/wp\/v2\/posts\/236","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/carson.fenimorefamily.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/carson.fenimorefamily.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/carson.fenimorefamily.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/carson.fenimorefamily.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=236"}],"version-history":[{"count":2,"href":"https:\/\/carson.fenimorefamily.com\/index.php?rest_route=\/wp\/v2\/posts\/236\/revisions"}],"predecessor-version":[{"id":238,"href":"https:\/\/carson.fenimorefamily.com\/index.php?rest_route=\/wp\/v2\/posts\/236\/revisions\/238"}],"wp:attachment":[{"href":"https:\/\/carson.fenimorefamily.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=236"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/carson.fenimorefamily.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=236"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/carson.fenimorefamily.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=236"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}