-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathatom.xml
More file actions
648 lines (563 loc) · 91.6 KB
/
atom.xml
File metadata and controls
648 lines (563 loc) · 91.6 KB
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
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>浮白</title>
<subtitle>种一棵树最好的时间是十年前,其次是现在</subtitle>
<link href="/atom.xml" rel="self"/>
<link href="http://fubai.tech/"/>
<updated>2016-06-01T02:10:00.000Z</updated>
<id>http://fubai.tech/</id>
<author>
<name>浮白</name>
</author>
<generator uri="http://hexo.io/">Hexo</generator>
<entry>
<title>构建公司内部自动化工具链</title>
<link href="http://fubai.tech/2016/05/31/%E6%9E%84%E5%BB%BA%E5%85%AC%E5%8F%B8%E5%86%85%E9%83%A8%E8%87%AA%E5%8A%A8%E5%8C%96%E5%B7%A5%E5%85%B7%E9%93%BE/"/>
<id>http://fubai.tech/2016/05/31/构建公司内部自动化工具链/</id>
<published>2016-05-31T12:04:35.000Z</published>
<updated>2016-06-01T02:10:00.000Z</updated>
<content type="html"><img src="/images/transfer.png">
<a id="more"></a>
<style type="text/css">.h1{font-weight:bold;font-size:24px;}.h2{font-weight:bold;font-size:22px;}.h3{font-weight:bold;font-size:20px;}.h4{font-weight:bold;font-size:18px;}.h5{font-weight:bold;font-size:16px;}.h6{font-weight:bold;font-size:14px;}
</style>
<p>我们要在内网安装GitLab,Nexus3和Jenkins。通过Docker把所有软件安装到一台主机上,假设这台主机的内网IP为192.168.0.55。首先要确保这台机器上安装了Docker和Git。</p>
<div class="h2">使用Docker安装Mysql</div>
<p><a href="https://github.com/sameersbn/docker-mysql" target="_blank" rel="external">GitHub -&gt; sameersbn/docker-mysql</a></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">docker pull sameersbn/mysql:latest</span><br><span class="line"></span><br><span class="line">mkdir -p /usr/docker-volume/gitlab/mysql</span><br><span class="line"></span><br><span class="line">docker run -tid --name=gitlab_mysql \</span><br><span class="line"> -p 3306:3306 \</span><br><span class="line"> -e &apos;DB_NAME=demo&apos; \</span><br><span class="line"> -e &apos;DB_USER=fubai&apos; \</span><br><span class="line"> -e &apos;DB_PASS=123456&apos; \</span><br><span class="line"> -v /usr/docker-volume/gitlab/mysql:/var/lib/mysql \</span><br><span class="line"> sameersbn/mysql:latest</span><br><span class="line"></span><br><span class="line">docker logs gitlab_mysql</span><br></pre></td></tr></table></figure>
<div class="h2">使用Docker安装Redis</div>
<p><a href="https://github.com/sameersbn/docker-redis" target="_blank" rel="external">GitHub -&gt; sameersbn/docker-redis</a></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">docker pull sameersbn/redis:latest</span><br><span class="line"></span><br><span class="line">mkdir -p /usr/docker-volume/gitlab/redis</span><br><span class="line"></span><br><span class="line">docker run -tid --name=gitlab_redis \</span><br><span class="line"> --restart=always \</span><br><span class="line"> -p 6379:6379 \</span><br><span class="line"> -v /usr/docker-volume/gitlab/redis:/var/lib/redis \</span><br><span class="line"> sameersbn/redis:latest</span><br><span class="line"></span><br><span class="line">docker logs gitlab_redis</span><br></pre></td></tr></table></figure>
<div class="h2">使用Docker安装GitLab</div>
<p><a href="https://github.com/sameersbn/docker-gitlab" target="_blank" rel="external">GitHub -&gt; sameersbn/docker-gitlab</a></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line">docker pull sameersbn/gitlab:8.7.6</span><br><span class="line"></span><br><span class="line">mkdir -p /usr/docker-volume/gitlab/data /usr/docker-volume/gitlab/backup /usr/docker-volume/gitlab/log</span><br><span class="line"></span><br><span class="line">docker run -tid --name=&apos;gitlab&apos; \</span><br><span class="line"> --link gitlab_mysql:mysql \</span><br><span class="line"> --link gitlab_redis:redisio \</span><br><span class="line"> -e &apos;GITLAB_PORT=80&apos; \</span><br><span class="line"> -e &apos;GITLAB_SSH_PORT=22&apos; \</span><br><span class="line"> -e &apos;GITLAB_HOST=192.168.0.55&apos; \</span><br><span class="line"> -e &apos;SMTP_ENABLED=true&apos; \</span><br><span class="line"> -e &apos;SMTP_DOMAIN=www.qq.com&apos; \</span><br><span class="line"> -e &apos;SMTP_HOST=smtp.exmail.qq.com&apos; \</span><br><span class="line"> -e &apos;SMTP_PORT=25&apos; \</span><br><span class="line"> -e &apos;SMTP_STARTTLS=false&apos; \</span><br><span class="line"> -e &apos;SMTP_USER=SMTP邮箱&apos; \</span><br><span class="line"> -e &apos;SMTP_PASS=SMTP密码&apos; \</span><br><span class="line"> -e &apos;SMTP_AUTHENTICATION=login&apos; \</span><br><span class="line"> -e &apos;GITLAB_BACKUP_DIR=/usr/docker-volume/gitlab/backup&apos; \</span><br><span class="line"> -e &apos;GITLAB_BACKUP_SCHEDULE=weekly&apos; \</span><br><span class="line"> -e &apos;GITLAB_BACKUP_EXPIRY=604800&apos; \</span><br><span class="line"> -e &apos;GITLAB_SECRETS_DB_KEY_BASE=64位随机字符串&apos; \</span><br><span class="line"> -p 80:80 \</span><br><span class="line"> -p 22:22 \</span><br><span class="line"> -v /var/run/docker.sock:/run/docker.sock \</span><br><span class="line"> -v $(which docker):/bin/docker \</span><br><span class="line"> -v /usr/docker-volume/gitlab/data:/home/git/data \</span><br><span class="line"> -v /usr/docker-volume/gitlab/log:/var/log/gitlab \</span><br><span class="line"> sameersbn/gitlab:8.7.6</span><br><span class="line"></span><br><span class="line">docker logs gitlab</span><br></pre></td></tr></table></figure>
<p>运行GitLab的Docker镜像时,将远程主机的<code>80</code>和<code>22</code>端口转发到了Docker上,所以要保证远程主机的80和22端口未被占用,如果远程主机的sshd在使用22端口,将其修改成其它的端口。</p>
<p>假设要将远程主机的sshd端口号修改为10022,需要将<code>/etc/ssh/sshd_config</code>的<code>Port</code>修改为<code>10022</code>,然后重启sshd: <code>service ssh restart</code>。</p>
<p>远程登录可以使用<code>ssh -p 10022 用户名@主机ip</code>,远程拷贝可以使用: <code>scp -P 10022 本地文件 用户名@远程主机IP:远程主机目录</code>。</p>
<p>64位随机字符串的生成可以使用: <code>pwgen -Bsv1 64</code></p>
<div class="h2">使用Docker安装Nexus3</div>
<p><a href="https://github.com/sonatype/docker-nexus3" target="_blank" rel="external">GitHub -&gt; sonatype/docker-nexus3</a></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">docker pull sonatype/nexus3</span><br><span class="line"></span><br><span class="line">mkdir -p /usr/docker-volume/nexus-data</span><br><span class="line"></span><br><span class="line">chown -R 200 /usr/docker-volume/nexus-data</span><br><span class="line"></span><br><span class="line">docker run -tid --name=nexus \</span><br><span class="line"> --privileged=true \</span><br><span class="line"> -p 8081:8081 \</span><br><span class="line"> -v /usr/docker-volume/nexus-data:/nexus-data \</span><br><span class="line"> sonatype/nexus3</span><br><span class="line"></span><br><span class="line">docker logs nexus</span><br></pre></td></tr></table></figure>
<p>安装Nexus3时,需要将数据卷的<code>uid</code>修改为Docker容器中<code>nexus用户的uid</code>,这个uid可以在对应的Dockfile中找到。</p>
<p>如果不修改,那么改数据卷的所属用户为<code>root</code>,Nexus3运行时,其运行用户<code>nexus将没有权限修改数据卷中的内容</code>,导致Nexus3无法正常运行。</p>
<div class="h2">使用Docker安装Jenkins</div>
<p><a href="https://github.com/jenkinsci/docker" target="_blank" rel="external">GitHub -&gt; jenkinsci/docker</a></p>
<div class="h3">构建Docker镜像</div>
<div class="h4">下载相关文件</div>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git clone https://github.com/jenkinsci/docker.git</span><br></pre></td></tr></table></figure>
<p>下载<a href="http://mirror.bit.edu.cn/apache/maven/maven-3/3.3.9/binaries/apache-maven-3.3.9-bin.tar.gz" target="_blank" rel="external">apache-maven-3.3.9-bin.tar.gz</a>,并移动到jenkinsci/docker文件夹内</p>
<p>下载<a href="https://github.com/krallin/tini/releases/download/v0.5.0/tini-static" target="_blank" rel="external">tini-static</a>(需要翻墙),并移动到jenkinsci/docker文件夹内,修改其名称为tini</p>
<div class="h4">在jenkinsci/docker文件夹下添加settings.xml</div>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br></pre></td><td class="code"><pre><span class="line">&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;</span><br><span class="line"></span><br><span class="line">&lt;settings xmlns=&quot;http://maven.apache.org/SETTINGS/1.0.0&quot;</span><br><span class="line"> xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;</span><br><span class="line"> xsi:schemaLocation=&quot;http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd&quot;&gt;</span><br><span class="line"> &lt;localRepository&gt;/var/jenkins_home/.m2/repository&lt;/localRepository&gt;</span><br><span class="line"></span><br><span class="line"> &lt;pluginGroups&gt;</span><br><span class="line"> &lt;/pluginGroups&gt;</span><br><span class="line"></span><br><span class="line"> &lt;proxies&gt;</span><br><span class="line"> &lt;/proxies&gt;</span><br><span class="line"></span><br><span class="line"> &lt;servers&gt;</span><br><span class="line"> &lt;server&gt;</span><br><span class="line"> &lt;id&gt;maven-releases&lt;/id&gt;</span><br><span class="line"> &lt;username&gt;Nexus用户名&lt;/username&gt;</span><br><span class="line"> &lt;password&gt;密码&lt;/password&gt;</span><br><span class="line"> &lt;/server&gt;</span><br><span class="line"> &lt;server&gt;</span><br><span class="line"> &lt;id&gt;maven-snapshots&lt;/id&gt;</span><br><span class="line"> &lt;username&gt;Nexus用户名&lt;/username&gt;</span><br><span class="line"> &lt;password&gt;密码&lt;/password&gt;</span><br><span class="line"> &lt;/server&gt;</span><br><span class="line"> &lt;/servers&gt;</span><br><span class="line"></span><br><span class="line"> &lt;mirrors&gt;</span><br><span class="line"> &lt;mirror&gt;</span><br><span class="line"> &lt;id&gt;nexus&lt;/id&gt;</span><br><span class="line"> &lt;mirrorOf&gt;*&lt;/mirrorOf&gt;</span><br><span class="line"> &lt;name&gt;mirrorOfAll&lt;/name&gt;</span><br><span class="line"> &lt;url&gt;http://192.168.0.55:8081/repository/maven-public/&lt;/url&gt;</span><br><span class="line"> &lt;/mirror&gt;</span><br><span class="line"> &lt;/mirrors&gt;</span><br><span class="line"></span><br><span class="line"> &lt;profiles&gt;</span><br><span class="line"> &lt;profile&gt;</span><br><span class="line"> &lt;id&gt;nexus&lt;/id&gt;</span><br><span class="line"> &lt;repositories&gt;</span><br><span class="line"> &lt;repository&gt;</span><br><span class="line"> &lt;id&gt;central&lt;/id&gt;</span><br><span class="line"> &lt;url&gt;http://central&lt;/url&gt;</span><br><span class="line"> &lt;releases&gt;</span><br><span class="line"> &lt;enabled&gt;true&lt;/enabled&gt;</span><br><span class="line"> &lt;/releases&gt;</span><br><span class="line"> &lt;snapshots&gt;</span><br><span class="line"> &lt;enabled&gt;true&lt;/enabled&gt;</span><br><span class="line"> &lt;/snapshots&gt;</span><br><span class="line"> &lt;/repository&gt;</span><br><span class="line"> &lt;/repositories&gt;</span><br><span class="line"> &lt;pluginRepositories&gt;</span><br><span class="line"> &lt;pluginRepository&gt;</span><br><span class="line"> &lt;id&gt;central&lt;/id&gt;</span><br><span class="line"> &lt;url&gt;http://central&lt;/url&gt;</span><br><span class="line"> &lt;releases&gt;</span><br><span class="line"> &lt;enabled&gt;true&lt;/enabled&gt;</span><br><span class="line"> &lt;/releases&gt;</span><br><span class="line"> &lt;snapshots&gt;</span><br><span class="line"> &lt;enabled&gt;true&lt;/enabled&gt;</span><br><span class="line"> &lt;/snapshots&gt;</span><br><span class="line"> &lt;/pluginRepository&gt;</span><br><span class="line"> &lt;/pluginRepositories&gt;</span><br><span class="line"> &lt;/profile&gt;</span><br><span class="line"> &lt;/profiles&gt;</span><br><span class="line"> </span><br><span class="line"> &lt;activeProfiles&gt;</span><br><span class="line"> &lt;activeProfile&gt;nexus&lt;/activeProfile&gt;</span><br><span class="line"> &lt;/activeProfiles&gt;</span><br><span class="line">&lt;/settings&gt;</span><br></pre></td></tr></table></figure>
<div class="h4">修改Dockerfile</div>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br></pre></td><td class="code"><pre><span class="line">FROM java:8-jdk</span><br><span class="line"></span><br><span class="line">RUN apt-get update &amp;&amp; apt-get install -y git curl zip &amp;&amp; rm -rf /var/lib/apt/lists/*</span><br><span class="line"></span><br><span class="line">ENV JENKINS_HOME /var/jenkins_home</span><br><span class="line">ENV JENKINS_SLAVE_AGENT_PORT 50000</span><br><span class="line"></span><br><span class="line">ARG user=jenkins</span><br><span class="line">ARG group=jenkins</span><br><span class="line">ARG uid=1000</span><br><span class="line">ARG gid=1000</span><br><span class="line"></span><br><span class="line"># Jenkins is run with user `jenkins`, uid = 1000</span><br><span class="line"># If you bind mount a volume from the host or a data container, </span><br><span class="line"># ensure you use the same uid</span><br><span class="line">RUN groupadd -g $&#123;gid&#125; $&#123;group&#125; \</span><br><span class="line"> &amp;&amp; useradd -d &quot;$JENKINS_HOME&quot; -u $&#123;uid&#125; -g $&#123;gid&#125; -m -s /bin/bash $&#123;user&#125;</span><br><span class="line"></span><br><span class="line"># Jenkins home directory is a volume, so configuration and build history </span><br><span class="line"># can be persisted and survive image upgrades</span><br><span class="line">VOLUME /var/jenkins_home</span><br><span class="line"></span><br><span class="line"># `/usr/share/jenkins/ref/` contains all reference configuration we want </span><br><span class="line"># to set on a fresh new installation. Use it to bundle additional plugins </span><br><span class="line"># or config file with your custom jenkins Docker image.</span><br><span class="line">RUN mkdir -p /usr/share/jenkins/ref/init.groovy.d</span><br><span class="line"></span><br><span class="line">ENV TINI_SHA 066ad710107dc7ee05d3aa6e4974f01dc98f3888</span><br><span class="line"></span><br><span class="line"># Use tini as subreaper in Docker container to adopt zombie processes </span><br><span class="line">COPY tini /bin/tini</span><br><span class="line">RUN chmod +x /bin/tini \</span><br><span class="line"> &amp;&amp; echo &quot;$TINI_SHA /bin/tini&quot; | sha1sum -c -</span><br><span class="line"></span><br><span class="line">COPY init.groovy /usr/share/jenkins/ref/init.groovy.d/tcp-slave-agent-port.groovy</span><br><span class="line"></span><br><span class="line">ARG JENKINS_VERSION</span><br><span class="line">ENV JENKINS_VERSION $&#123;JENKINS_VERSION:-1.651.2&#125;</span><br><span class="line">ARG JENKINS_SHA</span><br><span class="line">ENV JENKINS_SHA $&#123;JENKINS_SHA:-f61b8b604acba5076a93dcde28c0be2561d17bde&#125;</span><br><span class="line"></span><br><span class="line"># could use ADD but this one does not check Last-Modified header </span><br><span class="line"># see https://github.com/docker/docker/issues/8331</span><br><span class="line">RUN curl -fsSL http://repo.jenkins-ci.org/public/org/jenkins-ci/main/jenkins-war/$&#123;JENKINS_VERSION&#125;/jenkins-war-$&#123;JENKINS_VERSION&#125;.war -o /usr/share/jenkins/jenkins.war \</span><br><span class="line"> &amp;&amp; echo &quot;$JENKINS_SHA /usr/share/jenkins/jenkins.war&quot; | sha1sum -c -</span><br><span class="line"></span><br><span class="line">ENV JENKINS_UC https://updates.jenkins.io</span><br><span class="line">RUN chown -R $&#123;user&#125; &quot;$JENKINS_HOME&quot; /usr/share/jenkins/ref</span><br><span class="line"></span><br><span class="line">ADD ./apache-maven-3.3.9-bin.tar.gz /usr/local/lib</span><br><span class="line"></span><br><span class="line">ENV M2_HOME /usr/local/lib/apache-maven-3.3.9</span><br><span class="line"></span><br><span class="line">RUN ln -s /usr/local/lib/apache-maven-3.3.9/bin/mvn /usr/bin/mvn &amp;&amp; mkdir -p $JENKINS_HOME/.m2</span><br><span class="line"></span><br><span class="line">COPY settings.xml $JENKINS_HOME/.m2/settings.xml</span><br><span class="line"></span><br><span class="line"># for main web interface:</span><br><span class="line">EXPOSE 8080</span><br><span class="line"></span><br><span class="line"># will be used by attached slave agents:</span><br><span class="line">EXPOSE 50000</span><br><span class="line"></span><br><span class="line">ENV COPY_REFERENCE_FILE_LOG $JENKINS_HOME/copy_reference_file.log</span><br><span class="line"></span><br><span class="line">USER $&#123;user&#125;</span><br><span class="line"></span><br><span class="line">COPY jenkins.sh /usr/local/bin/jenkins.sh</span><br><span class="line">ENTRYPOINT [&quot;/bin/tini&quot;, &quot;--&quot;, &quot;/usr/local/bin/jenkins.sh&quot;]</span><br><span class="line"></span><br><span class="line"># from a derived Dockerfile, can use `RUN plugins.sh active.txt` to setup /usr/share/jenkins/ref/plugins from a support bundle</span><br><span class="line">COPY plugins.sh /usr/local/bin/plugins.sh</span><br></pre></td></tr></table></figure>
<div class="h4">构建镜像</div>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker build -t jenkins-maven .</span><br></pre></td></tr></table></figure>
<div class="h3">运行Jenkins</div>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">mkdir -p /usr/docker-volume/jenkins</span><br><span class="line"></span><br><span class="line">chown -R 1000 /usr/docker-volume/jenkins</span><br><span class="line"></span><br><span class="line">docker run -tid --name=jenkins \</span><br><span class="line"> --privileged=true \</span><br><span class="line"> -p 8082:8080 \</span><br><span class="line"> -p 50000:50000 \</span><br><span class="line"> -v /usr/docker-volume/jenkins:/var/jenkins_home jenkins-maven</span><br></pre></td></tr></table></figure>
<div class="h2">将GitLab上指定的项目关联到Slack指定的频道中</div>
<div class="h3">添加Slack的Webhook</div>
<ul>
<li><p>首先要为<code>channel</code>(<code>Slack</code>-&gt;<code>team</code>-&gt;<code>channel</code>)创建<code>webhooks</code>,Slack会给你一个webhooks的<code>url</code>,不同team的创建地址都不同,需要你自己找到自己team的webhooks的创建地址。</p>
</li>
<li><p>以管理员帐号登陆GitLab,然后是:某项目 -&gt; <code>Settings</code> -&gt; <code>Services</code> -&gt; <code>Slack</code>,现在进入到了GitLab上的指定项目的Slack设置页面,选中<code>Active</code>,将上一步的到的url输入到<code>Webhook</code>中,点击<code>Save changes</code>。</p>
</li>
</ul>
<p>Slack的webhook可以被GitLab调用。在code,wiki和issue等发生变化时,GibLab将特定的信息发送到对应的webhook上,然后Slack会将其发送到指定的频道中,如下图:</p>
<img src="/images/snapshot.png">
<div class="h2">配置Jenkins</div>
<div class="h3">安全配置</div>
<p>系统管理 -&gt; Configure Global Security,配置为下图:<br><img src="/images/s1.png"></p>
<p><code>保存</code>之后,页面右上角出现<code>注册</code>链接,点击进入后注册一个用户,然后进行下图的配置:</p>
<img src="/images/s2.png">
<p>先在<code>添加 用户/组:</code>中<code>添加</code>刚刚注册的用户,然后作出如图所示的配置,保存后就可以了。</p>
<p>上述配置是关闭Jenkins的匿名用户访问,并取消用户注册功能,建立了一个用户帐号<code>jenkins</code>,只有该用户可以登陆Jenkins。</p>
<div class="h3">安装插件</div>
<p>在可用插件中选择<code>Deploy to container Plugin</code>,<code>Git client plugin</code>,<code>Git plugin</code>,<code>GitLab Plugin</code>后安装</p>
<div class="h3">系统设置</div>
<div class="h4">JDK 设置</div>
<img src="/images/jdk-setting.png">
<div class="h4">Maven 设置</div>
<img src="/images/maven-setting.png">
<div class="h4">Git 设置</div>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">1. 查看容器id</span><br><span class="line">docker ps</span><br><span class="line"></span><br><span class="line">2. 进入容器</span><br><span class="line">docker exec -it &lt;容器id&gt; /bin/sh</span><br><span class="line"></span><br><span class="line">3. 为Git配置用户名密码</span><br><span class="line">git config --global user.email &quot;xxx@xxx.com&quot;</span><br><span class="line">git config --global user.name &quot;xxx&quot;</span><br><span class="line"></span><br><span class="line">4. 生成SSH key</span><br><span class="line">ssh-keygen -t rsa -C &quot;xxx@xxx.com&quot;</span><br><span class="line"></span><br><span class="line">5. 将SSH key生成的公钥添加到GitLab中,这里先要在GitLab中注册一个帐号。GitLab提供了deploy key的方式来为CI服务器提供Git服务,但是我这里并没有采用。</span><br></pre></td></tr></table></figure>
<div class="h4">GitLab 设置</div>
<img src="/images/gitlab-setting.png">
<div class="h2">创建Jenkins Task</div>
<div class="h3">构建一个maven项目</div>
<p>在上面构建Jenkins的Docker镜像时,我们已经为Jenkins安装并配置了Maven,所以可以不需要再为一个maven deploy操作配置nexus3私服的信息,下面开始配置:</p>
<p>先进入源码管理选项,选择Git,然后在<code>Credentials</code>处点击<code>Add</code>,进行如下图的设置:</p>
<img src="/images/task0.png">
<p>然后进行如下几张图的设置:</p>
<ul>
<li><p>图一:</p>
<img src="/images/task1.png">
</li>
<li><p>图二:</p>
<img src="/images/task2.png">
</li>
<li><p>图三:</p>
<img src="/images/task3.png">
</li>
<li><p>图四:</p>
<img src="/images/task4.png">
</li>
<li><p>图五:</p>
<img src="/images/task5.png">
</li>
<li><p>图六:</p>
<img src="/images/task6.png">
</li>
</ul>
<p><div class="h2">总结</div><br>通过创建Jenkins任务可以看到,Jenkins会使用Git从GitLab上拉取<code>demo-api</code>,然后通过Maven将其打包发布到Nexus中。最后使用将打包生成的war文件发布到Tomcat中去。</p>
<p>这个Jenkins任务的触发条件是GitLab,在<code>图三</code>中可以看到有一个<code>GitLab CI Service URL</code>,这个url就是这个Jenkins任务的<code>web hook</code>,需要将其拷贝粘贴到GitLab对应项目的<code>web hook</code>中,即图六所示。</p>
<p>这里的<code>demo-api</code>是我创建的一个Maven项目,对外提供了几个简单的REST API接口。通过Git将其push到GitLab上之后,在GitLab上创建该项目REST API对应的WIKI说明。</p>
<p>假设有两个开发人员<code>A</code>和<code>B</code>,A是后端开发人员,B是前端开发人员。A和B都在同一个Slack的频道中,而且,该频道的web hook在GibLab上被绑定到了A开发的后端项目上。现在,A修改了后台的Rest API,测试通过后,在GitLab上修改该API对应的WIKI说明。对WIKI的修改会向Slack频道中发送一条消息,那么,B现在就知道了A修改了API。然后A将代码提交到GitLab中,GitLab会调用Slack的web hook,将本次提交的相关信息发送到Slack的频道中。于是,B又收到了A确切提交的相关信息。与此同时,GitLab调用Jenkins的web hook,触发Jenkins任务。Jenkins使用Maven将后端项目编译打包后,部署到Tomcat中。那么B就能访问最新的API了。</p>
</content>
<summary type="html">
<img src="/images/transfer.png">
</summary>
</entry>
<entry>
<title>怎么写chaincode</title>
<link href="http://fubai.tech/2016/04/29/%E6%80%8E%E4%B9%88%E5%86%99chaincode/"/>
<id>http://fubai.tech/2016/04/29/怎么写chaincode/</id>
<published>2016-04-29T12:40:22.000Z</published>
<updated>2016-04-29T12:54:05.000Z</updated>
<content type="html"><h4 id="什么是chaincode"><a href="#什么是chaincode" class="headerlink" title="什么是chaincode?"></a>什么是chaincode?</h4><p>Chaincode是一段能让你和网络中共享的账本进行交互的代码。每当你在网络上进行交易,都是在调用chaincode的函数来读取或写入账本。</p>
<a id="more"></a>
<h4 id="实现chaincode的接口"><a href="#实现chaincode的接口" class="headerlink" title="实现chaincode的接口"></a>实现chaincode的接口</h4><p>第一,要在你的golang代码中实现chaincode shim接口。有三个主要的函数:Init,Invoke和Query。这三个函数都有相同的原型,他们都需要一个被命名为function的字符串参数和一个字符串数组参数。他们之间的不同之处在于被调用的时机。</p>
<h4 id="依赖"><a href="#依赖" class="headerlink" title="依赖"></a>依赖</h4><p>import语句列出了几个需要的依赖:</p>
<ul>
<li>fmt - 包含Println用于调试和记录日志。</li>
<li>errors - 标准go错误格式。</li>
<li>github.com/hyperledger/fabric/core/chaincode/shim - 和peer交互的代码。</li>
</ul>
<h4 id="Init"><a href="#Init" class="headerlink" title="Init()"></a>Init()</h4><p>Init会在第一次发布chaincode时被调用。正如函数名的含义,Init函数应该被用于chaincode初始化。在我们的例子中,我们用Init配置了账本上一个变量的初始状态。 </p>
<p>现在来修改chaincode.go。修改Init函数,把args参数的第一个元素的存储到键”hello_world”上。</p>
<pre><code>func (t *SimpleChaincode) Init(stub *shim.ChaincodeStub, function string, args []string) ([]byte, error) {
if len(args) != 1 {
return nil, errors.New(&quot;Incorrect number of arguments. Expecting 1&quot;)
}
err := stub.PutState(&quot;hello_world&quot;, []byte(args[0]))
if err != nil {
return nil, err
}
return nil, nil
}
</code></pre><p>通过shim的stub.PutState函数来完成,stub.PutState的第一个参数是字符串类型的键,第二个参数是byte数组类型的值。这个函数可能会返回一个错误,我们的代码里做了检查,如果错误出现了,就把这个错误返回。</p>
<h4 id="Invoke"><a href="#Invoke" class="headerlink" title="Invoke()"></a>Invoke()</h4><p>要用chaincode函数真正开始工作,那就该调用Invoke函数了。交易调用会成为链上的块。Invoke的结构很简单。它接收一个被命名为function的字符串参数,并基于这个参数调用chaincode的Go函数。</p>
<p>在你的chaincode.go文件中,修改Invoke函数,调用write方法。</p>
<pre><code>func (t *SimpleChaincode) Invoke(stub *shim.ChaincodeStub, function string, args []string) ([]byte, error) {
fmt.Println(&quot;invoke is running &quot; + function)
// Handle different functions
if function == &quot;init&quot; {
return t.Init(stub, &quot;init&quot;, args)
} else if function == &quot;write&quot; {
return t.write(stub, args)
}
fmt.Println(&quot;invoke did not find func: &quot; + function)
return nil, errors.New(&quot;Received unknown function invocation&quot;)
}
</code></pre><p>现在在chaincode.go中写下write函数:</p>
<pre><code>func (t *SimpleChaincode) write(stub *shim.ChaincodeStub, args []string) ([]byte, error) {
var name, value string
var err error
fmt.Println(&quot;running write()&quot;)
if len(args) != 2 {
return nil, errors.New(&quot;Incorrect number of arguments. Expecting 2. name of the variable and value to set&quot;)
}
name = args[0] //rename for funsies
value = args[1]
err = stub.PutState(name, []byte(value)) //write the variable into the chaincode state
if err != nil {
return nil, err
}
return nil, nil
}
</code></pre><p>write函数应该和上面改过的Init函数很像。一个主要的不同在于现在你可以自己设置PutState的key和value了。PutState会将key/value存储到区块链账本中。</p>
<h4 id="Query"><a href="#Query" class="headerlink" title="Query()"></a>Query()</h4><p>正如这个名字的含义,Query会在查询chaincode状态时被调用。Query不会导致区块被添加到链中。你将使用Query读取chaincode中的值。</p>
<p>在chaincode.go中,修改Query函数,调用read函数:</p>
<pre><code>func (t *SimpleChaincode) Query(stub *shim.ChaincodeStub, function string, args []string) ([]byte, error) {
fmt.Println(&quot;query is running &quot; + function)
// Handle different functions
if function == &quot;read&quot; { //read a variable
return t.read(stub, args)
}
fmt.Println(&quot;query did not find func: &quot; + function)
return nil, errors.New(&quot;Received unknown function query&quot;)
}
</code></pre><p>现在来在chaincode.go中写下read函数:</p>
<pre><code>func (t *SimpleChaincode) read(stub *shim.ChaincodeStub, args []string) ([]byte, error) {
var name, jsonResp string
var err error
if len(args) != 1 {
return nil, errors.New(&quot;Incorrect number of arguments. Expecting name of the var to query&quot;)
}
name = args[0]
valAsbytes, err := stub.GetState(name)
if err != nil {
jsonResp = &quot;{\&quot;Error\&quot;:\&quot;Failed to get state for &quot; + name + &quot;\&quot;}&quot;
return nil, errors.New(jsonResp)
}
return valAsbytes, nil
}
</code></pre><p>read函数使用了PutState的补充方法GetState。这个shim的方法只有一个参数,这个参数是要查询的key。这个函数会返回一个byte数组。</p>
<h4 id="Main"><a href="#Main" class="headerlink" title="Main()"></a>Main()</h4><p>最后,创建一个main函数,在为这个chaincode部署每个peer实例的时候,这个main方法就会被调用。这个main方法启动了chaincode,并把自己注册到peer中。拷贝下面的代码就行了,不需要修改:</p>
<pre><code>func main() {
err := shim.Start(new(SimpleChaincode))
if err != nil {
fmt.Printf(&quot;Error starting Simple chaincode: %s&quot;, err)
}
}
</code></pre></content>
<summary type="html">
<h4 id="什么是chaincode"><a href="#什么是chaincode" class="headerlink" title="什么是chaincode?"></a>什么是chaincode?</h4><p>Chaincode是一段能让你和网络中共享的账本进行交互的代码。每当你在网络上进行交易,都是在调用chaincode的函数来读取或写入账本。</p>
</summary>
</entry>
<entry>
<title>openblockchain设置开发网络环境</title>
<link href="http://fubai.tech/2016/04/29/openblockchain%E8%AE%BE%E7%BD%AE%E5%BC%80%E5%8F%91%E7%BD%91%E7%BB%9C%E7%8E%AF%E5%A2%83/"/>
<id>http://fubai.tech/2016/04/29/openblockchain设置开发网络环境/</id>
<published>2016-04-29T12:27:00.000Z</published>
<updated>2016-04-29T12:36:43.000Z</updated>
<content type="html"><p>本文档介绍了用Docker容器在本地开发机器上设置网络环境。</p>
<a id="more"></a>
<p>所有的命令都应该在Vagrant中运行。</p>
<p>注意:如果peer是通过Docker镜像启动的,而且开启了安全验证,那就需要给peer配置正确的CA地址(默认是localhost)。在core.yaml的paddr下的eca,tca和tlsca中指定CA地址。</p>
<h4 id="搭建Docker镜像"><a href="#搭建Docker镜像" class="headerlink" title="搭建Docker镜像"></a>搭建Docker镜像</h4><p>要为hyperledger/fabric创建Docker镜像,首先要使用命令docker ps -a and docker rm清除所有活跃的容器 (hyperledger-peer and chaincode) 。第二步,用docker images和docker rmi删除老的镜像。注意:不要删除其他的镜像 (比如busybox or openblockchain/baseimage) ,还需要他们来正确的运行。</p>
<p>现在我们准备好了构建一个新的Docker镜像:</p>
<pre><code>cd $GOPATH/src/github.com/hyperledger/fabric/core/container
go test -run BuildImage_Peer
</code></pre><p>再次使用docker images检查可用的镜像,你就能看见hyperledger-peer了。</p>
<h4 id="开启validating-peers"><a href="#开启validating-peers" class="headerlink" title="开启validating peers"></a>开启validating peers</h4><p>在Vagrant环境中,使用ip add命令找出docker0网络接口绑定的IP地址。比如:</p>
<pre><code>vagrant@vagrant-ubuntu-trusty-64:/opt/gopath/src/github.com/hyperledger/fabric$ ip add
&lt;&lt;&lt; detail removed &gt;&gt;&gt;
3: docker0: &lt;NO-CARRIER,BROADCAST,MULTICAST,UP&gt; mtu 1500 qdisc noqueue state DOWN group default
link/ether 02:42:ad:be:70:cb brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 scope global docker0
valid_lft forever preferred_lft forever
inet6 fe80::42:adff:febe:70cb/64 scope link
valid_lft forever preferred_lft forever
</code></pre><p>你的输出信息里会包含类似的东西 inet 172.17.0.1/16 scope global docker0。这表示docker0 接口绑定在172.17.0.1上。把这个IP地址作为CORE_VM_ENDPOINT选项的值。要了解更多关于这个环境变量的信息,请查看core.yaml。 </p>
<p>CORE_PEER_ID的值必须小写,因为我们将使用这个值作为我们构建的chaincode容器的一部分,而docker是不支持大写的。每个validating peer的ID都必须的唯一的。</p>
<p>默认情况下,我们使用一个叫做NOOPS的一致性插件,这个插件做不到真正的一致性。如果你想使用其他的一致性插件,请看文档的结尾部分:Using Consensus Plugin。</p>
<h4 id="开启第一个validating-peer"><a href="#开启第一个validating-peer" class="headerlink" title="开启第一个validating peer:"></a>开启第一个validating peer:</h4><pre><code>docker run --rm -it -e CORE_VM_ENDPOINT=http://172.17.0.1:4243 -e CORE_PEER_ID=vp0 -e CORE_PEER_ADDRESSAUTODETECT=true hyperledger-peer peer peer
</code></pre><p>如果开启安全认证,环境变量的配置就要考略到安全设置,CA地址和peer的ID和密码都要改变:</p>
<pre><code>docker run --rm -it -e CORE_VM_ENDPOINT=http://172.17.0.1:4243 -e CORE_PEER_ID=vp0 -e CORE_PEER_ADDRESSAUTODETECT=true -e CORE_SECURITY_ENABLED=true -e CORE_SECURITY_PRIVACY=true -e CORE_PEER_PKI_ECA_PADDR=172.17.0.1:50051 -e CORE_PEER_PKI_TCA_PADDR=172.17.0.1:50051 -e CORE_PEER_PKI_TLSCA_PADDR=172.17.0.1:50051 -e CORE_SECURITY_ENROLLID=vp0 -e CORE_SECURITY_ENROLLSECRET=XX hyperledger-peer peer peer
</code></pre><p>另外,validating peer (enrollID vp0 and enrollSecret XX) 要添加到membersrvc.yaml文件中。</p>
<h4 id="开启第二个validating-peer"><a href="#开启第二个validating-peer" class="headerlink" title="开启第二个validating peer:"></a>开启第二个validating peer:</h4><p>我们要获取第一个validating peer的IP地址,第一个peer作为根节点,新的peer要连接到根节点。 这个地址会在第一个peer的终端窗口中打印出来(比如172.17.0.2)。我们要使用”vp1”作为第二个validating peer的ID。</p>
<pre><code>docker run --rm -it -e CORE_VM_ENDPOINT=http://172.17.0.1:4243 -e CORE_PEER_ID=vp1 -e CORE_PEER_ADDRESSAUTODETECT=true -e CORE_PEER_DISCOVERY_ROOTNODE=172.17.0.2:30303 hyperledger-peer peer peer
</code></pre><p>你可以用类似的方式启动更多的validating peers。记得要修改ID。</p>
<h4 id="Deploy-Invoke-and-Query-a-Chaincode"><a href="#Deploy-Invoke-and-Query-a-Chaincode" class="headerlink" title="Deploy, Invoke, and Query a Chaincode"></a>Deploy, Invoke, and Query a Chaincode</h4><p>我们要用命令行接口发布一个chaincode到网络中。你可以在下面的目录中发现chaincode $GOPATH/src/github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02</p>
<p>现在来发布,用CORE_PEER_ADDRESS可以把chaincode发布到任意一个指定的validating peer:</p>
<pre><code>cd $GOPATH/src/github.com/hyperledger/fabric/peer
CORE_PEER_ADDRESS=172.17.0.2:30303 ./peer chaincode deploy -p github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02 -c &apos;{&quot;Function&quot;:&quot;init&quot;, &quot;Args&quot;: [&quot;a&quot;,&quot;100&quot;, &quot;b&quot;, &quot;200&quot;]}&apos;
</code></pre><p>在安全模式下要使用下面的命令:</p>
<pre><code>CORE_PEER_ADDRESS=172.17.0.2:30303 ./peer chaincode deploy -u jim -p github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02 -c &apos;{&quot;Function&quot;:&quot;init&quot;, &quot;Args&quot;: [&quot;a&quot;,&quot;100&quot;, &quot;b&quot;, &quot;200&quot;]}&apos;
</code></pre><p>你可以在所有validating peers的屏幕上看到信息:”Received build request for chaincode spec”。</p>
<p>当成功完成后,上面的命令就会打印出分配给刚发布的chaincode的”name”。这个”name”可以用作下面描述的invode和query命令的”-n”参数。这个”name”的值可以是:</p>
<pre><code>bb540edfc1ee2ac0f5e2ec6000677f4cd1c6728046d5e32dede7fea11a42f86a6943b76a8f9154f4792032551ed320871ff7b7076047e4184292e01e3421889c
</code></pre><p>在脚本中,这个名字可以被暂存以备接下来用。比如:</p>
<pre><code>NAME=`CORE_PEER_ADDRESS=172.17.0.2:30303 ./peer chaincode deploy ...`
</code></pre><p>然后用$NAME替换下面例子中的 <name_value_returned_from_deploy_command></name_value_returned_from_deploy_command></p>
<p>我们可以发起一笔’a’ 到’b’,价值10个单位的交易:</p>
<pre><code>CORE_PEER_ADDRESS=172.17.0.2:30303 ./peer chaincode invoke -n &lt;name_value_returned_from_deploy_command&gt; -c &apos;{&quot;Function&quot;: &quot;invoke&quot;, &quot;Args&quot;: [&quot;a&quot;, &quot;b&quot;, &quot;10&quot;]}&apos;
</code></pre><p>在安全模式下要使用下面的命令:</p>
<pre><code>CORE_PEER_ADDRESS=172.17.0.2:30303 ./peer chaincode invoke -u jim -n &lt;name_value_returned_from_deploy_command&gt; -c &apos;{&quot;Function&quot;: &quot;invoke&quot;, &quot;Args&quot;: [&quot;a&quot;, &quot;b&quot;, &quot;10&quot;]}&apos;
</code></pre><p>我们也可以运行一次查询,看看’a’当前拥有的值:</p>
<pre><code>CORE_PEER_ADDRESS=172.17.0.2:30303 ./peer chaincode query -l golang -n &lt;name_value_returned_from_deploy_command&gt; -c &apos;{&quot;Function&quot;: &quot;query&quot;, &quot;Args&quot;: [&quot;a&quot;]}&apos;
</code></pre><p>在安全模式下要使用下面的命令:</p>
<pre><code>CORE_PEER_ADDRESS=172.17.0.2:30303 ./peer chaincode query -u jim -l golang -n &lt;name_value_returned_from_deploy_command&gt; -c &apos;{&quot;Function&quot;: &quot;query&quot;, &quot;Args&quot;: [&quot;a&quot;]}&apos;
</code></pre><h4 id="Using-Consensus-Plugin"><a href="#Using-Consensus-Plugin" class="headerlink" title="Using Consensus Plugin"></a>Using Consensus Plugin</h4><p>一个一致性插件可能需要你设置一些指定的配置。比如,要使用框架里提供的Byzantine插件,要执行下面的配置:</p>
<ul>
<li>把core.yaml中的peer.validator.consensus设置为pbft</li>
<li>确保core.yaml的peer.id按顺序的设置为vpX,其中X是一个从0到N-1的整数值。比如,有4台validating peers,把peer.id设置为vp0,vp1,vp2,vp3。</li>
<li>在consensus/obcpbft/config.yaml中,把general.mode设置classic,batch或sieve中的一个值,把general.N设置为网络中validating peers的数量。(如果设置了batch,还要把general.batchsize设置为每批次中交易的数量。)</li>
<li>在consensus/obcpbft/config.yaml中,还可以选择设置批次执行的超时时间(general.timeout.batch),请求和执行之间可接受的延迟时间(general.timeout.request),以及view-change (general.timeout.viewchange)</li>
</ul>
<p>查看core.yaml和consensus/obcpbft/config.yaml获取更多的信息。</p>
<p>所有这些设置可以被命令行环境变量值替换,比如,CORE_PEER_VALIDATOR_CONSENSUS=pbft或者CORE_PBFT_GENERAL_MODE=sieve</p>
<p>原文地址:<a href="https://github.com/hyperledger/fabric/blob/master/docs/dev-setup/devnet-setup.md" target="_blank" rel="external">https://github.com/hyperledger/fabric/blob/master/docs/dev-setup/devnet-setup.md</a></p>
</content>
<summary type="html">
<p>本文档介绍了用Docker容器在本地开发机器上设置网络环境。</p>
</summary>
</entry>
<entry>
<title>在开发环境下编写,运行,测试chaincode</title>
<link href="http://fubai.tech/2016/04/29/%E5%9C%A8%E5%BC%80%E5%8F%91%E7%8E%AF%E5%A2%83%E4%B8%8B%E7%BC%96%E5%86%99%EF%BC%8C%E8%BF%90%E8%A1%8C%EF%BC%8C%E6%B5%8B%E8%AF%95chaincode/"/>
<id>http://fubai.tech/2016/04/29/在开发环境下编写,运行,测试chaincode/</id>
<published>2016-04-29T11:32:26.000Z</published>
<updated>2016-04-29T12:24:09.000Z</updated>
<content type="html"><p>开发者要能在不完整的终端网络中测试区块链。本文档描述了怎样在本地开发环境中编写,构建,测试区块链。</p>
<a id="more"></a>
<p>首先需要有多个Vagrant的终端窗体。一个Vagrant终端运行validating peer,一个运行chaincode,还有一个通过命令行接口或者REST API来执行交易。当启用了安全验证后,还需要一个运行CA服务。</p>
<h4 id="安全设置-可选"><a href="#安全设置-可选" class="headerlink" title="安全设置 (可选)"></a>安全设置 (可选)</h4><p>在命令行终端中,进入工作空间环境下的devenv子目录。登录Vagrant:</p>
<pre><code>vagrant ssh
</code></pre><p>要在开发环境中启用安全设置,首先要构建并运行CA服务:</p>
<pre><code>cd $GOPATH/src/github.com/hyperledger/fabric/membersrvc
go build
./membersrvc
</code></pre><p>上面的命令使用membersrvc.yaml中的默认配置构建运行了CA服务。默认配置中包含了很多已经注册到CA中的用户,这些用户写在配置文件的users部分。要在CA中注册其他用户用于测试,需要修改membersrvc.yaml的users部分,增加一对enrollmentID和enrollmentPW。</p>
<p>enrollmentPW前面有一个数字,代表了用户的角色,其中1代表client,2代表non-validating peer,4代表validating peer,8代表auditor。</p>
<h4 id="Vagrant-终端-1-validating-peer"><a href="#Vagrant-终端-1-validating-peer" class="headerlink" title="Vagrant 终端 1 (validating peer)"></a>Vagrant 终端 1 (validating peer)</h4><p>记住:在启用安全后,要运行peer,首先要修改core.yaml配置文件,设置security.enabled为true。也可以通过把环境变量CORE_SECURITY_ENABLED设置为true来运行peer。要启用交易的隐私和保密(要先启用安全),修改core.yaml的security.privacy为true。也可以通过把环境变量CORE_SECURITY_PRIVACY设置为true来运行peer。</p>
<p>在命令行终端中,进入工作空间环境下的devenv子目录。登录Vagrant:</p>
<pre><code>vagrant ssh
</code></pre><p>在把security.enabled和security.privacy设置为true之后,再构建和运行peer进程:</p>
<pre><code>cd $GOPATH/src/github.com/hyperledger/fabric/peer
go build
./peer peer --peer-chaincodedev
</code></pre><p>也可以通过环境变量来启用security和privacy:</p>
<pre><code>CORE_SECURITY_ENABLED=true CORE_SECURITY_PRIVACY=true ./peer peer --peer-chaincodedev
</code></pre><h4 id="Vagrant-终端-2-chaincode"><a href="#Vagrant-终端-2-chaincode" class="headerlink" title="Vagrant 终端 2 (chaincode)"></a>Vagrant 终端 2 (chaincode)</h4><p>在命令行终端中,进入工作空间环境下的devenv子目录。登录Vagrant:</p>
<pre><code>vagrant ssh
</code></pre><p>构建源码仓库提供的chaincode_example02:</p>
<pre><code>cd $GOPATH/src/github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02
go build
</code></pre><p>当你已经准备好要开始创建自己的chaincode时,在/fabric/examples/go/chaincode下创建一个子目录用来存放chaincode代码。你可以把chaincode_example02中的文件拷贝进去之后再修改</p>
<p>运行下面的chaincode命令,用validating peer(Vagrant 终端 1)开始并注册chaincode:</p>
<pre><code>CORE_CHAINCODE_ID_NAME=mycc CORE_PEER_ADDRESS=0.0.0.0:30303 ./chaincode_example02
</code></pre><p>chaincode的控制台会显示”Received REGISTERED, ready for invocations”,这证明chaincode已经准备好接收请求了。如果上面没有显示那段信息的话,那就是部署的过程中有错误。请重新看一遍上面的步骤,解决这个问题。遵循下面的步骤发布chaincode,调用或者查询交易。</p>
<h4 id="Vagrant-终端-3-CLI-or-REST-API"><a href="#Vagrant-终端-3-CLI-or-REST-API" class="headerlink" title="Vagrant 终端 3 (CLI or REST API)"></a>Vagrant 终端 3 (CLI or REST API)</h4><p>注意REST API的端口</p>
<p>REST接口的端口在core.yaml中定义的是5000。如果要在Vagrant中发送一个Rest请求给peer节点,使用的是5000端口。如果在Vagrant之外,也就是虚拟机之外发送REST请求,要使用3000端口。这是在构建虚拟机时,配置在Vagrantfile中的。</p>
<p>注意安全功能</p>
<p>现在的安全实现假定终端用户的安全认证发生在应用程序层,而不是在chaincode的基础架构中。只要该安全认证对应用程序来说是合适的就行。在用户认证成功之后 ,应用程序要在CA中执行一次注册。如果尝试在CA中对同一个用户注册第二次,就会报错。在注册期间,应用程序会给CA发送一个请求验证用户是否注册成功,CA会响应一个用户证书和密钥对。从CA收到的注册和交易证书会被存在本地的/var/hyperledger/production/crypto/client/文件夹中。用户要通过指定的peer节点进行交易,就必须要在该节点的认证资料存储目录中有自己的对应的信息。指定peer节点下的目录只允许用户通过该peer节点进行交易。如果终端用户要通过多于一个peer节点来执行交易,应用程序要负责把所有的认证资料复制到其他的peer节点上。这是必须的,因为在CA上重复注册同一个用户会失败。</p>
<p>当安全启用之后,命令行的命令和REST的请求中都必须包含已经登录的注册用户的enrollmentID ,否则就会导致错误。要登录一个注册后的用户,可以通过下面介绍的命令行或者REST API方式。</p>
<p>用下面的命令在命令行中登录,username是membersrvc.yaml的users部分配置的enrollmentID 。</p>
<p>在命令行终端中,进入工作空间环境下的devenv子目录。登录Vagrant:</p>
<pre><code>vagrant ssh
</code></pre><p>通过命令行接口登录,替换下面的username:</p>
<pre><code>cd $GOPATH/src/github.com/hyperledger/fabric/peer
./peer login &lt;username&gt;
</code></pre><p>该命令会提示输入密码,这个密码也是在membersrce.yaml中的。</p>
<p>通过REST API登录,发送一个POST请求到/registrar,要包含enrollmentID和enrollmentPW。记住,在Vagrant里面要用5000端口,在Vagrant外面要用3000端口。</p>
<p>REST Request:</p>
<pre><code>POST localhost:3000/registrar
{
&quot;enrollId&quot;: &quot;jim&quot;,
&quot;enrollSecret&quot;: &quot;NPKYL39uKbkj&quot;
}
</code></pre><p>REST Response:</p>
<pre><code>200 OK
{
&quot;OK&quot;: &quot;Login successful for user &apos;jim&apos;.&quot;
}
</code></pre><h4 id="通过命令行接口或者REST-API发布Chaincode"><a href="#通过命令行接口或者REST-API发布Chaincode" class="headerlink" title="通过命令行接口或者REST API发布Chaincode"></a>通过命令行接口或者REST API发布Chaincode</h4><p>首先,发送一个chaincode deploy transaction,只发送一次,到validating peer。命令行接口会通过core.yaml中的配置信息连接到validating peer。记住,一般deploy transaction要求一个path参数来定位,构建,发布chaincode。但是由于这里的介绍是为本地开发模式指定的,而且chaincode是手动发布的,所以使用了name参数来替代。 </p>
<pre><code>cd $GOPATH/src/github.com/hyperledger/fabric/peer
./peer chaincode deploy -n mycc -c &apos;{&quot;Function&quot;:&quot;init&quot;, &quot;Args&quot;: [&quot;a&quot;,&quot;100&quot;, &quot;b&quot;, &quot;200&quot;]}&apos;
</code></pre><p>也可以使用REST API来运行chaincode deploy transaction。记住,在Vagrant里面使用5000端口,在Vagrant外面使用3000端口。</p>
<p>REST Request:</p>
<pre><code>POST host:port/chaincode
{
&quot;jsonrpc&quot;: &quot;2.0&quot;,
&quot;method&quot;: &quot;deploy&quot;,
&quot;params&quot;: {
&quot;type&quot;: 1,
&quot;chaincodeID&quot;:{
&quot;name&quot;: &quot;mycc&quot;
},
&quot;ctorMsg&quot;: {
&quot;function&quot;:&quot;init&quot;,
&quot;args&quot;:[&quot;a&quot;, &quot;100&quot;, &quot;b&quot;, &quot;200&quot;]
}
},
&quot;id&quot;: 1
}
</code></pre><p>REST Response:</p>
<pre><code>{
&quot;jsonrpc&quot;: &quot;2.0&quot;,
&quot;result&quot;: {
&quot;status&quot;: &quot;OK&quot;,
&quot;message&quot;: &quot;mycc&quot;
},
&quot;id&quot;: 1
}
</code></pre><p>记住,当安全启用之后,要修改命令行的命令和REST API的请求内容,带上登录用户的enrollmentID。在命令行里,通过-u参数传递enrollmentID。在REST API里,通过secureContext。</p>
<pre><code>./peer chaincode deploy -u jim -n mycc -c &apos;{&quot;Function&quot;:&quot;init&quot;, &quot;Args&quot;: [&quot;a&quot;,&quot;100&quot;, &quot;b&quot;, &quot;200&quot;]}&apos;
</code></pre><p>REST Request:</p>
<pre><code>POST host:port/chaincode
{
&quot;jsonrpc&quot;: &quot;2.0&quot;,
&quot;method&quot;: &quot;deploy&quot;,
&quot;params&quot;: {
&quot;type&quot;: 1,
&quot;chaincodeID&quot;:{
&quot;name&quot;: &quot;mycc&quot;
},
&quot;ctorMsg&quot;: {
&quot;function&quot;:&quot;init&quot;,
&quot;args&quot;:[&quot;a&quot;, &quot;100&quot;, &quot;b&quot;, &quot;200&quot;]
},
&quot;secureContext&quot;: &quot;jim&quot;
},
&quot;id&quot;: 1
}
</code></pre><p>上面初始化了一个chaincode,包含了a和b的信息,假设是帐户余额信息,那么现在我们记下了a有100块,b有200块。</p>
<h4 id="通过命令行接口或者REST-API调用Chaincode交易"><a href="#通过命令行接口或者REST-API调用Chaincode交易" class="headerlink" title="通过命令行接口或者REST API调用Chaincode交易"></a>通过命令行接口或者REST API调用Chaincode交易</h4><p>在命令行中通过chaincode调用交易,-n参数需要和chaincode窗口(Vagrant 终端 2)中的-n参数匹配:</p>
<pre><code>./peer chaincode invoke -l golang -n mycc -c &apos;{&quot;Function&quot;: &quot;invoke&quot;, &quot;Args&quot;: [&quot;a&quot;, &quot;b&quot;, &quot;10&quot;]}&apos;
</code></pre><p>下面是通过REST API调用,注意端口哦:</p>
<p>REST Request:</p>
<pre><code>POST host:port/chaincode
{
&quot;jsonrpc&quot;: &quot;2.0&quot;,
&quot;method&quot;: &quot;invoke&quot;,
&quot;params&quot;: {
&quot;type&quot;: 1,
&quot;chaincodeID&quot;:{
&quot;name&quot;:&quot;mycc&quot;
},
&quot;ctorMsg&quot;: {
&quot;function&quot;:&quot;invoke&quot;,
&quot;args&quot;:[&quot;a&quot;, &quot;b&quot;, &quot;10&quot;]
}
},
&quot;id&quot;: 3
}
</code></pre><p>REST Response:</p>
<pre><code>{
&quot;jsonrpc&quot;: &quot;2.0&quot;,
&quot;result&quot;: {
&quot;status&quot;: &quot;OK&quot;,
&quot;message&quot;: &quot;5a4540e5-902b-422d-a6ab-e70ab36a2e6d&quot;
},
&quot;id&quot;: 3
}
</code></pre><p>下面是在启用安全之后的调用方式:</p>
<pre><code>./peer chaincode invoke -u jim -l golang -n mycc -c &apos;{&quot;Function&quot;: &quot;invoke&quot;, &quot;Args&quot;: [&quot;a&quot;, &quot;b&quot;, &quot;10&quot;]}&apos;
</code></pre><p>REST Request:</p>
<pre><code>POST host:port/chaincode
{
&quot;jsonrpc&quot;: &quot;2.0&quot;,
&quot;method&quot;: &quot;invoke&quot;,
&quot;params&quot;: {
&quot;type&quot;: 1,
&quot;chaincodeID&quot;:{
&quot;name&quot;:&quot;mycc&quot;
},
&quot;ctorMsg&quot;: {
&quot;function&quot;:&quot;invoke&quot;,
&quot;args&quot;:[&quot;a&quot;, &quot;b&quot;, &quot;10&quot;]
},
&quot;secureContext&quot;: &quot;jim&quot;
},
&quot;id&quot;: 3
}
</code></pre><p>上面发起了一笔交易,将a的10块钱给了b。</p>
<h4 id="通过命令行接口或者REST-API查询Chaincode"><a href="#通过命令行接口或者REST-API查询Chaincode" class="headerlink" title="通过命令行接口或者REST API查询Chaincode"></a>通过命令行接口或者REST API查询Chaincode</h4><p>查询chaincode中的指定信息:</p>
<pre><code>./peer chaincode query -l golang -n mycc -c &apos;{&quot;Function&quot;: &quot;query&quot;, &quot;Args&quot;: [&quot;b&quot;]}&apos;
</code></pre><p>下面是响应信息:</p>
<pre><code>210
</code></pre><p>下面是通过REST API的方式查询chaincode信息:</p>
<p>REST Request:</p>
<pre><code>POST host:port/chaincode
{
&quot;jsonrpc&quot;: &quot;2.0&quot;,
&quot;method&quot;: &quot;query&quot;,
&quot;params&quot;: {
&quot;type&quot;: 1,
&quot;chaincodeID&quot;:{
&quot;name&quot;:&quot;mycc&quot;
},
&quot;ctorMsg&quot;: {
&quot;function&quot;:&quot;query&quot;,
&quot;args&quot;:[&quot;a&quot;]
}
},
&quot;id&quot;: 5
}
</code></pre><p>REST Response:</p>
<pre><code>{
&quot;jsonrpc&quot;: &quot;2.0&quot;,
&quot;result&quot;: {
&quot;status&quot;: &quot;OK&quot;,
&quot;message&quot;: &quot;90&quot;
},
&quot;id&quot;: 5
}
</code></pre><p>下面是安全启用之后的调用方式:</p>
<pre><code>./peer chaincode query -u jim -l golang -n mycc -c &apos;{&quot;Function&quot;: &quot;query&quot;, &quot;Args&quot;: [&quot;b&quot;]}&apos;
</code></pre><p>REST Request:</p>
<pre><code>POST host:port/chaincode
{
&quot;jsonrpc&quot;: &quot;2.0&quot;,
&quot;method&quot;: &quot;query&quot;,
&quot;params&quot;: {
&quot;type&quot;: 1,
&quot;chaincodeID&quot;:{
&quot;name&quot;:&quot;mycc&quot;
},
&quot;ctorMsg&quot;: {
&quot;function&quot;:&quot;query&quot;,
&quot;args&quot;:[&quot;a&quot;]
},
&quot;secureContext&quot;: &quot;jim&quot;
},
&quot;id&quot;: 5
}
</code></pre><h4 id="删除启用了安全之后,产生的临时文件"><a href="#删除启用了安全之后,产生的临时文件" class="headerlink" title="删除启用了安全之后,产生的临时文件"></a>删除启用了安全之后,产生的临时文件</h4><p>在安全模式下测试完chaincode后,要删除CA服务生成的临时文件,要删除客户端注册证书,注册key,交易证书链等等。如果你想注册一个前面已经注册的用户,就必须删除这些文件。</p>
<p>在命令行终端中,进入到工作空间环境的devenv子目录。登录到Vagrant终端:</p>
<pre><code>vagrant ssh
</code></pre><p>然后运行:</p>
<pre><code>rm -rf /var/hyperledger/production
</code></pre><p>原文地址:<a href="https://github.com/hyperledger/fabric/blob/master/docs/API/SandboxSetup.md" target="_blank" rel="external">https://github.com/hyperledger/fabric/blob/master/docs/API/SandboxSetup.md</a></p>
</content>
<summary type="html">
<p>开发者要能在不完整的终端网络中测试区块链。本文档描述了怎样在本地开发环境中编写,构建,测试区块链。</p>
</summary>
</entry>
<entry>
<title>安装openblockchain</title>
<link href="http://fubai.tech/2016/04/29/%E5%AE%89%E8%A3%85openblockchain/"/>
<id>http://fubai.tech/2016/04/29/安装openblockchain/</id>
<published>2016-04-29T10:56:20.000Z</published>
<updated>2016-04-29T12:25:08.000Z</updated>
<content type="html"><h4 id="先决条件"><a href="#先决条件" class="headerlink" title="先决条件"></a>先决条件</h4><ul>
<li><a href="https://git-scm.com/downloads" target="_blank" rel="external">Git client</a></li>
<li><a href="https://golang.org/" target="_blank" rel="external">Go</a> - 1.6 or later</li>
<li><a href="https://www.vagrantup.com/" target="_blank" rel="external">Vagrant</a> - 1.7.4 or later</li>
<li><a href="https://www.virtualbox.org/" target="_blank" rel="external">VirtualBox</a> - 5.0 or later</li>
<li>在BIOS中启用虚拟化 - 不同的机器设置方法不同</li>
</ul>
<a id="more"></a>
<h4 id="克隆peer项目"><a href="#克隆peer项目" class="headerlink" title="克隆peer项目"></a>克隆peer项目</h4><p>fork一个你自己的分支仓库,地址为 <a href="https://github.com/&lt;username&gt;/fabric.git" target="_blank" rel="external">https://github.com/&lt;username&gt;/fabric.git</a></p>
<pre><code>cd $GOPATH/src
mkdir -p github.com/hyperledger
cd github.com/hyperledger
git clone https://github.com/&lt;username&gt;/fabric.git
</code></pre><h4 id="使用Vagrant引导虚拟机"><a href="#使用Vagrant引导虚拟机" class="headerlink" title="使用Vagrant引导虚拟机"></a>使用Vagrant引导虚拟机</h4><pre><code>cd $GOPATH/src/github.com/hyperledger/fabric/devenv
vagrant up --构建虚拟机
</code></pre><h4 id="构建基础核心"><a href="#构建基础核心" class="headerlink" title="构建基础核心"></a>构建基础核心</h4><pre><code>cd $GOPATH/src/github.com/hyperledger/fabric/devenv
vagrant ssh --登录到虚拟机
cd $GOPATH/src/github.com/hyperledger/fabric/peer
go build
</code></pre><h4 id="启动peer"><a href="#启动peer" class="headerlink" title="启动peer"></a>启动peer</h4><pre><code>cd $GOPATH/src/github.com/hyperledger/fabric/peer
./peer peer
</code></pre><h4 id="单元测试"><a href="#单元测试" class="headerlink" title="单元测试"></a>单元测试</h4><pre><code>cd $GOPATH/src/github.com/hyperledger/fabric/peer
go test -timeout=20m $(go list github.com/hyperledger/fabric/... | grep -v /vendor/ | grep -v /examples/)
</code></pre><h4 id="Behave-Tests"><a href="#Behave-Tests" class="headerlink" title="Behave Tests"></a>Behave Tests</h4><pre><code>cd $GOPATH/src/github.com/hyperledger/fabric/bddtests
behave
</code></pre><h4 id="最后"><a href="#最后" class="headerlink" title="最后"></a>最后</h4><ul>
<li><p>主机必须支持虚拟化,并且开启,阿里云的ECS是不支持虚拟化的</p>
</li>
<li><p>GOPATH必须是属于当前用户的,该用户最好不是root</p>
</li>
<li><p>第一次vagrant up的过程,需要翻墙下载,保证网络通畅</p>
</li>
<li><p>$GOPATH/src/github.com/hyperledger/fabric/devenv下的setup.sh中,会安装pyyaml,这个东西死活会报错,导致整个安装进程失败,可以先将其从setup.sh中删掉,然后再执行vagrant up</p>
</li>
</ul>
<p>项目地址:<a href="https://github.com/hyperledger/fabric" target="_blank" rel="external">https://github.com/hyperledger/fabric</a></p>
<p>原文地址:<a href="https://github.com/hyperledger/fabric/blob/master/docs/dev-setup/devenv.md" target="_blank" rel="external">https://github.com/hyperledger/fabric/blob/master/docs/dev-setup/devenv.md</a></p>
</content>
<summary type="html">
<h4 id="先决条件"><a href="#先决条件" class="headerlink" title="先决条件"></a>先决条件</h4><ul>
<li><a href="https://git-scm.com/downloads">Git client</a></li>
<li><a href="https://golang.org/">Go</a> - 1.6 or later</li>
<li><a href="https://www.vagrantup.com/">Vagrant</a> - 1.7.4 or later</li>
<li><a href="https://www.virtualbox.org/">VirtualBox</a> - 5.0 or later</li>
<li>在BIOS中启用虚拟化 - 不同的机器设置方法不同</li>
</ul>
</summary>
<category term="openblockchain setup" scheme="http://fubai.tech/tags/openblockchain-setup/"/>
</entry>
</feed>