-
Notifications
You must be signed in to change notification settings - Fork 3
/
index.xml
2498 lines (1622 loc) · 135 KB
/
index.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>Docker Saigon</title>
<link>http://docker-saigon.github.io/</link>
<description>Recent content on Docker Saigon</description>
<generator>Hugo -- gohugo.io</generator>
<language>en-us</language>
<copyright>Code released under the Apache 2.0 license.</copyright>
<lastBuildDate>Wed, 28 Oct 2015 14:31:10 +0700</lastBuildDate>
<atom:link href="http://docker-saigon.github.io/index.xml" rel="self" type="application/rss+xml" />
<item>
<title>about</title>
<link>http://docker-saigon.github.io/about/</link>
<pubDate>Wed, 28 Oct 2015 14:31:10 +0700</pubDate>
<guid>http://docker-saigon.github.io/about/</guid>
<description>
<p>Docker Saigon is the community of Docker users in Ho Chi Minh City, Vietnam.</p>
<h2 id="where-can-you-find-us:6083a88ee3411b0d17ce02d738f69d47">Where can you find us?</h2>
<ul>
<li><a href="http://meetup.com/docker-saigon">Meetup</a></li>
<li><a href="https://speakerdeck.com/dockersaigon">SpeakerDeck</a></li>
<li><a href="http://github.com/docker-saigon">GitHub</a></li>
<li><a href="https://www.youtube.com/channel/UC1t_GbTJudAAK9Wqkg6-uLw">Youtube</a></li>
<li><a href="http://www.facebook.com/DockerSaigon">Facebook</a></li>
<li><a href="http://twitter.com/docker_saigon">Twitter</a></li>
<li><a href="http://dockersaigon.herokuapp.com">Slack (auto-invite app)</a></li>
<li><a href="http://dockersaigon.reddit.com">Reddit</a></li>
</ul>
<h2 id="docker:6083a88ee3411b0d17ce02d738f69d47">Docker?</h2>
<p><a href="http://docker.com">Docker</a> is an open-source project to easily create lightweight, portable, self-sufficient containers from any application. The same container that a developer builds and tests on a laptop can run at scale, in production, on VMs, bare metal, OpenStack clusters, public clouds and more.</p>
<p>See our Docker Fundamentals live streaming at Lazada&hellip; (link to video pending)</p>
<p>Thanks for reading!</p>
</description>
</item>
<item>
<title>contact</title>
<link>http://docker-saigon.github.io/contact/</link>
<pubDate>Wed, 28 Oct 2015 22:17:33 +0700</pubDate>
<guid>http://docker-saigon.github.io/contact/</guid>
<description><p>Want to get in touch with us? Fill out the form below to send us a message and we will try to get back to you as soon as possible!</p>
</description>
</item>
<item>
<title>Docker For Windows Beta</title>
<link>http://docker-saigon.github.io/post/Docker-Beta/</link>
<pubDate>Mon, 18 Apr 2016 00:34:41 +0700</pubDate>
<guid>http://docker-saigon.github.io/post/Docker-Beta/</guid>
<description>
<p><strong>Note</strong>: The research for this post was done on a Beta client and technical details are subject to change.</p>
<p>As indicated in previous posts, we&rsquo;ve been using Docker on Windows with Hyper-V for a while. Hearing that the new Docker client for Windows would be Alpine-based and focused on Hyper-V made us eager to see for ourselves.</p>
<h2 id="hyper-v-configuration:ebf9573d6838c40027746e9d7482622a">Hyper-V configuration</h2>
<p>The first issue to overcome when using Hyper-V on Windows is the lack of DNS/DHCP &amp; NAT services. The new Docker client handles the Virtual Switch NAT configuration for us and adds a clever solution for DNS &amp; DHCP.</p>
<p>As part of the installation process a <code>DockerNAT</code> Internal Virtual Switch is created and the Virtual Interface on the Windows host for this switch gets a static IP:</p>
<pre><code>New-VMSwitch -Name &quot;DockerNAT&quot; -SwitchType Internal
Get-NetAdapter &quot;vEthernet (DockerNAT)&quot; | New-NetIPAddress -AddressFamily IPv4 `
-IPAddress &quot;10.0.75.1&quot; -PrefixLength 24
</code></pre>
<p>A NAT object is created to handle Network Address Translation for the &ldquo;10.0.75.0/24&rdquo; subnet:</p>
<pre><code>New-NetNat –Name $SwitchName `
–InternalIPInterfaceAddressPrefix &quot;10.0.75.0/24&quot;
</code></pre>
<p><strong>Tip</strong>: If any of these steps failed, ensure a Switch with the name &ldquo;DockerNAT&rdquo; was created, the IP was assigned to the Virtual Interface and that <code>Get-NetNat</code> lists a NAT with the correct subnet. Also ensure these hard-coded subnets do not overlap with already existing interfaces (We had to manually fix these things while testing the beta).</p>
<p>Next, the <code>MobyLinuxVM</code> Virtual Machine is created in Hyper-V. MobyLinuxVM uses an Alpine bootcd which has Hyper-V Integration Services, such as the <code>Key-Value Pair Exchange</code> service (hv_kvp_daemon). The Hyper-V KVP Daemon allows communication between the Hyper-V Host and the Linux Guest (i.e to retrieve the Guest IP and send two-way messages as we&rsquo;ll see later).</p>
<p>Finally, Docker bundles a <code>com.docker.proxy.exe</code> binary which proxies the ports from the MobyLinuxVM on your windows host. At the time of writing (Docker Beta 7), this includes the DNS (port 53 TPC/UDP), DHCP (port 67 UDP) and Docker daemon (port 2375 TCP).</p>
<p>If you&rsquo;ve been running alternative solutions for your Hyper-V set-up, you need to ensure the above ports are available as follows..</p>
<p>See if any process is using port 53:</p>
<pre><code>netstat -aon | findstr :53
</code></pre>
<p>Once you have the process id (<code>&lt;pid&gt;</code>) of the process holding the port, get the name:</p>
<pre><code>tasklist /SVC | findstr &lt;pid&gt;
</code></pre>
<p>The <code>com.docker.proxy.exe</code> will proxy all DNS requests from the internal network of your Windows laptop to the DNS server used by your Windows host, effectively isolating the MobyLinuxVM from the network configuration changes as you move your laptop around.</p>
<p>To ensure this process can work properly, docker automatically creates <code>DockerTcp</code> &amp; <code>DockerUdp</code> firewall rules and removes them when you close the client.</p>
<pre><code>New-NetFirewallRule -Name &quot;DockerTcp&quot; -DisplayName &quot;DockerTcp&quot; `
-Program &quot;C:\&lt;path&gt;\&lt;to&gt;\com.docker.proxy.exe&quot; -Protocol TCP `
-Profile Any -EdgeTraversalPolicy DeferToUser -Enabled True
New-NetFirewallRule -Name &quot;DockerUdp&quot; -DisplayName &quot;DockerUdp&quot; `
-Program &quot;C:\&lt;path&gt;\&lt;to&gt;\com.docker.proxy.exe&quot; -Protocol UDP `
-Profile Any -EdgeTraversalPolicy DeferToUser -Enabled True
</code></pre>
<p>Having the Docker daemon port opened locally, allows your docker client to talk to localhost, however - it seems that going forward a named pipe solution will be used instead, if the VM was created successfully you should see the named pipe connected to its COM port:</p>
<pre><code>Get-VMComPort -VMName MobyLinuxVM | fl | Out-String
</code></pre>
<p>See also the docker client code for handling <a href="https://github.com/docker/docker/blob/v1.11.0/vendor/src/github.com/docker/go-connections/sockets/sockets_windows.go">Windows Named Pipes</a> going forward.</p>
<p>If the MobyLinuxVM booted successfully, we may confirm the Hyper-V integration Services are running:</p>
<pre><code>Get-VMIntegrationService -VMName MobyLinuxVM -Name &quot;Key-Value Pair Exchange&quot;
</code></pre>
<p>And that the <code>com.docker.proxy.exe</code> DHCP service provided an IP to the VM - which we can query thanks to the Hyper-V Integration Services:</p>
<pre><code>$(Get-VM MobyLinuxVM).NetworkAdapters[0]
</code></pre>
<h2 id="troubleshooting:ebf9573d6838c40027746e9d7482622a">Troubleshooting</h2>
<p>All settings are stored under <code>%APPDATA%\Docker\</code> folder, this folder is replicated across machines in an Enterprise setting where Roaming is enabled.</p>
<p>All logs are stored under <code>%LOCALAPPDATA%\Docker\</code> folder.</p>
<p>To monitor the latest logs use the following PowerShell command:</p>
<pre><code>gc $(gi $env:LocalAppData\Docker\* | sort LastAccessTime -Desc | select -First 1) -Wait
</code></pre>
<p>This will auto-refresh for every event written to the log.</p>
<h2 id="docker-toolbox-migration:ebf9573d6838c40027746e9d7482622a">Docker ToolBox Migration</h2>
<p>Switching on the Hyper-V role on Windows will disable VirtualBox (and you won&rsquo;t be able to use the Docker ToolBox until you switch Hyper-V off &amp; reboot). If a Docker Toolbox installation is detected, a migration path is offered (using <code>qemu-img</code>). This will convert the <code>%USERPROFILE%\.docker\machine\machines\&lt;machine-name&gt;\disk.vmdk</code> to vhdx:</p>
<pre><code>qemu-img.exe convert &lt;path-to-vmdk&gt; -O vhdx -o subformat=dynamic -p &quot;C:\Users\Public\Documents\Hyper-V\Virtual hard disks\MobyLinuxVM.vhdx\&quot;
</code></pre>
<p>If you were already using Docker-Machine &amp; Docker-Compose with Hyper-V, you can continue to do so side-by-side with the Docker for Windows client.</p>
<h2 id="mounting-volumes:ebf9573d6838c40027746e9d7482622a">Mounting Volumes</h2>
<p>One of the big improvements the new Docker for Windows promises is how Volume mounts will be handled.</p>
<p>A handy dialog is provided to streamline everything for us.</p>
<figure >
<img src="http://docker-saigon.github.io/img/beta7-shares.png" alt="shares dialog" />
</figure>
<p>The current implementation will share the whole drive (and not individual folders). Enabling a Drive share will prompt for credentials.</p>
<p>Credentials are stored with the <code>target</code> &ldquo;Docker Host Filesystem Access&rdquo; under the Windows &gt; Control Panel &gt; Credential Manager &gt; Windows Credentials Store by the configuration tool. This uses <code>System.Security.Cryptography</code> to encrypt the credentials with currentuser scope.</p>
<p>If the credential manager already contains credentials for the specified target, they will be overwritten.</p>
<p>Next, the drive is shared on the Windows Host:</p>
<pre><code>net share C=C:\ /grant:&lt;username&gt;,FULL /CACHE:None
</code></pre>
<p>This Samba share now needs to be mounted into the MobyLinuxVM and this is automated through the Hyper-V <a href="https://technet.microsoft.com/en-us/library/dn798287.aspx">Key-Value Pair Exchange</a> Integration Service. A detailed explanation is available <a href="http://dlafferty.blogspot.com.ee/2013/09/hyper-v-kvp-data-exchange-for-cloudstack.html">here</a>.</p>
<p>The way this is supposed to work is as follows: our Windows host puts a <code>mount authentication token</code> packaged in a <code>KvpExchangeDataItem</code> on the VMBus:</p>
<pre><code>class Msvm_KvpExchangeDataItem : CIM_ManagedElement
{
uint16 Source = 0;
string Name = &quot;cifsmount&quot;;
string Data = &quot;authToken&quot;;
};
</code></pre>
<p>The Authentication token is a serialized string containing the mount points and mount options:</p>
<pre><code>/c;/C;username=&lt;username&gt;,password=&lt;password&gt;,noperm
</code></pre>
<p>On the Alpine guest the <code>hv_utils</code> kernel driver module notifies the <code>hv_kvp_daemon</code>. This daemon writes the kvp to the pool file (<code>/var/lib/hyperv/.kv_pool_*</code>).</p>
<p>At this stage a process on MobyLinuxVM needs to make the directory and mount the share from the host - but this was failing at the time of writing:</p>
<pre><code> #for both upper and lower case
mount -t cifs //10.0.75.1/C /C -o username=&lt;username&gt;,password=&lt;password&gt;,noperm
</code></pre>
<p>If the share worked fine, our docker client would be sending any volume mount commands through the socket opened by the <code>com.docker.proxy.exe</code>, this proxy re-writes the path if needed: <code>C:\Users\test\</code> becomes <code>/C/Users/test</code>, allowing us to mount Windows folders into our Docker containers.</p>
<p>However, there are still limitations due to the SMB protocol (lack of support for inotify and symlinks), which will cause problems with live reloads.</p>
<p><strong>Troubleshooting</strong>: We can verify that the auth token exists on the VMBus with the following PowerShell script:</p>
<pre><code>$VmMgmt = Get-WmiObject -Namespace root\virtualization\v2 -Class `
Msvm_VirtualSystemManagementService
$vm = Get-WmiObject -Namespace root\virtualization\v2 -Class `
Msvm_ComputerSystem -Filter {ElementName='MobyLinuxVM'}
($vm.GetRelated(&quot;Msvm_KvpExchangeComponent&quot;)[0] `
).GetRelated(&quot;Msvm_KvpExchangeComponentSettingData&quot;).HostExchangeItems | % { `
$GuestExchangeItemXml = ([XML]$_).SelectSingleNode(`
&quot;/INSTANCE/PROPERTY[@NAME='Name']/VALUE[child::text() = 'cifsmount']&quot;)
if ($GuestExchangeItemXml -ne $null)
{
$GuestExchangeItemXml.SelectSingleNode(`
&quot;/INSTANCE/PROPERTY[@NAME='Data']/VALUE/child::text()&quot;).Value
}
}
</code></pre>
<p>So far, I have not been able to find which process is monitoring the <code>/var/lib/hyperv/.kv_pool_0</code> files on the Alpine guest.</p>
<h2 id="private-registries:ebf9573d6838c40027746e9d7482622a">Private Registries</h2>
<p>At the moment, the beta for Windows does not support <code>DOCKER_OPTS</code> or TLS certs <strong>yet</strong>.</p>
<p>We can get root access to the MobyLinuxVM as follows:</p>
<pre><code> #get a privileged container with access to Docker daemon
docker run --privileged -it --rm -v /var/run/docker.sock:/var/run/docker.sock -v /usr/bin/docker:/usr/bin/docker alpine sh
#run a container with full root access to MobyLinuxVM and no seccomp profile (so you can mount stuff)
docker run --net=host --ipc=host --uts=host --pid=host -it --security-opt=seccomp=unconfined --privileged --rm -v /:/host alpine /bin/sh
#switch to host FS
chroot /host
</code></pre>
<p>Poking around in the VM reveals the following:</p>
<p>The VM (Alpine-based) uses <a href="http://wiki.alpinelinux.org/wiki/Alpine_Linux_Init_System">OpenRC as its init system</a>.</p>
<pre><code>rc-status
</code></pre>
<p>Shows the status of all services, but some of the init scripts do not implement status and show up as &ldquo;crashed&rdquo; while it seems their process is still running (<code>ps -a</code>).</p>
<p>The Docker init script relies on a <code>/usr/bin/mobyconfig</code> script. This <code>mobyconfig</code> script requires the kernel to boot with a <code>com.docker.database</code> label specifying the location of the config file or it bails. If the label is present - <code>/Database</code> is mounted using the <a href="https://en.wikipedia.org/wiki/9P_%28protocol%29">Plan 9 Filesystem Protocol</a>, which was the original filesystem for Docker for Mac.</p>
<p>The <code>mobyconfig</code> script is able to retrieve network and <code>insecure-registry</code> configuration for the Docker deamon or pick up a config file from <code>/etc/docker/daemon.json</code>. This looks like a very promising solution, once it is fully implemented.</p>
<p>As the whole disk is a Temporary filesystem with only the <code>/var/</code> mountpoint (to <code>/dev/sda2</code>) persisted, changes made to any of the scripts are not persisted across reboots. It is possible to temporarily change the Docker options and <code>/etc/init.d/docker restart</code> the daemon.</p>
<h2 id="conclusion:ebf9573d6838c40027746e9d7482622a">Conclusion</h2>
<p>Many improvements are coming with the Docker client for Windows, we are looking forward at testing the Docker client for Mac next.</p>
</description>
</item>
<item>
<title>Docker Caveats</title>
<link>http://docker-saigon.github.io/post/Docker-Caveats/</link>
<pubDate>Mon, 11 Apr 2016 20:17:12 +0700</pubDate>
<guid>http://docker-saigon.github.io/post/Docker-Caveats/</guid>
<description>
<p>We can&rsquo;t deny Linux Containers are a very powerful concept combining clever Linux kernel features and Docker&rsquo;s open source tools make containers easily accessible to developers of any background.</p>
<p>At container summit 2016, <a href="https://twitter.com/bcantrill">Bryan Cantrill</a> eloquently compared the industry disruption this causes, and the issues mass industry adoption entails, to the issues which may show up after <a href="http://containersummit.io/events/nyc-2016/videos/the-evolving-container-ecosystem">you&rsquo;ve taught peasants to read</a> <em>(about 28 minutes into the linked video of the panel discussion).</em></p>
<p>Issues such as: improper usage of the technology and unpleasant surprises due to a poor understanding of the underlying features enabling the technology.</p>
<p>Yesterday, a brilliant Downfall parody made by <a href="https://twitter.com/nukemberg">Avishai Ish-Shalom</a> highlights some of the surprises &amp; frustrations which may cause shock to those that are unprepared:</p>
<blockquote class="twitter-tweet"><p lang="en" dir="ltr">This is hilarious! Hitler uses Docker <a href="https://t.co/cmXB2Clj8D">https://t.co/cmXB2Clj8D</a> <br><br>via <a href="https://twitter.com/nukemberg">@nukemberg</a> ht <a href="https://twitter.com/m1keil">@m1keil</a> <a href="https://twitter.com/hashtag/linux?src=hash">#linux</a> <a href="https://twitter.com/hashtag/cloudcomputing?src=hash">#cloudcomputing</a> <a href="https://twitter.com/hashtag/devops?src=hash">#devops</a> <a href="https://twitter.com/hashtag/sysadmin?src=hash">#sysadmin</a></p>&mdash; nixCraft (@nixcraft) <a href="https://twitter.com/nixcraft/status/719146833558183936">April 10, 2016</a></blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>
<p>In this blog post, we&rsquo;d like to take a look at each of these statements and deconstruct them for a better understanding of what makes this short so clever, while at the same time - it serves as a great caveat for anyone hoping to get the best out of running Docker in production.</p>
<h2 id="isolation:4c461b6a7a614440939d8002a0e574c8">Isolation</h2>
<p>The video starts with what looks like a very popular CI/CD setup using Docker&rsquo;s public image registry, the Docker Hub and its multi-container management tool, Docker-Compose. Although it should be noted that Docker-Compose is still primarily aimed at Development and Testing environments and is probably not suited for larger production deployments, as clearly outlined in the <a href="https://docs.docker.com/compose/production/">Docker docs</a> at the time of this blog post.</p>
<figure >
<img src="http://docker-saigon.github.io/img/caveat/caveat01.png" alt="Untrusted Images" />
</figure>
<figure >
<img src="http://docker-saigon.github.io/img/caveat/caveat02.png" alt="Kernel Panic in a Shared Kernel" />
</figure>
<p><strong>This highlights a first issue of sharing the kernel: reduced reliability and redundancy.</strong></p>
<figure >
<img src="http://docker-saigon.github.io/img/caveat/caveat03.png" alt="Isolation my ass!" />
</figure>
<p>We believe, the take-away here should be:</p>
<blockquote>
<p>Containers should not be used without ensuring that reliability and redundancy of every resource is incorporated into the overall design of your infrastructure.</p>
</blockquote>
<p>You may gain back reliability by using shared storage, service orchestration, monitoring and a framework with built-in self-healing features such as <a href="http://container-solutions.com/rescheduling-containers-on-node-failures-with-docker-swarm-1-1/">the container rescheduling on node failure&rdquo; features added to Swarm</a>; Or the ingrained concept of &ldquo;The Reconciliation Loop&rdquo; in <a href="http://kubernetes.io/docs/user-guide/replicasets/">Kubernetes ReplicaSets</a>.</p>
<p>Although a snarky comment on the above is also included in the video:</p>
<figure >
<img src="http://docker-saigon.github.io/img/caveat/caveat09.png" alt="Keep it Simple, Stupid" />
<figcaption>
<p>
<a href="https://twitter.com/hashtag/GIFEE">
#GIFEE
</a>
</p>
</figcaption>
</figure>
<p>Later on, another concern related to the implementation of isolation provided by container runtimes is also highlighted:</p>
<figure >
<img src="http://docker-saigon.github.io/img/caveat/caveat08.png" alt="Resource Isolation in a Shared Kernel" />
</figure>
<p>Disillusionment comes from treating Docker like magic.</p>
<p>Covered in detail by <a href="https://www.youtube.com/watch?v=sK5i-N34im8">Jérôme Petazzoni in his DockerCon EU 2015 presentation</a>, control groups are integral to what makes up a linux container and fundamental to the resource usage control per process group. A fix for the above complaint is added to Docker 1.11, details can be found in the below Twitter conversation between the video creator and Docker maintainer <a href="https://github.com/jfrazelle">@jfrazelle</a>:</p>
<blockquote class="twitter-tweet"><p lang="en" dir="ltr"><a href="https://twitter.com/frazelledazzell">@frazelledazzell</a> <a href="https://twitter.com/francesc">@francesc</a> <a href="https://twitter.com/nixcraft">@nixcraft</a> <a href="https://twitter.com/m1keil">@m1keil</a> nproc cgroup support will only be in 1.11.0<a href="https://t.co/lCKjdNmx5Y">https://t.co/lCKjdNmx5Y</a></p>&mdash; Avishai Ish-Shalom (@nukemberg) <a href="https://twitter.com/nukemberg/status/719326696084606978">April 11, 2016</a></blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>
<p>Care is also required surrounding entropy depletion in cloud environments, which is certainly very relevant in shared-kernel scenarios and we may refer to <a href="https://github.com/gesellix/haveged">HAVEGED</a> as a work-around for this.</p>
<h2 id="image-security:4c461b6a7a614440939d8002a0e574c8">Image Security</h2>
<p>The 2nd issue highlighted above was the mis-placed trust in container images pulled from public registries.</p>
<figure >
<img src="http://docker-saigon.github.io/img/caveat/caveat04.png" alt="Untrusted Images" />
</figure>
<p>The very apt &ldquo;<a href="http://sobersecurity.blogspot.com.ee/2016/03/containers-are-like-sandwiches.html">Sandwich Analogy</a>&rdquo; does a great job explaining why using non-official public images from the Docker Hub should be a concern.</p>
<blockquote>
<p>Let&rsquo;s think about Containers in the context of Sandwiches. You can pick up a sandwich. You can look at it, you can tell basically what&rsquo;s going on inside. Are there tomatoes? Lettuce? Ham? Turkey? It&rsquo;s not that hard. There can be things hiding, but for the most part you can get the big details. This is just like a container. Fedora? Red Hat? Ubuntu? It has httpd, great. What about a shell? systemd? Cool. There can be scary bits hidden in there too. Someone decided to replace /bin/sh with a python script? That&rsquo;s just like hiding the olives under the lettuce. What sort of monster would do such a thing!</p>
</blockquote>
<p>The security of image contents was big in the news all of 2014 &amp; 2015. Docker has been working diligently to add the required building blocks to fill the gaps. <a href="https://docs.docker.com/engine/userguide/storagedriver/imagesandcontainers/#content-addressable-storage">Content Addressable image layers</a> to verify image content against signed manifests, Registry repositories with proper pull validation no longer requiring Image IDs to be treated as secrets, <a href="https://blog.docker.com/2015/11/dockercon-eu-2015-docker-universal-control-plane/">Nautilus deep inspections</a> on the hub ensuring exposed vulnerabilities are patched in the <strong>official</strong> public Images, <a href="https://blog.docker.com/2016/02/docker-engine-1-10-security/">User Namespaces, Seccomp and AppArmor profiles</a> as well as <a href="https://blog.docker.com/2015/12/docker-webinar-qa-intro-to-docker-security/">other Security additions</a> to the Docker Engine, &hellip;.</p>
<p>Refer also to the <a href="https://docs.docker.com/engine/security/">Docker docs</a> and <a href="https://www.docker.com/docker-security">the Docker Security Portal</a>.</p>
<h2 id="docker-defaults:4c461b6a7a614440939d8002a0e574c8">Docker Defaults</h2>
<p>As highlighted in our <a href="http://docker-saigon.github.io/post/Docker-Internals/">Docker Internals</a> blog post, if your Linux Kernel &gt; 2.6.x - you need to disable the <code>userland-proxy</code> on the Docker daemon in favor of Hairpin NAT!</p>
<figure >
<img src="http://docker-saigon.github.io/img/caveat/caveat13.png" alt="docker-proxy" />
</figure>
<p>In general, careful study of the docker defaults is required to ensure the optimal configuration for your environment and use-case. Things such as selecting the appropriate Copy-on-Write Filesystem are all covered in the Docker docs.</p>
<h2 id="containers-vs-vms:4c461b6a7a614440939d8002a0e574c8">Containers vs VMs</h2>
<p>Containers provide significant advantages over Virtual Machines for the use of &ldquo;Application Packaging&rdquo; due to the fact that they take a short time to build, are moved around easily and can start and stop very quickly compared to VMs.</p>
<figure >
<img src="http://docker-saigon.github.io/img/caveat/caveat05.png" alt="Inception" />
</figure>
<p>Unfortunately, in Windows &amp; OSX - virtualisation is required to run the Linux kernel and work with Linux containers. If this is not fully understood, this may cause frustration.</p>
<p>Docker is also improving this with the newest Docker client (which is in private beta at the time of writing). The approach used by the newer Docker clients integrates more deeply with the host operating system which greatly streamlines the developer experience on non-Linux operating systems.</p>
<h2 id="distribution-deployment:4c461b6a7a614440939d8002a0e574c8">Distribution &amp; Deployment</h2>
<p>The Docker tools not only popularized Container technology, they also included critical shipping functionality making Containers an increasingly popular way to package and deploy code. Container images solve many real-world problems with existing packaging and deployment tools.</p>
<figure >
<img src="http://docker-saigon.github.io/img/caveat/caveat06.png" alt="Bloated Images" />
</figure>
<figure >
<img src="http://docker-saigon.github.io/img/caveat/caveat07.png" alt="Use Package Managers" />
</figure>
<p>However, as containers were being adopted by the masses without differentiating them from the way Virtual Machines tend to be used, images were often shipped with full Linux distributions and countless unnecessary binaries packaged within. This does not only bloat the images, causing slow deployment times, but also increases the attack surface for the application running in production.</p>
<p>Luckily the community has been adopting slim <code>Application containers</code>, using minimal Linux distributions such as Alpine - which is now being <a href="https://news.ycombinator.com/item?id=11000378">used for all the Official docker images</a> and statically compiled binaries that only rely on the kernel they are built for.</p>
<figure >
<img src="http://docker-saigon.github.io/img/caveat/caveat14.png" alt="Scalable Apps" />
</figure>
<p>Scalability in your App is still up to you and will require you to explore the scenarios enabled by Containers.</p>
<p>The concept of Container <a href="http://kubernetes.io/docs/user-guide/pods/">Pods</a> encourage the decomposition of applications into even smaller modular, focused, cooperating containers. The isolation provided by containers are sufficient to allow the design of reusable components which lead to more reliable, more scalable and faster to build services than applications built from monolithic containers. We believe these concepts require a change in mindset of what it means to build applications for the cloud. Read more about: <a href="http://blog.kubernetes.io/2015/06/the-distributed-system-toolkit-patterns.html">Patterns for Composite Containers</a>.</p>
<p>But even for existing legacy applications, which may be less &ldquo;CloudNative&rdquo;, containers enable powerfull deployment patterns such as <a href="https://www.joyent.com/blog/dbaas-simplicity-no-lock-in">The autopilot pattern</a> pioneered by Joyent.</p>
<h2 id="microsoft:4c461b6a7a614440939d8002a0e574c8">Microsoft</h2>
<p>
<figure >
<img src="http://docker-saigon.github.io/img/caveat/caveat10.png" alt="Microsoft Containers" />
</figure>
</p>
<p>Microsoft committed early on to supporting the Docker API for Windows containers with Windows Server 2016. After contributing to ensure the Docker client tools worked well on Windows, implementing Filesystem and Container fundamentals in the Windows Kernel and even open sourcing the Dot Net Core CLR.</p>
<p>
<figure >
<img src="http://docker-saigon.github.io/img/caveat/caveat11.png" alt="Microsoft Containers" />
</figure>
</p>
<p>Microsoft seems to have gone full-out by extending Project Astoria (an Android emulator) into an impressive Windows SubSystem for Linux (WSL) announced just last week and surprising everyone.</p>
<p>
<figure >
<img src="http://docker-saigon.github.io/img/caveat/caveat12.png" alt="Bash on Windows" />
</figure>
</p>
<p>The current Linux Kernel API features integrated with Windows however, are targeted at the most common Linux system calls and just enough to <a href="http://arstechnica.com/information-technology/2016/04/why-microsoft-needed-to-make-windows-run-linux-software/">make Windows a more attractive platform for software development</a> (at the moment).</p>
<p>Integrating these recent events into a wonderfully joyful way, our hats are off to the creator of this video!</p>
<p><a href="https://news.ycombinator.com/item?id=11477020">Discuss on Hacker-News</a></p>
<p>Reference: <a href="http://blog.takipi.com/ignore-the-hype-5-docker-misconceptions-java-developers-should-consider/">Ignore the Hype</a></p>
</description>
</item>
<item>
<title>TLS secured Private Registries</title>
<link>http://docker-saigon.github.io/post/Private-Registry-Setup/</link>
<pubDate>Tue, 22 Mar 2016 14:52:43 +0700</pubDate>
<guid>http://docker-saigon.github.io/post/Private-Registry-Setup/</guid>
<description>
<p>An intermezzo after creating a small swarm cluster in <a href="http://docker-saigon.github.io/post/Swarm-Week-2016-Part1/">our previous post</a> and before deploying &amp; scaling the sample voting app on this cluster.</p>
<p>In this post we will use <code>Docker-Machine</code> to provision a <code>Boot2Docker</code> host for a local Docker <code>Registry</code> and explain how to configure other Machines (i.e. <code>Boot2Docker</code> &amp; <code>CoreOS</code> machines) to push and pull from this Registry using TLS.</p>
<p>This setup is great for giving demonstrations where internet access is not guaranteed. We will not be configuring basic authentication or more advanced features such as web hooks, but provide links for how to do this.</p>
<p>We will, again, be using Windows 10, Hyper-V and PowerShell for this setup (as there aren&rsquo;t many guides out there using this setup), but it should be trivial to repeat these steps on OSX.</p>
<h2 id="1-create-configure-the-machine-to-host-the-registry:21a6fde08c8e60098cde90e87b1d737a">1. Create &amp; Configure the Machine to host the Registry</h2>
<p>Use Docker-Machine to create a TLS secured Docker Engine. For the full details on our environment configuration, refer to our previous post on <a href="http://docker-saigon.github.io/post/Swarm-Week-2016-Part1/">How to create a Swarm cluster.</a></p>
<p>As seen in that post, using Hyper-V and an elevated Powershell session with the <code>dm</code> alias (<code>New-Alias dm Docker-Machine</code>), we may run the following command to create our <code>registry0</code> machine:</p>
<pre><code>dm create `
--driver hyperv `
--hyperv-virtual-switch &quot;VMWare NAT&quot; `
--hyperv-memory &quot;512&quot; registry0
</code></pre>
<p><strong>Note</strong>: As a result of the above command, <code>Docker-Machine</code> will have created a PKI for us. The Certificate Authority private key as well as self-signed CA certificate are stored under <code>~/.docker/machine/certs/</code>, we will use this information when generating the TLS assets for our registry.</p>
<p>Configure a static IP (192.168.233.3) for the newly created machine.</p>
<p>Using PowerShell with a single command from the Host:</p>
<pre><code>echo &quot;kill ``more /var/run/udhcpc.eth0.pid```n`
ifconfig eth0 192.168.233.3 netmask 255.255.255.0 broadcast 192.168.233.255 up`n`
route add default gw 192.168.233.2&quot; | `
dm ssh registry0 &quot;sudo tee /var/lib/boot2docker/bootsync.sh&quot; &gt; $null
</code></pre>
<p>(see Swarm post referred to earlier for a detailed explanation of these commands)</p>
<p>Now, bounce the machine:</p>
<pre><code>dm restart registry0
</code></pre>
<p>After changing the IP, we have to re-generate the certificates used by our <code>registry0</code> machine:</p>
<pre><code>dm regenerate-certs registry0
</code></pre>
<p>Add DNS entries for <code>registry0</code> (in our setup, this is handled through the <code>/etc/hosts</code> file on the VM Host):</p>
<pre><code>&quot;192.168.233.3 registry0`n192.168.233.3 registry0.localdomain&quot; | ac $env:Windir\System32\Drivers\etc\hosts
</code></pre>
<p><strong>Note</strong>: Requires an elevated PowerShell session.</p>
<h2 id="2-prepare-the-tls-assets-for-the-registry:21a6fde08c8e60098cde90e87b1d737a">2. Prepare the TLS assets for the Registry</h2>
<p>For convenience, we will use the PKI created by <code>Docker-Machine</code> to generate a signed certificate.</p>
<p>First, generate the private key to be used by the registry server:</p>
<pre><code>openssl genrsa -out registry-key.pem 2048
</code></pre>
<p>Next, we need to create a signing request. We will use a config file <code>registry-openssl.cnf</code> with the following contents:</p>
<pre><code>[req]
req_extensions = v3_req
distinguished_name = req_distinguished_name
[req_distinguished_name]
[ v3_req ]
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
subjectAltName = @alt_names
[alt_names]
DNS.1 = registry0.localdomain
DNS.2 = registry0
IP.1 = 192.168.233.3
IP.2 = 192.168.150.104
</code></pre>
<p><strong>Note</strong>: Make sure to replace/add any hostnames and IPs the registry will be reachable on by other Docker Engines into the above snippet.</p>
<p>Use the private key and the configuration file to create a certificate signing request (using git-bash):</p>
<pre><code>openssl req -new -key registry-key.pem -out registry.csr -subj &quot;/CN=registry0.localdomain&quot; -config registry-openssl.cnf
</code></pre>
<p>Use the CA created by <code>Docker-Machine</code> to sign the certificate for the registry:</p>
<pre><code>cp ~/.docker/machine/certs/ca*-pem .
openssl x509 -req -in registry.csr -CA &quot;ca.pem&quot; -CAkey &quot;ca-key.pem&quot; -CAcreateserial -out &quot;registry.pem&quot; -days 365 -extensions v3_req -extfile registry-openssl.cnf
</code></pre>
<p>Copy the registry private key, signed certificate as well as certificate authority to the registry server:</p>
<pre><code>scp -i ~/.docker/machine/machines/registry0/id_rsa registry.pem registry-key.pem ca.pem docker@registry0:.
</code></pre>
<h2 id="3-create-the-registry-container:21a6fde08c8e60098cde90e87b1d737a">3. Create the Registry Container</h2>
<p>We now have all ingredients to run a basic registry server on the <code>registry0</code> Machine. We will use a minimal Registry configuration, refer to the <a href="https://docs.docker.com/registry/configuration/">official Docker docs</a> for more configuration options.</p>
<p>SSH to our Machine with <code>dm ssh registry0</code> or alternatively with the following command:</p>
<pre><code>ssh -i ~/.docker/machine/machines/registry0/id_rsa docker@registry0
</code></pre>
<p>Prepare the folder structure and data for the registry server</p>
<pre><code>sudo -i
mkdir /var/lib/boot2docker/registry-certs/
mkdir /var/lib/boot2docker/registry-data/
mv ~docker/registry-*.pem /var/lib/boot2docker/registry-certs/
</code></pre>
<p>Start the Registry container (this will pull the image automatically from the Docker Hub):</p>
<pre><code>docker run -d -p 443:5000 --restart=always --name registry \
-v /var/lib/boot2docker/registry-certs:/certs \
-e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/registry.pem \
-e REGISTRY_HTTP_TLS_KEY=/certs/registry-key.pem \
-v /var/lib/boot2docker/registry-data:/var/lib/registry \
registry:2
</code></pre>
<p><strong>Note</strong>: may need to chain the <code>registry.pem</code> certificate with the <code>ca.pem</code> certificate for this to work (to be confirmed)</p>
<p>From any other machine, confirm the registry works with the following command (assuming <code>ca.pem</code> lives in <code>PWD</code>)</p>
<pre><code>curl --cacert ca.pem https://registry0/v2/
</code></pre>
<p><strong>Note</strong>: To give an example of the more advanced configuration options, refer to <a href="https://docs.docker.com/registry/configuration/#notifications">the configuration of webhooks</a>:</p>
<p><code>REGISTRY_NOTIFICATIONS_ENDPOINTS_{name,url,headers, ...}</code> ENV variables which allow us to call out systems such as <a href="https://github.com/ehazlett/conduit">Conduit</a> and automatically deploy images a build server may push to this registry.</p>
<p><img src="http://docker-saigon.github.io/img/notifications.png" alt="registry notifications" /></p>
<p>A more complicated setup may be managed through <code>Docker-Compose</code>.</p>
<h2 id="4-ensuring-your-docker-engine-can-push-pull-from-this-registry:21a6fde08c8e60098cde90e87b1d737a">4. Ensuring your Docker Engine can push/pull from this registry.</h2>
<p>Servers who do not trust the CA which signed the Registry certificate will not be able to push/pull from our Registry. The steps below show how to make a server trust our CA.</p>
<h3 id="for-boot2docker-machines:21a6fde08c8e60098cde90e87b1d737a">For Boot2Docker machines:</h3>
<p>Add the Certificate Authority to a <code>Boot2Docker</code> machine (See: <a href="https://github.com/boot2docker/boot2docker/blob/v1.10.3/README.md#installing-secure-registry-certificates">B2d - Installing Secure Registry Certificates</a>):</p>
<pre><code>dm scp ca.pem &lt;machine&gt;:~
dm ssh &lt;machine&gt; sudo mkdir -p /var/lib/boot2docker/certs/
dm ssh &lt;machine&gt; sudo mv ~/ca.pem /var/lib/boot2docker/certs/
dm restart &lt;machine&gt;
</code></pre>
<p>Once the machine has rebooted, you will be able to push/pull from the local registry.</p>
<h3 id="for-coreos-machines:21a6fde08c8e60098cde90e87b1d737a">For CoreOS machines:</h3>
<p>Similar to Boot2Docker, add the Certificate Authority and update the certificates:</p>
<pre><code>scp ca.pem core@&lt;machine&gt;:~
ssh core@&lt;machine&gt; sudo mv ca.pem /etc/ssl/certs
ssh core@&lt;machine&gt; sudo update-ca-certificates
</code></pre>
<h3 id="for-ubuntu-debian-rhel-centos:21a6fde08c8e60098cde90e87b1d737a">For Ubuntu, Debian, RHEL, CentOS, &hellip;</h3>
<p>Refer to the <a href="https://docs.docker.com/docker-trusted-registry/configure/config-security/#install-registry-certificates-on-client-docker-daemons">official documentation</a> from the DTR (the setup is the same for our TLS secured private registry).</p>
<h2 id="5-usage-tips-for-your-private-registry:21a6fde08c8e60098cde90e87b1d737a">5. Usage tips for your private Registry</h2>
<p>To pull a Docker Image from the Hub and make it available on your local registry, enter the following commands (example with the official alpine-based nginx image):</p>
<pre><code>docker pull nginx:mainline-alpine
docker tag nginx:mainline-alpine registry0.localdomain/nginx:mainline-alpine
docker push registry0.localdomain/nginx:mainline-alpine
</code></pre>
<p>From then on, all local machines may easily serve static content with the following command:</p>
<pre><code>docker run -d --name web -v --restart=always /path/to/html:/etc/nginx/html:ro registry0.localdomain/nginx:mainline-alpine
</code></pre>
<p><strong>Tip</strong>: this nginx server can be deployed on our registry server to serve static binaries / yaml files for bootstrapping scripts for our cluster as well as the images stored in its repositories.</p>
<p>There are a few Registry web UI which allow you to list repositories, images and tags for a v2 Registry, but several lack basic features.</p>
<p>Alternatively, the contents may be listed with the following <code>curl</code> &amp; <code>jq</code> commands as well:</p>
<pre><code>#list repositories
curl -s https://registry0.localdomain/v2/_catalog | jq -r .repositories[]
#list tags of an image
curl -s https://registry0.localdomain/v2/nginx/tags/list | jq -r .tags[]
</code></pre>
<p>For more actions, refer to the <a href="https://github.com/docker/distribution/blob/v2.3.1/docs/spec/api.md#deleting-an-image">Registry v2 API</a></p>
</description>
</item>
<item>
<title>Swarm week 2016 - Part 1: Cluster Setup</title>
<link>http://docker-saigon.github.io/post/Swarm-Week-2016-Part1/</link>
<pubDate>Fri, 11 Mar 2016 10:29:20 +0700</pubDate>
<guid>http://docker-saigon.github.io/post/Swarm-Week-2016-Part1/</guid>
<description>
<p>In this post we will be creating a local <code>Swarm</code> cluster running in VMs on <code>Boot2Docker</code>.</p>
<p>We will be using <code>Consul</code> as a kvstore for:</p>
<ul>
<li>node discovery &amp; overlay networking,</li>
<li>swarm leader election, and</li>
<li>as a config store for other cluster components (i.e Interlock config).</li>
</ul>
<p>Swarm makes use of the <a href="https://github.com/docker/libkv">libkv</a> library to support not only consul but multiple store backends: (<code>etcd</code>,<code>zookeeper</code>,..).</p>
<p>All Docker Engines will be created through <code>Docker-Machine</code> with TLS enabled. Additionally, we will see <strong>how to configure Boot2Docker with a static IP</strong> and install the <a href="https://github.com/gondor/docker-volume-netshare">netshare</a> <code>Volume Driver</code> to <strong>mount VM host folders across all cluster nodes for persistence</strong> - allowing any statefull containers to be re-scheduled on different nodes without loss of data.</p>
<p>In a future post, we will look at deploying and scaling the <a href="https://github.com/docker/swarm-microservice-demo-v1">sample voting app</a> on top of this cluster with <code>Docker-Compose</code>, using the latest <code>Interlock</code> images with TLS authentication for communication with Swarm.</p>
<p>In the sample set-up in this first part, we will be using a <strong>single-node</strong> Consul cluster and a <strong>single-node</strong> Swarm-manager cluster. For High Availability we would need to deploy several Consul nodes and Swarm-Manager replicas behind a load balancer, which may be explored in a future post.</p>
<p>Finally, automation of all the manual steps using <a href="nathanleclaire.com/blog/2015/11/10/using-ansible-with-docker-machine-to-bootstrap-host-nodes/">Ansible containers</a> would be the perfect conclusion of this series.</p>
<p>We will be using Windows 10, Hyper-V and PowerShell for this setup, but it should be possible to repeat a similar setup on OSX (replacing CIFS by NFS in the netshare, for example).</p>
<h2 id="windows-10-environment-setup:e3eed6f67421eff48e81c37460ec6ac3">Windows 10 Environment Setup</h2>
<p>The quickest way to get everything ready on Windows would be by installing <a href="https://github.com/git-for-windows">git-for-windows</a> and the <a href="https://www.docker.com/products/docker-toolbox">Docker Toolbox</a> (VirtualBox).</p>
<p>However, <strong>if you are required to use the Hyper-V role&hellip;</strong> - the Docker Toolbox can/should not be used.</p>
<p>The following steps will guide you how to use <code>docker</code>, <code>docker-machine</code> and <code>docker-compose</code> with Hyper-V on Windows 10 (64 bit):</p>
<ol>
<li><p>Hyper-V &amp; NAT Setup</p>
<p>Before <a href="http://www.thomasmaurer.ch/2015/11/hyper-v-virtual-switch-using-nat-configuration/">NAT support was added to Hyper-V (Q3 2015)</a> in Windows 10, it was recommended to <a href="http://thomasvochten.com/archive/2014/01/hyper-v-nat/">use VMWare&rsquo;s NAT &amp; DHCP services with Hyper-V</a>.</p>
<p>It is also possible to use Internet Connection Sharing (ICS) with your Virtual Network, but I strongly advise against it. ICS requires manual re-configuration when switching between Ethernet and WiFi adapters, which is not suitable.</p>
<p>At the time of writing, I still prefer to use the VMWare networking services with Hyper-V as it still provides the most features. You could even extract the <code>vmnetconfig.exe</code> UI tool from the VMWare Workstation installation source to easily manage your virtual networks (after only installing VMWare Player components):
<img src="http://docker-saigon.github.io/img/hyper-v-vmnetconf.png" alt="vmnetconf" /></p>
<p>The VM networking services provided by the VMWare tools also include a DNS server which forwards any DNS requests from VMs to the host machine. This means that you only need to maintain the <code>etc/hosts</code> file centrally on the Hyper-V host for easy, IP-less, inter-VM communication.</p>
<p>Before we move on, note down the name of your Virtual Switch configured with VMWare NAT, mine is <code>VMWare Nat</code>.</p>
<p>However, if you decide to use the new NAT switches introduced for Hyper-V on Windows 10, you will still need to find a solution for <a href="https://4sysops.com/archives/native-nat-in-windows-10-hyper-v-using-a-nat-virtual-switch/#dhcp-server-for-windows">DHCP</a> as well as <a href="http://unbound.net/index.html">DNS</a>.</p></li>
<li><p>Git, ssh, scp, openssl, &hellip;</p>
<p>Installing <a href="https://github.com/git-for-windows">git-for-windows</a> is mandatory for a decent console experience on Windows. The git-for-windows bundle also removes the need for putty, plink &amp; pageant when working with Linux machines.</p>
<p>Even though the Windows 10 console has greatly improved (transparency, multi-line selections, full-screen mode, <code>CTRL+C/V</code> support, &hellip;), I still recommend the usage of <a href="https://conemu.github.io/">ConEmu</a> as it has more features (quickly splitting console panels, switching between consoles, configurable short-cuts, &hellip;).</p></li>
<li><p>Docker setup</p>
<p>In a bash console, execute the following commands:</p>
<p>Download the <code>docker</code> Windows 64 bit binary:</p>
<pre><code> curl -Lo /usr/bin/docker.exe https://get.docker.com/builds/Windows/x86_64/docker-1.10.3.exe
</code></pre>
<p>Download <code>docker-machine</code> Windows 64 bit binary (includes hyperv driver)</p>
<pre><code> curl -Lo /usr/bin/docker-machine.exe https://github.com/docker/machine/releases/download/v0.6.0/docker-machine-Windows-x86_64.exe
</code></pre>
<p>Download <code>docker-compose</code> Windows 64 bit binary</p>
<pre><code> curl -Lo /usr/bin/docker-compose.exe https://github.com/docker/compose/releases/download/1.6.2/docker-compose-Windows-x86_64.exe
</code></pre></li>
<li><p>PowerShell set-up</p>
<p>To control Hyper-V, PowerShell needs to have Administrative privileges. in ConEmu pressing <code>WINDOWS+SHIFT+W</code> allows you to quickly create such a session:</p>
<p><img src="http://docker-saigon.github.io/img/powershell-admin.png" alt="PowerShell Admin" /></p>
<p>Make sure your <code>$PATH</code> environment variable includes the <code>/usr/bin/</code> directory where we downloaded all the binaries earlier:</p>
<pre><code> $env:Path.Contains(&quot;$env:LOCALAPPDATA\Programs\Git\usr\bin&quot;)
</code></pre>
<p>Should return <code>True</code>.</p>
<p>Confirm the Docker tools are working:</p>
<pre><code> docker --version; docker-machine --version; docker-compose --version
</code></pre>
<p>Should return something similar to the following:</p>
<pre><code> Docker version 1.10.3, build 20f81dd
docker-machine.exe version 0.6.0, build e27fb87
docker-compose version 1.6.2, build e80fc83
</code></pre>
<p>During this guide, we will use aliases as follows:</p>
<pre><code> New-Alias &quot;dm&quot; &quot;docker-machine&quot;
</code></pre></li>
<li><p>Shared Folder Set-up</p>
<p>For this demo we assume a <code>demo</code> user with password <code>demo</code> is created on the Hyper-V host and a folder share read/writeable to this user exists under the name <code>demo</code>.</p></li>
</ol>
<h2 id="set-up-the-key-value-store:e3eed6f67421eff48e81c37460ec6ac3">Set up the Key Value Store</h2>
<p>We will run Consul using a Docker machine. After provisioning the machine, we will configure a static IP, launch the Consul container and confirm Consul is working.</p>
<ol>
<li><p>Provision the <code>consul0</code> machine</p>
<p>Generic command:</p>
<pre><code>docker-machine create consul0
</code></pre>
<p>In PowerShell using Hyper-V and setting custom memory:</p>
<pre><code>dm create `
--driver hyperv `
--hyperv-virtual-switch &quot;VMWare NAT&quot; `
--hyperv-memory &quot;512&quot; consul0
</code></pre></li>
<li><p>Set a Static IP (<a href="https://github.com/docker/machine/issues/1709">ref</a>) and reboot the machine.</p>
<p>In this sample setup, VMs use the <code>192.168.233.0/24</code> subnet with the NAT gateway on <code>192.168.233.2</code> and a DHCP range of <code>128-254</code>. We will assign <code>192.168.233.10</code> as the static IP for our Consul node. Keep in mind you may need to update these values to match your configuration.</p>
<p>By default, DHCP is enabled on the Boot2Docker interfaces, but we may disable it by killing the process managing a particular interface:</p>
<pre><code>kill `more /var/run/udhcpc.eth0.pid`
</code></pre>
<p>Do not run the following commands on the Boot2Docker VM just yet, we will add them to the boot process at a later stage.</p>
<p>To set a static IP and ensure a default route to the gateway, we would use the following 2 commands:</p>
<pre><code>ifconfig eth0 192.168.233.10 netmask 255.255.255.0 broadcast 192.168.233.255 up
route add default gw 192.168.233.2
</code></pre>
<p>If we weren&rsquo;t using PowerShell, We may add the above commands to the boot script as follows (quote the heredoc label to avoid backticks from being evaluated):</p>
<pre><code>cat &lt;&lt;&quot;EOF&quot; | sudo tee /var/lib/boot2docker/bootsync.sh
kill `more /var/run/udhcpc.eth0.pid`
ifconfig eth0 192.168.233.10 netmask 255.255.255.0 broadcast 192.168.233.255 up
route add default gw 192.168.233.2
EOF
</code></pre>
<p>Or, using PowerShell with a single command from the Host:</p>
<pre><code>echo &quot;kill ``more /var/run/udhcpc.eth0.pid```n`
ifconfig eth0 192.168.233.10 netmask 255.255.255.0 broadcast 192.168.233.255 up`n`
route add default gw 192.168.233.2&quot; | `
dm ssh consul0 &quot;sudo tee /var/lib/boot2docker/bootsync.sh&quot; &gt; $null
</code></pre>
<p>Bounce the box</p>
<pre><code>dm restart consul0
</code></pre></li>
<li><p>Regenerate the certificates</p>
<p>Docker-Machine generated certificates are only valid for the old IP, changing the IP requires us to regenerate the certificates:</p>
<pre><code>dm regenerate-certs consul0
</code></pre></li>
<li><p>Start Consul</p>
<p>Docker-Machine helps you manage your environment configuration to target the right Boot2Docker VM:</p>
<pre><code>docker-machine env consul0
</code></pre>
<p>Activating this environment in PowerShell (using <code>iex</code> as an alias for <code>Invoke-Expression</code>), looks as follows:</p>
<pre><code>dm env consul0 | iex
</code></pre>
<p>Confirm all is working:</p>
<pre><code>docker info
</code></pre>
<p>Launch a single node Consul container, exposing its DNS and the Consul API:</p>
<pre><code>docker run -d -p 192.168.233.10:8500:8500 -p 192.168.233.10:53:8600/udp --name consul -h consul --restart always gliderlabs/consul-server -bootstrap
</code></pre>
<p>Follow the boot process of your Consul node:</p>
<pre><code>docker logs -f consul
</code></pre>
<p>Press <code>CTRL+C</code> and add an entry for the static consul IP to your hosts file (if your virtual network forwards DNS queries to your host, this will allow all your nodes to point to the <code>consul0</code> node by its hostname).</p>
<pre><code>&quot;consul0&quot; | `
% { &quot;$($(Get-VM $_).NetworkAdapters[0].IpAddresses[0]) $_&quot; } | `
ac $env:Windir\System32\Drivers\etc\hosts
</code></pre>
<p>Confirm Consul works:</p>
<pre><code>iwr http://consul0:8500/v1/catalog/nodes | ConvertFrom-Json
</code></pre></li>
</ol>
<h2 id="set-up-the-swarm-manager:e3eed6f67421eff48e81c37460ec6ac3">Set up the Swarm Manager</h2>
<p>We will now create a single Swarm Manager (no replication) and use the following <code>Docker-Machine</code> <a href="https://docs.docker.com/machine/reference/create/">flags</a> to configure our box:</p>
<p>Swarm flags:</p>
<table>
<thead>
<tr>
<th>Flag</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>--swarm</code></td>
<td>Provision swarm agent, <a href="https://docs.docker.com/swarm/reference/join/">see docs</a></td>
</tr>
<tr>
<td><code>--swarm-master</code></td>
<td>Provision swarm manager, <a href="https://docs.docker.com/swarm/reference/manage/">see docs</a></td>
</tr>
<tr>
<td><code>--swarm-discovery</code> &nbsp;</td>
<td>Discovery method, <a href="https://docs.docker.com/swarm/reference/manage/#discovery-discovery-backend">see docs</a></td>
</tr>
</tbody>
</table>
<p>We also specify Engine <a href="https://docs.docker.com/engine/reference/commandline/daemon">configuration options</a> to enable <strong>Node Discovery</strong> in the created Docker engine, this is required to support overlay networking:</p>
<table>
<thead>
<tr>
<th>Option</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>--cluster-store</code></td>
<td>kvstore URL</td>
</tr>
<tr>
<td><code>--cluster-advertise</code></td>
<td>URL for cluster nodes to reach this node, <a href="https://docs.docker.com/engine/reference/commandline/daemon/#nodes-discovery">see docs</a></td>
</tr>
<tr>
<td><code>--cluster-store-opt</code> &nbsp;</td>
<td>additional cluster options</td>
</tr>
</tbody>
</table>
<p>Below is an overview of default sockets used by Docker components:</p>
<table>
<thead>
<tr>
<th>Port</th>