mirror of
https://github.com/clearlinux/docker.git
synced 2026-09-06 21:51:33 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
53f1bf0f99 | ||
|
|
9dc59797e0 | ||
|
|
25e443a3c7 | ||
|
|
33e70864a2 | ||
|
|
d6e6214d37 | ||
|
|
70f1bd3104 | ||
|
|
f7c2a00557 | ||
|
|
8498b44eac | ||
|
|
e2dcfc2cf7 | ||
|
|
9b4c151142 | ||
|
|
50239e0573 | ||
|
|
42c23b0f04 | ||
|
|
eec91e7941 | ||
|
|
3f17844b6e | ||
|
|
bcdeb37bb6 | ||
|
|
362e9d6b3c | ||
|
|
c4ab498920 | ||
|
|
cb70eedfda | ||
|
|
75a7f4d90c | ||
|
|
eaeb969138 | ||
|
|
d7e2fc8982 | ||
|
|
f20c738963 | ||
|
|
fd7ab143bf | ||
|
|
82cdd21a34 | ||
|
|
2bc35287a0 | ||
|
|
b4f7078a02 | ||
|
|
9e68913397 | ||
|
|
304a80fcd5 | ||
|
|
04f1d4dcdb | ||
|
|
171d681724 | ||
|
|
cd4c1ac356 | ||
|
|
b8af68a92b | ||
|
|
9de4590498 | ||
|
|
0ef6fed5c7 | ||
|
|
383f95bba1 | ||
|
|
1211065c8d | ||
|
|
844c13bce6 | ||
|
|
6014db4a7e | ||
|
|
bf504f2afa | ||
|
|
61a8020e51 | ||
|
|
7eaa59f626 | ||
|
|
2cccbbdadd | ||
|
|
b700ee006a | ||
|
|
0169cf15dd | ||
|
|
234f5ac39f | ||
|
|
d575918038 | ||
|
|
66beafa9f3 | ||
|
|
3cbec95177 | ||
|
|
8e5ab5bfca | ||
|
|
9d867a389b | ||
|
|
4f9f83d6c6 | ||
|
|
145c2008ae | ||
|
|
4eaba8de91 | ||
|
|
434c1613a4 | ||
|
|
18da26c62a | ||
|
|
aeb304b37c | ||
|
|
1da8c50ded | ||
|
|
1cd9529ad3 | ||
|
|
f78d45863c | ||
|
|
3656db66d2 | ||
|
|
78c843c8ef | ||
|
|
ac821f2446 | ||
|
|
2fe4467d73 | ||
|
|
194d4b9376 | ||
|
|
1de02a70de | ||
|
|
5e941f1ca0 | ||
|
|
511a62a099 | ||
|
|
256d46fe68 | ||
|
|
76ee860ece | ||
|
|
2ae1f29dfe | ||
|
|
4b80ec9aae | ||
|
|
fef41ef7bf | ||
|
|
f946a486ea | ||
|
|
e008c7c068 | ||
|
|
669e4bac30 | ||
|
|
f6362fbb0e | ||
|
|
c1cd824570 | ||
|
|
4546832507 | ||
|
|
b5934711d0 | ||
|
|
ed8f75d25c | ||
|
|
cfbd9ea16d | ||
|
|
75dd1663e0 | ||
|
|
3c67a28493 | ||
|
|
440422a963 | ||
|
|
fc2f5758cf | ||
|
|
fe302fbfd2 | ||
|
|
72d02ecdde | ||
|
|
baa687bed2 | ||
|
|
30ea0bebce | ||
|
|
9e1da3ec9c | ||
|
|
b76574f855 | ||
|
|
457375ea37 | ||
|
|
7e580aacec | ||
|
|
0e64b987e8 | ||
|
|
bc74f65068 | ||
|
|
5c741ef11d | ||
|
|
152459b727 | ||
|
|
f04142c1f7 | ||
|
|
af05ab399e | ||
|
|
27159ce6ba | ||
|
|
51576069ad | ||
|
|
d33ffe44a9 | ||
|
|
afe230718e | ||
|
|
9261690593 | ||
|
|
e12bba66ea | ||
|
|
92c3a319fb | ||
|
|
323e86032d | ||
|
|
c06d903edd | ||
|
|
9a9d3239e1 | ||
|
|
33110ddc3f | ||
|
|
6341768393 | ||
|
|
ad96d5ff04 | ||
|
|
492ce4c665 | ||
|
|
76ab8fa00f | ||
|
|
007964793d | ||
|
|
bed87ea103 | ||
|
|
823674816e | ||
|
|
8d3e35cd8d | ||
|
|
84ed18827a | ||
|
|
693ff4d2ae | ||
|
|
596810d8db | ||
|
|
661a8a0e0c | ||
|
|
629c6e3649 | ||
|
|
c7aaf831d7 | ||
|
|
e9624bf715 | ||
|
|
2a209afe5f | ||
|
|
c001a5af67 | ||
|
|
359a6f49b9 | ||
|
|
e42144674f | ||
|
|
37abc07852 | ||
|
|
61abc3f8ac | ||
|
|
5fc56b6b47 | ||
|
|
059950b095 | ||
|
|
9ab85f4d12 | ||
|
|
3cf23b93ea | ||
|
|
3ba6835ead | ||
|
|
dc13b9473f | ||
|
|
b00d5f0185 | ||
|
|
8e71391572 | ||
|
|
077c2496ed | ||
|
|
b94e9ed0de | ||
|
|
02884ee429 | ||
|
|
8145e57cee | ||
|
|
c964494d31 | ||
|
|
c6e83b8779 | ||
|
|
369e39aea1 | ||
|
|
af0b2e38c3 | ||
|
|
87b4bb9fcc | ||
|
|
f5e6c2d060 | ||
|
|
f0f8462d18 | ||
|
|
0013aa7d9f | ||
|
|
1d7f22c0d4 | ||
|
|
6a693176d6 | ||
|
|
8523d5518c | ||
|
|
6c4393ccbb | ||
|
|
3885ef585b | ||
|
|
388057f11a | ||
|
|
c69e6a90e4 | ||
|
|
71c05bb87c | ||
|
|
637850063c | ||
|
|
dcc9980550 | ||
|
|
e405337926 | ||
|
|
5cdb3aec50 | ||
|
|
b314f19db8 | ||
|
|
353243a725 | ||
|
|
879aa29cb0 | ||
|
|
1e5ba57de3 | ||
|
|
bc6d872841 | ||
|
|
981560c436 | ||
|
|
d589cc3622 | ||
|
|
69a9614cb4 | ||
|
|
e2ac0e6b80 | ||
|
|
01dd7e7459 | ||
|
|
84a3600ea8 | ||
|
|
cb9e0aee48 | ||
|
|
52d3137713 | ||
|
|
4c7d24bc8b | ||
|
|
87c8437a90 | ||
|
|
6fab249b21 | ||
|
|
da24945070 | ||
|
|
ca113bb1b2 | ||
|
|
9ff36cb00c | ||
|
|
62f873aa1f | ||
|
|
2091b59721 | ||
|
|
88edba7e86 | ||
|
|
5fe4c9a39a | ||
|
|
2fc0084f6b | ||
|
|
7cf7dda87d | ||
|
|
bb76157d24 | ||
|
|
1d9139bb89 | ||
|
|
8149439d95 | ||
|
|
402a58a75a | ||
|
|
9c7a8edddd | ||
|
|
cf30b85eb1 | ||
|
|
ccbb5d3492 | ||
|
|
5a1bfd9aa9 | ||
|
|
8cc19765b4 | ||
|
|
8ba8783bcc | ||
|
|
4ec0b51578 | ||
|
|
7f1b179c67 | ||
|
|
b3974abe4f | ||
|
|
403f9fc357 | ||
|
|
498b6031b1 | ||
|
|
f26da9638f | ||
|
|
126b17a0ff | ||
|
|
34d294c461 | ||
|
|
45c2b5dc1a | ||
|
|
f56945d71b | ||
|
|
b8e7ec1b74 | ||
|
|
3bbe8ee055 | ||
|
|
2448058ee2 | ||
|
|
ca174ae84d | ||
|
|
f9dd0da182 | ||
|
|
e7fdcc15c5 | ||
|
|
67b0b97a8f | ||
|
|
310fbe7bb7 | ||
|
|
3f2a5912ee | ||
|
|
65102d6b36 | ||
|
|
997a32706f | ||
|
|
5cf6ad4565 | ||
|
|
bf8e0277bb | ||
|
|
5957dd9091 | ||
|
|
49d7b87cfc | ||
|
|
f417c4b099 | ||
|
|
ef57752bce | ||
|
|
4f8b6c3283 | ||
|
|
01fea3cf11 | ||
|
|
eba3c36b38 | ||
|
|
49c4231f07 | ||
|
|
ec4657b28a | ||
|
|
304d39cc50 | ||
|
|
cd4f7321c9 | ||
|
|
132db329d4 | ||
|
|
6998c3c387 | ||
|
|
26f846bf77 | ||
|
|
97c3de7e6b | ||
|
|
b5c984f9b4 | ||
|
|
249f76bebd | ||
|
|
e7df38dbd0 | ||
|
|
efb4c800a7 | ||
|
|
0cbeda7391 | ||
|
|
1717227636 | ||
|
|
50dd9791f7 | ||
|
|
9990db2f5a | ||
|
|
2d1155407a | ||
|
|
37dcff0c13 | ||
|
|
38f1838e82 | ||
|
|
807a305f36 | ||
|
|
cb1c90975b | ||
|
|
363738b8f2 | ||
|
|
6d420407ca | ||
|
|
157d99a727 | ||
|
|
360a694c52 | ||
|
|
c5bc7d5158 | ||
|
|
16eba6bbb5 | ||
|
|
0dd6c6645b | ||
|
|
70f44d5531 | ||
|
|
45aba3dc95 | ||
|
|
c22ff0296e | ||
|
|
00f1398f7a | ||
|
|
74f853a2ae | ||
|
|
20881f1f78 | ||
|
|
3108f0526e | ||
|
|
22ef38ee79 | ||
|
|
6d5b73c2a6 | ||
|
|
b7d1d35c27 | ||
|
|
f1aeac361a | ||
|
|
d9fe0647cb | ||
|
|
059bb7a262 | ||
|
|
ec9a9a08b8 | ||
|
|
8f64759881 | ||
|
|
2a5998baf1 | ||
|
|
dcf0279a50 | ||
|
|
d7928b9a67 | ||
|
|
15867ff430 | ||
|
|
3560c922b1 | ||
|
|
04aca7c9e3 | ||
|
|
6113e1d62d | ||
|
|
cdf0cf495d | ||
|
|
1dc34e2b96 | ||
|
|
8d6df3a7e2 | ||
|
|
e5f8ab6160 | ||
|
|
5c42b2b512 | ||
|
|
d3f074494a | ||
|
|
434f06d03d | ||
|
|
5a85456d48 | ||
|
|
980eda4c25 | ||
|
|
bf05eb8ac0 | ||
|
|
f3f9f652e1 | ||
|
|
2205bb43ea | ||
|
|
5af87d1475 | ||
|
|
35430e8920 | ||
|
|
4d2ba779e1 | ||
|
|
f1f39616eb | ||
|
|
4b8c41c4a2 | ||
|
|
e88368b34c | ||
|
|
4d5ecdbeb4 | ||
|
|
114e01cdc1 | ||
|
|
7f7926525a | ||
|
|
02ddaad5d9 | ||
|
|
4e7cb37dcc | ||
|
|
ca6f0aa107 | ||
|
|
847411a1ee | ||
|
|
7b17d55599 | ||
|
|
958b4a8757 | ||
|
|
714acf5ade | ||
|
|
962a66cd36 | ||
|
|
f9cb6ae46a | ||
|
|
433c8e9c7d | ||
|
|
ff8a4ba0aa | ||
|
|
dcaaecc815 | ||
|
|
2cac813937 | ||
|
|
fcc0ac6109 | ||
|
|
c5d4459a02 | ||
|
|
1182797c6d | ||
|
|
a482bfd715 | ||
|
|
8ad46ef401 | ||
|
|
854cc5f559 | ||
|
|
57cd17f656 | ||
|
|
99141ea3ca | ||
|
|
3061e9f374 | ||
|
|
19ad299600 | ||
|
|
177a2f5946 | ||
|
|
1f44fd8624 | ||
|
|
c065e564fb | ||
|
|
342bd43b76 | ||
|
|
b380866f44 | ||
|
|
dc333878d2 | ||
|
|
261c2e23d3 | ||
|
|
957db15ef4 | ||
|
|
a9ed238bb7 | ||
|
|
35690e76b4 | ||
|
|
2a0efb2324 | ||
|
|
a4ccbc6e95 | ||
|
|
2824b05235 | ||
|
|
fbfb7595b1 | ||
|
|
b840b73b08 | ||
|
|
1f3cdc11ee | ||
|
|
95708dd35c | ||
|
|
a51fb4dd35 | ||
|
|
4cbb6ce13b | ||
|
|
1cb4557cc8 | ||
|
|
c33d26a8da | ||
|
|
5a9adfe9fb | ||
|
|
f3685333c0 | ||
|
|
fc45535197 | ||
|
|
8f27e23b4b | ||
|
|
4194617bfe | ||
|
|
d8bcd1c231 | ||
|
|
f6b4a1ec95 | ||
|
|
7ddd4fe66a | ||
|
|
dcf4633e95 | ||
|
|
b30dc8c3ea | ||
|
|
feef16bd88 | ||
|
|
f9901ead06 | ||
|
|
31638ab2ad | ||
|
|
33d8c736fc | ||
|
|
9ebac49be0 | ||
|
|
65ba2868d7 | ||
|
|
a963ff5d8d | ||
|
|
c0e51a8f27 | ||
|
|
f2ebccb5aa | ||
|
|
db2e2e831b | ||
|
|
9ee9d2f995 | ||
|
|
4dc156252b | ||
|
|
747967b4a4 | ||
|
|
02b5202432 | ||
|
|
7f07ae9e42 | ||
|
|
a89a98e594 | ||
|
|
7848007c3a | ||
|
|
40ed10cc32 | ||
|
|
96d1e9bb5a | ||
|
|
e3c49843d7 | ||
|
|
3e7b9763aa | ||
|
|
393562340c | ||
|
|
d5891f9fb0 | ||
|
|
09607bb8f6 | ||
|
|
35044efce5 | ||
|
|
652f07bb59 | ||
|
|
54024ddd8a | ||
|
|
b543516556 | ||
|
|
e37a7d4981 | ||
|
|
7e7c931d2b | ||
|
|
3a14d4c923 | ||
|
|
15457febbb | ||
|
|
df1621914b | ||
|
|
f77bbfca56 | ||
|
|
87a250b711 | ||
|
|
ccc1a5dcfb | ||
|
|
ca2bbe716c | ||
|
|
13ab83a8a5 | ||
|
|
429c3108da | ||
|
|
bdbb0371a7 | ||
|
|
c1c65f972a | ||
|
|
4b8a176ee0 | ||
|
|
4dfa28fb95 | ||
|
|
8227ea35cf | ||
|
|
1099d172a2 | ||
|
|
1c3a674444 | ||
|
|
25c4c87c86 | ||
|
|
26f4d6bf59 | ||
|
|
be7eb4bfcb | ||
|
|
5eb472025a | ||
|
|
bdd12bb703 | ||
|
|
ef00317a70 | ||
|
|
3ff845904d | ||
|
|
ec488fa123 | ||
|
|
d7fac67e0a | ||
|
|
f7c40a87f3 | ||
|
|
ee81405567 | ||
|
|
23b3747945 | ||
|
|
1c7ca51f32 | ||
|
|
1edde0e8a3 | ||
|
|
596facd124 | ||
|
|
4fd389eee5 | ||
|
|
6a9fb81c57 | ||
|
|
5fb6d6e47c | ||
|
|
a4d97a4e80 | ||
|
|
3362aaa4df | ||
|
|
8fa6e2b103 | ||
|
|
b2503a72f1 | ||
|
|
bb662bc12c | ||
|
|
79bf2c2b0e | ||
|
|
746ba127bf | ||
|
|
e7402ed9cc | ||
|
|
fb4672c52c | ||
|
|
9420e8def7 | ||
|
|
4f6ce1ba9e | ||
|
|
2a9c18af52 | ||
|
|
86970d00bb | ||
|
|
da054148dc | ||
|
|
0174951195 | ||
|
|
caa7cf14c0 | ||
|
|
700a71e6b6 | ||
|
|
02e0fdee57 | ||
|
|
baf23d3c3e | ||
|
|
5b75aea704 | ||
|
|
d91e145332 | ||
|
|
1384db5e7f | ||
|
|
ff147707b2 | ||
|
|
05430c7170 | ||
|
|
eb79e8c5dd | ||
|
|
b48fc96579 | ||
|
|
e0b59ab52b | ||
|
|
a6a274f312 | ||
|
|
4f5790d104 | ||
|
|
70c976de03 | ||
|
|
4947f61c20 | ||
|
|
1de23f1b81 | ||
|
|
b283900764 | ||
|
|
82f1514895 | ||
|
|
e47f9984f8 | ||
|
|
b038b0cd44 | ||
|
|
7e8b2c3836 | ||
|
|
dd9f4524d1 | ||
|
|
a52e23c5e4 | ||
|
|
0d2924408b | ||
|
|
91d721aaf4 | ||
|
|
76afb6e73d | ||
|
|
c0662488c7 | ||
|
|
971cf56d89 | ||
|
|
865649d7ac | ||
|
|
50bb4a1636 | ||
|
|
3c0c75bbf9 | ||
|
|
7f95c7aeec | ||
|
|
395a24ffd5 | ||
|
|
45d94944f3 | ||
|
|
a13241d370 | ||
|
|
e8491ae54c | ||
|
|
464ded79fc | ||
|
|
c1ae1a0e1c | ||
|
|
c542b2f873 | ||
|
|
7e691e11b0 | ||
|
|
1b8eef4efb | ||
|
|
2a29bf6245 | ||
|
|
0d1a825137 | ||
|
|
60b97576cf | ||
|
|
54d3b4dd28 | ||
|
|
8f39f0b57d | ||
|
|
d5c7e92a9a | ||
|
|
110b944f45 | ||
|
|
13c521526d | ||
|
|
516cf54843 | ||
|
|
356af1540f | ||
|
|
2e6b241dc7 | ||
|
|
94e5081bac | ||
|
|
e179a24ad5 | ||
|
|
da864a845b | ||
|
|
640682d56c | ||
|
|
66a159342b | ||
|
|
7c882a8003 | ||
|
|
7d440f70fd | ||
|
|
0c9b319dd0 | ||
|
|
7c08aeeba4 | ||
|
|
7072d2aaca | ||
|
|
21161dbd51 | ||
|
|
cf86e2bb22 | ||
|
|
d789750851 | ||
|
|
fb8d488896 | ||
|
|
dbe7d67c18 | ||
|
|
6c863b49ef | ||
|
|
89fb51f606 | ||
|
|
256b7537e3 | ||
|
|
c4923757f1 | ||
|
|
387aeb78fb | ||
|
|
99a9783abc | ||
|
|
0e24db3a68 | ||
|
|
db99966724 | ||
|
|
d063c8d941 | ||
|
|
249f5a65a5 | ||
|
|
494cd07f72 | ||
|
|
607c1a520e | ||
|
|
bf61d41d6c | ||
|
|
ce965b8c43 | ||
|
|
f7a2f0b937 | ||
|
|
4576d0f802 | ||
|
|
515070d513 | ||
|
|
1cbdaebaa1 | ||
|
|
ff567f8729 | ||
|
|
279791bc74 | ||
|
|
b64ce8e33c | ||
|
|
1e704a4ddc | ||
|
|
31111f61e0 | ||
|
|
217b6070f0 | ||
|
|
36c26a0f0f | ||
|
|
a675e249b1 | ||
|
|
acc2aec988 | ||
|
|
0e021ed470 | ||
|
|
b9eb5e04ae | ||
|
|
0e44864b66 | ||
|
|
e661473bcd | ||
|
|
98c94dd4db | ||
|
|
656b66e51b | ||
|
|
c9375d14fc | ||
|
|
489c370fcc | ||
|
|
aa6c99aff6 | ||
|
|
92384649cf | ||
|
|
c2413889bb | ||
|
|
e81da876df | ||
|
|
f0dbdba5c0 | ||
|
|
0324e567ad | ||
|
|
ef5cf6c1ec | ||
|
|
afaddd04f7 | ||
|
|
8e43db95f2 | ||
|
|
7a116220e7 | ||
|
|
894a68d2ee | ||
|
|
dc57d4ca26 | ||
|
|
bc8a1081b0 | ||
|
|
33ccd29ae7 | ||
|
|
2aaaf90320 | ||
|
|
99f1675566 | ||
|
|
7e4d008403 | ||
|
|
b0515a7016 | ||
|
|
8ff7b70c91 | ||
|
|
01284cbf73 | ||
|
|
10e10c9573 | ||
|
|
b73065ab33 | ||
|
|
d93023daa9 | ||
|
|
81866087fe | ||
|
|
e70030a0c3 | ||
|
|
3bd45824da | ||
|
|
13c913d883 | ||
|
|
92beaed066 | ||
|
|
6b04913e73 | ||
|
|
93810b289c | ||
|
|
ea59ce60c5 | ||
|
|
a1fc8e17a7 | ||
|
|
f903feee03 | ||
|
|
26adda6c31 | ||
|
|
7e09c6332d | ||
|
|
3b0cbc59ea | ||
|
|
95f3f77fc4 | ||
|
|
bba5fd4555 | ||
|
|
9bceae2440 | ||
|
|
e7269b9841 | ||
|
|
8cf0f2dbe5 | ||
|
|
3e014aa662 | ||
|
|
333bc23f21 | ||
|
|
7cf1877098 | ||
|
|
4918769b1a | ||
|
|
4b7c071e9c | ||
|
|
ad7c6bc950 | ||
|
|
2e4ee72201 | ||
|
|
4870265a9f | ||
|
|
43fd85eb8f | ||
|
|
b629810fe0 | ||
|
|
07d9e4353b | ||
|
|
ac5bc86771 | ||
|
|
85956c70b5 | ||
|
|
8c38c30985 | ||
|
|
89a2c8e2cd | ||
|
|
f34a62ea19 | ||
|
|
255b6aadfa | ||
|
|
5c175357aa | ||
|
|
240d5b3fa1 | ||
|
|
689bcd1dc3 | ||
|
|
8bce284496 | ||
|
|
95ccb78aa7 | ||
|
|
83a2e92d47 | ||
|
|
d401e9d3ac | ||
|
|
3db381bf08 | ||
|
|
f248a8e13c | ||
|
|
47cc6c8081 | ||
|
|
c405d53b6e | ||
|
|
bc39ac71e6 | ||
|
|
2110b3cca8 | ||
|
|
414795856a | ||
|
|
2f74b1c84b | ||
|
|
e8da76605f | ||
|
|
f16e60665b | ||
|
|
3ba9893786 | ||
|
|
7b1c6ccabd | ||
|
|
6ee2964a4f | ||
|
|
49c62879b8 | ||
|
|
34745ee0f4 | ||
|
|
d21bd5b964 | ||
|
|
82220ea2ad | ||
|
|
655b16c712 | ||
|
|
eb2d0d4bf5 | ||
|
|
cc851dbb3f | ||
|
|
e40fd1e3e1 | ||
|
|
dab84f7e8b | ||
|
|
7df8ec2093 | ||
|
|
a2ffa637ce | ||
|
|
ed6ca109bf | ||
|
|
6e48b73955 | ||
|
|
664acd2971 | ||
|
|
3acfc60028 | ||
|
|
0e64a4d7e7 | ||
|
|
104a86936a | ||
|
|
df697b4318 | ||
|
|
27fc01271e | ||
|
|
97ab118fbb | ||
|
|
fc659b68e4 | ||
|
|
99f6b43f4f | ||
|
|
2b92aa71f9 | ||
|
|
f854529ae8 | ||
|
|
e32debcf5f | ||
|
|
0e08e1d695 | ||
|
|
65b62307c3 | ||
|
|
03e5d94b12 | ||
|
|
0ca533ca35 | ||
|
|
d94a027da6 | ||
|
|
7250f94874 | ||
|
|
4196c704f0 | ||
|
|
adb48ef319 | ||
|
|
ee7d9b0bde | ||
|
|
2f4526d5c4 | ||
|
|
261285c2c2 | ||
|
|
cbc49d7d76 | ||
|
|
4dc90405e3 | ||
|
|
b7abe9dab5 | ||
|
|
cd455ca6fa | ||
|
|
ca56b35e53 | ||
|
|
095aab9d97 | ||
|
|
ace059e409 | ||
|
|
9da2b3590e | ||
|
|
e99ab1df97 | ||
|
|
4967f9f19c | ||
|
|
fde157425c | ||
|
|
a0e5657cb6 | ||
|
|
f4a98b4598 | ||
|
|
53a07d5475 | ||
|
|
93b258413f | ||
|
|
c0bfb75e5f | ||
|
|
1043055b10 | ||
|
|
620bc5b9e1 | ||
|
|
6d6097cddf | ||
|
|
42277d0329 | ||
|
|
d62df6b2b5 | ||
|
|
97779ff7cf | ||
|
|
9afa48a92f | ||
|
|
ad723bbfe7 | ||
|
|
f15cd71bb8 | ||
|
|
94bf5b0011 | ||
|
|
d542318d63 | ||
|
|
6e3068700f | ||
|
|
fac190959f | ||
|
|
1dcdc3deb7 | ||
|
|
ee256ce6bf | ||
|
|
5fe699f813 | ||
|
|
7561e2570c | ||
|
|
640ca68e4f | ||
|
|
f9b9dfc82d | ||
|
|
c978f0fa5c | ||
|
|
d91bf33df3 | ||
|
|
310a174260 | ||
|
|
2eb404ab14 | ||
|
|
60e426938e | ||
|
|
c2912c82aa | ||
|
|
9041d6a47b | ||
|
|
8abd328f53 | ||
|
|
ae780fb5ea | ||
|
|
152037f011 | ||
|
|
0367032bd1 | ||
|
|
edca9f7e9c | ||
|
|
e19cc1e843 | ||
|
|
feabce3bcc | ||
|
|
ded74b0bb3 | ||
|
|
ffee5faae8 | ||
|
|
aa3697520a | ||
|
|
c1bb33ea4d | ||
|
|
6545e53803 | ||
|
|
d30806590c | ||
|
|
823174de4d | ||
|
|
d5f9160441 | ||
|
|
37df1d92d8 | ||
|
|
dabac81824 | ||
|
|
bb62c281f5 | ||
|
|
3565bf8d00 | ||
|
|
f4c17a202b | ||
|
|
9a4b0b9823 | ||
|
|
9107565d06 | ||
|
|
7d95d300ab | ||
|
|
4fda3314d8 | ||
|
|
e906485b07 | ||
|
|
1daf242c8b | ||
|
|
967010ae8c | ||
|
|
d03022b9ca | ||
|
|
6d67ac2a1b | ||
|
|
2d425af1b1 | ||
|
|
ed19693f50 | ||
|
|
ee27444098 | ||
|
|
194c1dbbd8 | ||
|
|
a9eac7eab4 | ||
|
|
7c28683f08 | ||
|
|
c18e849451 | ||
|
|
a665517151 | ||
|
|
0d3c899528 | ||
|
|
863eebe7bd | ||
|
|
3c5350ba92 | ||
|
|
c52c95f97f | ||
|
|
85a5139665 | ||
|
|
ad4b09cdb8 | ||
|
|
e594c788e4 | ||
|
|
f84dc1e908 | ||
|
|
826aaa0e9b | ||
|
|
1328be7c29 | ||
|
|
ff4f32d58f | ||
|
|
462ac1efcf | ||
|
|
1332f400f7 | ||
|
|
a292c04ddb | ||
|
|
37c4513cf9 | ||
|
|
b584c21ca4 | ||
|
|
c92507341d | ||
|
|
9f0feaa2e1 | ||
|
|
0f830aa431 | ||
|
|
5f05cb4817 | ||
|
|
4778039dd2 | ||
|
|
b180770b1d | ||
|
|
4f5c2cbccc | ||
|
|
c3acd9bece | ||
|
|
cb21a40490 | ||
|
|
5025b4d094 | ||
|
|
509e25cf04 | ||
|
|
135c1fce90 | ||
|
|
d517fd3d77 | ||
|
|
b4e1b8d2e2 | ||
|
|
45bd52d472 | ||
|
|
534a991cff | ||
|
|
23015fa14d | ||
|
|
fb46d911c2 | ||
|
|
85b776995c | ||
|
|
fa44555fb4 | ||
|
|
3e7c50e8a1 | ||
|
|
ccefe47897 | ||
|
|
ff85031980 | ||
|
|
017ecefd66 | ||
|
|
88f710f0e7 | ||
|
|
6496059154 | ||
|
|
bcce3cbdd1 | ||
|
|
bbf644ed62 | ||
|
|
d89ce09a76 | ||
|
|
e3e041b6bf | ||
|
|
0a35b1fb36 | ||
|
|
3894add8a9 | ||
|
|
74d54b9b2e | ||
|
|
31fd11860b | ||
|
|
b081a740b3 | ||
|
|
db869ecce5 | ||
|
|
537149829a | ||
|
|
ba10e28927 | ||
|
|
f4855a7cf0 | ||
|
|
22e7e107ad | ||
|
|
edd90d46c7 | ||
|
|
f435970695 | ||
|
|
cb18a6e1b9 | ||
|
|
ce05083d4b | ||
|
|
723de87681 | ||
|
|
c22e377a6d | ||
|
|
3f0d0075f8 | ||
|
|
f8c9f11f06 | ||
|
|
80319add55 | ||
|
|
818ec10da3 | ||
|
|
34e28ccc88 | ||
|
|
792403f2dc | ||
|
|
8f5c33dc1f | ||
|
|
06c1f000e8 | ||
|
|
00b3acb8ab | ||
|
|
420ba9c85a | ||
|
|
0f829bf5cf | ||
|
|
1363de0934 | ||
|
|
d06116d2e8 | ||
|
|
595210a370 | ||
|
|
c9b916b293 | ||
|
|
1e6370fd4b | ||
|
|
a59a66528b | ||
|
|
b048e9dffc | ||
|
|
c000e6a7fc | ||
|
|
aa3de0b849 | ||
|
|
648d759517 | ||
|
|
5c190fa926 | ||
|
|
03fe5632d0 | ||
|
|
edde4f55e0 | ||
|
|
7447867edd | ||
|
|
c1c74cb0b1 | ||
|
|
17b7194d91 | ||
|
|
15ad2915b9 | ||
|
|
d6887b769c | ||
|
|
10362870db | ||
|
|
a7db125480 | ||
|
|
f6c64827c8 | ||
|
|
30b759ffa9 | ||
|
|
35ca35ffb6 | ||
|
|
a4067b1b44 | ||
|
|
b0a49a30c7 | ||
|
|
6097644e4b | ||
|
|
fa3837abf1 | ||
|
|
baff72bc82 | ||
|
|
99377de7d2 | ||
|
|
0ef5bcb17d | ||
|
|
fd1c43f0e0 | ||
|
|
dc06496dc8 | ||
|
|
cfbe76e559 | ||
|
|
2fafe1efce | ||
|
|
181b9baddd | ||
|
|
8240e37b87 | ||
|
|
23cf3c7a33 | ||
|
|
e37bb50628 | ||
|
|
2819cfb3f3 | ||
|
|
a479f7659d | ||
|
|
b02a591f57 | ||
|
|
c654075654 | ||
|
|
5a3dcbb3f6 | ||
|
|
cce6f00c0c | ||
|
|
4db64111bd | ||
|
|
e97364ecd7 | ||
|
|
2bd089dadb | ||
|
|
5bd0437eed | ||
|
|
a81393787f | ||
|
|
b45e280ee8 | ||
|
|
5867f9e761 | ||
|
|
6132f378e0 | ||
|
|
3cf4b2c7c1 | ||
|
|
d70cbbf1fc | ||
|
|
b7e7104e92 | ||
|
|
7e60a6b1ea | ||
|
|
45979a7ef7 | ||
|
|
5c9213258a | ||
|
|
68074fce68 | ||
|
|
c42056b969 | ||
|
|
341addeccd | ||
|
|
47904290a5 | ||
|
|
a18c26392f | ||
|
|
77ad95d372 | ||
|
|
fee61895f2 | ||
|
|
f6a78f89ba | ||
|
|
081543c49a | ||
|
|
4054f31471 | ||
|
|
76a07371c5 | ||
|
|
5d364fda3c | ||
|
|
28311f61be | ||
|
|
70b731735c | ||
|
|
67453d6b48 | ||
|
|
c14450ae5c | ||
|
|
593566438d | ||
|
|
ca5913ff3e | ||
|
|
85f3ec88a6 | ||
|
|
b2707dccc1 | ||
|
|
b826351337 | ||
|
|
5797e7e34e | ||
|
|
089a60c2cf | ||
|
|
a99a8386fd | ||
|
|
dfd0deefbb | ||
|
|
2183644578 | ||
|
|
e836b0064b | ||
|
|
986906cd7b | ||
|
|
8d48119340 | ||
|
|
cdce873ea0 | ||
|
|
5a01f7485c | ||
|
|
45b50730e3 | ||
|
|
40eaa82fc6 | ||
|
|
9946981c61 | ||
|
|
d6cf41cbe6 | ||
|
|
c6b4076125 | ||
|
|
b79bd4e864 | ||
|
|
2f24b9e05c | ||
|
|
a63cfe7153 | ||
|
|
cd289cc10c | ||
|
|
894eff64b4 | ||
|
|
71e15d1c3c | ||
|
|
74daeccec5 | ||
|
|
102522bcd1 | ||
|
|
b3cbf424ec | ||
|
|
33972627b7 | ||
|
|
4234fc699f | ||
|
|
4a707a8800 | ||
|
|
b986fd00e0 | ||
|
|
f368fd9f9f | ||
|
|
6c1c404501 | ||
|
|
796d7a49f0 | ||
|
|
ffc850244f | ||
|
|
83623675ce | ||
|
|
46f644c074 | ||
|
|
1bc2ab05ec | ||
|
|
1d935c6307 | ||
|
|
b7a3fc687e | ||
|
|
718b1f9fe7 | ||
|
|
45cedefadb | ||
|
|
1e723bc95a | ||
|
|
082d142024 | ||
|
|
9dd98df1a3 | ||
|
|
e854b7b2e6 | ||
|
|
289350e633 | ||
|
|
8ae5348a51 | ||
|
|
557e3ec88e | ||
|
|
dfe45e1ad5 | ||
|
|
d5480fb78d | ||
|
|
c6dc90ccb9 | ||
|
|
02037a9b53 | ||
|
|
71d46eaf02 | ||
|
|
f4ba0d4267 | ||
|
|
d48ea32186 | ||
|
|
33e4d73629 | ||
|
|
07324a37eb | ||
|
|
dd49cc45c8 | ||
|
|
21be3b76e9 | ||
|
|
9cfbaecfe5 | ||
|
|
ebee8f28ac | ||
|
|
03e36caeb1 | ||
|
|
f482432a76 | ||
|
|
c75926be4f | ||
|
|
bd0e4fde9a | ||
|
|
de75241b62 | ||
|
|
228b7af516 | ||
|
|
d14058bc29 | ||
|
|
5b361f31f7 | ||
|
|
c24c5c3b60 | ||
|
|
44d0f941f2 | ||
|
|
b7826f5666 | ||
|
|
27ca0c225a | ||
|
|
ad152efbed | ||
|
|
14bbbcd571 | ||
|
|
3d39336a46 | ||
|
|
6a4afb7f8e | ||
|
|
c01f6df43e | ||
|
|
e89396809f | ||
|
|
4f3b8033f2 | ||
|
|
ebb934c1b0 | ||
|
|
2801624462 | ||
|
|
6921ca4813 | ||
|
|
59856a20bf | ||
|
|
b187cc40cd | ||
|
|
58281b4f18 | ||
|
|
672f1e0683 | ||
|
|
dd806b4ecd | ||
|
|
843f9091f2 | ||
|
|
53da0507e4 | ||
|
|
bd847f66c6 | ||
|
|
e503f6a878 | ||
|
|
6678a26d1c | ||
|
|
e37dcd726f | ||
|
|
8ddfb4d6aa | ||
|
|
28f2fe9167 | ||
|
|
3c90e96b6d | ||
|
|
46a1cd69a9 | ||
|
|
9b088ada7e | ||
|
|
0508bd8da7 | ||
|
|
446ca4b57b | ||
|
|
4f2e59f94a | ||
|
|
0a436e03b8 | ||
|
|
c66a827c98 | ||
|
|
fe99e51634 | ||
|
|
49b5c44ee9 | ||
|
|
64bc08f1c4 | ||
|
|
2d4ac06426 | ||
|
|
9749d94fb0 | ||
|
|
630ae43e7d | ||
|
|
268928ab35 | ||
|
|
4cd59b96ed | ||
|
|
055bbb79c1 | ||
|
|
19dc3b0792 | ||
|
|
20d24a450c | ||
|
|
eca861a99d | ||
|
|
d757bd0904 | ||
|
|
47838051be | ||
|
|
fa806f26af | ||
|
|
34eab42833 | ||
|
|
3c80bd76cf | ||
|
|
c983023661 | ||
|
|
6a9f4ecf9b | ||
|
|
24e02043a2 | ||
|
|
c8f885a4d0 | ||
|
|
b07314e2e0 | ||
|
|
eed00a4afd | ||
|
|
6679f3b053 | ||
|
|
70ab25a5db | ||
|
|
bcb8d3fd86 | ||
|
|
b9ca311008 | ||
|
|
37186d9ef4 | ||
|
|
03a28da5f7 | ||
|
|
b44d113120 | ||
|
|
35bcba8011 | ||
|
|
f2bc7ebf1e | ||
|
|
e5239b9859 | ||
|
|
8a2fd914b2 | ||
|
|
f3d51bb3d5 | ||
|
|
d06a0ba1a7 | ||
|
|
8374dac021 | ||
|
|
3bc73fa21e | ||
|
|
0d7044955a | ||
|
|
20a763e519 | ||
|
|
5ec2fea6dd | ||
|
|
908bb65dcf | ||
|
|
d368c2dee9 | ||
|
|
82dd417ef6 | ||
|
|
b57d7dca9d | ||
|
|
8e41181591 | ||
|
|
fdf1fccd3e | ||
|
|
bf6e241d97 | ||
|
|
f0cdbaa6c8 | ||
|
|
e0d6bae1eb | ||
|
|
d6ff912917 | ||
|
|
ad04cacd28 | ||
|
|
62823cfb97 | ||
|
|
9ae5054c34 | ||
|
|
8878943ac9 | ||
|
|
8e3844cd34 | ||
|
|
1a32c4a1df | ||
|
|
98edd0e751 | ||
|
|
98a1314251 | ||
|
|
34edbd4f7e | ||
|
|
2ea52dddec | ||
|
|
396274fa6d | ||
|
|
28e75b23b3 | ||
|
|
ad5796de9f | ||
|
|
3a6868bc2f | ||
|
|
34145f9840 | ||
|
|
58ea690b41 | ||
|
|
3b92ab3465 | ||
|
|
76f97a64fa | ||
|
|
5974794942 | ||
|
|
368d0385e1 | ||
|
|
58ffd03bf1 | ||
|
|
9ce1d02ef6 | ||
|
|
251d1261b0 | ||
|
|
a0a5170991 | ||
|
|
b3a70d767d | ||
|
|
91ee679549 | ||
|
|
52fe452497 | ||
|
|
846524115b | ||
|
|
fac4cedcc1 | ||
|
|
ded973219e | ||
|
|
dd4aab8411 | ||
|
|
d04beb7f43 | ||
|
|
a2603477dd | ||
|
|
ad322d7cca | ||
|
|
da3bb9a7c6 | ||
|
|
0e6ee9632c | ||
|
|
fcee6056dc | ||
|
|
ea813d8593 | ||
|
|
d13c2ed24e | ||
|
|
75df4953f4 | ||
|
|
f703b8b839 | ||
|
|
6380b42edb | ||
|
|
ce53e21ea6 | ||
|
|
35fef275b3 | ||
|
|
fa3266efa5 | ||
|
|
113bb396cd | ||
|
|
1fca99ad90 | ||
|
|
e42d3a1bfa | ||
|
|
3528990c73 | ||
|
|
8ee4473d92 | ||
|
|
212b582362 | ||
|
|
969e48dd5a | ||
|
|
d9b7ec6458 | ||
|
|
46c9c5c843 | ||
|
|
7a9c711832 | ||
|
|
6756e786ac | ||
|
|
84431ec03c | ||
|
|
d605e82bad | ||
|
|
2ea19238ff | ||
|
|
df36f9db05 | ||
|
|
74982bda32 | ||
|
|
6d769f4b9b | ||
|
|
1a8a540209 | ||
|
|
6c206f7d78 | ||
|
|
110d3b7794 | ||
|
|
c0e95fa68a | ||
|
|
e3b58d3027 | ||
|
|
9b029a0854 | ||
|
|
49d35cc0ae | ||
|
|
c6702bebe1 | ||
|
|
690c3839fd | ||
|
|
050cf70136 | ||
|
|
df8f95ac74 | ||
|
|
0f91418b26 | ||
|
|
4ff649ce85 | ||
|
|
c4394decf8 | ||
|
|
f159f4710b | ||
|
|
740a97f1a8 | ||
|
|
eee6d3dae9 | ||
|
|
559724ac35 | ||
|
|
3f141e1fd3 | ||
|
|
9f8e5a93b4 | ||
|
|
78d995bbd6 | ||
|
|
e7ee2f443a | ||
|
|
b8a8962833 | ||
|
|
b54ba5095b | ||
|
|
f18889bf67 | ||
|
|
6e4a818ee6 | ||
|
|
2357fecc92 | ||
|
|
23dc52f528 | ||
|
|
c3154fdf4d | ||
|
|
f1d0625cf8 | ||
|
|
230dc07d37 | ||
|
|
c46d9933ec | ||
|
|
bcb081a269 | ||
|
|
57892365ef | ||
|
|
075253238d | ||
|
|
f6b56e996d | ||
|
|
18d572abb4 | ||
|
|
37a236947e | ||
|
|
c1f6914e43 | ||
|
|
b1eae313ad | ||
|
|
a359e52f29 | ||
|
|
bf98fff925 | ||
|
|
e6c3da42e7 | ||
|
|
d5220bc081 | ||
|
|
66ef6c0f6e | ||
|
|
20772f90ff | ||
|
|
9a60f36ccc | ||
|
|
69a93b36d5 | ||
|
|
466a88b9a8 | ||
|
|
f0620da74a | ||
|
|
dffb72ca89 | ||
|
|
128893062b | ||
|
|
98018df078 | ||
|
|
4a3b039c2a | ||
|
|
c627ff6e20 | ||
|
|
d593f57952 | ||
|
|
c2b273df5d | ||
|
|
cc18a9c650 | ||
|
|
f861c493bf | ||
|
|
d80b50d4b4 | ||
|
|
5b84252c73 | ||
|
|
f352ec945f | ||
|
|
714e424d74 | ||
|
|
f7fa6c2b0b | ||
|
|
b866254a19 | ||
|
|
108b6c644b | ||
|
|
9ce7b1c009 | ||
|
|
076434ef10 | ||
|
|
f2807042c2 | ||
|
|
d4c7340131 | ||
|
|
331f983593 | ||
|
|
1adbadde80 | ||
|
|
843ef645d2 | ||
|
|
4440bde0eb | ||
|
|
f83d556bc0 | ||
|
|
d8a18ea3ae | ||
|
|
c864647721 | ||
|
|
2891e828bd | ||
|
|
465d5313c5 | ||
|
|
02d1d238cd | ||
|
|
1f85ed6825 | ||
|
|
ef82690144 | ||
|
|
f4432d50c3 | ||
|
|
820a3b962a | ||
|
|
99a8306898 | ||
|
|
bd16107e97 | ||
|
|
5105263dac | ||
|
|
7b5c579b77 | ||
|
|
dcfb993ac7 | ||
|
|
dd9ee039a6 | ||
|
|
15d658d36b | ||
|
|
59281d6f80 | ||
|
|
29be20f987 | ||
|
|
5a8c32dc8e | ||
|
|
3d9b4379a5 | ||
|
|
ab882da03b | ||
|
|
e2594d162e | ||
|
|
ebb9b5e85b | ||
|
|
98f9d3e81c | ||
|
|
091fb89294 | ||
|
|
db91cac44f | ||
|
|
8dd3607bd1 | ||
|
|
3ebda17f0f | ||
|
|
9149c45745 | ||
|
|
969ab9c450 | ||
|
|
588f8e1cec | ||
|
|
f753dfe6b3 | ||
|
|
d1ad0e278d | ||
|
|
72cfa3de35 | ||
|
|
3396a183c6 | ||
|
|
1c6af604e8 | ||
|
|
ccc2276469 | ||
|
|
78a71b1273 | ||
|
|
2191419f4c | ||
|
|
f4a4f1ca87 | ||
|
|
f925edd12d | ||
|
|
12715c8ddc | ||
|
|
093b85b72f | ||
|
|
326dadd224 | ||
|
|
a3510c99f1 | ||
|
|
262d57e387 | ||
|
|
551092f9c0 | ||
|
|
3f802f4a13 | ||
|
|
d6f53049c4 | ||
|
|
5e3386473a | ||
|
|
0b9c8e2860 | ||
|
|
42fe550c9e | ||
|
|
f5bd137216 | ||
|
|
348696f3fe | ||
|
|
6da071985f | ||
|
|
56e02dd0c7 | ||
|
|
e0a7013836 | ||
|
|
467dbb75f1 | ||
|
|
2f6ce27fde | ||
|
|
c349b4d56c | ||
|
|
62e84785b6 | ||
|
|
215094903a | ||
|
|
8a7c0495e0 | ||
|
|
885afebe07 | ||
|
|
e06372d6f4 | ||
|
|
b5a48eaed3 | ||
|
|
a8059059c6 | ||
|
|
c8c69a1499 | ||
|
|
0469e47674 | ||
|
|
5b630d436d | ||
|
|
9c06420b18 | ||
|
|
87872006ce | ||
|
|
abfa7a204d | ||
|
|
5b0eaef602 | ||
|
|
9694fb85d7 | ||
|
|
bfee2c726e | ||
|
|
ab4fb9bbfa | ||
|
|
fbd5b20c38 | ||
|
|
ff30eb96b6 | ||
|
|
749a7d0e4f | ||
|
|
d9f769930b | ||
|
|
d750060f0c | ||
|
|
bdbac9f7a1 | ||
|
|
13201775de | ||
|
|
ccc3969536 | ||
|
|
89ee524229 | ||
|
|
9fce6f662a | ||
|
|
9087ef9a77 | ||
|
|
aa2ab5143b | ||
|
|
2c147dd721 | ||
|
|
ee64e099e0 | ||
|
|
30726c3785 | ||
|
|
41973d41e9 | ||
|
|
f69c465231 | ||
|
|
75f4fd978d | ||
|
|
e9a1246527 | ||
|
|
d627ff9697 | ||
|
|
04c16f347b | ||
|
|
9c829cb5b4 | ||
|
|
83acd37161 | ||
|
|
b21f898620 | ||
|
|
646afab28d | ||
|
|
f6653c3fa5 | ||
|
|
18962d0ff3 | ||
|
|
b22c973110 | ||
|
|
319988336c | ||
|
|
67c9ce6dd1 | ||
|
|
687d27ab57 | ||
|
|
6aff117164 | ||
|
|
e69f714219 | ||
|
|
276d2bbf1d | ||
|
|
e6affb1b1a | ||
|
|
f409c11916 | ||
|
|
3885ee00c5 | ||
|
|
5325703c27 | ||
|
|
45543d012e | ||
|
|
8a18999d23 | ||
|
|
07a887032a | ||
|
|
1843a71911 | ||
|
|
9ce577782c | ||
|
|
422d4afdd5 | ||
|
|
09a08e0a9f | ||
|
|
5142e83d93 | ||
|
|
0418702cfc | ||
|
|
674e5c8503 | ||
|
|
2ec141da54 | ||
|
|
20b1e19641 | ||
|
|
f11fb706f6 | ||
|
|
bca19a22c5 | ||
|
|
62b45f0827 | ||
|
|
92a2b635a3 | ||
|
|
d7979ef2d0 | ||
|
|
c5d8844d80 | ||
|
|
c7cda86e84 | ||
|
|
4caa604793 | ||
|
|
7f9ba14b18 | ||
|
|
72660a1a2f | ||
|
|
d4eab77f0c | ||
|
|
9708597b0b | ||
|
|
15bc2240ac | ||
|
|
631c449183 | ||
|
|
84a0274885 | ||
|
|
5ad8840024 | ||
|
|
8dfc47307d | ||
|
|
aae04def7b | ||
|
|
f51eb0e4b3 | ||
|
|
8b6b187a8d | ||
|
|
8b26e4ea3c | ||
|
|
1d8562b290 | ||
|
|
9662f9e56a | ||
|
|
25d71fb01b | ||
|
|
12ffb522a6 | ||
|
|
0077678844 | ||
|
|
53f2c5d6e8 | ||
|
|
49597f0f52 | ||
|
|
c84d74df8c | ||
|
|
3c9f9945c9 | ||
|
|
80ebff0fa4 | ||
|
|
62c0f433fa | ||
|
|
44eb1b3892 | ||
|
|
4cb57a5438 | ||
|
|
2e5642452b | ||
|
|
4947e32acb | ||
|
|
6c87db97a6 | ||
|
|
f127c471a1 | ||
|
|
280901e5fb | ||
|
|
f14db49346 | ||
|
|
f1cdba2937 | ||
|
|
0794f0b518 | ||
|
|
e2409ad337 | ||
|
|
ca92bc7798 | ||
|
|
e4f35dd4cf | ||
|
|
2cebe09924 | ||
|
|
e5f1b6b9a4 | ||
|
|
79fc90b646 | ||
|
|
fb7c4214ce | ||
|
|
06a092bdb5 | ||
|
|
5d25f3232c | ||
|
|
1a1c89556f | ||
|
|
05219d6b52 | ||
|
|
9cc3d7a18b | ||
|
|
e09863fedb | ||
|
|
2ba1300773 | ||
|
|
6cb908bb82 | ||
|
|
5ee3c58d25 | ||
|
|
c3773740d9 | ||
|
|
0ca133dd76 | ||
|
|
68934878f1 | ||
|
|
ef1d1aefa7 | ||
|
|
c015d26e96 | ||
|
|
f6760fca88 | ||
|
|
ec61c46bf7 | ||
|
|
90cb66f08d | ||
|
|
999a8d7249 | ||
|
|
13acf72a3e | ||
|
|
aa213b48a4 | ||
|
|
9b2a5964fc | ||
|
|
1110bb8e98 | ||
|
|
168e2f8c49 | ||
|
|
86ef6422f3 | ||
|
|
3af60bf375 | ||
|
|
123c80467b | ||
|
|
edba1af304 | ||
|
|
875e16c11b | ||
|
|
703905d7ec | ||
|
|
d52c149075 | ||
|
|
3f95d1b9bf | ||
|
|
def9598ed9 | ||
|
|
529ee848da | ||
|
|
64b817a5c1 | ||
|
|
02b8d14bdd | ||
|
|
025c759e44 | ||
|
|
940d58806c | ||
|
|
a2fb870ce3 | ||
|
|
e737856a7f | ||
|
|
ae1909b482 | ||
|
|
d75282eb14 | ||
|
|
cd9886f0a8 | ||
|
|
a43bae4c0b | ||
|
|
91ae135896 | ||
|
|
57b49efc98 | ||
|
|
3bd73a9633 | ||
|
|
e3acbff2ed | ||
|
|
d6e5c2c276 | ||
|
|
4dc04d7690 | ||
|
|
3e12349831 | ||
|
|
7c50221de5 | ||
|
|
3d63087f78 | ||
|
|
1408f08c40 | ||
|
|
3b23f02229 | ||
|
|
fd5099c9fe | ||
|
|
68b09cbe3d | ||
|
|
92cd2f5bad | ||
|
|
8d1cd63dfa | ||
|
|
2c4c10fb4a | ||
|
|
722d4e916a | ||
|
|
4ff649a4ea | ||
|
|
641ddaeb03 | ||
|
|
2ba5c91547 | ||
|
|
25e7227c81 | ||
|
|
04cd0a392b | ||
|
|
db9d68c3e4 | ||
|
|
88cb9f3116 | ||
|
|
55f9610cde | ||
|
|
6178dc7f1b | ||
|
|
b8f8f9d07e | ||
|
|
1643943402 | ||
|
|
28d38620f0 | ||
|
|
1ce9b3ca9c | ||
|
|
213365c2d2 | ||
|
|
7f02bd3b7a | ||
|
|
ceb33818cd | ||
|
|
18fc707fdf | ||
|
|
c3027fa9ac | ||
|
|
4249867e5b | ||
|
|
c804a5f827 | ||
|
|
be77ee33bc | ||
|
|
5928ed5d45 | ||
|
|
075d30dbce | ||
|
|
6a6a2ad8a4 | ||
|
|
279fe144e1 | ||
|
|
cc80bd41c4 | ||
|
|
06183e6cdc | ||
|
|
6249cc3373 | ||
|
|
80f34c6aeb | ||
|
|
a2f526dadc | ||
|
|
429d2f85cb | ||
|
|
2ca018b2eb | ||
|
|
3e6e08ce00 | ||
|
|
3e491f8698 | ||
|
|
ccffa69766 | ||
|
|
10190be5d7 | ||
|
|
65a4e30825 | ||
|
|
e63960caae | ||
|
|
e2ca600fd8 | ||
|
|
4860df1689 | ||
|
|
ced93bcabd | ||
|
|
0e21de9a25 | ||
|
|
3104fc8d33 | ||
|
|
2409df9285 | ||
|
|
2e37be973f | ||
|
|
6115348dd9 | ||
|
|
416d098688 | ||
|
|
6bbe66d2e6 | ||
|
|
3782e34e67 | ||
|
|
84790aafd8 | ||
|
|
fea2d5f2fe | ||
|
|
9f1c9686e0 | ||
|
|
e0a6f27d1b | ||
|
|
9130ee7513 | ||
|
|
65c8e9242c | ||
|
|
1d654f6156 | ||
|
|
4af24e11a4 | ||
|
|
583f5868c9 | ||
|
|
d94b186080 | ||
|
|
5b8cfbe15c | ||
|
|
0dbc51f4d2 | ||
|
|
754ed9043d | ||
|
|
ba17f4a06a | ||
|
|
b9149f45bf | ||
|
|
b6c4b325a4 | ||
|
|
965de6ef50 | ||
|
|
303490168f | ||
|
|
c7c2399be9 | ||
|
|
120a520a22 | ||
|
|
7c03bd1e7a | ||
|
|
049d28868e | ||
|
|
8934f13615 | ||
|
|
dcf9dfb129 | ||
|
|
7c9604e32b | ||
|
|
b302ae329c | ||
|
|
ff6b6f2ce1 | ||
|
|
d49f141fb3 | ||
|
|
590fc58de7 | ||
|
|
c03561eea8 | ||
|
|
4179f25286 | ||
|
|
e54e8fa920 | ||
|
|
2f1c05d997 | ||
|
|
baa4618e57 | ||
|
|
dcc1e3562f | ||
|
|
f6fa353dd8 | ||
|
|
d4fa619ed1 | ||
|
|
8aa9985ad0 | ||
|
|
2c85b964e3 | ||
|
|
9159c819c3 | ||
|
|
484ba4a8c5 | ||
|
|
97b7b173b9 | ||
|
|
29f69211c9 | ||
|
|
553ce165c1 | ||
|
|
310ddec823 | ||
|
|
6926ba558f | ||
|
|
97d1d6f5d2 | ||
|
|
5f7abd5347 | ||
|
|
946bbee39a | ||
|
|
bdc0e8f825 | ||
|
|
1b08ab92d1 | ||
|
|
feda3db1dd | ||
|
|
ce97a71adf | ||
|
|
d00fb40967 | ||
|
|
0f249c85ea | ||
|
|
a37b42b57c | ||
|
|
dd8c59892c | ||
|
|
a97cf23355 | ||
|
|
030cc8d5cc | ||
|
|
c22f2617ad | ||
|
|
c860945be2 | ||
|
|
51d0c9238b | ||
|
|
22df1249b5 | ||
|
|
bdaa87ff21 | ||
|
|
db0ccaac9b | ||
|
|
4089a20cf4 | ||
|
|
75ac50a9a0 | ||
|
|
58e0c68132 | ||
|
|
cd6aeaf979 | ||
|
|
708cd34586 | ||
|
|
4dcc0f316c | ||
|
|
dae585c6e4 | ||
|
|
b1d994e3b9 | ||
|
|
dde8f74cea | ||
|
|
9e3d18e606 | ||
|
|
3e9575e275 | ||
|
|
07fee44559 | ||
|
|
b6bff0cbb1 | ||
|
|
ead7eb619e | ||
|
|
29de2432ea | ||
|
|
ffcba1236c | ||
|
|
0f088d28c5 | ||
|
|
16917275ee | ||
|
|
09ab2bfa1d | ||
|
|
b9f0695924 | ||
|
|
7bade49d4c | ||
|
|
3a123bc479 | ||
|
|
5bc344ab73 | ||
|
|
4bd287e107 | ||
|
|
6a56b7b391 | ||
|
|
7dac26ce69 | ||
|
|
793fd983ef | ||
|
|
2424480e2c | ||
|
|
f5a8e90d10 | ||
|
|
2e7df5182c | ||
|
|
ea2486d631 | ||
|
|
2e72882216 | ||
|
|
d1e1a8e78c | ||
|
|
ad3b091d53 | ||
|
|
26229d78f2 | ||
|
|
e0c24ccfc3 | ||
|
|
108635582f | ||
|
|
0c0077ed6f | ||
|
|
9a604acc23 | ||
|
|
cd9f7f29d1 | ||
|
|
a7068510a5 | ||
|
|
73c6d9f135 | ||
|
|
3043c26419 | ||
|
|
e66e0289ab | ||
|
|
6166380d76 | ||
|
|
e4752c8c1a | ||
|
|
99c27fa0dd | ||
|
|
d5a57a4b5e | ||
|
|
b14c251862 | ||
|
|
bcd6ca3685 | ||
|
|
46f59dd933 | ||
|
|
e1fa989ec9 | ||
|
|
7d0b8c726c | ||
|
|
5b27652ac6 | ||
|
|
394941b6b0 | ||
|
|
0f134b4bf8 | ||
|
|
0badda9f15 | ||
|
|
e3f68b22d8 | ||
|
|
8ca7b0646e | ||
|
|
f7542664e3 | ||
|
|
17ffb0ac84 | ||
|
|
b2aa877bf0 | ||
|
|
bb241c10e2 | ||
|
|
3852d05990 | ||
|
|
63876e7dbd | ||
|
|
bb06fe8dd9 | ||
|
|
7cc90f2bc5 | ||
|
|
01ce312c2d | ||
|
|
f4b63d9eea | ||
|
|
12d575a6b1 | ||
|
|
01e98bf0dd | ||
|
|
f1dd299227 | ||
|
|
94053b4225 | ||
|
|
77ff537697 | ||
|
|
362f1735e6 | ||
|
|
7813f2a25e | ||
|
|
3781a2cc4b | ||
|
|
d47df21a33 | ||
|
|
0ac672fea6 | ||
|
|
c19fa83a8a | ||
|
|
844a9ab85e | ||
|
|
a45490243b | ||
|
|
b06f627139 | ||
|
|
8742649aa7 | ||
|
|
0e71e368a8 | ||
|
|
066873ebd2 | ||
|
|
945033f1cc | ||
|
|
df86cb9a5c | ||
|
|
0afed3eded | ||
|
|
39ff542142 | ||
|
|
5d8efc107d | ||
|
|
1a226f0e28 | ||
|
|
7c00201222 | ||
|
|
2db99441c8 | ||
|
|
48a892bee5 | ||
|
|
fb005a3da8 | ||
|
|
d639f61ec1 | ||
|
|
a3b1a9f01a | ||
|
|
507cef8bce | ||
|
|
166eba3e28 | ||
|
|
e9011122fb | ||
|
|
fc3a8e409d | ||
|
|
8eeff01939 | ||
|
|
64450ae3f8 |
+6
-3
@@ -5,10 +5,7 @@ docker/docker
|
|||||||
a.out
|
a.out
|
||||||
*.orig
|
*.orig
|
||||||
build_src
|
build_src
|
||||||
command-line-arguments.test
|
|
||||||
.flymake*
|
.flymake*
|
||||||
docker.test
|
|
||||||
auth/auth.test
|
|
||||||
.idea
|
.idea
|
||||||
.DS_Store
|
.DS_Store
|
||||||
docs/_build
|
docs/_build
|
||||||
@@ -16,3 +13,9 @@ docs/_static
|
|||||||
docs/_templates
|
docs/_templates
|
||||||
.gopath/
|
.gopath/
|
||||||
.dotcloud
|
.dotcloud
|
||||||
|
*.test
|
||||||
|
bundles/
|
||||||
|
.hg/
|
||||||
|
.git/
|
||||||
|
vendor/pkg/
|
||||||
|
pyenv
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# Generate AUTHORS: git log --all --format='%aN <%aE>' | sort -uf | grep -v vagrant-ubuntu-12
|
# Generate AUTHORS: git log --format='%aN <%aE>' | sort -uf | grep -v vagrant-ubuntu-12
|
||||||
<charles.hooper@dotcloud.com> <chooper@plumata.com>
|
<charles.hooper@dotcloud.com> <chooper@plumata.com>
|
||||||
<daniel.mizyrycki@dotcloud.com> <daniel@dotcloud.com>
|
<daniel.mizyrycki@dotcloud.com> <daniel@dotcloud.com>
|
||||||
<daniel.mizyrycki@dotcloud.com> <mzdaniel@glidelink.net>
|
<daniel.mizyrycki@dotcloud.com> <mzdaniel@glidelink.net>
|
||||||
@@ -25,3 +25,16 @@ Walter Stanish <walter@pratyeka.org>
|
|||||||
Roberto Hashioka <roberto_hashioka@hotmail.com>
|
Roberto Hashioka <roberto_hashioka@hotmail.com>
|
||||||
Konstantin Pelykh <kpelykh@zettaset.com>
|
Konstantin Pelykh <kpelykh@zettaset.com>
|
||||||
David Sissitka <me@dsissitka.com>
|
David Sissitka <me@dsissitka.com>
|
||||||
|
Nolan Darilek <nolan@thewordnerd.info>
|
||||||
|
<mastahyeti@gmail.com> <mastahyeti@users.noreply.github.com>
|
||||||
|
Benoit Chesneau <bchesneau@gmail.com>
|
||||||
|
Jordan Arentsen <blissdev@gmail.com>
|
||||||
|
Daniel Garcia <daniel@danielgarcia.info>
|
||||||
|
Miguel Angel Fernández <elmendalerenda@gmail.com>
|
||||||
|
Bhiraj Butala <abhiraj.butala@gmail.com>
|
||||||
|
Faiz Khan <faizkhan00@gmail.com>
|
||||||
|
Victor Lyuboslavsky <victor@victoreda.com>
|
||||||
|
Jean-Baptiste Barth <jeanbaptiste.barth@gmail.com>
|
||||||
|
Matthew Mueller <mattmuelle@gmail.com>
|
||||||
|
<mosoni@ebay.com> <mohitsoni1989@gmail.com>
|
||||||
|
Shih-Yuan Lee <fourdollars@gmail.com>
|
||||||
|
|||||||
@@ -5,87 +5,151 @@
|
|||||||
#
|
#
|
||||||
Al Tobey <al@ooyala.com>
|
Al Tobey <al@ooyala.com>
|
||||||
Alex Gaynor <alex.gaynor@gmail.com>
|
Alex Gaynor <alex.gaynor@gmail.com>
|
||||||
|
Alexander Larsson <alexl@redhat.com>
|
||||||
Alexey Shamrin <shamrin@gmail.com>
|
Alexey Shamrin <shamrin@gmail.com>
|
||||||
Andrea Luzzardi <aluzzardi@gmail.com>
|
Andrea Luzzardi <aluzzardi@gmail.com>
|
||||||
|
Andreas Savvides <andreas@editd.com>
|
||||||
Andreas Tiefenthaler <at@an-ti.eu>
|
Andreas Tiefenthaler <at@an-ti.eu>
|
||||||
|
Andrew Macgregor <andrew.macgregor@agworld.com.au>
|
||||||
Andrew Munsell <andrew@wizardapps.net>
|
Andrew Munsell <andrew@wizardapps.net>
|
||||||
Andrews Medina <andrewsmedina@gmail.com>
|
Andrews Medina <andrewsmedina@gmail.com>
|
||||||
Andy Rothfusz <github@metaliveblog.com>
|
Andy Rothfusz <github@metaliveblog.com>
|
||||||
Andy Smith <github@anarkystic.com>
|
Andy Smith <github@anarkystic.com>
|
||||||
Anthony Bishopric <git@anthonybishopric.com>
|
Anthony Bishopric <git@anthonybishopric.com>
|
||||||
Antony Messerli <amesserl@rackspace.com>
|
Antony Messerli <amesserl@rackspace.com>
|
||||||
|
Asbjørn Enge <asbjorn@hanafjedle.net>
|
||||||
Barry Allard <barry.allard@gmail.com>
|
Barry Allard <barry.allard@gmail.com>
|
||||||
|
Ben Toews <mastahyeti@gmail.com>
|
||||||
|
Benoit Chesneau <bchesneau@gmail.com>
|
||||||
|
Bhiraj Butala <abhiraj.butala@gmail.com>
|
||||||
|
Bouke Haarsma <bouke@webatoom.nl>
|
||||||
Brandon Liu <bdon@bdon.org>
|
Brandon Liu <bdon@bdon.org>
|
||||||
|
Brandon Philips <brandon@ifup.co>
|
||||||
Brian McCallister <brianm@skife.org>
|
Brian McCallister <brianm@skife.org>
|
||||||
|
Brian Olsen <brian@maven-group.org>
|
||||||
|
Brian Shumate <brian@couchbase.com>
|
||||||
|
Briehan Lombaard <briehan.lombaard@gmail.com>
|
||||||
Bruno Bigras <bigras.bruno@gmail.com>
|
Bruno Bigras <bigras.bruno@gmail.com>
|
||||||
Caleb Spare <cespare@gmail.com>
|
Caleb Spare <cespare@gmail.com>
|
||||||
Calen Pennington <cale@edx.org>
|
Calen Pennington <cale@edx.org>
|
||||||
Charles Hooper <charles.hooper@dotcloud.com>
|
Charles Hooper <charles.hooper@dotcloud.com>
|
||||||
Christopher Currie <codemonkey+github@gmail.com>
|
Christopher Currie <codemonkey+github@gmail.com>
|
||||||
|
Colin Dunklau <colin.dunklau@gmail.com>
|
||||||
|
Colin Rice <colin@daedrum.net>
|
||||||
|
Dan Buch <d.buch@modcloth.com>
|
||||||
|
Daniel Garcia <daniel@danielgarcia.info>
|
||||||
Daniel Gasienica <daniel@gasienica.ch>
|
Daniel Gasienica <daniel@gasienica.ch>
|
||||||
Daniel Mizyrycki <daniel.mizyrycki@dotcloud.com>
|
Daniel Mizyrycki <daniel.mizyrycki@dotcloud.com>
|
||||||
|
Daniel Nordberg <dnordberg@gmail.com>
|
||||||
Daniel Robinson <gottagetmac@gmail.com>
|
Daniel Robinson <gottagetmac@gmail.com>
|
||||||
Daniel Von Fange <daniel@leancoder.com>
|
Daniel Von Fange <daniel@leancoder.com>
|
||||||
Daniel YC Lin <dlin.tw@gmail.com>
|
Daniel YC Lin <dlin.tw@gmail.com>
|
||||||
|
Darren Coxall <darren@darrencoxall.com>
|
||||||
David Calavera <david.calavera@gmail.com>
|
David Calavera <david.calavera@gmail.com>
|
||||||
David Sissitka <me@dsissitka.com>
|
David Sissitka <me@dsissitka.com>
|
||||||
|
Deni Bertovic <deni@kset.org>
|
||||||
Dominik Honnef <dominik@honnef.co>
|
Dominik Honnef <dominik@honnef.co>
|
||||||
Don Spaulding <donspauldingii@gmail.com>
|
Don Spaulding <donspauldingii@gmail.com>
|
||||||
Dr Nic Williams <drnicwilliams@gmail.com>
|
Dr Nic Williams <drnicwilliams@gmail.com>
|
||||||
|
Dražen Lučanin <kermit666@gmail.com>
|
||||||
Elias Probst <mail@eliasprobst.eu>
|
Elias Probst <mail@eliasprobst.eu>
|
||||||
|
Emily Rose <emily@contactvibe.com>
|
||||||
Eric Hanchrow <ehanchrow@ine.com>
|
Eric Hanchrow <ehanchrow@ine.com>
|
||||||
Eric Myhre <hash@exultant.us>
|
Eric Myhre <hash@exultant.us>
|
||||||
Erno Hopearuoho <erno.hopearuoho@gmail.com>
|
Erno Hopearuoho <erno.hopearuoho@gmail.com>
|
||||||
|
Evan Phoenix <evan@fallingsnow.net>
|
||||||
Evan Wies <evan@neomantra.net>
|
Evan Wies <evan@neomantra.net>
|
||||||
ezbercih <cem.ezberci@gmail.com>
|
ezbercih <cem.ezberci@gmail.com>
|
||||||
Fabrizio Regini <freegenie@gmail.com>
|
Fabrizio Regini <freegenie@gmail.com>
|
||||||
|
Faiz Khan <faizkhan00@gmail.com>
|
||||||
|
Fareed Dudhia <fareeddudhia@googlemail.com>
|
||||||
Flavio Castelli <fcastelli@suse.com>
|
Flavio Castelli <fcastelli@suse.com>
|
||||||
Francisco Souza <f@souza.cc>
|
Francisco Souza <f@souza.cc>
|
||||||
Frederick F. Kautz IV <fkautz@alumni.cmu.edu>
|
Frederick F. Kautz IV <fkautz@alumni.cmu.edu>
|
||||||
Gabriel Monroy <gabriel@opdemand.com>
|
Gabriel Monroy <gabriel@opdemand.com>
|
||||||
Gareth Rushgrove <gareth@morethanseven.net>
|
Gareth Rushgrove <gareth@morethanseven.net>
|
||||||
|
Greg Thornton <xdissent@me.com>
|
||||||
Guillaume J. Charmes <guillaume.charmes@dotcloud.com>
|
Guillaume J. Charmes <guillaume.charmes@dotcloud.com>
|
||||||
|
Gurjeet Singh <gurjeet@singh.im>
|
||||||
|
Guruprasad <lgp171188@gmail.com>
|
||||||
Harley Laue <losinggeneration@gmail.com>
|
Harley Laue <losinggeneration@gmail.com>
|
||||||
|
Hector Castro <hectcastro@gmail.com>
|
||||||
Hunter Blanks <hunter@twilio.com>
|
Hunter Blanks <hunter@twilio.com>
|
||||||
|
Isao Jonas <isao.jonas@gmail.com>
|
||||||
|
James Carr <james.r.carr@gmail.com>
|
||||||
|
James Turnbull <james@lovedthanlost.net>
|
||||||
|
Jason McVetta <jason.mcvetta@gmail.com>
|
||||||
|
Jean-Baptiste Barth <jeanbaptiste.barth@gmail.com>
|
||||||
Jeff Lindsay <progrium@gmail.com>
|
Jeff Lindsay <progrium@gmail.com>
|
||||||
Jeremy Grosser <jeremy@synack.me>
|
Jeremy Grosser <jeremy@synack.me>
|
||||||
|
Jim Alateras <jima@comware.com.au>
|
||||||
|
Jimmy Cuadra <jimmy@jimmycuadra.com>
|
||||||
|
Joe Van Dyk <joe@tanga.com>
|
||||||
Joffrey F <joffrey@dotcloud.com>
|
Joffrey F <joffrey@dotcloud.com>
|
||||||
Johan Euphrosine <proppy@google.com>
|
Johan Euphrosine <proppy@google.com>
|
||||||
John Costa <john.costa@gmail.com>
|
John Costa <john.costa@gmail.com>
|
||||||
Jon Wedaman <jweede@gmail.com>
|
Jon Wedaman <jweede@gmail.com>
|
||||||
Jonas Pfenniger <jonas@pfenniger.name>
|
Jonas Pfenniger <jonas@pfenniger.name>
|
||||||
|
Jonathan Mueller <j.mueller@apoveda.ch>
|
||||||
Jonathan Rudenberg <jonathan@titanous.com>
|
Jonathan Rudenberg <jonathan@titanous.com>
|
||||||
|
Joost Cassee <joost@cassee.net>
|
||||||
|
Jordan Arentsen <blissdev@gmail.com>
|
||||||
Joseph Anthony Pasquale Holsten <joseph@josephholsten.com>
|
Joseph Anthony Pasquale Holsten <joseph@josephholsten.com>
|
||||||
|
Josh Poimboeuf <jpoimboe@redhat.com>
|
||||||
Julien Barbier <write0@gmail.com>
|
Julien Barbier <write0@gmail.com>
|
||||||
Jérôme Petazzoni <jerome.petazzoni@dotcloud.com>
|
Jérôme Petazzoni <jerome.petazzoni@dotcloud.com>
|
||||||
Karan Lyons <karan@karanlyons.com>
|
Karan Lyons <karan@karanlyons.com>
|
||||||
|
Karl Grzeszczak <karl@karlgrz.com>
|
||||||
|
Kawsar Saiyeed <kawsar.saiyeed@projiris.com>
|
||||||
Keli Hu <dev@keli.hu>
|
Keli Hu <dev@keli.hu>
|
||||||
Ken Cochrane <kencochrane@gmail.com>
|
Ken Cochrane <kencochrane@gmail.com>
|
||||||
|
Kevin Clark <kevin.clark@gmail.com>
|
||||||
Kevin J. Lynagh <kevin@keminglabs.com>
|
Kevin J. Lynagh <kevin@keminglabs.com>
|
||||||
kim0 <email.ahmedkamal@googlemail.com>
|
kim0 <email.ahmedkamal@googlemail.com>
|
||||||
Kimbro Staken <kstaken@kstaken.com>
|
Kimbro Staken <kstaken@kstaken.com>
|
||||||
Kiran Gangadharan <kiran.daredevil@gmail.com>
|
Kiran Gangadharan <kiran.daredevil@gmail.com>
|
||||||
Konstantin Pelykh <kpelykh@zettaset.com>
|
Konstantin Pelykh <kpelykh@zettaset.com>
|
||||||
|
Kyle Conroy <kyle.j.conroy@gmail.com>
|
||||||
|
Laurie Voss <github@seldo.com>
|
||||||
Louis Opter <kalessin@kalessin.fr>
|
Louis Opter <kalessin@kalessin.fr>
|
||||||
|
Manuel Meurer <manuel@krautcomputing.com>
|
||||||
Marco Hennings <marco.hennings@freiheit.com>
|
Marco Hennings <marco.hennings@freiheit.com>
|
||||||
Marcus Farkas <toothlessgear@finitebox.com>
|
Marcus Farkas <toothlessgear@finitebox.com>
|
||||||
|
Marcus Ramberg <marcus@nordaaker.com>
|
||||||
Mark McGranaghan <mmcgrana@gmail.com>
|
Mark McGranaghan <mmcgrana@gmail.com>
|
||||||
|
Marko Mikulicic <mmikulicic@gmail.com>
|
||||||
|
Markus Fix <lispmeister@gmail.com>
|
||||||
|
Martin Redmond <martin@tinychat.com>
|
||||||
|
Matt Apperson <me@mattapperson.com>
|
||||||
|
Mathieu Le Marec - Pasquet <kiorky@cryptelium.net>
|
||||||
|
Matt Bachmann <bachmann.matt@gmail.com>
|
||||||
|
Matthew Mueller <mattmuelle@gmail.com>
|
||||||
Maxim Treskin <zerthurd@gmail.com>
|
Maxim Treskin <zerthurd@gmail.com>
|
||||||
meejah <meejah@meejah.ca>
|
meejah <meejah@meejah.ca>
|
||||||
Michael Crosby <crosby.michael@gmail.com>
|
Michael Crosby <crosby.michael@gmail.com>
|
||||||
|
Michael Gorsuch <gorsuch@github.com>
|
||||||
|
Miguel Angel Fernández <elmendalerenda@gmail.com>
|
||||||
Mike Gaffney <mike@uberu.com>
|
Mike Gaffney <mike@uberu.com>
|
||||||
Mikhail Sobolev <mss@mawhrin.net>
|
Mikhail Sobolev <mss@mawhrin.net>
|
||||||
|
Mohit Soni <mosoni@ebay.com>
|
||||||
|
Morten Siebuhr <sbhr@sbhr.dk>
|
||||||
Nan Monnand Deng <monnand@gmail.com>
|
Nan Monnand Deng <monnand@gmail.com>
|
||||||
Nate Jones <nate@endot.org>
|
Nate Jones <nate@endot.org>
|
||||||
Nelson Chen <crazysim@gmail.com>
|
Nelson Chen <crazysim@gmail.com>
|
||||||
Niall O'Higgins <niallo@unworkable.org>
|
Niall O'Higgins <niallo@unworkable.org>
|
||||||
|
Nick Payne <nick@kurai.co.uk>
|
||||||
Nick Stenning <nick.stenning@digital.cabinet-office.gov.uk>
|
Nick Stenning <nick.stenning@digital.cabinet-office.gov.uk>
|
||||||
Nick Stinemates <nick@stinemates.org>
|
Nick Stinemates <nick@stinemates.org>
|
||||||
|
Nolan Darilek <nolan@thewordnerd.info>
|
||||||
odk- <github@odkurzacz.org>
|
odk- <github@odkurzacz.org>
|
||||||
|
Pascal Borreli <pascal@borreli.com>
|
||||||
Paul Bowsher <pbowsher@globalpersonals.co.uk>
|
Paul Bowsher <pbowsher@globalpersonals.co.uk>
|
||||||
Paul Hammond <paul@paulhammond.org>
|
Paul Hammond <paul@paulhammond.org>
|
||||||
|
Paul Nasrat <pnasrat@gmail.com>
|
||||||
Phil Spitler <pspitler@gmail.com>
|
Phil Spitler <pspitler@gmail.com>
|
||||||
Piotr Bogdan <ppbogdan@gmail.com>
|
Piotr Bogdan <ppbogdan@gmail.com>
|
||||||
|
pysqz <randomq@126.com>
|
||||||
|
Ramon van Alteren <ramon@vanalteren.nl>
|
||||||
Renato Riccieri Santos Zannon <renato.riccieri@gmail.com>
|
Renato Riccieri Santos Zannon <renato.riccieri@gmail.com>
|
||||||
Rhys Hiltner <rhys@twitch.tv>
|
Rhys Hiltner <rhys@twitch.tv>
|
||||||
Robert Obryk <robryk@gmail.com>
|
Robert Obryk <robryk@gmail.com>
|
||||||
@@ -93,21 +157,41 @@ Roberto Hashioka <roberto_hashioka@hotmail.com>
|
|||||||
Ryan Fowler <rwfowler@gmail.com>
|
Ryan Fowler <rwfowler@gmail.com>
|
||||||
Sam Alba <sam.alba@gmail.com>
|
Sam Alba <sam.alba@gmail.com>
|
||||||
Sam J Sharpe <sam.sharpe@digital.cabinet-office.gov.uk>
|
Sam J Sharpe <sam.sharpe@digital.cabinet-office.gov.uk>
|
||||||
|
Scott Bessler <scottbessler@gmail.com>
|
||||||
|
Sean P. Kane <skane@newrelic.com>
|
||||||
Shawn Siefkas <shawn.siefkas@meredith.com>
|
Shawn Siefkas <shawn.siefkas@meredith.com>
|
||||||
|
Shih-Yuan Lee <fourdollars@gmail.com>
|
||||||
Silas Sewell <silas@sewell.org>
|
Silas Sewell <silas@sewell.org>
|
||||||
Solomon Hykes <solomon@dotcloud.com>
|
Solomon Hykes <solomon@dotcloud.com>
|
||||||
|
Song Gao <song@gao.io>
|
||||||
|
Sridatta Thatipamala <sthatipamala@gmail.com>
|
||||||
Sridhar Ratnakumar <sridharr@activestate.com>
|
Sridhar Ratnakumar <sridharr@activestate.com>
|
||||||
|
Steeve Morin <steeve.morin@gmail.com>
|
||||||
Stefan Praszalowicz <stefan@greplin.com>
|
Stefan Praszalowicz <stefan@greplin.com>
|
||||||
|
Sven Dowideit <SvenDowideit@home.org.au>
|
||||||
Thatcher Peskens <thatcher@dotcloud.com>
|
Thatcher Peskens <thatcher@dotcloud.com>
|
||||||
|
Thermionix <bond711@gmail.com>
|
||||||
|
Thijs Terlouw <thijsterlouw@gmail.com>
|
||||||
Thomas Bikeev <thomas.bikeev@mac.com>
|
Thomas Bikeev <thomas.bikeev@mac.com>
|
||||||
|
Thomas Frössman <thomasf@jossystem.se>
|
||||||
Thomas Hansen <thomas.hansen@gmail.com>
|
Thomas Hansen <thomas.hansen@gmail.com>
|
||||||
Tianon Gravi <admwiggin@gmail.com>
|
Tianon Gravi <admwiggin@gmail.com>
|
||||||
Tim Terhorst <mynamewastaken+git@gmail.com>
|
Tim Terhorst <mynamewastaken+git@gmail.com>
|
||||||
Tobias Bieniek <Tobias.Bieniek@gmx.de>
|
Tobias Bieniek <Tobias.Bieniek@gmx.de>
|
||||||
|
Tobias Schmidt <ts@soundcloud.com>
|
||||||
Tobias Schwab <tobias.schwab@dynport.de>
|
Tobias Schwab <tobias.schwab@dynport.de>
|
||||||
Tom Hulihan <hulihan.tom159@gmail.com>
|
Tom Hulihan <hulihan.tom159@gmail.com>
|
||||||
|
Tommaso Visconti <tommaso.visconti@gmail.com>
|
||||||
|
Tyler Brock <tyler.brock@gmail.com>
|
||||||
unclejack <unclejacksons@gmail.com>
|
unclejack <unclejacksons@gmail.com>
|
||||||
|
Victor Coisne <victor.coisne@dotcloud.com>
|
||||||
|
Victor Lyuboslavsky <victor@victoreda.com>
|
||||||
Victor Vieux <victor.vieux@dotcloud.com>
|
Victor Vieux <victor.vieux@dotcloud.com>
|
||||||
|
Vincent Bernat <bernat@luffy.cx>
|
||||||
Vivek Agarwal <me@vivek.im>
|
Vivek Agarwal <me@vivek.im>
|
||||||
|
Vladimir Kirillov <proger@wilab.org.ua>
|
||||||
Walter Stanish <walter@pratyeka.org>
|
Walter Stanish <walter@pratyeka.org>
|
||||||
|
Wes Morgan <cap10morgan@gmail.com>
|
||||||
Will Dietz <w@wdtz.org>
|
Will Dietz <w@wdtz.org>
|
||||||
|
Yang Bai <hamo.by@gmail.com>
|
||||||
|
Zaiste! <oh@zaiste.net>
|
||||||
|
|||||||
+762
-209
File diff suppressed because it is too large
Load Diff
+22
-61
@@ -1,7 +1,14 @@
|
|||||||
# Contributing to Docker
|
# Contributing to Docker
|
||||||
|
|
||||||
Want to hack on Docker? Awesome! Here are instructions to get you started. They are probably not perfect, please let us know if anything feels
|
Want to hack on Docker? Awesome! Here are instructions to get you
|
||||||
wrong or incomplete.
|
started. They are probably not perfect, please let us know if anything
|
||||||
|
feels wrong or incomplete.
|
||||||
|
|
||||||
|
## Build Environment
|
||||||
|
|
||||||
|
For instructions on setting up your development environment, please
|
||||||
|
see our dedicated [dev environment setup
|
||||||
|
docs](http://docs.docker.io/en/latest/contributing/devenvironment/).
|
||||||
|
|
||||||
## Contribution guidelines
|
## Contribution guidelines
|
||||||
|
|
||||||
@@ -23,7 +30,7 @@ that feature *on top of* docker.
|
|||||||
### Discuss your design on the mailing list
|
### Discuss your design on the mailing list
|
||||||
|
|
||||||
We recommend discussing your plans [on the mailing
|
We recommend discussing your plans [on the mailing
|
||||||
list](https://groups.google.com/forum/?fromgroups#!forum/docker-club)
|
list](https://groups.google.com/forum/?fromgroups#!forum/docker-dev)
|
||||||
before starting to code - especially for more ambitious contributions.
|
before starting to code - especially for more ambitious contributions.
|
||||||
This gives other contributors a chance to point you in the right
|
This gives other contributors a chance to point you in the right
|
||||||
direction, give feedback on your design, and maybe point out if someone
|
direction, give feedback on your design, and maybe point out if someone
|
||||||
@@ -55,8 +62,10 @@ Submit unit tests for your changes. Go has a great test framework built in; use
|
|||||||
it! Take a look at existing tests for inspiration. Run the full test suite on
|
it! Take a look at existing tests for inspiration. Run the full test suite on
|
||||||
your branch before submitting a pull request.
|
your branch before submitting a pull request.
|
||||||
|
|
||||||
Make sure you include relevant updates or additions to documentation when
|
Update the documentation when creating or modifying features. Test
|
||||||
creating or modifying features.
|
your documentation changes for clarity, concision, and correctness, as
|
||||||
|
well as a clean docmuent build. See ``docs/README.md`` for more
|
||||||
|
information on building the docs and how docs get released.
|
||||||
|
|
||||||
Write clean code. Universally formatted code promotes ease of writing, reading,
|
Write clean code. Universally formatted code promotes ease of writing, reading,
|
||||||
and maintenance. Always run `go fmt` before committing your changes. Most
|
and maintenance. Always run `go fmt` before committing your changes. Most
|
||||||
@@ -89,53 +98,17 @@ name and email address match your git configuration. The AUTHORS file is
|
|||||||
regenerated occasionally from the git commit history, so a mismatch may result
|
regenerated occasionally from the git commit history, so a mismatch may result
|
||||||
in your changes being overwritten.
|
in your changes being overwritten.
|
||||||
|
|
||||||
|
### Approval
|
||||||
|
|
||||||
## Decision process
|
Docker maintainers use LGTM (looks good to me) in comments on the code review
|
||||||
|
to indicate acceptance.
|
||||||
|
|
||||||
### How are decisions made?
|
A change requires LGTMs from an absolute majority of the maintainers of each
|
||||||
|
component affected. For example, if a change affects docs/ and registry/, it
|
||||||
|
needs an absolute majority from the maintainers of docs/ AND, separately, an
|
||||||
|
absolute majority of the maintainers of registry
|
||||||
|
|
||||||
Short answer: with pull requests to the docker repository.
|
For more details see [MAINTAINERS.md](hack/MAINTAINERS.md)
|
||||||
|
|
||||||
Docker is an open-source project with an open design philosophy. This means that the repository is the source of truth for EVERY aspect of the project,
|
|
||||||
including its philosophy, design, roadmap and APIs. *If it's part of the project, it's in the repo. It's in the repo, it's part of the project.*
|
|
||||||
|
|
||||||
As a result, all decisions can be expressed as changes to the repository. An implementation change is a change to the source code. An API change is a change to
|
|
||||||
the API specification. A philosophy change is a change to the philosophy manifesto. And so on.
|
|
||||||
|
|
||||||
All decisions affecting docker, big and small, follow the same 3 steps:
|
|
||||||
|
|
||||||
* Step 1: Open a pull request. Anyone can do this.
|
|
||||||
|
|
||||||
* Step 2: Discuss the pull request. Anyone can do this.
|
|
||||||
|
|
||||||
* Step 3: Accept or refuse a pull request. The relevant maintainer does this (see below "Who decides what?")
|
|
||||||
|
|
||||||
|
|
||||||
### Who decides what?
|
|
||||||
|
|
||||||
So all decisions are pull requests, and the relevant maintainer makes the decision by accepting or refusing the pull request.
|
|
||||||
But how do we identify the relevant maintainer for a given pull request?
|
|
||||||
|
|
||||||
Docker follows the timeless, highly efficient and totally unfair system known as [Benevolent dictator for life](http://en.wikipedia.org/wiki/Benevolent_Dictator_for_Life),
|
|
||||||
with yours truly, Solomon Hykes, in the role of BDFL.
|
|
||||||
This means that all decisions are made by default by me. Since making every decision myself would be highly unscalable, in practice decisions are spread across multiple maintainers.
|
|
||||||
|
|
||||||
The relevant maintainer for a pull request is assigned in 3 steps:
|
|
||||||
|
|
||||||
* Step 1: Determine the subdirectory affected by the pull request. This might be src/registry, docs/source/api, or any other part of the repo.
|
|
||||||
|
|
||||||
* Step 2: Find the MAINTAINERS file which affects this directory. If the directory itself does not have a MAINTAINERS file, work your way up the the repo hierarchy until you find one.
|
|
||||||
|
|
||||||
* Step 3: The first maintainer listed is the primary maintainer. The pull request is assigned to him. He may assign it to other listed maintainers, at his discretion.
|
|
||||||
|
|
||||||
|
|
||||||
### I'm a maintainer, should I make pull requests too?
|
|
||||||
|
|
||||||
Primary maintainers are not required to create pull requests when changing their own subdirectory, but secondary maintainers are.
|
|
||||||
|
|
||||||
### Who assigns maintainers?
|
|
||||||
|
|
||||||
Solomon.
|
|
||||||
|
|
||||||
### How can I become a maintainer?
|
### How can I become a maintainer?
|
||||||
|
|
||||||
@@ -146,15 +119,3 @@ Solomon.
|
|||||||
Don't forget: being a maintainer is a time investment. Make sure you will have time to make yourself available.
|
Don't forget: being a maintainer is a time investment. Make sure you will have time to make yourself available.
|
||||||
You don't have to be a maintainer to make a difference on the project!
|
You don't have to be a maintainer to make a difference on the project!
|
||||||
|
|
||||||
### What are a maintainer's responsibility?
|
|
||||||
|
|
||||||
It is every maintainer's responsibility to:
|
|
||||||
|
|
||||||
* 1) Expose a clear roadmap for improving their component.
|
|
||||||
* 2) Deliver prompt feedback and decisions on pull requests.
|
|
||||||
* 3) Be available to anyone with questions, bug reports, criticism etc. on their component. This includes irc, github requests and the mailing list.
|
|
||||||
* 4) Make sure their component respects the philosophy, design and roadmap of the project.
|
|
||||||
|
|
||||||
### How is this process changed?
|
|
||||||
|
|
||||||
Just like everything else: by making a pull request :)
|
|
||||||
|
|||||||
+58
-22
@@ -1,30 +1,66 @@
|
|||||||
# This file describes the standard way to build Docker, using docker
|
# This file describes the standard way to build Docker, using docker
|
||||||
docker-version 0.4.2
|
#
|
||||||
|
# Usage:
|
||||||
|
#
|
||||||
|
# # Assemble the full dev environment. This is slow the first time.
|
||||||
|
# docker build -t docker .
|
||||||
|
#
|
||||||
|
# # Mount your source in an interactive container for quick testing:
|
||||||
|
# docker run -v `pwd`:/go/src/github.com/dotcloud/docker -privileged -i -t docker bash
|
||||||
|
#
|
||||||
|
# # Run the test suite:
|
||||||
|
# docker run -privileged docker hack/make.sh test
|
||||||
|
#
|
||||||
|
# # Publish a release:
|
||||||
|
# docker run -privileged \
|
||||||
|
# -e AWS_S3_BUCKET=baz \
|
||||||
|
# -e AWS_ACCESS_KEY=foo \
|
||||||
|
# -e AWS_SECRET_KEY=bar \
|
||||||
|
# -e GPG_PASSPHRASE=gloubiboulga \
|
||||||
|
# docker hack/release.sh
|
||||||
|
#
|
||||||
|
# Note: Apparmor used to mess with privileged mode, but this is no longer
|
||||||
|
# the case. Therefore, you don't have to disable it anymore.
|
||||||
|
#
|
||||||
|
|
||||||
|
docker-version 0.6.1
|
||||||
from ubuntu:12.04
|
from ubuntu:12.04
|
||||||
maintainer Solomon Hykes <solomon@dotcloud.com>
|
maintainer Solomon Hykes <solomon@dotcloud.com>
|
||||||
|
|
||||||
# Build dependencies
|
# Build dependencies
|
||||||
run apt-get install -y -q curl
|
|
||||||
run apt-get install -y -q git
|
|
||||||
# Install Go
|
|
||||||
run curl -s https://go.googlecode.com/files/go1.1.1.linux-amd64.tar.gz | tar -v -C /usr/local -xz
|
|
||||||
env PATH /usr/local/go/bin:/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/bin:/sbin
|
|
||||||
env GOPATH /go
|
|
||||||
env CGO_ENABLED 0
|
|
||||||
run cd /tmp && echo 'package main' > t.go && go test -a -i -v
|
|
||||||
# Download dependencies
|
|
||||||
run PKG=github.com/kr/pty REV=27435c699; git clone http://$PKG /go/src/$PKG && cd /go/src/$PKG && git checkout -f $REV
|
|
||||||
run PKG=github.com/gorilla/context/ REV=708054d61e5; git clone http://$PKG /go/src/$PKG && cd /go/src/$PKG && git checkout -f $REV
|
|
||||||
run PKG=github.com/gorilla/mux/ REV=9b36453141c; git clone http://$PKG /go/src/$PKG && cd /go/src/$PKG && git checkout -f $REV
|
|
||||||
# Run dependencies
|
|
||||||
run apt-get install -y iptables
|
|
||||||
# lxc requires updating ubuntu sources
|
|
||||||
run echo 'deb http://archive.ubuntu.com/ubuntu precise main universe' > /etc/apt/sources.list
|
run echo 'deb http://archive.ubuntu.com/ubuntu precise main universe' > /etc/apt/sources.list
|
||||||
run apt-get update
|
run apt-get update
|
||||||
run apt-get install -y lxc
|
run apt-get install -y -q curl
|
||||||
run apt-get install -y aufs-tools
|
run apt-get install -y -q git
|
||||||
|
run apt-get install -y -q mercurial
|
||||||
|
run apt-get install -y -q build-essential libsqlite3-dev
|
||||||
|
|
||||||
|
# Install Go
|
||||||
|
run curl -s https://go.googlecode.com/files/go1.2rc5.src.tar.gz | tar -v -C /usr/local -xz
|
||||||
|
env PATH /usr/local/go/bin:/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/bin:/sbin
|
||||||
|
env GOPATH /go:/go/src/github.com/dotcloud/docker/vendor
|
||||||
|
run cd /usr/local/go/src && ./make.bash && go install -ldflags '-w -linkmode external -extldflags "-static -Wl,--unresolved-symbols=ignore-in-shared-libs"' -tags netgo -a std
|
||||||
|
|
||||||
|
# Ubuntu stuff
|
||||||
|
run apt-get install -y -q ruby1.9.3 rubygems libffi-dev
|
||||||
|
run gem install --no-rdoc --no-ri fpm
|
||||||
|
run apt-get install -y -q reprepro dpkg-sig
|
||||||
|
|
||||||
|
run apt-get install -y -q python-pip
|
||||||
|
run pip install s3cmd==1.1.0-beta3
|
||||||
|
run pip install python-magic==0.4.6
|
||||||
|
run /bin/echo -e '[default]\naccess_key=$AWS_ACCESS_KEY\nsecret_key=$AWS_SECRET_KEY\n' > /.s3cfg
|
||||||
|
|
||||||
|
# Runtime dependencies
|
||||||
|
run apt-get install -y -q iptables
|
||||||
|
run apt-get install -y -q lxc
|
||||||
|
run apt-get install -y -q aufs-tools
|
||||||
|
|
||||||
|
volume /var/lib/docker
|
||||||
|
workdir /go/src/github.com/dotcloud/docker
|
||||||
|
|
||||||
|
# Wrap all commands in the "docker-in-docker" script to allow nested containers
|
||||||
|
entrypoint ["hack/dind"]
|
||||||
|
|
||||||
# Upload docker source
|
# Upload docker source
|
||||||
add . /go/src/github.com/dotcloud/docker
|
add . /go/src/github.com/dotcloud/docker
|
||||||
# Build the binary
|
|
||||||
run cd /go/src/github.com/dotcloud/docker/docker && go install -ldflags "-X main.GITCOMMIT '??' -d -w"
|
|
||||||
env PATH /usr/local/go/bin:/go/bin:/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/bin:/sbin
|
|
||||||
cmd ["docker"]
|
|
||||||
|
|||||||
@@ -15,22 +15,16 @@ to put them - so we put them here :)
|
|||||||
* Run linter on codebase
|
* Run linter on codebase
|
||||||
* Unify build commands and regular commands
|
* Unify build commands and regular commands
|
||||||
* Move source code into src/ subdir for clarity
|
* Move source code into src/ subdir for clarity
|
||||||
* Clean up the Makefile, it's a mess
|
|
||||||
* docker build: on non-existent local path for ADD, don't show full absolute path on the host
|
* docker build: on non-existent local path for ADD, don't show full absolute path on the host
|
||||||
* mount into /dockerinit rather than /sbin/init
|
|
||||||
* docker tag foo REPO:TAG
|
* docker tag foo REPO:TAG
|
||||||
* use size header for progress bar in pull
|
* use size header for progress bar in pull
|
||||||
* Clean up context upload in build!!!
|
* Clean up context upload in build!!!
|
||||||
* Parallel pull
|
* Parallel pull
|
||||||
* Ensure /proc/sys/net/ipv4/ip_forward is 1
|
|
||||||
* Force DNS to public!
|
|
||||||
* Always generate a resolv.conf per container, to avoid changing resolv.conf under thne container's feet
|
* Always generate a resolv.conf per container, to avoid changing resolv.conf under thne container's feet
|
||||||
* Save metadata with import/export
|
* Save metadata with import/export (#1974)
|
||||||
* Upgrade dockerd without stopping containers
|
* Upgrade dockerd without stopping containers
|
||||||
* bring back git revision info, looks like it was lost
|
* Simple command to remove all untagged images (`docker rmi $(docker images | awk '/^<none>/ { print $3 }')`)
|
||||||
* Simple command to remove all untagged images
|
|
||||||
* Simple command to clean up containers for disk space
|
* Simple command to clean up containers for disk space
|
||||||
* Caching after an ADD
|
* Caching after an ADD (#880)
|
||||||
* entry point config
|
|
||||||
* bring back git revision info, looks like it was lost
|
|
||||||
* Clean up the ProgressReader api, it's a PITA to use
|
* Clean up the ProgressReader api, it's a PITA to use
|
||||||
|
* Use netlink instead of iproute2/iptables (#925)
|
||||||
|
|||||||
+6
-5
@@ -1,5 +1,6 @@
|
|||||||
Solomon Hykes <solomon@dotcloud.com>
|
Solomon Hykes <solomon@dotcloud.com> (@shykes)
|
||||||
Guillaume Charmes <guillaume@dotcloud.com>
|
Guillaume Charmes <guillaume@dotcloud.com> (@creack)
|
||||||
Victor Vieux <victor@dotcloud.com>
|
Victor Vieux <victor@dotcloud.com> (@vieux)
|
||||||
api.go: Victor Vieux <victor@dotcloud.com>
|
Michael Crosby <michael@crosbymichael.com> (@crosbymichael)
|
||||||
Vagrantfile: Daniel Mizyrycki <daniel@dotcloud.com>
|
api.go: Victor Vieux <victor@dotcloud.com> (@vieux)
|
||||||
|
Vagrantfile: Daniel Mizyrycki <daniel@dotcloud.com> (@mzdaniel)
|
||||||
|
|||||||
@@ -1,95 +0,0 @@
|
|||||||
DOCKER_PACKAGE := github.com/dotcloud/docker
|
|
||||||
RELEASE_VERSION := $(shell git tag | grep -E "v[0-9\.]+$$" | sort -nr | head -n 1)
|
|
||||||
SRCRELEASE := docker-$(RELEASE_VERSION)
|
|
||||||
BINRELEASE := docker-$(RELEASE_VERSION).tgz
|
|
||||||
BUILD_SRC := build_src
|
|
||||||
BUILD_PATH := ${BUILD_SRC}/src/${DOCKER_PACKAGE}
|
|
||||||
|
|
||||||
GIT_ROOT := $(shell git rev-parse --show-toplevel)
|
|
||||||
BUILD_DIR := $(CURDIR)/.gopath
|
|
||||||
|
|
||||||
GOPATH ?= $(BUILD_DIR)
|
|
||||||
export GOPATH
|
|
||||||
|
|
||||||
GO_OPTIONS ?= -a -ldflags='-w -d'
|
|
||||||
ifeq ($(VERBOSE), 1)
|
|
||||||
GO_OPTIONS += -v
|
|
||||||
endif
|
|
||||||
|
|
||||||
GIT_COMMIT = $(shell git rev-parse --short HEAD)
|
|
||||||
GIT_STATUS = $(shell test -n "`git status --porcelain`" && echo "+CHANGES")
|
|
||||||
|
|
||||||
BUILD_OPTIONS = -a -ldflags "-X main.GITCOMMIT $(GIT_COMMIT)$(GIT_STATUS) -d -w"
|
|
||||||
|
|
||||||
SRC_DIR := $(GOPATH)/src
|
|
||||||
|
|
||||||
DOCKER_DIR := $(SRC_DIR)/$(DOCKER_PACKAGE)
|
|
||||||
DOCKER_MAIN := $(DOCKER_DIR)/docker
|
|
||||||
|
|
||||||
DOCKER_BIN_RELATIVE := bin/docker
|
|
||||||
DOCKER_BIN := $(CURDIR)/$(DOCKER_BIN_RELATIVE)
|
|
||||||
|
|
||||||
.PHONY: all clean test hack release srcrelease $(BINRELEASE) $(SRCRELEASE) $(DOCKER_BIN) $(DOCKER_DIR)
|
|
||||||
|
|
||||||
all: $(DOCKER_BIN)
|
|
||||||
|
|
||||||
$(DOCKER_BIN): $(DOCKER_DIR)
|
|
||||||
@mkdir -p $(dir $@)
|
|
||||||
@(cd $(DOCKER_MAIN); CGO_ENABLED=0 go build $(GO_OPTIONS) $(BUILD_OPTIONS) -o $@)
|
|
||||||
@echo $(DOCKER_BIN_RELATIVE) is created.
|
|
||||||
|
|
||||||
$(DOCKER_DIR):
|
|
||||||
@mkdir -p $(dir $@)
|
|
||||||
@if [ -h $@ ]; then rm -f $@; fi; ln -sf $(CURDIR)/ $@
|
|
||||||
@(cd $(DOCKER_MAIN); go get -d $(GO_OPTIONS))
|
|
||||||
|
|
||||||
whichrelease:
|
|
||||||
echo $(RELEASE_VERSION)
|
|
||||||
|
|
||||||
release: $(BINRELEASE)
|
|
||||||
s3cmd -P put $(BINRELEASE) s3://get.docker.io/builds/`uname -s`/`uname -m`/docker-$(RELEASE_VERSION).tgz
|
|
||||||
s3cmd -P put docker-latest.tgz s3://get.docker.io/builds/`uname -s`/`uname -m`/docker-latest.tgz
|
|
||||||
s3cmd -P put $(SRCRELEASE)/bin/docker s3://get.docker.io/builds/`uname -s`/`uname -m`/docker
|
|
||||||
|
|
||||||
srcrelease: $(SRCRELEASE)
|
|
||||||
deps: $(DOCKER_DIR)
|
|
||||||
|
|
||||||
# A clean checkout of $RELEASE_VERSION, with vendored dependencies
|
|
||||||
$(SRCRELEASE):
|
|
||||||
rm -fr $(SRCRELEASE)
|
|
||||||
git clone $(GIT_ROOT) $(SRCRELEASE)
|
|
||||||
cd $(SRCRELEASE); git checkout -q $(RELEASE_VERSION)
|
|
||||||
|
|
||||||
# A binary release ready to be uploaded to a mirror
|
|
||||||
$(BINRELEASE): $(SRCRELEASE)
|
|
||||||
rm -f $(BINRELEASE)
|
|
||||||
cd $(SRCRELEASE); make; cp -R bin docker-$(RELEASE_VERSION); tar -f ../$(BINRELEASE) -zv -c docker-$(RELEASE_VERSION)
|
|
||||||
cd $(SRCRELEASE); cp -R bin docker-latest; tar -f ../docker-latest.tgz -zv -c docker-latest
|
|
||||||
|
|
||||||
clean:
|
|
||||||
@rm -rf $(dir $(DOCKER_BIN))
|
|
||||||
ifeq ($(GOPATH), $(BUILD_DIR))
|
|
||||||
@rm -rf $(BUILD_DIR)
|
|
||||||
else ifneq ($(DOCKER_DIR), $(realpath $(DOCKER_DIR)))
|
|
||||||
@rm -f $(DOCKER_DIR)
|
|
||||||
endif
|
|
||||||
|
|
||||||
test:
|
|
||||||
# Copy docker source and dependencies for testing
|
|
||||||
rm -rf ${BUILD_SRC}; mkdir -p ${BUILD_PATH}
|
|
||||||
tar --exclude=${BUILD_SRC} -cz . | tar -xz -C ${BUILD_PATH}
|
|
||||||
GOPATH=${CURDIR}/${BUILD_SRC} go get -d
|
|
||||||
# Do the test
|
|
||||||
sudo -E GOPATH=${CURDIR}/${BUILD_SRC} CGO_ENABLED=0 go test ${GO_OPTIONS}
|
|
||||||
|
|
||||||
testall: all
|
|
||||||
@(cd $(DOCKER_DIR); CGO_ENABLED=0 sudo -E go test ./... $(GO_OPTIONS))
|
|
||||||
|
|
||||||
fmt:
|
|
||||||
@gofmt -s -l -w .
|
|
||||||
|
|
||||||
hack:
|
|
||||||
cd $(CURDIR)/hack && vagrant up
|
|
||||||
|
|
||||||
ssh-dev:
|
|
||||||
cd $(CURDIR)/hack && vagrant ssh
|
|
||||||
@@ -1,11 +1,19 @@
|
|||||||
Docker
|
Docker
|
||||||
Copyright 2012-2013 dotCloud, inc.
|
Copyright 2012-2013 Docker, Inc.
|
||||||
|
|
||||||
This product includes software developed at dotCloud, inc. (http://www.dotcloud.com).
|
This product includes software developed at Docker, Inc. (http://www.docker.com).
|
||||||
|
|
||||||
This product contains software (https://github.com/kr/pty) developed by Keith Rarick, licensed under the MIT License.
|
This product contains software (https://github.com/kr/pty) developed
|
||||||
|
by Keith Rarick, licensed under the MIT License.
|
||||||
|
|
||||||
Transfers of Docker shall be in accordance with applicable export controls of any country and all other applicable
|
The following is courtesy of our legal counsel:
|
||||||
legal requirements. Docker shall not be distributed or downloaded to or in Cuba, Iran, North Korea, Sudan or Syria
|
|
||||||
and shall not be distributed or downloaded to any person on the Denied Persons List administered by the U.S.
|
|
||||||
Department of Commerce.
|
Use and transfer of Docker may be subject to certain restrictions by the
|
||||||
|
United States and other governments.
|
||||||
|
It is your responsibility to ensure that your use and/or transfer does not
|
||||||
|
violate applicable laws.
|
||||||
|
|
||||||
|
For more information, please see http://www.bis.doc.gov
|
||||||
|
|
||||||
|
See also http://www.apache.org/dev/crypto.html and/or seek legal counsel.
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
Docker: the Linux container engine
|
Docker: the Linux container engine
|
||||||
==================================
|
==================================
|
||||||
|
|
||||||
Docker is an open-source engine which automates the deployment of
|
Docker is an open source project to pack, ship and run any application
|
||||||
applications as highly portable, self-sufficient containers.
|
as a lightweight container
|
||||||
|
|
||||||
Docker containers are both *hardware-agnostic* and
|
Docker containers are both *hardware-agnostic* and
|
||||||
*platform-agnostic*. This means that they can run anywhere, from your
|
*platform-agnostic*. This means that they can run anywhere, from your
|
||||||
@@ -18,7 +18,7 @@ Platform-as-a-Service. It benefits directly from the experience
|
|||||||
accumulated over several years of large-scale operation and support of
|
accumulated over several years of large-scale operation and support of
|
||||||
hundreds of thousands of applications and databases.
|
hundreds of thousands of applications and databases.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
## Better than VMs
|
## Better than VMs
|
||||||
|
|
||||||
@@ -140,144 +140,25 @@ Note that Docker doesn't care *how* dependencies are built - as long
|
|||||||
as they can be built by running a Unix command in a container.
|
as they can be built by running a Unix command in a container.
|
||||||
|
|
||||||
|
|
||||||
Install instructions
|
Getting started
|
||||||
==================
|
===============
|
||||||
|
|
||||||
Quick install on Ubuntu 12.04 and 12.10
|
Docker can be installed on your local machine as well as servers - both bare metal and virtualized.
|
||||||
---------------------------------------
|
It is available as a binary on most modern Linux systems, or as a VM on Windows, Mac and other systems.
|
||||||
|
|
||||||
```bash
|
We also offer an interactive tutorial for quickly learning the basics of using Docker.
|
||||||
curl get.docker.io | sudo sh -x
|
|
||||||
```
|
|
||||||
|
|
||||||
Binary installs
|
|
||||||
----------------
|
|
||||||
|
|
||||||
Docker supports the following binary installation methods. Note that
|
For up-to-date install instructions and online tutorials, see the [Getting Started page](http://www.docker.io/gettingstarted/).
|
||||||
some methods are community contributions and not yet officially
|
|
||||||
supported.
|
|
||||||
|
|
||||||
* [Ubuntu 12.04 and 12.10 (officially supported)](http://docs.docker.io/en/latest/installation/ubuntulinux/)
|
|
||||||
* [Arch Linux](http://docs.docker.io/en/latest/installation/archlinux/)
|
|
||||||
* [Mac OS X (with Vagrant)](http://docs.docker.io/en/latest/installation/vagrant/)
|
|
||||||
* [Windows (with Vagrant)](http://docs.docker.io/en/latest/installation/windows/)
|
|
||||||
* [Amazon EC2 (with Vagrant)](http://docs.docker.io/en/latest/installation/amazon/)
|
|
||||||
|
|
||||||
Installing from source
|
|
||||||
----------------------
|
|
||||||
|
|
||||||
1. Make sure you have a [Go language](http://golang.org/doc/install)
|
|
||||||
compiler >= 1.1 and [git](http://git-scm.com) installed.
|
|
||||||
2. Checkout the source code
|
|
||||||
|
|
||||||
```bash
|
|
||||||
git clone http://github.com/dotcloud/docker
|
|
||||||
```
|
|
||||||
|
|
||||||
3. Build the ``docker`` binary
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cd docker
|
|
||||||
make VERBOSE=1
|
|
||||||
sudo cp ./bin/docker /usr/local/bin/docker
|
|
||||||
```
|
|
||||||
|
|
||||||
Usage examples
|
Usage examples
|
||||||
==============
|
==============
|
||||||
|
|
||||||
First run the ``docker`` daemon
|
Docker can be used to run short-lived commands, long-running daemons (app servers, databases etc.),
|
||||||
-------------------------------
|
interactive shell sessions, etc.
|
||||||
|
|
||||||
All the examples assume your machine is running the ``docker``
|
You can find a [list of real-world examples](http://docs.docker.io/en/latest/examples/) in the documentation.
|
||||||
daemon. To run the ``docker`` daemon in the background, simply type:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# On a production system you want this running in an init script
|
|
||||||
sudo docker -d &
|
|
||||||
```
|
|
||||||
|
|
||||||
Now you can run ``docker`` in client mode: all commands will be
|
|
||||||
forwarded to the ``docker`` daemon, so the client can run from any
|
|
||||||
account.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Now you can run docker commands from any account.
|
|
||||||
docker help
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
Throwaway shell in a base Ubuntu image
|
|
||||||
--------------------------------------
|
|
||||||
|
|
||||||
```bash
|
|
||||||
docker pull ubuntu:12.10
|
|
||||||
|
|
||||||
# Run an interactive shell, allocate a tty, attach stdin and stdout
|
|
||||||
# To detach the tty without exiting the shell, use the escape sequence Ctrl-p + Ctrl-q
|
|
||||||
docker run -i -t ubuntu:12.10 /bin/bash
|
|
||||||
```
|
|
||||||
|
|
||||||
Starting a long-running worker process
|
|
||||||
--------------------------------------
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Start a very useful long-running process
|
|
||||||
JOB=$(docker run -d ubuntu /bin/sh -c "while true; do echo Hello world; sleep 1; done")
|
|
||||||
|
|
||||||
# Collect the output of the job so far
|
|
||||||
docker logs $JOB
|
|
||||||
|
|
||||||
# Kill the job
|
|
||||||
docker kill $JOB
|
|
||||||
```
|
|
||||||
|
|
||||||
Running an irc bouncer
|
|
||||||
----------------------
|
|
||||||
|
|
||||||
```bash
|
|
||||||
BOUNCER_ID=$(docker run -d -p 6667 -u irc shykes/znc zncrun $USER $PASSWORD)
|
|
||||||
echo "Configure your irc client to connect to port $(docker port $BOUNCER_ID 6667) of this machine"
|
|
||||||
```
|
|
||||||
|
|
||||||
Running Redis
|
|
||||||
-------------
|
|
||||||
|
|
||||||
```bash
|
|
||||||
REDIS_ID=$(docker run -d -p 6379 shykes/redis redis-server)
|
|
||||||
echo "Configure your redis client to connect to port $(docker port $REDIS_ID 6379) of this machine"
|
|
||||||
```
|
|
||||||
|
|
||||||
Share your own image!
|
|
||||||
---------------------
|
|
||||||
|
|
||||||
```bash
|
|
||||||
CONTAINER=$(docker run -d ubuntu:12.10 apt-get install -y curl)
|
|
||||||
docker commit -m "Installed curl" $CONTAINER $USER/betterbase
|
|
||||||
docker push $USER/betterbase
|
|
||||||
```
|
|
||||||
|
|
||||||
A list of publicly available images is [available
|
|
||||||
here](https://github.com/dotcloud/docker/wiki/Public-docker-images).
|
|
||||||
|
|
||||||
Expose a service on a TCP port
|
|
||||||
------------------------------
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Expose port 4444 of this container, and tell netcat to listen on it
|
|
||||||
JOB=$(docker run -d -p 4444 base /bin/nc -l -p 4444)
|
|
||||||
|
|
||||||
# Which public port is NATed to my container?
|
|
||||||
PORT=$(docker port $JOB 4444)
|
|
||||||
|
|
||||||
# Connect to the public port via the host's public address
|
|
||||||
# Please note that because of how routing works connecting to localhost or 127.0.0.1 $PORT will not work.
|
|
||||||
# Replace *eth0* according to your local interface name.
|
|
||||||
IP=$(ip -o -4 addr list eth0 | perl -n -e 'if (m{inet\s([\d\.]+)\/\d+\s}xms) { print $1 }')
|
|
||||||
echo hello world | nc $IP $PORT
|
|
||||||
|
|
||||||
# Verify that the network connection worked
|
|
||||||
echo "Daemon received: $(docker logs $JOB)"
|
|
||||||
```
|
|
||||||
|
|
||||||
Under the hood
|
Under the hood
|
||||||
--------------
|
--------------
|
||||||
@@ -301,155 +182,20 @@ Contributing to Docker
|
|||||||
======================
|
======================
|
||||||
|
|
||||||
Want to hack on Docker? Awesome! There are instructions to get you
|
Want to hack on Docker? Awesome! There are instructions to get you
|
||||||
started on the website:
|
started [here](CONTRIBUTING.md).
|
||||||
http://docs.docker.io/en/latest/contributing/contributing/
|
|
||||||
|
|
||||||
They are probably not perfect, please let us know if anything feels
|
They are probably not perfect, please let us know if anything feels
|
||||||
wrong or incomplete.
|
wrong or incomplete.
|
||||||
|
|
||||||
|
|
||||||
Note
|
|
||||||
----
|
|
||||||
|
|
||||||
We also keep the documentation in this repository. The website
|
|
||||||
documentation is generated using Sphinx using these sources. Please
|
|
||||||
find it under docs/sources/ and read more about it
|
|
||||||
https://github.com/dotcloud/docker/tree/master/docs/README.md
|
|
||||||
|
|
||||||
Please feel free to fix / update the documentation and send us pull
|
|
||||||
requests. More tutorials are also welcome.
|
|
||||||
|
|
||||||
|
|
||||||
Setting up a dev environment
|
|
||||||
----------------------------
|
|
||||||
|
|
||||||
Instructions that have been verified to work on Ubuntu 12.10,
|
|
||||||
|
|
||||||
```bash
|
|
||||||
sudo apt-get -y install lxc curl xz-utils golang git
|
|
||||||
|
|
||||||
export GOPATH=~/go/
|
|
||||||
export PATH=$GOPATH/bin:$PATH
|
|
||||||
|
|
||||||
mkdir -p $GOPATH/src/github.com/dotcloud
|
|
||||||
cd $GOPATH/src/github.com/dotcloud
|
|
||||||
git clone https://github.com/dotcloud/docker.git
|
|
||||||
cd docker
|
|
||||||
|
|
||||||
go get -v github.com/dotcloud/docker/...
|
|
||||||
go install -v github.com/dotcloud/docker/...
|
|
||||||
```
|
|
||||||
|
|
||||||
Then run the docker daemon,
|
|
||||||
|
|
||||||
```bash
|
|
||||||
sudo $GOPATH/bin/docker -d
|
|
||||||
```
|
|
||||||
|
|
||||||
Run the `go install` command (above) to recompile docker.
|
|
||||||
|
|
||||||
|
|
||||||
What is a Standard Container?
|
|
||||||
=============================
|
|
||||||
|
|
||||||
Docker defines a unit of software delivery called a Standard
|
|
||||||
Container. The goal of a Standard Container is to encapsulate a
|
|
||||||
software component and all its dependencies in a format that is
|
|
||||||
self-describing and portable, so that any compliant runtime can run it
|
|
||||||
without extra dependencies, regardless of the underlying machine and
|
|
||||||
the contents of the container.
|
|
||||||
|
|
||||||
The spec for Standard Containers is currently a work in progress, but
|
|
||||||
it is very straightforward. It mostly defines 1) an image format, 2) a
|
|
||||||
set of standard operations, and 3) an execution environment.
|
|
||||||
|
|
||||||
A great analogy for this is the shipping container. Just like how
|
|
||||||
Standard Containers are a fundamental unit of software delivery,
|
|
||||||
shipping containers are a fundamental unit of physical delivery.
|
|
||||||
|
|
||||||
### 1. STANDARD OPERATIONS
|
|
||||||
|
|
||||||
Just like shipping containers, Standard Containers define a set of
|
|
||||||
STANDARD OPERATIONS. Shipping containers can be lifted, stacked,
|
|
||||||
locked, loaded, unloaded and labelled. Similarly, Standard Containers
|
|
||||||
can be started, stopped, copied, snapshotted, downloaded, uploaded and
|
|
||||||
tagged.
|
|
||||||
|
|
||||||
|
|
||||||
### 2. CONTENT-AGNOSTIC
|
|
||||||
|
|
||||||
Just like shipping containers, Standard Containers are
|
|
||||||
CONTENT-AGNOSTIC: all standard operations have the same effect
|
|
||||||
regardless of the contents. A shipping container will be stacked in
|
|
||||||
exactly the same way whether it contains Vietnamese powder coffee or
|
|
||||||
spare Maserati parts. Similarly, Standard Containers are started or
|
|
||||||
uploaded in the same way whether they contain a postgres database, a
|
|
||||||
php application with its dependencies and application server, or Java
|
|
||||||
build artifacts.
|
|
||||||
|
|
||||||
|
|
||||||
### 3. INFRASTRUCTURE-AGNOSTIC
|
|
||||||
|
|
||||||
Both types of containers are INFRASTRUCTURE-AGNOSTIC: they can be
|
|
||||||
transported to thousands of facilities around the world, and
|
|
||||||
manipulated by a wide variety of equipment. A shipping container can
|
|
||||||
be packed in a factory in Ukraine, transported by truck to the nearest
|
|
||||||
routing center, stacked onto a train, loaded into a German boat by an
|
|
||||||
Australian-built crane, stored in a warehouse at a US facility,
|
|
||||||
etc. Similarly, a standard container can be bundled on my laptop,
|
|
||||||
uploaded to S3, downloaded, run and snapshotted by a build server at
|
|
||||||
Equinix in Virginia, uploaded to 10 staging servers in a home-made
|
|
||||||
Openstack cluster, then sent to 30 production instances across 3 EC2
|
|
||||||
regions.
|
|
||||||
|
|
||||||
|
|
||||||
### 4. DESIGNED FOR AUTOMATION
|
|
||||||
|
|
||||||
Because they offer the same standard operations regardless of content
|
|
||||||
and infrastructure, Standard Containers, just like their physical
|
|
||||||
counterparts, are extremely well-suited for automation. In fact, you
|
|
||||||
could say automation is their secret weapon.
|
|
||||||
|
|
||||||
Many things that once required time-consuming and error-prone human
|
|
||||||
effort can now be programmed. Before shipping containers, a bag of
|
|
||||||
powder coffee was hauled, dragged, dropped, rolled and stacked by 10
|
|
||||||
different people in 10 different locations by the time it reached its
|
|
||||||
destination. 1 out of 50 disappeared. 1 out of 20 was damaged. The
|
|
||||||
process was slow, inefficient and cost a fortune - and was entirely
|
|
||||||
different depending on the facility and the type of goods.
|
|
||||||
|
|
||||||
Similarly, before Standard Containers, by the time a software
|
|
||||||
component ran in production, it had been individually built,
|
|
||||||
configured, bundled, documented, patched, vendored, templated, tweaked
|
|
||||||
and instrumented by 10 different people on 10 different
|
|
||||||
computers. Builds failed, libraries conflicted, mirrors crashed,
|
|
||||||
post-it notes were lost, logs were misplaced, cluster updates were
|
|
||||||
half-broken. The process was slow, inefficient and cost a fortune -
|
|
||||||
and was entirely different depending on the language and
|
|
||||||
infrastructure provider.
|
|
||||||
|
|
||||||
|
|
||||||
### 5. INDUSTRIAL-GRADE DELIVERY
|
|
||||||
|
|
||||||
There are 17 million shipping containers in existence, packed with
|
|
||||||
every physical good imaginable. Every single one of them can be loaded
|
|
||||||
onto the same boats, by the same cranes, in the same facilities, and
|
|
||||||
sent anywhere in the World with incredible efficiency. It is
|
|
||||||
embarrassing to think that a 30 ton shipment of coffee can safely
|
|
||||||
travel half-way across the World in *less time* than it takes a
|
|
||||||
software team to deliver its code from one datacenter to another
|
|
||||||
sitting 10 miles away.
|
|
||||||
|
|
||||||
With Standard Containers we can put an end to that embarrassment, by
|
|
||||||
making INDUSTRIAL-GRADE DELIVERY of software a reality.
|
|
||||||
|
|
||||||
|
|
||||||
### Legal
|
### Legal
|
||||||
|
|
||||||
Transfers of Docker shall be in accordance with applicable export
|
*Brought to you courtesy of our legal counsel. For more context,
|
||||||
controls of any country and all other applicable legal requirements.
|
please see the Notice document.*
|
||||||
Docker shall not be distributed or downloaded to or in Cuba, Iran,
|
|
||||||
North Korea, Sudan or Syria and shall not be distributed or downloaded
|
|
||||||
to any person on the Denied Persons List administered by the U.S.
|
|
||||||
Department of Commerce.
|
|
||||||
|
|
||||||
|
Use and transfer of Docker may be subject to certain restrictions by the
|
||||||
|
United States and other governments.
|
||||||
|
It is your responsibility to ensure that your use and/or transfer does not
|
||||||
|
violate applicable laws.
|
||||||
|
|
||||||
|
For more information, please see http://www.bis.doc.gov
|
||||||
|
|||||||
Vendored
+129
-52
@@ -4,65 +4,135 @@
|
|||||||
BOX_NAME = ENV['BOX_NAME'] || "ubuntu"
|
BOX_NAME = ENV['BOX_NAME'] || "ubuntu"
|
||||||
BOX_URI = ENV['BOX_URI'] || "http://files.vagrantup.com/precise64.box"
|
BOX_URI = ENV['BOX_URI'] || "http://files.vagrantup.com/precise64.box"
|
||||||
VF_BOX_URI = ENV['BOX_URI'] || "http://files.vagrantup.com/precise64_vmware_fusion.box"
|
VF_BOX_URI = ENV['BOX_URI'] || "http://files.vagrantup.com/precise64_vmware_fusion.box"
|
||||||
|
AWS_BOX_URI = ENV['BOX_URI'] || "https://github.com/mitchellh/vagrant-aws/raw/master/dummy.box"
|
||||||
AWS_REGION = ENV['AWS_REGION'] || "us-east-1"
|
AWS_REGION = ENV['AWS_REGION'] || "us-east-1"
|
||||||
AWS_AMI = ENV['AWS_AMI'] || "ami-d0f89fb9"
|
AWS_AMI = ENV['AWS_AMI'] || "ami-69f5a900"
|
||||||
|
AWS_INSTANCE_TYPE = ENV['AWS_INSTANCE_TYPE'] || 't1.micro'
|
||||||
|
|
||||||
FORWARD_DOCKER_PORTS = ENV['FORWARD_DOCKER_PORTS']
|
FORWARD_DOCKER_PORTS = ENV['FORWARD_DOCKER_PORTS']
|
||||||
|
|
||||||
|
SSH_PRIVKEY_PATH = ENV["SSH_PRIVKEY_PATH"]
|
||||||
|
|
||||||
|
# A script to upgrade from the 12.04 kernel to the raring backport kernel (3.8)
|
||||||
|
# and install docker.
|
||||||
|
$script = <<SCRIPT
|
||||||
|
# The username to add to the docker group will be passed as the first argument
|
||||||
|
# to the script. If nothing is passed, default to "vagrant".
|
||||||
|
user="$1"
|
||||||
|
if [ -z "$user" ]; then
|
||||||
|
user=vagrant
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Adding an apt gpg key is idempotent.
|
||||||
|
wget -q -O - https://get.docker.io/gpg | apt-key add -
|
||||||
|
|
||||||
|
# Creating the docker.list file is idempotent, but it may overrite desired
|
||||||
|
# settings if it already exists. This could be solved with md5sum but it
|
||||||
|
# doesn't seem worth it.
|
||||||
|
echo 'deb http://get.docker.io/ubuntu docker main' > \
|
||||||
|
/etc/apt/sources.list.d/docker.list
|
||||||
|
|
||||||
|
# Update remote package metadata. 'apt-get update' is idempotent.
|
||||||
|
apt-get update -q
|
||||||
|
|
||||||
|
# Install docker. 'apt-get install' is idempotent.
|
||||||
|
apt-get install -q -y lxc-docker
|
||||||
|
|
||||||
|
usermod -a -G docker "$user"
|
||||||
|
|
||||||
|
tmp=`mktemp -q` && {
|
||||||
|
# Only install the backport kernel, don't bother upgrade if the backport is
|
||||||
|
# already installed. We want parse the output of apt so we need to save it
|
||||||
|
# with 'tee'. NOTE: The installation of the kernel will trigger dkms to
|
||||||
|
# install vboxguest if needed.
|
||||||
|
apt-get install -q -y --no-upgrade linux-image-generic-lts-raring | \
|
||||||
|
tee "$tmp"
|
||||||
|
|
||||||
|
# Parse the number of installed packages from the output
|
||||||
|
NUM_INST=`awk '$2 == "upgraded," && $4 == "newly" { print $3 }' "$tmp"`
|
||||||
|
rm "$tmp"
|
||||||
|
}
|
||||||
|
|
||||||
|
# If the number of installed packages is greater than 0, we want to reboot (the
|
||||||
|
# backport kernel was installed but is not running).
|
||||||
|
if [ "$NUM_INST" -gt 0 ];
|
||||||
|
then
|
||||||
|
echo "Rebooting down to activate new kernel."
|
||||||
|
echo "/vagrant will not be mounted. Use 'vagrant halt' followed by"
|
||||||
|
echo "'vagrant up' to ensure /vagrant is mounted."
|
||||||
|
shutdown -r now
|
||||||
|
fi
|
||||||
|
SCRIPT
|
||||||
|
|
||||||
|
# We need to install the virtualbox guest additions *before* we do the normal
|
||||||
|
# docker installation. As such this script is prepended to the common docker
|
||||||
|
# install script above. This allows the install of the backport kernel to
|
||||||
|
# trigger dkms to build the virtualbox guest module install.
|
||||||
|
$vbox_script = <<VBOX_SCRIPT + $script
|
||||||
|
# Install the VirtualBox guest additions if they aren't already installed.
|
||||||
|
if [ ! -d /opt/VBoxGuestAdditions-4.3.2/ ]; then
|
||||||
|
# Update remote package metadata. 'apt-get update' is idempotent.
|
||||||
|
apt-get update -q
|
||||||
|
|
||||||
|
# Kernel Headers and dkms are required to build the vbox guest kernel
|
||||||
|
# modules.
|
||||||
|
apt-get install -q -y linux-headers-generic-lts-raring dkms
|
||||||
|
|
||||||
|
echo 'Downloading VBox Guest Additions...'
|
||||||
|
wget -cq http://dlc.sun.com.edgesuite.net/virtualbox/4.3.2/VBoxGuestAdditions_4.3.2.iso
|
||||||
|
|
||||||
|
mount -o loop,ro /home/vagrant/VBoxGuestAdditions_4.3.2.iso /mnt
|
||||||
|
/mnt/VBoxLinuxAdditions.run --nox11
|
||||||
|
umount /mnt
|
||||||
|
fi
|
||||||
|
VBOX_SCRIPT
|
||||||
|
|
||||||
Vagrant::Config.run do |config|
|
Vagrant::Config.run do |config|
|
||||||
# Setup virtual machine box. This VM configuration code is always executed.
|
# Setup virtual machine box. This VM configuration code is always executed.
|
||||||
config.vm.box = BOX_NAME
|
config.vm.box = BOX_NAME
|
||||||
config.vm.box_url = BOX_URI
|
config.vm.box_url = BOX_URI
|
||||||
config.vm.forward_port 4243, 4243
|
|
||||||
|
|
||||||
# Provision docker and new kernel if deployment was not done
|
# Use the specified private key path if it is specified and not empty.
|
||||||
if Dir.glob("#{File.dirname(__FILE__)}/.vagrant/machines/default/*/id").empty?
|
if SSH_PRIVKEY_PATH
|
||||||
# Add lxc-docker package
|
config.ssh.private_key_path = SSH_PRIVKEY_PATH
|
||||||
pkg_cmd = "apt-get update -qq; apt-get install -q -y python-software-properties; " \
|
|
||||||
"add-apt-repository -y ppa:dotcloud/lxc-docker; apt-get update -qq; " \
|
|
||||||
"apt-get install -q -y lxc-docker; "
|
|
||||||
# Listen on all interfaces so that the daemon is accessible from the host
|
|
||||||
pkg_cmd << "sed -i -E 's| /usr/bin/docker -d| /usr/bin/docker -d -H 0.0.0.0|' /etc/init/docker.conf;"
|
|
||||||
# Add X.org Ubuntu backported 3.8 kernel
|
|
||||||
pkg_cmd << "add-apt-repository -y ppa:ubuntu-x-swat/r-lts-backport; " \
|
|
||||||
"apt-get update -qq; apt-get install -q -y linux-image-3.8.0-19-generic; "
|
|
||||||
# Add guest additions if local vbox VM
|
|
||||||
is_vbox = true
|
|
||||||
ARGV.each do |arg| is_vbox &&= !arg.downcase.start_with?("--provider") end
|
|
||||||
if is_vbox
|
|
||||||
pkg_cmd << "apt-get install -q -y linux-headers-3.8.0-19-generic dkms; " \
|
|
||||||
"echo 'Downloading VBox Guest Additions...'; " \
|
|
||||||
"wget -q http://dlc.sun.com.edgesuite.net/virtualbox/4.2.12/VBoxGuestAdditions_4.2.12.iso; "
|
|
||||||
# Prepare the VM to add guest additions after reboot
|
|
||||||
pkg_cmd << "echo -e 'mount -o loop,ro /home/vagrant/VBoxGuestAdditions_4.2.12.iso /mnt\n" \
|
|
||||||
"echo yes | /mnt/VBoxLinuxAdditions.run\numount /mnt\n" \
|
|
||||||
"rm /root/guest_additions.sh; ' > /root/guest_additions.sh; " \
|
|
||||||
"chmod 700 /root/guest_additions.sh; " \
|
|
||||||
"sed -i -E 's#^exit 0#[ -x /root/guest_additions.sh ] \\&\\& /root/guest_additions.sh#' /etc/rc.local; " \
|
|
||||||
"echo 'Installation of VBox Guest Additions is proceeding in the background.'; " \
|
|
||||||
"echo '\"vagrant reload\" can be used in about 2 minutes to activate the new guest additions.'; "
|
|
||||||
end
|
|
||||||
# Activate new kernel
|
|
||||||
pkg_cmd << "shutdown -r +1; "
|
|
||||||
config.vm.provision :shell, :inline => pkg_cmd
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
config.ssh.forward_agent = true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
# Providers were added on Vagrant >= 1.1.0
|
# Providers were added on Vagrant >= 1.1.0
|
||||||
|
#
|
||||||
|
# NOTE: The vagrant "vm.provision" appends its arguments to a list and executes
|
||||||
|
# them in order. If you invoke "vm.provision :shell, :inline => $script"
|
||||||
|
# twice then vagrant will run the script two times. Unfortunately when you use
|
||||||
|
# providers and the override argument to set up provisioners (like the vbox
|
||||||
|
# guest extensions) they 1) don't replace the other provisioners (they append
|
||||||
|
# to the end of the list) and 2) you can't control the order the provisioners
|
||||||
|
# are executed (you can only append to the list). If you want the virtualbox
|
||||||
|
# only script to run before the other script, you have to jump through a lot of
|
||||||
|
# hoops.
|
||||||
|
#
|
||||||
|
# Here is my only repeatable solution: make one script that is common ($script)
|
||||||
|
# and another script that is the virtual box guest *prepended* to the common
|
||||||
|
# script. Only ever use "vm.provision" *one time* per provider. That means
|
||||||
|
# every single provider has an override, and every single one configures
|
||||||
|
# "vm.provision". Much saddness, but such is life.
|
||||||
Vagrant::VERSION >= "1.1.0" and Vagrant.configure("2") do |config|
|
Vagrant::VERSION >= "1.1.0" and Vagrant.configure("2") do |config|
|
||||||
config.vm.provider :aws do |aws, override|
|
config.vm.provider :aws do |aws, override|
|
||||||
aws.access_key_id = ENV["AWS_ACCESS_KEY_ID"]
|
username = "ubuntu"
|
||||||
aws.secret_access_key = ENV["AWS_SECRET_ACCESS_KEY"]
|
override.vm.box_url = AWS_BOX_URI
|
||||||
|
override.vm.provision :shell, :inline => $script, :args => username
|
||||||
|
aws.access_key_id = ENV["AWS_ACCESS_KEY"]
|
||||||
|
aws.secret_access_key = ENV["AWS_SECRET_KEY"]
|
||||||
aws.keypair_name = ENV["AWS_KEYPAIR_NAME"]
|
aws.keypair_name = ENV["AWS_KEYPAIR_NAME"]
|
||||||
override.ssh.private_key_path = ENV["AWS_SSH_PRIVKEY"]
|
override.ssh.username = username
|
||||||
override.ssh.username = "ubuntu"
|
|
||||||
aws.region = AWS_REGION
|
aws.region = AWS_REGION
|
||||||
aws.ami = AWS_AMI
|
aws.ami = AWS_AMI
|
||||||
aws.instance_type = "t1.micro"
|
aws.instance_type = AWS_INSTANCE_TYPE
|
||||||
end
|
end
|
||||||
|
|
||||||
config.vm.provider :rackspace do |rs|
|
config.vm.provider :rackspace do |rs, override|
|
||||||
config.ssh.private_key_path = ENV["RS_PRIVATE_KEY"]
|
override.vm.provision :shell, :inline => $script
|
||||||
rs.username = ENV["RS_USERNAME"]
|
rs.username = ENV["RS_USERNAME"]
|
||||||
rs.api_key = ENV["RS_API_KEY"]
|
rs.api_key = ENV["RS_API_KEY"]
|
||||||
rs.public_key_path = ENV["RS_PUBLIC_KEY"]
|
rs.public_key_path = ENV["RS_PUBLIC_KEY"]
|
||||||
@@ -71,28 +141,35 @@ Vagrant::VERSION >= "1.1.0" and Vagrant.configure("2") do |config|
|
|||||||
end
|
end
|
||||||
|
|
||||||
config.vm.provider :vmware_fusion do |f, override|
|
config.vm.provider :vmware_fusion do |f, override|
|
||||||
override.vm.box = BOX_NAME
|
|
||||||
override.vm.box_url = VF_BOX_URI
|
override.vm.box_url = VF_BOX_URI
|
||||||
override.vm.synced_folder ".", "/vagrant", disabled: true
|
override.vm.synced_folder ".", "/vagrant", disabled: true
|
||||||
|
override.vm.provision :shell, :inline => $script
|
||||||
f.vmx["displayName"] = "docker"
|
f.vmx["displayName"] = "docker"
|
||||||
end
|
end
|
||||||
|
|
||||||
config.vm.provider :virtualbox do |vb|
|
config.vm.provider :virtualbox do |vb, override|
|
||||||
config.vm.box = BOX_NAME
|
override.vm.provision :shell, :inline => $vbox_script
|
||||||
config.vm.box_url = BOX_URI
|
vb.customize ["modifyvm", :id, "--natdnshostresolver1", "on"]
|
||||||
|
vb.customize ["modifyvm", :id, "--natdnsproxy1", "on"]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# If this is a version 1 config, virtualbox is the only option. A version 2
|
||||||
|
# config would have already been set in the above provider section.
|
||||||
|
Vagrant::VERSION < "1.1.0" and Vagrant::Config.run do |config|
|
||||||
|
config.vm.provision :shell, :inline => $vbox_script
|
||||||
|
end
|
||||||
|
|
||||||
if !FORWARD_DOCKER_PORTS.nil?
|
if !FORWARD_DOCKER_PORTS.nil?
|
||||||
Vagrant::VERSION < "1.1.0" and Vagrant::Config.run do |config|
|
Vagrant::VERSION < "1.1.0" and Vagrant::Config.run do |config|
|
||||||
(49000..49900).each do |port|
|
(49000..49900).each do |port|
|
||||||
config.vm.forward_port port, port
|
config.vm.forward_port port, port
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
Vagrant::VERSION >= "1.1.0" and Vagrant.configure("2") do |config|
|
Vagrant::VERSION >= "1.1.0" and Vagrant.configure("2") do |config|
|
||||||
(49000..49900).each do |port|
|
(49000..49900).each do |port|
|
||||||
config.vm.network :forwarded_port, :host => port, :guest => port
|
config.vm.network :forwarded_port, :host => port, :guest => port
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
+143
-83
@@ -1,88 +1,148 @@
|
|||||||
package docker
|
package docker
|
||||||
|
|
||||||
type APIHistory struct {
|
import "strings"
|
||||||
ID string `json:"Id"`
|
|
||||||
Tags []string `json:",omitempty"`
|
type (
|
||||||
Created int64
|
APIHistory struct {
|
||||||
CreatedBy string `json:",omitempty"`
|
ID string `json:"Id"`
|
||||||
|
Tags []string `json:",omitempty"`
|
||||||
|
Created int64
|
||||||
|
CreatedBy string `json:",omitempty"`
|
||||||
|
Size int64
|
||||||
|
}
|
||||||
|
|
||||||
|
APIImages struct {
|
||||||
|
ID string `json:"Id"`
|
||||||
|
RepoTags []string `json:",omitempty"`
|
||||||
|
Created int64
|
||||||
|
Size int64
|
||||||
|
VirtualSize int64
|
||||||
|
ParentId string `json:",omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
APIImagesOld struct {
|
||||||
|
Repository string `json:",omitempty"`
|
||||||
|
Tag string `json:",omitempty"`
|
||||||
|
ID string `json:"Id"`
|
||||||
|
Created int64
|
||||||
|
Size int64
|
||||||
|
VirtualSize int64
|
||||||
|
}
|
||||||
|
|
||||||
|
APIInfo struct {
|
||||||
|
Debug bool
|
||||||
|
Containers int
|
||||||
|
Images int
|
||||||
|
NFd int `json:",omitempty"`
|
||||||
|
NGoroutines int `json:",omitempty"`
|
||||||
|
MemoryLimit bool `json:",omitempty"`
|
||||||
|
SwapLimit bool `json:",omitempty"`
|
||||||
|
IPv4Forwarding bool `json:",omitempty"`
|
||||||
|
LXCVersion string `json:",omitempty"`
|
||||||
|
NEventsListener int `json:",omitempty"`
|
||||||
|
KernelVersion string `json:",omitempty"`
|
||||||
|
IndexServerAddress string `json:",omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
APITop struct {
|
||||||
|
Titles []string
|
||||||
|
Processes [][]string
|
||||||
|
}
|
||||||
|
|
||||||
|
APIRmi struct {
|
||||||
|
Deleted string `json:",omitempty"`
|
||||||
|
Untagged string `json:",omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
APIContainers struct {
|
||||||
|
ID string `json:"Id"`
|
||||||
|
Image string
|
||||||
|
Command string
|
||||||
|
Created int64
|
||||||
|
Status string
|
||||||
|
Ports []APIPort
|
||||||
|
SizeRw int64
|
||||||
|
SizeRootFs int64
|
||||||
|
Names []string
|
||||||
|
}
|
||||||
|
|
||||||
|
APIContainersOld struct {
|
||||||
|
ID string `json:"Id"`
|
||||||
|
Image string
|
||||||
|
Command string
|
||||||
|
Created int64
|
||||||
|
Status string
|
||||||
|
Ports string
|
||||||
|
SizeRw int64
|
||||||
|
SizeRootFs int64
|
||||||
|
}
|
||||||
|
|
||||||
|
APIID struct {
|
||||||
|
ID string `json:"Id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
APIRun struct {
|
||||||
|
ID string `json:"Id"`
|
||||||
|
Warnings []string `json:",omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
APIPort struct {
|
||||||
|
PrivatePort int64
|
||||||
|
PublicPort int64
|
||||||
|
Type string
|
||||||
|
IP string
|
||||||
|
}
|
||||||
|
|
||||||
|
APIVersion struct {
|
||||||
|
Version string
|
||||||
|
GitCommit string `json:",omitempty"`
|
||||||
|
GoVersion string `json:",omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
APIWait struct {
|
||||||
|
StatusCode int
|
||||||
|
}
|
||||||
|
|
||||||
|
APIAuth struct {
|
||||||
|
Status string
|
||||||
|
}
|
||||||
|
|
||||||
|
APIImageConfig struct {
|
||||||
|
ID string `json:"Id"`
|
||||||
|
*Config
|
||||||
|
}
|
||||||
|
|
||||||
|
APICopy struct {
|
||||||
|
Resource string
|
||||||
|
HostPath string
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
func (api APIImages) ToLegacy() []APIImagesOld {
|
||||||
|
outs := []APIImagesOld{}
|
||||||
|
for _, repotag := range api.RepoTags {
|
||||||
|
components := strings.SplitN(repotag, ":", 2)
|
||||||
|
outs = append(outs, APIImagesOld{
|
||||||
|
ID: api.ID,
|
||||||
|
Repository: components[0],
|
||||||
|
Tag: components[1],
|
||||||
|
Created: api.Created,
|
||||||
|
Size: api.Size,
|
||||||
|
VirtualSize: api.VirtualSize,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return outs
|
||||||
}
|
}
|
||||||
|
|
||||||
type APIImages struct {
|
func (api APIContainers) ToLegacy() *APIContainersOld {
|
||||||
Repository string `json:",omitempty"`
|
return &APIContainersOld{
|
||||||
Tag string `json:",omitempty"`
|
ID: api.ID,
|
||||||
ID string `json:"Id"`
|
Image: api.Image,
|
||||||
Created int64
|
Command: api.Command,
|
||||||
Size int64
|
Created: api.Created,
|
||||||
VirtualSize int64
|
Status: api.Status,
|
||||||
}
|
Ports: displayablePorts(api.Ports),
|
||||||
|
SizeRw: api.SizeRw,
|
||||||
type APIInfo struct {
|
SizeRootFs: api.SizeRootFs,
|
||||||
Debug bool
|
}
|
||||||
Containers int
|
|
||||||
Images int
|
|
||||||
NFd int `json:",omitempty"`
|
|
||||||
NGoroutines int `json:",omitempty"`
|
|
||||||
MemoryLimit bool `json:",omitempty"`
|
|
||||||
SwapLimit bool `json:",omitempty"`
|
|
||||||
LXCVersion string `json:",omitempty"`
|
|
||||||
NEventsListener int `json:",omitempty"`
|
|
||||||
KernelVersion string `json:",omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type APITop struct {
|
|
||||||
Titles []string
|
|
||||||
Processes [][]string
|
|
||||||
}
|
|
||||||
|
|
||||||
type APIRmi struct {
|
|
||||||
Deleted string `json:",omitempty"`
|
|
||||||
Untagged string `json:",omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type APIContainers struct {
|
|
||||||
ID string `json:"Id"`
|
|
||||||
Image string
|
|
||||||
Command string
|
|
||||||
Created int64
|
|
||||||
Status string
|
|
||||||
Ports string
|
|
||||||
SizeRw int64
|
|
||||||
SizeRootFs int64
|
|
||||||
}
|
|
||||||
|
|
||||||
type APISearch struct {
|
|
||||||
Name string
|
|
||||||
Description string
|
|
||||||
}
|
|
||||||
|
|
||||||
type APIID struct {
|
|
||||||
ID string `json:"Id"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type APIRun struct {
|
|
||||||
ID string `json:"Id"`
|
|
||||||
Warnings []string `json:",omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type APIPort struct {
|
|
||||||
Port string
|
|
||||||
}
|
|
||||||
|
|
||||||
type APIVersion struct {
|
|
||||||
Version string
|
|
||||||
GitCommit string `json:",omitempty"`
|
|
||||||
GoVersion string `json:",omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type APIWait struct {
|
|
||||||
StatusCode int
|
|
||||||
}
|
|
||||||
|
|
||||||
type APIAuth struct {
|
|
||||||
Status string
|
|
||||||
}
|
|
||||||
|
|
||||||
type APIImageConfig struct {
|
|
||||||
ID string `json:"Id"`
|
|
||||||
*Config
|
|
||||||
}
|
}
|
||||||
|
|||||||
-1170
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,19 @@
|
|||||||
|
package docker
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestJsonContentType(t *testing.T) {
|
||||||
|
if !matchesContentType("application/json", "application/json") {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
|
||||||
|
if !matchesContentType("application/json; charset=utf-8", "application/json") {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
|
||||||
|
if matchesContentType("dockerapplication/json", "application/json") {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
Michael Crosby <michael@crosbymichael.com> (@crosbymichael)
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package docker
|
package archive
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"archive/tar"
|
"archive/tar"
|
||||||
@@ -98,7 +98,7 @@ func TarFilter(path string, compression Compression, filter []string) (io.Reader
|
|||||||
|
|
||||||
// Untar reads a stream of bytes from `archive`, parses it as a tar archive,
|
// Untar reads a stream of bytes from `archive`, parses it as a tar archive,
|
||||||
// and unpacks it into the directory at `path`.
|
// and unpacks it into the directory at `path`.
|
||||||
// The archive may be compressed with one of the following algorithgms:
|
// The archive may be compressed with one of the following algorithms:
|
||||||
// identity (uncompressed), gzip, bzip2, xz.
|
// identity (uncompressed), gzip, bzip2, xz.
|
||||||
// FIXME: specify behavior when target path exists vs. doesn't exist.
|
// FIXME: specify behavior when target path exists vs. doesn't exist.
|
||||||
func Untar(archive io.Reader, path string) error {
|
func Untar(archive io.Reader, path string) error {
|
||||||
@@ -109,16 +109,17 @@ func Untar(archive io.Reader, path string) error {
|
|||||||
buf := make([]byte, 10)
|
buf := make([]byte, 10)
|
||||||
totalN := 0
|
totalN := 0
|
||||||
for totalN < 10 {
|
for totalN < 10 {
|
||||||
if n, err := archive.Read(buf[totalN:]); err != nil {
|
n, err := archive.Read(buf[totalN:])
|
||||||
|
if err != nil {
|
||||||
if err == io.EOF {
|
if err == io.EOF {
|
||||||
return fmt.Errorf("Tarball too short")
|
return fmt.Errorf("Tarball too short")
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
} else {
|
|
||||||
totalN += n
|
|
||||||
utils.Debugf("[tar autodetect] n: %d", n)
|
|
||||||
}
|
}
|
||||||
|
totalN += n
|
||||||
|
utils.Debugf("[tar autodetect] n: %d", n)
|
||||||
}
|
}
|
||||||
|
|
||||||
compression := DetectCompression(buf)
|
compression := DetectCompression(buf)
|
||||||
|
|
||||||
utils.Debugf("Archive compression detected: %s", compression.Extension())
|
utils.Debugf("Archive compression detected: %s", compression.Extension())
|
||||||
@@ -173,7 +174,7 @@ func CopyWithTar(src, dst string) error {
|
|||||||
}
|
}
|
||||||
// Create dst, copy src's content into it
|
// Create dst, copy src's content into it
|
||||||
utils.Debugf("Creating dest directory: %s", dst)
|
utils.Debugf("Creating dest directory: %s", dst)
|
||||||
if err := os.MkdirAll(dst, 0700); err != nil && !os.IsExist(err) {
|
if err := os.MkdirAll(dst, 0755); err != nil && !os.IsExist(err) {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
utils.Debugf("Calling TarUntar(%s, %s)", src, dst)
|
utils.Debugf("Calling TarUntar(%s, %s)", src, dst)
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package docker
|
package archive
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
@@ -1 +0,0 @@
|
|||||||
../registry/MAINTAINERS
|
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
Sam Alba <sam@dotcloud.com> (@samalba)
|
||||||
|
Joffrey Fuhrer <joffrey@dotcloud.com> (@shin-)
|
||||||
|
Ken Cochrane <ken@dotcloud.com> (@kencochrane)
|
||||||
+97
-18
@@ -5,6 +5,7 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/dotcloud/docker/utils"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
@@ -18,17 +19,18 @@ const CONFIGFILE = ".dockercfg"
|
|||||||
// Only used for user auth + account creation
|
// Only used for user auth + account creation
|
||||||
const INDEXSERVER = "https://index.docker.io/v1/"
|
const INDEXSERVER = "https://index.docker.io/v1/"
|
||||||
|
|
||||||
//const INDEXSERVER = "http://indexstaging-docker.dotcloud.com/"
|
//const INDEXSERVER = "https://indexstaging-docker.dotcloud.com/v1/"
|
||||||
|
|
||||||
var (
|
var (
|
||||||
ErrConfigFileMissing = errors.New("The Auth config file is missing")
|
ErrConfigFileMissing = errors.New("The Auth config file is missing")
|
||||||
)
|
)
|
||||||
|
|
||||||
type AuthConfig struct {
|
type AuthConfig struct {
|
||||||
Username string `json:"username,omitempty"`
|
Username string `json:"username,omitempty"`
|
||||||
Password string `json:"password,omitempty"`
|
Password string `json:"password,omitempty"`
|
||||||
Auth string `json:"auth"`
|
Auth string `json:"auth"`
|
||||||
Email string `json:"email"`
|
Email string `json:"email"`
|
||||||
|
ServerAddress string `json:"serveraddress,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ConfigFile struct {
|
type ConfigFile struct {
|
||||||
@@ -75,35 +77,43 @@ func LoadConfig(rootPath string) (*ConfigFile, error) {
|
|||||||
configFile := ConfigFile{Configs: make(map[string]AuthConfig), rootPath: rootPath}
|
configFile := ConfigFile{Configs: make(map[string]AuthConfig), rootPath: rootPath}
|
||||||
confFile := path.Join(rootPath, CONFIGFILE)
|
confFile := path.Join(rootPath, CONFIGFILE)
|
||||||
if _, err := os.Stat(confFile); err != nil {
|
if _, err := os.Stat(confFile); err != nil {
|
||||||
return &configFile, ErrConfigFileMissing
|
return &configFile, nil //missing file is not an error
|
||||||
}
|
}
|
||||||
b, err := ioutil.ReadFile(confFile)
|
b, err := ioutil.ReadFile(confFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return &configFile, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := json.Unmarshal(b, &configFile.Configs); err != nil {
|
if err := json.Unmarshal(b, &configFile.Configs); err != nil {
|
||||||
arr := strings.Split(string(b), "\n")
|
arr := strings.Split(string(b), "\n")
|
||||||
if len(arr) < 2 {
|
if len(arr) < 2 {
|
||||||
return nil, fmt.Errorf("The Auth config file is empty")
|
return &configFile, fmt.Errorf("The Auth config file is empty")
|
||||||
}
|
}
|
||||||
authConfig := AuthConfig{}
|
authConfig := AuthConfig{}
|
||||||
origAuth := strings.Split(arr[0], " = ")
|
origAuth := strings.Split(arr[0], " = ")
|
||||||
|
if len(origAuth) != 2 {
|
||||||
|
return &configFile, fmt.Errorf("Invalid Auth config file")
|
||||||
|
}
|
||||||
authConfig.Username, authConfig.Password, err = decodeAuth(origAuth[1])
|
authConfig.Username, authConfig.Password, err = decodeAuth(origAuth[1])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return &configFile, err
|
||||||
}
|
}
|
||||||
origEmail := strings.Split(arr[1], " = ")
|
origEmail := strings.Split(arr[1], " = ")
|
||||||
|
if len(origEmail) != 2 {
|
||||||
|
return &configFile, fmt.Errorf("Invalid Auth config file")
|
||||||
|
}
|
||||||
authConfig.Email = origEmail[1]
|
authConfig.Email = origEmail[1]
|
||||||
|
authConfig.ServerAddress = IndexServerAddress()
|
||||||
configFile.Configs[IndexServerAddress()] = authConfig
|
configFile.Configs[IndexServerAddress()] = authConfig
|
||||||
} else {
|
} else {
|
||||||
for k, authConfig := range configFile.Configs {
|
for k, authConfig := range configFile.Configs {
|
||||||
authConfig.Username, authConfig.Password, err = decodeAuth(authConfig.Auth)
|
authConfig.Username, authConfig.Password, err = decodeAuth(authConfig.Auth)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return &configFile, err
|
||||||
}
|
}
|
||||||
authConfig.Auth = ""
|
authConfig.Auth = ""
|
||||||
configFile.Configs[k] = authConfig
|
configFile.Configs[k] = authConfig
|
||||||
|
authConfig.ServerAddress = k
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return &configFile, nil
|
return &configFile, nil
|
||||||
@@ -124,7 +134,7 @@ func SaveConfig(configFile *ConfigFile) error {
|
|||||||
authCopy.Auth = encodeAuth(&authCopy)
|
authCopy.Auth = encodeAuth(&authCopy)
|
||||||
authCopy.Username = ""
|
authCopy.Username = ""
|
||||||
authCopy.Password = ""
|
authCopy.Password = ""
|
||||||
|
authCopy.ServerAddress = ""
|
||||||
configs[k] = authCopy
|
configs[k] = authCopy
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -140,19 +150,31 @@ func SaveConfig(configFile *ConfigFile) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// try to register/login to the registry server
|
// try to register/login to the registry server
|
||||||
func Login(authConfig *AuthConfig) (string, error) {
|
func Login(authConfig *AuthConfig, factory *utils.HTTPRequestFactory) (string, error) {
|
||||||
client := &http.Client{}
|
client := &http.Client{}
|
||||||
reqStatusCode := 0
|
reqStatusCode := 0
|
||||||
var status string
|
var status string
|
||||||
var reqBody []byte
|
var reqBody []byte
|
||||||
jsonBody, err := json.Marshal(authConfig)
|
|
||||||
|
serverAddress := authConfig.ServerAddress
|
||||||
|
if serverAddress == "" {
|
||||||
|
serverAddress = IndexServerAddress()
|
||||||
|
}
|
||||||
|
|
||||||
|
loginAgainstOfficialIndex := serverAddress == IndexServerAddress()
|
||||||
|
|
||||||
|
// to avoid sending the server address to the server it should be removed before marshalled
|
||||||
|
authCopy := *authConfig
|
||||||
|
authCopy.ServerAddress = ""
|
||||||
|
|
||||||
|
jsonBody, err := json.Marshal(authCopy)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", fmt.Errorf("Config Error: %s", err)
|
return "", fmt.Errorf("Config Error: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// using `bytes.NewReader(jsonBody)` here causes the server to respond with a 411 status.
|
// using `bytes.NewReader(jsonBody)` here causes the server to respond with a 411 status.
|
||||||
b := strings.NewReader(string(jsonBody))
|
b := strings.NewReader(string(jsonBody))
|
||||||
req1, err := http.Post(IndexServerAddress()+"users/", "application/json; charset=utf-8", b)
|
req1, err := http.Post(serverAddress+"users/", "application/json; charset=utf-8", b)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", fmt.Errorf("Server Error: %s", err)
|
return "", fmt.Errorf("Server Error: %s", err)
|
||||||
}
|
}
|
||||||
@@ -164,14 +186,22 @@ func Login(authConfig *AuthConfig) (string, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if reqStatusCode == 201 {
|
if reqStatusCode == 201 {
|
||||||
status = "Account created. Please use the confirmation link we sent" +
|
if loginAgainstOfficialIndex {
|
||||||
" to your e-mail to activate it."
|
status = "Account created. Please use the confirmation link we sent" +
|
||||||
|
" to your e-mail to activate it."
|
||||||
|
} else {
|
||||||
|
status = "Account created. Please see the documentation of the registry " + serverAddress + " for instructions how to activate it."
|
||||||
|
}
|
||||||
} else if reqStatusCode == 403 {
|
} else if reqStatusCode == 403 {
|
||||||
|
if loginAgainstOfficialIndex {
|
||||||
|
return "", fmt.Errorf("Login: Your account hasn't been activated. " +
|
||||||
|
"Please check your e-mail for a confirmation link.")
|
||||||
|
}
|
||||||
return "", fmt.Errorf("Login: Your account hasn't been activated. " +
|
return "", fmt.Errorf("Login: Your account hasn't been activated. " +
|
||||||
"Please check your e-mail for a confirmation link.")
|
"Please see the documentation of the registry " + serverAddress + " for instructions how to activate it.")
|
||||||
} else if reqStatusCode == 400 {
|
} else if reqStatusCode == 400 {
|
||||||
if string(reqBody) == "\"Username or email already exists\"" {
|
if string(reqBody) == "\"Username or email already exists\"" {
|
||||||
req, err := http.NewRequest("GET", IndexServerAddress()+"users/", nil)
|
req, err := factory.NewRequest("GET", serverAddress+"users/", nil)
|
||||||
req.SetBasicAuth(authConfig.Username, authConfig.Password)
|
req.SetBasicAuth(authConfig.Username, authConfig.Password)
|
||||||
resp, err := client.Do(req)
|
resp, err := client.Do(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -198,3 +228,52 @@ func Login(authConfig *AuthConfig) (string, error) {
|
|||||||
}
|
}
|
||||||
return status, nil
|
return status, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// this method matches a auth configuration to a server address or a url
|
||||||
|
func (config *ConfigFile) ResolveAuthConfig(registry string) AuthConfig {
|
||||||
|
if registry == IndexServerAddress() || len(registry) == 0 {
|
||||||
|
// default to the index server
|
||||||
|
return config.Configs[IndexServerAddress()]
|
||||||
|
}
|
||||||
|
// if its not the index server there are three cases:
|
||||||
|
//
|
||||||
|
// 1. this is a full config url -> it should be used as is
|
||||||
|
// 2. it could be a full url, but with the wrong protocol
|
||||||
|
// 3. it can be the hostname optionally with a port
|
||||||
|
//
|
||||||
|
// as there is only one auth entry which is fully qualified we need to start
|
||||||
|
// parsing and matching
|
||||||
|
|
||||||
|
swapProtocol := func(url string) string {
|
||||||
|
if strings.HasPrefix(url, "http:") {
|
||||||
|
return strings.Replace(url, "http:", "https:", 1)
|
||||||
|
}
|
||||||
|
if strings.HasPrefix(url, "https:") {
|
||||||
|
return strings.Replace(url, "https:", "http:", 1)
|
||||||
|
}
|
||||||
|
return url
|
||||||
|
}
|
||||||
|
|
||||||
|
resolveIgnoringProtocol := func(url string) AuthConfig {
|
||||||
|
if c, found := config.Configs[url]; found {
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
registrySwappedProtocol := swapProtocol(url)
|
||||||
|
// now try to match with the different protocol
|
||||||
|
if c, found := config.Configs[registrySwappedProtocol]; found {
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
return AuthConfig{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// match both protocols as it could also be a server name like httpfoo
|
||||||
|
if strings.HasPrefix(registry, "http:") || strings.HasPrefix(registry, "https:") {
|
||||||
|
return resolveIgnoringProtocol(registry)
|
||||||
|
}
|
||||||
|
|
||||||
|
url := "https://" + registry
|
||||||
|
if !strings.Contains(registry, "/") {
|
||||||
|
url = url + "/v1/"
|
||||||
|
}
|
||||||
|
return resolveIgnoringProtocol(url)
|
||||||
|
}
|
||||||
|
|||||||
+87
-57
@@ -1,11 +1,8 @@
|
|||||||
package auth
|
package auth
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/rand"
|
|
||||||
"encoding/hex"
|
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -29,68 +26,34 @@ func TestEncodeAuth(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestLogin(t *testing.T) {
|
func setupTempConfigFile() (*ConfigFile, error) {
|
||||||
os.Setenv("DOCKER_INDEX_URL", "https://indexstaging-docker.dotcloud.com")
|
root, err := ioutil.TempDir("", "docker-test-auth")
|
||||||
defer os.Setenv("DOCKER_INDEX_URL", "")
|
|
||||||
authConfig := &AuthConfig{Username: "unittester", Password: "surlautrerivejetattendrai", Email: "noise+unittester@dotcloud.com"}
|
|
||||||
status, err := Login(authConfig)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
return nil, err
|
||||||
}
|
|
||||||
if status != "Login Succeeded" {
|
|
||||||
t.Fatalf("Expected status \"Login Succeeded\", found \"%s\" instead", status)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCreateAccount(t *testing.T) {
|
|
||||||
os.Setenv("DOCKER_INDEX_URL", "https://indexstaging-docker.dotcloud.com")
|
|
||||||
defer os.Setenv("DOCKER_INDEX_URL", "")
|
|
||||||
tokenBuffer := make([]byte, 16)
|
|
||||||
_, err := rand.Read(tokenBuffer)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
token := hex.EncodeToString(tokenBuffer)[:12]
|
|
||||||
username := "ut" + token
|
|
||||||
authConfig := &AuthConfig{Username: username, Password: "test42", Email: "docker-ut+" + token + "@example.com"}
|
|
||||||
status, err := Login(authConfig)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
expectedStatus := "Account created. Please use the confirmation link we sent" +
|
|
||||||
" to your e-mail to activate it."
|
|
||||||
if status != expectedStatus {
|
|
||||||
t.Fatalf("Expected status: \"%s\", found \"%s\" instead.", expectedStatus, status)
|
|
||||||
}
|
|
||||||
|
|
||||||
status, err = Login(authConfig)
|
|
||||||
if err == nil {
|
|
||||||
t.Fatalf("Expected error but found nil instead")
|
|
||||||
}
|
|
||||||
|
|
||||||
expectedError := "Login: Account is not Active"
|
|
||||||
|
|
||||||
if !strings.Contains(err.Error(), expectedError) {
|
|
||||||
t.Fatalf("Expected message \"%s\" but found \"%s\" instead", expectedError, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSameAuthDataPostSave(t *testing.T) {
|
|
||||||
root, err := ioutil.TempDir("", "docker-test")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
}
|
||||||
configFile := &ConfigFile{
|
configFile := &ConfigFile{
|
||||||
rootPath: root,
|
rootPath: root,
|
||||||
Configs: make(map[string]AuthConfig, 1),
|
Configs: make(map[string]AuthConfig),
|
||||||
}
|
}
|
||||||
|
|
||||||
configFile.Configs["testIndex"] = AuthConfig{
|
for _, registry := range []string{"testIndex", IndexServerAddress()} {
|
||||||
Username: "docker-user",
|
configFile.Configs[registry] = AuthConfig{
|
||||||
Password: "docker-pass",
|
Username: "docker-user",
|
||||||
Email: "docker@docker.io",
|
Password: "docker-pass",
|
||||||
|
Email: "docker@docker.io",
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return configFile, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSameAuthDataPostSave(t *testing.T) {
|
||||||
|
configFile, err := setupTempConfigFile()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer os.RemoveAll(configFile.rootPath)
|
||||||
|
|
||||||
err = SaveConfig(configFile)
|
err = SaveConfig(configFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@@ -110,3 +73,70 @@ func TestSameAuthDataPostSave(t *testing.T) {
|
|||||||
t.Fail()
|
t.Fail()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestResolveAuthConfigIndexServer(t *testing.T) {
|
||||||
|
configFile, err := setupTempConfigFile()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer os.RemoveAll(configFile.rootPath)
|
||||||
|
|
||||||
|
for _, registry := range []string{"", IndexServerAddress()} {
|
||||||
|
resolved := configFile.ResolveAuthConfig(registry)
|
||||||
|
if resolved != configFile.Configs[IndexServerAddress()] {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestResolveAuthConfigFullURL(t *testing.T) {
|
||||||
|
configFile, err := setupTempConfigFile()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer os.RemoveAll(configFile.rootPath)
|
||||||
|
|
||||||
|
registryAuth := AuthConfig{
|
||||||
|
Username: "foo-user",
|
||||||
|
Password: "foo-pass",
|
||||||
|
Email: "foo@example.com",
|
||||||
|
}
|
||||||
|
localAuth := AuthConfig{
|
||||||
|
Username: "bar-user",
|
||||||
|
Password: "bar-pass",
|
||||||
|
Email: "bar@example.com",
|
||||||
|
}
|
||||||
|
configFile.Configs["https://registry.example.com/v1/"] = registryAuth
|
||||||
|
configFile.Configs["http://localhost:8000/v1/"] = localAuth
|
||||||
|
|
||||||
|
validRegistries := map[string][]string{
|
||||||
|
"https://registry.example.com/v1/": {
|
||||||
|
"https://registry.example.com/v1/",
|
||||||
|
"http://registry.example.com/v1/",
|
||||||
|
"registry.example.com",
|
||||||
|
"registry.example.com/v1/",
|
||||||
|
},
|
||||||
|
"http://localhost:8000/v1/": {
|
||||||
|
"https://localhost:8000/v1/",
|
||||||
|
"http://localhost:8000/v1/",
|
||||||
|
"localhost:8000",
|
||||||
|
"localhost:8000/v1/",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for configKey, registries := range validRegistries {
|
||||||
|
for _, registry := range registries {
|
||||||
|
var (
|
||||||
|
configured AuthConfig
|
||||||
|
ok bool
|
||||||
|
)
|
||||||
|
resolved := configFile.ResolveAuthConfig(registry)
|
||||||
|
if configured, ok = configFile.Configs[configKey]; !ok {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
if resolved.Email != configured.Email {
|
||||||
|
t.Errorf("%s -> %q != %q\n", registry, resolved.Email, configured.Email)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
-147
@@ -1,147 +0,0 @@
|
|||||||
package docker
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"github.com/dotcloud/docker/utils"
|
|
||||||
"os"
|
|
||||||
"path"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
var defaultDns = []string{"8.8.8.8", "8.8.4.4"}
|
|
||||||
|
|
||||||
type Builder struct {
|
|
||||||
runtime *Runtime
|
|
||||||
repositories *TagStore
|
|
||||||
graph *Graph
|
|
||||||
|
|
||||||
config *Config
|
|
||||||
image *Image
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewBuilder(runtime *Runtime) *Builder {
|
|
||||||
return &Builder{
|
|
||||||
runtime: runtime,
|
|
||||||
graph: runtime.graph,
|
|
||||||
repositories: runtime.repositories,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (builder *Builder) Create(config *Config) (*Container, error) {
|
|
||||||
// Lookup image
|
|
||||||
img, err := builder.repositories.LookupImage(config.Image)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if img.Config != nil {
|
|
||||||
MergeConfig(config, img.Config)
|
|
||||||
}
|
|
||||||
|
|
||||||
if config.Cmd == nil || len(config.Cmd) == 0 {
|
|
||||||
return nil, fmt.Errorf("No command specified")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate id
|
|
||||||
id := GenerateID()
|
|
||||||
// Generate default hostname
|
|
||||||
// FIXME: the lxc template no longer needs to set a default hostname
|
|
||||||
if config.Hostname == "" {
|
|
||||||
config.Hostname = id[:12]
|
|
||||||
}
|
|
||||||
|
|
||||||
var args []string
|
|
||||||
var entrypoint string
|
|
||||||
|
|
||||||
if len(config.Entrypoint) != 0 {
|
|
||||||
entrypoint = config.Entrypoint[0]
|
|
||||||
args = append(config.Entrypoint[1:], config.Cmd...)
|
|
||||||
} else {
|
|
||||||
entrypoint = config.Cmd[0]
|
|
||||||
args = config.Cmd[1:]
|
|
||||||
}
|
|
||||||
|
|
||||||
container := &Container{
|
|
||||||
// FIXME: we should generate the ID here instead of receiving it as an argument
|
|
||||||
ID: id,
|
|
||||||
Created: time.Now(),
|
|
||||||
Path: entrypoint,
|
|
||||||
Args: args, //FIXME: de-duplicate from config
|
|
||||||
Config: config,
|
|
||||||
Image: img.ID, // Always use the resolved image id
|
|
||||||
NetworkSettings: &NetworkSettings{},
|
|
||||||
// FIXME: do we need to store this in the container?
|
|
||||||
SysInitPath: sysInitPath,
|
|
||||||
}
|
|
||||||
container.root = builder.runtime.containerRoot(container.ID)
|
|
||||||
// Step 1: create the container directory.
|
|
||||||
// This doubles as a barrier to avoid race conditions.
|
|
||||||
if err := os.Mkdir(container.root, 0700); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(config.Dns) == 0 && len(builder.runtime.Dns) == 0 && utils.CheckLocalDns() {
|
|
||||||
//"WARNING: Docker detected local DNS server on resolv.conf. Using default external servers: %v", defaultDns
|
|
||||||
builder.runtime.Dns = defaultDns
|
|
||||||
}
|
|
||||||
|
|
||||||
// If custom dns exists, then create a resolv.conf for the container
|
|
||||||
if len(config.Dns) > 0 || len(builder.runtime.Dns) > 0 {
|
|
||||||
var dns []string
|
|
||||||
if len(config.Dns) > 0 {
|
|
||||||
dns = config.Dns
|
|
||||||
} else {
|
|
||||||
dns = builder.runtime.Dns
|
|
||||||
}
|
|
||||||
container.ResolvConfPath = path.Join(container.root, "resolv.conf")
|
|
||||||
f, err := os.Create(container.ResolvConfPath)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer f.Close()
|
|
||||||
for _, dns := range dns {
|
|
||||||
if _, err := f.Write([]byte("nameserver " + dns + "\n")); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
container.ResolvConfPath = "/etc/resolv.conf"
|
|
||||||
}
|
|
||||||
|
|
||||||
// Step 2: save the container json
|
|
||||||
if err := container.ToDisk(); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
// Step 3: register the container
|
|
||||||
if err := builder.runtime.Register(container); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return container, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Commit creates a new filesystem image from the current state of a container.
|
|
||||||
// The image can optionally be tagged into a repository
|
|
||||||
func (builder *Builder) Commit(container *Container, repository, tag, comment, author string, config *Config) (*Image, error) {
|
|
||||||
// FIXME: freeze the container before copying it to avoid data corruption?
|
|
||||||
// FIXME: this shouldn't be in commands.
|
|
||||||
if err := container.EnsureMounted(); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
rwTar, err := container.ExportRw()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
// Create a new image from the container's base layers + a new layer from container changes
|
|
||||||
img, err := builder.graph.Create(rwTar, container, comment, author, config)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
// Register the image if needed
|
|
||||||
if repository != "" {
|
|
||||||
if err := builder.repositories.Set(repository, tag, img.ID, true); err != nil {
|
|
||||||
return img, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return img, nil
|
|
||||||
}
|
|
||||||
+99
-70
@@ -1,9 +1,9 @@
|
|||||||
package docker
|
package docker
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/dotcloud/docker/archive"
|
||||||
"github.com/dotcloud/docker/utils"
|
"github.com/dotcloud/docker/utils"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
@@ -23,14 +23,15 @@ type BuildFile interface {
|
|||||||
|
|
||||||
type buildFile struct {
|
type buildFile struct {
|
||||||
runtime *Runtime
|
runtime *Runtime
|
||||||
builder *Builder
|
|
||||||
srv *Server
|
srv *Server
|
||||||
|
|
||||||
image string
|
image string
|
||||||
maintainer string
|
maintainer string
|
||||||
config *Config
|
config *Config
|
||||||
context string
|
context string
|
||||||
verbose bool
|
verbose bool
|
||||||
|
utilizeCache bool
|
||||||
|
rm bool
|
||||||
|
|
||||||
tmpContainers map[string]struct{}
|
tmpContainers map[string]struct{}
|
||||||
tmpImages map[string]struct{}
|
tmpImages map[string]struct{}
|
||||||
@@ -38,15 +39,11 @@ type buildFile struct {
|
|||||||
out io.Writer
|
out io.Writer
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *buildFile) clearTmp(containers, images map[string]struct{}) {
|
func (b *buildFile) clearTmp(containers map[string]struct{}) {
|
||||||
for c := range containers {
|
for c := range containers {
|
||||||
tmp := b.runtime.Get(c)
|
tmp := b.runtime.Get(c)
|
||||||
b.runtime.Destroy(tmp)
|
b.runtime.Destroy(tmp)
|
||||||
utils.Debugf("Removing container %s", c)
|
fmt.Fprintf(b.out, "Removing intermediate container %s\n", utils.TruncateID(c))
|
||||||
}
|
|
||||||
for i := range images {
|
|
||||||
b.runtime.graph.Delete(i)
|
|
||||||
utils.Debugf("Removing image %s", i)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -55,7 +52,7 @@ func (b *buildFile) CmdFrom(name string) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
if b.runtime.graph.IsNotExist(err) {
|
if b.runtime.graph.IsNotExist(err) {
|
||||||
remote, tag := utils.ParseRepositoryTag(name)
|
remote, tag := utils.ParseRepositoryTag(name)
|
||||||
if err := b.srv.ImagePull(remote, tag, b.out, utils.NewStreamFormatter(false), nil); err != nil {
|
if err := b.srv.ImagePull(remote, tag, b.out, utils.NewStreamFormatter(false), nil, nil, true); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
image, err = b.runtime.repositories.LookupImage(name)
|
image, err = b.runtime.repositories.LookupImage(name)
|
||||||
@@ -68,6 +65,9 @@ func (b *buildFile) CmdFrom(name string) error {
|
|||||||
}
|
}
|
||||||
b.image = image.ID
|
b.image = image.ID
|
||||||
b.config = &Config{}
|
b.config = &Config{}
|
||||||
|
if image.Config != nil {
|
||||||
|
b.config = image.Config
|
||||||
|
}
|
||||||
if b.config.Env == nil || len(b.config.Env) == 0 {
|
if b.config.Env == nil || len(b.config.Env) == 0 {
|
||||||
b.config.Env = append(b.config.Env, "HOME=/", "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin")
|
b.config.Env = append(b.config.Env, "HOME=/", "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin")
|
||||||
}
|
}
|
||||||
@@ -92,17 +92,21 @@ func (b *buildFile) CmdRun(args string) error {
|
|||||||
b.config.Cmd = nil
|
b.config.Cmd = nil
|
||||||
MergeConfig(b.config, config)
|
MergeConfig(b.config, config)
|
||||||
|
|
||||||
|
defer func(cmd []string) { b.config.Cmd = cmd }(cmd)
|
||||||
|
|
||||||
utils.Debugf("Command to be executed: %v", b.config.Cmd)
|
utils.Debugf("Command to be executed: %v", b.config.Cmd)
|
||||||
|
|
||||||
if cache, err := b.srv.ImageGetCached(b.image, b.config); err != nil {
|
if b.utilizeCache {
|
||||||
return err
|
if cache, err := b.srv.ImageGetCached(b.image, b.config); err != nil {
|
||||||
} else if cache != nil {
|
return err
|
||||||
fmt.Fprintf(b.out, " ---> Using cache\n")
|
} else if cache != nil {
|
||||||
utils.Debugf("[BUILDER] Use cached version")
|
fmt.Fprintf(b.out, " ---> Using cache\n")
|
||||||
b.image = cache.ID
|
utils.Debugf("[BUILDER] Use cached version")
|
||||||
return nil
|
b.image = cache.ID
|
||||||
} else {
|
return nil
|
||||||
utils.Debugf("[BUILDER] Cache miss")
|
} else {
|
||||||
|
utils.Debugf("[BUILDER] Cache miss")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cid, err := b.run()
|
cid, err := b.run()
|
||||||
@@ -112,7 +116,7 @@ func (b *buildFile) CmdRun(args string) error {
|
|||||||
if err := b.commit(cid, cmd, "run"); err != nil {
|
if err := b.commit(cid, cmd, "run"); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
b.config.Cmd = cmd
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -167,9 +171,9 @@ func (b *buildFile) CmdEnv(args string) error {
|
|||||||
|
|
||||||
if envKey >= 0 {
|
if envKey >= 0 {
|
||||||
b.config.Env[envKey] = replacedVar
|
b.config.Env[envKey] = replacedVar
|
||||||
return nil
|
} else {
|
||||||
|
b.config.Env = append(b.config.Env, replacedVar)
|
||||||
}
|
}
|
||||||
b.config.Env = append(b.config.Env, replacedVar)
|
|
||||||
return b.commit("", b.config.Cmd, fmt.Sprintf("ENV %s", replacedVar))
|
return b.commit("", b.config.Cmd, fmt.Sprintf("ENV %s", replacedVar))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -192,6 +196,11 @@ func (b *buildFile) CmdExpose(args string) error {
|
|||||||
return b.commit("", b.config.Cmd, fmt.Sprintf("EXPOSE %v", ports))
|
return b.commit("", b.config.Cmd, fmt.Sprintf("EXPOSE %v", ports))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *buildFile) CmdUser(args string) error {
|
||||||
|
b.config.User = args
|
||||||
|
return b.commit("", b.config.Cmd, fmt.Sprintf("USER %v", args))
|
||||||
|
}
|
||||||
|
|
||||||
func (b *buildFile) CmdInsert(args string) error {
|
func (b *buildFile) CmdInsert(args string) error {
|
||||||
return fmt.Errorf("INSERT has been deprecated. Please use ADD instead")
|
return fmt.Errorf("INSERT has been deprecated. Please use ADD instead")
|
||||||
}
|
}
|
||||||
@@ -217,6 +226,11 @@ func (b *buildFile) CmdEntrypoint(args string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *buildFile) CmdWorkdir(workdir string) error {
|
||||||
|
b.config.WorkingDir = workdir
|
||||||
|
return b.commit("", b.config.Cmd, fmt.Sprintf("WORKDIR %v", workdir))
|
||||||
|
}
|
||||||
|
|
||||||
func (b *buildFile) CmdVolume(args string) error {
|
func (b *buildFile) CmdVolume(args string) error {
|
||||||
if args == "" {
|
if args == "" {
|
||||||
return fmt.Errorf("Volume cannot be empty")
|
return fmt.Errorf("Volume cannot be empty")
|
||||||
@@ -278,20 +292,20 @@ func (b *buildFile) addContext(container *Container, orig, dest string) error {
|
|||||||
}
|
}
|
||||||
fi, err := os.Stat(origPath)
|
fi, err := os.Stat(origPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return fmt.Errorf("%s: no such file or directory", orig)
|
||||||
}
|
}
|
||||||
if fi.IsDir() {
|
if fi.IsDir() {
|
||||||
if err := CopyWithTar(origPath, destPath); err != nil {
|
if err := archive.CopyWithTar(origPath, destPath); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// First try to unpack the source as an archive
|
// First try to unpack the source as an archive
|
||||||
} else if err := UntarPath(origPath, destPath); err != nil {
|
} else if err := archive.UntarPath(origPath, destPath); err != nil {
|
||||||
utils.Debugf("Couldn't untar %s to %s: %s", origPath, destPath, err)
|
utils.Debugf("Couldn't untar %s to %s: %s", origPath, destPath, err)
|
||||||
// If that fails, just copy it as a regular file
|
// If that fails, just copy it as a regular file
|
||||||
if err := os.MkdirAll(path.Dir(destPath), 0755); err != nil {
|
if err := os.MkdirAll(path.Dir(destPath), 0755); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := CopyWithTar(origPath, destPath); err != nil {
|
if err := archive.CopyWithTar(origPath, destPath); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -322,7 +336,7 @@ func (b *buildFile) CmdAdd(args string) error {
|
|||||||
|
|
||||||
b.config.Image = b.image
|
b.config.Image = b.image
|
||||||
// Create the container and start it
|
// Create the container and start it
|
||||||
container, err := b.builder.Create(b.config)
|
container, _, err := b.runtime.Create(b.config, "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -357,7 +371,7 @@ func (b *buildFile) run() (string, error) {
|
|||||||
b.config.Image = b.image
|
b.config.Image = b.image
|
||||||
|
|
||||||
// Create the container and start it
|
// Create the container and start it
|
||||||
c, err := b.builder.Create(b.config)
|
c, _, err := b.runtime.Create(b.config, "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
@@ -368,15 +382,21 @@ func (b *buildFile) run() (string, error) {
|
|||||||
c.Path = b.config.Cmd[0]
|
c.Path = b.config.Cmd[0]
|
||||||
c.Args = b.config.Cmd[1:]
|
c.Args = b.config.Cmd[1:]
|
||||||
|
|
||||||
|
var errCh chan error
|
||||||
|
|
||||||
|
if b.verbose {
|
||||||
|
errCh = utils.Go(func() error {
|
||||||
|
return <-c.Attach(nil, nil, b.out, b.out)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
//start the container
|
//start the container
|
||||||
hostConfig := &HostConfig{}
|
if err := c.Start(); err != nil {
|
||||||
if err := c.Start(hostConfig); err != nil {
|
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
if b.verbose {
|
if errCh != nil {
|
||||||
err = <-c.Attach(nil, nil, b.out, b.out)
|
if err := <-errCh; err != nil {
|
||||||
if err != nil {
|
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -400,20 +420,26 @@ func (b *buildFile) commit(id string, autoCmd []string, comment string) error {
|
|||||||
b.config.Cmd = []string{"/bin/sh", "-c", "#(nop) " + comment}
|
b.config.Cmd = []string{"/bin/sh", "-c", "#(nop) " + comment}
|
||||||
defer func(cmd []string) { b.config.Cmd = cmd }(cmd)
|
defer func(cmd []string) { b.config.Cmd = cmd }(cmd)
|
||||||
|
|
||||||
if cache, err := b.srv.ImageGetCached(b.image, b.config); err != nil {
|
if b.utilizeCache {
|
||||||
return err
|
if cache, err := b.srv.ImageGetCached(b.image, b.config); err != nil {
|
||||||
} else if cache != nil {
|
return err
|
||||||
fmt.Fprintf(b.out, " ---> Using cache\n")
|
} else if cache != nil {
|
||||||
utils.Debugf("[BUILDER] Use cached version")
|
fmt.Fprintf(b.out, " ---> Using cache\n")
|
||||||
b.image = cache.ID
|
utils.Debugf("[BUILDER] Use cached version")
|
||||||
return nil
|
b.image = cache.ID
|
||||||
} else {
|
return nil
|
||||||
utils.Debugf("[BUILDER] Cache miss")
|
} else {
|
||||||
|
utils.Debugf("[BUILDER] Cache miss")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
container, err := b.builder.Create(b.config)
|
|
||||||
|
container, warnings, err := b.runtime.Create(b.config, "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
for _, warning := range warnings {
|
||||||
|
fmt.Fprintf(b.out, " ---> [Warning] %s\n", warning)
|
||||||
|
}
|
||||||
b.tmpContainers[container.ID] = struct{}{}
|
b.tmpContainers[container.ID] = struct{}{}
|
||||||
fmt.Fprintf(b.out, " ---> Running in %s\n", utils.TruncateID(container.ID))
|
fmt.Fprintf(b.out, " ---> Running in %s\n", utils.TruncateID(container.ID))
|
||||||
id = container.ID
|
id = container.ID
|
||||||
@@ -432,7 +458,7 @@ func (b *buildFile) commit(id string, autoCmd []string, comment string) error {
|
|||||||
autoConfig := *b.config
|
autoConfig := *b.config
|
||||||
autoConfig.Cmd = autoCmd
|
autoConfig.Cmd = autoCmd
|
||||||
// Commit the container
|
// Commit the container
|
||||||
image, err := b.builder.Commit(container, "", "", "", b.maintainer, &autoConfig)
|
image, err := b.runtime.Commit(container, "", "", "", b.maintainer, &autoConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -441,34 +467,32 @@ func (b *buildFile) commit(id string, autoCmd []string, comment string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Long lines can be split with a backslash
|
||||||
|
var lineContinuation = regexp.MustCompile(`\s*\\\s*\n`)
|
||||||
|
|
||||||
func (b *buildFile) Build(context io.Reader) (string, error) {
|
func (b *buildFile) Build(context io.Reader) (string, error) {
|
||||||
// FIXME: @creack any reason for using /tmp instead of ""?
|
|
||||||
// FIXME: @creack "name" is a terrible variable name
|
// FIXME: @creack "name" is a terrible variable name
|
||||||
name, err := ioutil.TempDir("/tmp", "docker-build")
|
name, err := ioutil.TempDir("", "docker-build")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
if err := Untar(context, name); err != nil {
|
if err := archive.Untar(context, name); err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
defer os.RemoveAll(name)
|
defer os.RemoveAll(name)
|
||||||
b.context = name
|
b.context = name
|
||||||
dockerfile, err := os.Open(path.Join(name, "Dockerfile"))
|
filename := path.Join(name, "Dockerfile")
|
||||||
if err != nil {
|
if _, err := os.Stat(filename); os.IsNotExist(err) {
|
||||||
return "", fmt.Errorf("Can't build a directory with no Dockerfile")
|
return "", fmt.Errorf("Can't build a directory with no Dockerfile")
|
||||||
}
|
}
|
||||||
// FIXME: "file" is also a terrible variable name ;)
|
fileBytes, err := ioutil.ReadFile(filename)
|
||||||
file := bufio.NewReader(dockerfile)
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
dockerfile := string(fileBytes)
|
||||||
|
dockerfile = lineContinuation.ReplaceAllString(dockerfile, "")
|
||||||
stepN := 0
|
stepN := 0
|
||||||
for {
|
for _, line := range strings.Split(dockerfile, "\n") {
|
||||||
line, err := file.ReadString('\n')
|
|
||||||
if err != nil {
|
|
||||||
if err == io.EOF && line == "" {
|
|
||||||
break
|
|
||||||
} else if err != io.EOF {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
line = strings.Trim(strings.Replace(line, "\t", " ", -1), " \t\r\n")
|
line = strings.Trim(strings.Replace(line, "\t", " ", -1), " \t\r\n")
|
||||||
// Skip comments and empty line
|
// Skip comments and empty line
|
||||||
if len(line) == 0 || line[0] == '#' {
|
if len(line) == 0 || line[0] == '#' {
|
||||||
@@ -480,15 +504,16 @@ func (b *buildFile) Build(context io.Reader) (string, error) {
|
|||||||
}
|
}
|
||||||
instruction := strings.ToLower(strings.Trim(tmp[0], " "))
|
instruction := strings.ToLower(strings.Trim(tmp[0], " "))
|
||||||
arguments := strings.Trim(tmp[1], " ")
|
arguments := strings.Trim(tmp[1], " ")
|
||||||
stepN += 1
|
|
||||||
// FIXME: only count known instructions as build steps
|
|
||||||
fmt.Fprintf(b.out, "Step %d : %s %s\n", stepN, strings.ToUpper(instruction), arguments)
|
|
||||||
|
|
||||||
method, exists := reflect.TypeOf(b).MethodByName("Cmd" + strings.ToUpper(instruction[:1]) + strings.ToLower(instruction[1:]))
|
method, exists := reflect.TypeOf(b).MethodByName("Cmd" + strings.ToUpper(instruction[:1]) + strings.ToLower(instruction[1:]))
|
||||||
if !exists {
|
if !exists {
|
||||||
fmt.Fprintf(b.out, "# Skipping unknown instruction %s\n", strings.ToUpper(instruction))
|
fmt.Fprintf(b.out, "# Skipping unknown instruction %s\n", strings.ToUpper(instruction))
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
stepN += 1
|
||||||
|
fmt.Fprintf(b.out, "Step %d : %s %s\n", stepN, strings.ToUpper(instruction), arguments)
|
||||||
|
|
||||||
ret := method.Func.Call([]reflect.Value{reflect.ValueOf(b), reflect.ValueOf(arguments)})[0].Interface()
|
ret := method.Func.Call([]reflect.Value{reflect.ValueOf(b), reflect.ValueOf(arguments)})[0].Interface()
|
||||||
if ret != nil {
|
if ret != nil {
|
||||||
return "", ret.(error)
|
return "", ret.(error)
|
||||||
@@ -498,14 +523,16 @@ func (b *buildFile) Build(context io.Reader) (string, error) {
|
|||||||
}
|
}
|
||||||
if b.image != "" {
|
if b.image != "" {
|
||||||
fmt.Fprintf(b.out, "Successfully built %s\n", utils.TruncateID(b.image))
|
fmt.Fprintf(b.out, "Successfully built %s\n", utils.TruncateID(b.image))
|
||||||
|
if b.rm {
|
||||||
|
b.clearTmp(b.tmpContainers)
|
||||||
|
}
|
||||||
return b.image, nil
|
return b.image, nil
|
||||||
}
|
}
|
||||||
return "", fmt.Errorf("An error occured during the build\n")
|
return "", fmt.Errorf("An error occurred during the build\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewBuildFile(srv *Server, out io.Writer, verbose bool) BuildFile {
|
func NewBuildFile(srv *Server, out io.Writer, verbose, utilizeCache, rm bool) BuildFile {
|
||||||
return &buildFile{
|
return &buildFile{
|
||||||
builder: NewBuilder(srv.runtime),
|
|
||||||
runtime: srv.runtime,
|
runtime: srv.runtime,
|
||||||
srv: srv,
|
srv: srv,
|
||||||
config: &Config{},
|
config: &Config{},
|
||||||
@@ -513,5 +540,7 @@ func NewBuildFile(srv *Server, out io.Writer, verbose bool) BuildFile {
|
|||||||
tmpContainers: make(map[string]struct{}),
|
tmpContainers: make(map[string]struct{}),
|
||||||
tmpImages: make(map[string]struct{}),
|
tmpImages: make(map[string]struct{}),
|
||||||
verbose: verbose,
|
verbose: verbose,
|
||||||
|
utilizeCache: utilizeCache,
|
||||||
|
rm: rm,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -99,7 +99,7 @@ func Changes(layers []string, rw string) ([]Change, error) {
|
|||||||
changes = append(changes, change)
|
changes = append(changes, change)
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil && !os.IsNotExist(err) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return changes, nil
|
return changes, nil
|
||||||
|
|||||||
+1178
-353
File diff suppressed because it is too large
Load Diff
@@ -1,380 +0,0 @@
|
|||||||
package docker
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bufio"
|
|
||||||
"fmt"
|
|
||||||
"github.com/dotcloud/docker/utils"
|
|
||||||
"io"
|
|
||||||
"io/ioutil"
|
|
||||||
"strings"
|
|
||||||
"testing"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
func closeWrap(args ...io.Closer) error {
|
|
||||||
e := false
|
|
||||||
ret := fmt.Errorf("Error closing elements")
|
|
||||||
for _, c := range args {
|
|
||||||
if err := c.Close(); err != nil {
|
|
||||||
e = true
|
|
||||||
ret = fmt.Errorf("%s\n%s", ret, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if e {
|
|
||||||
return ret
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func setTimeout(t *testing.T, msg string, d time.Duration, f func()) {
|
|
||||||
c := make(chan bool)
|
|
||||||
|
|
||||||
// Make sure we are not too long
|
|
||||||
go func() {
|
|
||||||
time.Sleep(d)
|
|
||||||
c <- true
|
|
||||||
}()
|
|
||||||
go func() {
|
|
||||||
f()
|
|
||||||
c <- false
|
|
||||||
}()
|
|
||||||
if <-c && msg != "" {
|
|
||||||
t.Fatal(msg)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func assertPipe(input, output string, r io.Reader, w io.Writer, count int) error {
|
|
||||||
for i := 0; i < count; i++ {
|
|
||||||
if _, err := w.Write([]byte(input)); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
o, err := bufio.NewReader(r).ReadString('\n')
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if strings.Trim(o, " \r\n") != output {
|
|
||||||
return fmt.Errorf("Unexpected output. Expected [%s], received [%s]", output, o)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// TestRunHostname checks that 'docker run -h' correctly sets a custom hostname
|
|
||||||
func TestRunHostname(t *testing.T) {
|
|
||||||
stdout, stdoutPipe := io.Pipe()
|
|
||||||
|
|
||||||
cli := NewDockerCli(nil, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr)
|
|
||||||
defer cleanup(globalRuntime)
|
|
||||||
|
|
||||||
c := make(chan struct{})
|
|
||||||
go func() {
|
|
||||||
defer close(c)
|
|
||||||
if err := cli.CmdRun("-h", "foobar", unitTestImageID, "hostname"); err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
setTimeout(t, "Reading command output time out", 2*time.Second, func() {
|
|
||||||
cmdOutput, err := bufio.NewReader(stdout).ReadString('\n')
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
if cmdOutput != "foobar\n" {
|
|
||||||
t.Fatalf("'hostname' should display '%s', not '%s'", "foobar\n", cmdOutput)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
setTimeout(t, "CmdRun timed out", 5*time.Second, func() {
|
|
||||||
<-c
|
|
||||||
})
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestRunExit(t *testing.T) {
|
|
||||||
stdin, stdinPipe := io.Pipe()
|
|
||||||
stdout, stdoutPipe := io.Pipe()
|
|
||||||
|
|
||||||
cli := NewDockerCli(stdin, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr)
|
|
||||||
defer cleanup(globalRuntime)
|
|
||||||
|
|
||||||
c1 := make(chan struct{})
|
|
||||||
go func() {
|
|
||||||
cli.CmdRun("-i", unitTestImageID, "/bin/cat")
|
|
||||||
close(c1)
|
|
||||||
}()
|
|
||||||
|
|
||||||
setTimeout(t, "Read/Write assertion timed out", 2*time.Second, func() {
|
|
||||||
if err := assertPipe("hello\n", "hello", stdout, stdinPipe, 15); err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
container := globalRuntime.List()[0]
|
|
||||||
|
|
||||||
// Closing /bin/cat stdin, expect it to exit
|
|
||||||
if err := stdin.Close(); err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// as the process exited, CmdRun must finish and unblock. Wait for it
|
|
||||||
setTimeout(t, "Waiting for CmdRun timed out", 10*time.Second, func() {
|
|
||||||
<-c1
|
|
||||||
|
|
||||||
go func() {
|
|
||||||
cli.CmdWait(container.ID)
|
|
||||||
}()
|
|
||||||
|
|
||||||
if _, err := bufio.NewReader(stdout).ReadString('\n'); err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
// Make sure that the client has been disconnected
|
|
||||||
setTimeout(t, "The client should have been disconnected once the remote process exited.", 2*time.Second, func() {
|
|
||||||
// Expecting pipe i/o error, just check that read does not block
|
|
||||||
stdin.Read([]byte{})
|
|
||||||
})
|
|
||||||
|
|
||||||
// Cleanup pipes
|
|
||||||
if err := closeWrap(stdin, stdinPipe, stdout, stdoutPipe); err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Expected behaviour: the process dies when the client disconnects
|
|
||||||
func TestRunDisconnect(t *testing.T) {
|
|
||||||
|
|
||||||
stdin, stdinPipe := io.Pipe()
|
|
||||||
stdout, stdoutPipe := io.Pipe()
|
|
||||||
|
|
||||||
cli := NewDockerCli(stdin, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr)
|
|
||||||
defer cleanup(globalRuntime)
|
|
||||||
|
|
||||||
c1 := make(chan struct{})
|
|
||||||
go func() {
|
|
||||||
// We're simulating a disconnect so the return value doesn't matter. What matters is the
|
|
||||||
// fact that CmdRun returns.
|
|
||||||
cli.CmdRun("-i", unitTestImageID, "/bin/cat")
|
|
||||||
close(c1)
|
|
||||||
}()
|
|
||||||
|
|
||||||
setTimeout(t, "Read/Write assertion timed out", 2*time.Second, func() {
|
|
||||||
if err := assertPipe("hello\n", "hello", stdout, stdinPipe, 15); err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
// Close pipes (simulate disconnect)
|
|
||||||
if err := closeWrap(stdin, stdinPipe, stdout, stdoutPipe); err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// as the pipes are close, we expect the process to die,
|
|
||||||
// therefore CmdRun to unblock. Wait for CmdRun
|
|
||||||
setTimeout(t, "Waiting for CmdRun timed out", 2*time.Second, func() {
|
|
||||||
<-c1
|
|
||||||
})
|
|
||||||
|
|
||||||
// Client disconnect after run -i should cause stdin to be closed, which should
|
|
||||||
// cause /bin/cat to exit.
|
|
||||||
setTimeout(t, "Waiting for /bin/cat to exit timed out", 2*time.Second, func() {
|
|
||||||
container := globalRuntime.List()[0]
|
|
||||||
container.Wait()
|
|
||||||
if container.State.Running {
|
|
||||||
t.Fatalf("/bin/cat is still running after closing stdin")
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Expected behaviour: the process dies when the client disconnects
|
|
||||||
func TestRunDisconnectTty(t *testing.T) {
|
|
||||||
|
|
||||||
stdin, stdinPipe := io.Pipe()
|
|
||||||
stdout, stdoutPipe := io.Pipe()
|
|
||||||
|
|
||||||
cli := NewDockerCli(stdin, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr)
|
|
||||||
defer cleanup(globalRuntime)
|
|
||||||
|
|
||||||
c1 := make(chan struct{})
|
|
||||||
go func() {
|
|
||||||
// We're simulating a disconnect so the return value doesn't matter. What matters is the
|
|
||||||
// fact that CmdRun returns.
|
|
||||||
if err := cli.CmdRun("-i", "-t", unitTestImageID, "/bin/cat"); err != nil {
|
|
||||||
utils.Debugf("Error CmdRun: %s\n", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
close(c1)
|
|
||||||
}()
|
|
||||||
|
|
||||||
setTimeout(t, "Waiting for the container to be started timed out", 10*time.Second, func() {
|
|
||||||
for {
|
|
||||||
// Client disconnect after run -i should keep stdin out in TTY mode
|
|
||||||
l := globalRuntime.List()
|
|
||||||
if len(l) == 1 && l[0].State.Running {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
time.Sleep(10 * time.Millisecond)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
// Client disconnect after run -i should keep stdin out in TTY mode
|
|
||||||
container := globalRuntime.List()[0]
|
|
||||||
|
|
||||||
setTimeout(t, "Read/Write assertion timed out", 2000*time.Second, func() {
|
|
||||||
if err := assertPipe("hello\n", "hello", stdout, stdinPipe, 15); err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
// Close pipes (simulate disconnect)
|
|
||||||
if err := closeWrap(stdin, stdinPipe, stdout, stdoutPipe); err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// In tty mode, we expect the process to stay alive even after client's stdin closes.
|
|
||||||
// Do not wait for run to finish
|
|
||||||
|
|
||||||
// Give some time to monitor to do his thing
|
|
||||||
container.WaitTimeout(500 * time.Millisecond)
|
|
||||||
if !container.State.Running {
|
|
||||||
t.Fatalf("/bin/cat should still be running after closing stdin (tty mode)")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TestAttachStdin checks attaching to stdin without stdout and stderr.
|
|
||||||
// 'docker run -i -a stdin' should sends the client's stdin to the command,
|
|
||||||
// then detach from it and print the container id.
|
|
||||||
func TestRunAttachStdin(t *testing.T) {
|
|
||||||
|
|
||||||
stdin, stdinPipe := io.Pipe()
|
|
||||||
stdout, stdoutPipe := io.Pipe()
|
|
||||||
|
|
||||||
cli := NewDockerCli(stdin, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr)
|
|
||||||
defer cleanup(globalRuntime)
|
|
||||||
|
|
||||||
ch := make(chan struct{})
|
|
||||||
go func() {
|
|
||||||
defer close(ch)
|
|
||||||
cli.CmdRun("-i", "-a", "stdin", unitTestImageID, "sh", "-c", "echo hello && cat")
|
|
||||||
}()
|
|
||||||
|
|
||||||
// Send input to the command, close stdin
|
|
||||||
setTimeout(t, "Write timed out", 10*time.Second, func() {
|
|
||||||
if _, err := stdinPipe.Write([]byte("hi there\n")); err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
if err := stdinPipe.Close(); err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
container := globalRuntime.List()[0]
|
|
||||||
|
|
||||||
// Check output
|
|
||||||
setTimeout(t, "Reading command output time out", 10*time.Second, func() {
|
|
||||||
cmdOutput, err := bufio.NewReader(stdout).ReadString('\n')
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
if cmdOutput != container.ShortID()+"\n" {
|
|
||||||
t.Fatalf("Wrong output: should be '%s', not '%s'\n", container.ShortID()+"\n", cmdOutput)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
// wait for CmdRun to return
|
|
||||||
setTimeout(t, "Waiting for CmdRun timed out", 5*time.Second, func() {
|
|
||||||
// Unblock hijack end
|
|
||||||
stdout.Read([]byte{})
|
|
||||||
<-ch
|
|
||||||
})
|
|
||||||
|
|
||||||
setTimeout(t, "Waiting for command to exit timed out", 5*time.Second, func() {
|
|
||||||
container.Wait()
|
|
||||||
})
|
|
||||||
|
|
||||||
// Check logs
|
|
||||||
if cmdLogs, err := container.ReadLog("json"); err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
} else {
|
|
||||||
if output, err := ioutil.ReadAll(cmdLogs); err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
} else {
|
|
||||||
expectedLogs := []string{"{\"log\":\"hello\\n\",\"stream\":\"stdout\"", "{\"log\":\"hi there\\n\",\"stream\":\"stdout\""}
|
|
||||||
for _, expectedLog := range expectedLogs {
|
|
||||||
if !strings.Contains(string(output), expectedLog) {
|
|
||||||
t.Fatalf("Unexpected logs: should contains '%s', it is not '%s'\n", expectedLog, output)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Expected behaviour, the process stays alive when the client disconnects
|
|
||||||
func TestAttachDisconnect(t *testing.T) {
|
|
||||||
stdin, stdinPipe := io.Pipe()
|
|
||||||
stdout, stdoutPipe := io.Pipe()
|
|
||||||
|
|
||||||
cli := NewDockerCli(stdin, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr)
|
|
||||||
defer cleanup(globalRuntime)
|
|
||||||
|
|
||||||
go func() {
|
|
||||||
// Start a process in daemon mode
|
|
||||||
if err := cli.CmdRun("-d", "-i", unitTestImageID, "/bin/cat"); err != nil {
|
|
||||||
utils.Debugf("Error CmdRun: %s\n", err)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
setTimeout(t, "Waiting for CmdRun timed out", 10*time.Second, func() {
|
|
||||||
if _, err := bufio.NewReader(stdout).ReadString('\n'); err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
setTimeout(t, "Waiting for the container to be started timed out", 10*time.Second, func() {
|
|
||||||
for {
|
|
||||||
l := globalRuntime.List()
|
|
||||||
if len(l) == 1 && l[0].State.Running {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
time.Sleep(10 * time.Millisecond)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
container := globalRuntime.List()[0]
|
|
||||||
|
|
||||||
// Attach to it
|
|
||||||
c1 := make(chan struct{})
|
|
||||||
go func() {
|
|
||||||
// We're simulating a disconnect so the return value doesn't matter. What matters is the
|
|
||||||
// fact that CmdAttach returns.
|
|
||||||
cli.CmdAttach(container.ID)
|
|
||||||
close(c1)
|
|
||||||
}()
|
|
||||||
|
|
||||||
setTimeout(t, "First read/write assertion timed out", 2*time.Second, func() {
|
|
||||||
if err := assertPipe("hello\n", "hello", stdout, stdinPipe, 15); err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
// Close pipes (client disconnects)
|
|
||||||
if err := closeWrap(stdin, stdinPipe, stdout, stdoutPipe); err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wait for attach to finish, the client disconnected, therefore, Attach finished his job
|
|
||||||
setTimeout(t, "Waiting for CmdAttach timed out", 2*time.Second, func() {
|
|
||||||
<-c1
|
|
||||||
})
|
|
||||||
|
|
||||||
// We closed stdin, expect /bin/cat to still be running
|
|
||||||
// Wait a little bit to make sure container.monitor() did his thing
|
|
||||||
err := container.WaitTimeout(500 * time.Millisecond)
|
|
||||||
if err == nil || !container.State.Running {
|
|
||||||
t.Fatalf("/bin/cat is not running after closing stdin")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try to avoid the timeoout in destroy. Best effort, don't check error
|
|
||||||
cStdin, _ := container.StdinPipe()
|
|
||||||
cStdin.Close()
|
|
||||||
container.Wait()
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
package docker
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/dotcloud/docker/engine"
|
||||||
|
"net"
|
||||||
|
)
|
||||||
|
|
||||||
|
// FIXME: separate runtime configuration from http api configuration
|
||||||
|
type DaemonConfig struct {
|
||||||
|
Pidfile string
|
||||||
|
Root string
|
||||||
|
AutoRestart bool
|
||||||
|
EnableCors bool
|
||||||
|
Dns []string
|
||||||
|
EnableIptables bool
|
||||||
|
BridgeIface string
|
||||||
|
DefaultIp net.IP
|
||||||
|
InterContainerCommunication bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// ConfigFromJob creates and returns a new DaemonConfig object
|
||||||
|
// by parsing the contents of a job's environment.
|
||||||
|
func ConfigFromJob(job *engine.Job) *DaemonConfig {
|
||||||
|
var config DaemonConfig
|
||||||
|
config.Pidfile = job.Getenv("Pidfile")
|
||||||
|
config.Root = job.Getenv("Root")
|
||||||
|
config.AutoRestart = job.GetenvBool("AutoRestart")
|
||||||
|
config.EnableCors = job.GetenvBool("EnableCors")
|
||||||
|
if dns := job.Getenv("Dns"); dns != "" {
|
||||||
|
config.Dns = []string{dns}
|
||||||
|
}
|
||||||
|
config.EnableIptables = job.GetenvBool("EnableIptables")
|
||||||
|
if br := job.Getenv("BridgeIface"); br != "" {
|
||||||
|
config.BridgeIface = br
|
||||||
|
} else {
|
||||||
|
config.BridgeIface = DefaultNetworkBridge
|
||||||
|
}
|
||||||
|
config.DefaultIp = net.ParseIP(job.Getenv("DefaultIp"))
|
||||||
|
config.InterContainerCommunication = job.GetenvBool("InterContainerCommunication")
|
||||||
|
return &config
|
||||||
|
}
|
||||||
+149
@@ -0,0 +1,149 @@
|
|||||||
|
package docker
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestCompareConfig(t *testing.T) {
|
||||||
|
volumes1 := make(map[string]struct{})
|
||||||
|
volumes1["/test1"] = struct{}{}
|
||||||
|
config1 := Config{
|
||||||
|
Dns: []string{"1.1.1.1", "2.2.2.2"},
|
||||||
|
PortSpecs: []string{"1111:1111", "2222:2222"},
|
||||||
|
Env: []string{"VAR1=1", "VAR2=2"},
|
||||||
|
VolumesFrom: "11111111",
|
||||||
|
Volumes: volumes1,
|
||||||
|
}
|
||||||
|
config2 := Config{
|
||||||
|
Dns: []string{"0.0.0.0", "2.2.2.2"},
|
||||||
|
PortSpecs: []string{"1111:1111", "2222:2222"},
|
||||||
|
Env: []string{"VAR1=1", "VAR2=2"},
|
||||||
|
VolumesFrom: "11111111",
|
||||||
|
Volumes: volumes1,
|
||||||
|
}
|
||||||
|
config3 := Config{
|
||||||
|
Dns: []string{"1.1.1.1", "2.2.2.2"},
|
||||||
|
PortSpecs: []string{"0000:0000", "2222:2222"},
|
||||||
|
Env: []string{"VAR1=1", "VAR2=2"},
|
||||||
|
VolumesFrom: "11111111",
|
||||||
|
Volumes: volumes1,
|
||||||
|
}
|
||||||
|
config4 := Config{
|
||||||
|
Dns: []string{"1.1.1.1", "2.2.2.2"},
|
||||||
|
PortSpecs: []string{"0000:0000", "2222:2222"},
|
||||||
|
Env: []string{"VAR1=1", "VAR2=2"},
|
||||||
|
VolumesFrom: "22222222",
|
||||||
|
Volumes: volumes1,
|
||||||
|
}
|
||||||
|
volumes2 := make(map[string]struct{})
|
||||||
|
volumes2["/test2"] = struct{}{}
|
||||||
|
config5 := Config{
|
||||||
|
Dns: []string{"1.1.1.1", "2.2.2.2"},
|
||||||
|
PortSpecs: []string{"0000:0000", "2222:2222"},
|
||||||
|
Env: []string{"VAR1=1", "VAR2=2"},
|
||||||
|
VolumesFrom: "11111111",
|
||||||
|
Volumes: volumes2,
|
||||||
|
}
|
||||||
|
if CompareConfig(&config1, &config2) {
|
||||||
|
t.Fatalf("CompareConfig should return false, Dns are different")
|
||||||
|
}
|
||||||
|
if CompareConfig(&config1, &config3) {
|
||||||
|
t.Fatalf("CompareConfig should return false, PortSpecs are different")
|
||||||
|
}
|
||||||
|
if CompareConfig(&config1, &config4) {
|
||||||
|
t.Fatalf("CompareConfig should return false, VolumesFrom are different")
|
||||||
|
}
|
||||||
|
if CompareConfig(&config1, &config5) {
|
||||||
|
t.Fatalf("CompareConfig should return false, Volumes are different")
|
||||||
|
}
|
||||||
|
if !CompareConfig(&config1, &config1) {
|
||||||
|
t.Fatalf("CompareConfig should return true")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMergeConfig(t *testing.T) {
|
||||||
|
volumesImage := make(map[string]struct{})
|
||||||
|
volumesImage["/test1"] = struct{}{}
|
||||||
|
volumesImage["/test2"] = struct{}{}
|
||||||
|
configImage := &Config{
|
||||||
|
Dns: []string{"1.1.1.1", "2.2.2.2"},
|
||||||
|
PortSpecs: []string{"1111:1111", "2222:2222"},
|
||||||
|
Env: []string{"VAR1=1", "VAR2=2"},
|
||||||
|
VolumesFrom: "1111",
|
||||||
|
Volumes: volumesImage,
|
||||||
|
}
|
||||||
|
|
||||||
|
volumesUser := make(map[string]struct{})
|
||||||
|
volumesUser["/test3"] = struct{}{}
|
||||||
|
configUser := &Config{
|
||||||
|
Dns: []string{"3.3.3.3"},
|
||||||
|
PortSpecs: []string{"3333:2222", "3333:3333"},
|
||||||
|
Env: []string{"VAR2=3", "VAR3=3"},
|
||||||
|
Volumes: volumesUser,
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := MergeConfig(configUser, configImage); err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(configUser.Dns) != 3 {
|
||||||
|
t.Fatalf("Expected 3 dns, 1.1.1.1, 2.2.2.2 and 3.3.3.3, found %d", len(configUser.Dns))
|
||||||
|
}
|
||||||
|
for _, dns := range configUser.Dns {
|
||||||
|
if dns != "1.1.1.1" && dns != "2.2.2.2" && dns != "3.3.3.3" {
|
||||||
|
t.Fatalf("Expected 1.1.1.1 or 2.2.2.2 or 3.3.3.3, found %s", dns)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(configUser.ExposedPorts) != 3 {
|
||||||
|
t.Fatalf("Expected 3 ExposedPorts, 1111, 2222 and 3333, found %d", len(configUser.ExposedPorts))
|
||||||
|
}
|
||||||
|
for portSpecs := range configUser.ExposedPorts {
|
||||||
|
if portSpecs.Port() != "1111" && portSpecs.Port() != "2222" && portSpecs.Port() != "3333" {
|
||||||
|
t.Fatalf("Expected 1111 or 2222 or 3333, found %s", portSpecs)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(configUser.Env) != 3 {
|
||||||
|
t.Fatalf("Expected 3 env var, VAR1=1, VAR2=3 and VAR3=3, found %d", len(configUser.Env))
|
||||||
|
}
|
||||||
|
for _, env := range configUser.Env {
|
||||||
|
if env != "VAR1=1" && env != "VAR2=3" && env != "VAR3=3" {
|
||||||
|
t.Fatalf("Expected VAR1=1 or VAR2=3 or VAR3=3, found %s", env)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(configUser.Volumes) != 3 {
|
||||||
|
t.Fatalf("Expected 3 volumes, /test1, /test2 and /test3, found %d", len(configUser.Volumes))
|
||||||
|
}
|
||||||
|
for v := range configUser.Volumes {
|
||||||
|
if v != "/test1" && v != "/test2" && v != "/test3" {
|
||||||
|
t.Fatalf("Expected /test1 or /test2 or /test3, found %s", v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if configUser.VolumesFrom != "1111" {
|
||||||
|
t.Fatalf("Expected VolumesFrom to be 1111, found %s", configUser.VolumesFrom)
|
||||||
|
}
|
||||||
|
|
||||||
|
ports, _, err := parsePortSpecs([]string{"0000"})
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
configImage2 := &Config{
|
||||||
|
ExposedPorts: ports,
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := MergeConfig(configUser, configImage2); err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(configUser.ExposedPorts) != 4 {
|
||||||
|
t.Fatalf("Expected 4 ExposedPorts, 0000, 1111, 2222 and 3333, found %d", len(configUser.ExposedPorts))
|
||||||
|
}
|
||||||
|
for portSpecs := range configUser.ExposedPorts {
|
||||||
|
if portSpecs.Port() != "0000" && portSpecs.Port() != "1111" && portSpecs.Port() != "2222" && portSpecs.Port() != "3333" {
|
||||||
|
t.Fatalf("Expected 0000 or 1111 or 2222 or 3333, found %s", portSpecs)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+690
-352
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,161 @@
|
|||||||
|
package docker
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestParseLxcConfOpt(t *testing.T) {
|
||||||
|
opts := []string{"lxc.utsname=docker", "lxc.utsname = docker "}
|
||||||
|
|
||||||
|
for _, o := range opts {
|
||||||
|
k, v, err := parseLxcOpt(o)
|
||||||
|
if err != nil {
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
if k != "lxc.utsname" {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
if v != "docker" {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestParseNetworkOptsPrivateOnly(t *testing.T) {
|
||||||
|
ports, bindings, err := parsePortSpecs([]string{"192.168.1.100::80"})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if len(ports) != 1 {
|
||||||
|
t.Logf("Expected 1 got %d", len(ports))
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
if len(bindings) != 1 {
|
||||||
|
t.Logf("Expected 1 got %d", len(bindings))
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
for k := range ports {
|
||||||
|
if k.Proto() != "tcp" {
|
||||||
|
t.Logf("Expected tcp got %s", k.Proto())
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
if k.Port() != "80" {
|
||||||
|
t.Logf("Expected 80 got %s", k.Port())
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
b, exists := bindings[k]
|
||||||
|
if !exists {
|
||||||
|
t.Log("Binding does not exist")
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
if len(b) != 1 {
|
||||||
|
t.Logf("Expected 1 got %d", len(b))
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
s := b[0]
|
||||||
|
if s.HostPort != "" {
|
||||||
|
t.Logf("Expected \"\" got %s", s.HostPort)
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
if s.HostIp != "192.168.1.100" {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestParseNetworkOptsPublic(t *testing.T) {
|
||||||
|
ports, bindings, err := parsePortSpecs([]string{"192.168.1.100:8080:80"})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if len(ports) != 1 {
|
||||||
|
t.Logf("Expected 1 got %d", len(ports))
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
if len(bindings) != 1 {
|
||||||
|
t.Logf("Expected 1 got %d", len(bindings))
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
for k := range ports {
|
||||||
|
if k.Proto() != "tcp" {
|
||||||
|
t.Logf("Expected tcp got %s", k.Proto())
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
if k.Port() != "80" {
|
||||||
|
t.Logf("Expected 80 got %s", k.Port())
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
b, exists := bindings[k]
|
||||||
|
if !exists {
|
||||||
|
t.Log("Binding does not exist")
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
if len(b) != 1 {
|
||||||
|
t.Logf("Expected 1 got %d", len(b))
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
s := b[0]
|
||||||
|
if s.HostPort != "8080" {
|
||||||
|
t.Logf("Expected 8080 got %s", s.HostPort)
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
if s.HostIp != "192.168.1.100" {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestParseNetworkOptsUdp(t *testing.T) {
|
||||||
|
ports, bindings, err := parsePortSpecs([]string{"192.168.1.100::6000/udp"})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if len(ports) != 1 {
|
||||||
|
t.Logf("Expected 1 got %d", len(ports))
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
if len(bindings) != 1 {
|
||||||
|
t.Logf("Expected 1 got %d", len(bindings))
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
for k := range ports {
|
||||||
|
if k.Proto() != "udp" {
|
||||||
|
t.Logf("Expected udp got %s", k.Proto())
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
if k.Port() != "6000" {
|
||||||
|
t.Logf("Expected 6000 got %s", k.Port())
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
b, exists := bindings[k]
|
||||||
|
if !exists {
|
||||||
|
t.Log("Binding does not exist")
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
if len(b) != 1 {
|
||||||
|
t.Logf("Expected 1 got %d", len(b))
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
s := b[0]
|
||||||
|
if s.HostPort != "" {
|
||||||
|
t.Logf("Expected \"\" got %s", s.HostPort)
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
if s.HostIp != "192.168.1.100" {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetFullName(t *testing.T) {
|
||||||
|
name, err := getFullName("testing")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if name != "/testing" {
|
||||||
|
t.Fatalf("Expected /testing got %s", name)
|
||||||
|
}
|
||||||
|
if _, err := getFullName(""); err == nil {
|
||||||
|
t.Fatal("Error should not be nil")
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
# [PackageDev] target_format: plist, ext: tmLanguage
|
||||||
|
---
|
||||||
|
name: Dockerfile
|
||||||
|
scopeName: source.dockerfile
|
||||||
|
uuid: a39d8795-59d2-49af-aa00-fe74ee29576e
|
||||||
|
|
||||||
|
patterns:
|
||||||
|
# Keywords
|
||||||
|
- name: keyword.control.dockerfile
|
||||||
|
match: ^\s*(FROM|MAINTAINER|RUN|CMD|EXPOSE|ENV|ADD)\s
|
||||||
|
- name: keyword.operator.dockerfile
|
||||||
|
match: ^\s*(ENTRYPOINT|VOLUME|USER|WORKDIR)\s
|
||||||
|
# String
|
||||||
|
- name: string.quoted.double.dockerfile
|
||||||
|
begin: "\""
|
||||||
|
end: "\""
|
||||||
|
patterns:
|
||||||
|
- name: constant.character.escaped.dockerfile
|
||||||
|
match: \\.
|
||||||
|
# Comment
|
||||||
|
- name: comment.block.dockerfile
|
||||||
|
match: ^\s*#.*$
|
||||||
|
...
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>name</key>
|
||||||
|
<string>Dockerfile</string>
|
||||||
|
<key>patterns</key>
|
||||||
|
<array>
|
||||||
|
<dict>
|
||||||
|
<key>match</key>
|
||||||
|
<string>^\s*(FROM|MAINTAINER|RUN|CMD|EXPOSE|ENV|ADD)\s</string>
|
||||||
|
<key>name</key>
|
||||||
|
<string>keyword.control.dockerfile</string>
|
||||||
|
</dict>
|
||||||
|
<dict>
|
||||||
|
<key>match</key>
|
||||||
|
<string>^\s*(ENTRYPOINT|VOLUME|USER|WORKDIR)\s</string>
|
||||||
|
<key>name</key>
|
||||||
|
<string>keyword.operator.dockerfile</string>
|
||||||
|
</dict>
|
||||||
|
<dict>
|
||||||
|
<key>begin</key>
|
||||||
|
<string>"</string>
|
||||||
|
<key>end</key>
|
||||||
|
<string>"</string>
|
||||||
|
<key>name</key>
|
||||||
|
<string>string.quoted.double.dockerfile</string>
|
||||||
|
<key>patterns</key>
|
||||||
|
<array>
|
||||||
|
<dict>
|
||||||
|
<key>match</key>
|
||||||
|
<string>\\.</string>
|
||||||
|
<key>name</key>
|
||||||
|
<string>constant.character.escaped.dockerfile</string>
|
||||||
|
</dict>
|
||||||
|
</array>
|
||||||
|
</dict>
|
||||||
|
<dict>
|
||||||
|
<key>match</key>
|
||||||
|
<string>^\s*#.*$</string>
|
||||||
|
<key>name</key>
|
||||||
|
<string>comment.block.dockerfile</string>
|
||||||
|
</dict>
|
||||||
|
</array>
|
||||||
|
<key>scopeName</key>
|
||||||
|
<string>source.dockerfile</string>
|
||||||
|
<key>uuid</key>
|
||||||
|
<string>a39d8795-59d2-49af-aa00-fe74ee29576e</string>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
Asbjorn Enge <asbjorn@hanafjedle.net> (@asbjornenge)
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
# Dockerfile.tmLanguage
|
||||||
|
|
||||||
|
Pretty basic Dockerfile.tmLanguage for Sublime Text syntax highlighting.
|
||||||
|
|
||||||
|
PR's with syntax updates, suggestions etc. are all very much appreciated!
|
||||||
|
|
||||||
|
I'll get to making this installable via Package Control soon!
|
||||||
|
|
||||||
|
enjoy.
|
||||||
+1
-1
@@ -1 +1 @@
|
|||||||
# Maintainer wanted! Enroll on #docker@freenode
|
Tianon Gravi <admwiggin@gmail.com> (@tianon)
|
||||||
|
|||||||
Executable
+543
@@ -0,0 +1,543 @@
|
|||||||
|
#!bash
|
||||||
|
#
|
||||||
|
# bash completion file for core docker commands
|
||||||
|
#
|
||||||
|
# This script provides supports completion of:
|
||||||
|
# - commands and their options
|
||||||
|
# - container ids
|
||||||
|
# - image repos and tags
|
||||||
|
# - filepaths
|
||||||
|
#
|
||||||
|
# To enable the completions either:
|
||||||
|
# - place this file in /etc/bash_completion.d
|
||||||
|
# or
|
||||||
|
# - copy this file and add the line below to your .bashrc after
|
||||||
|
# bash completion features are loaded
|
||||||
|
# . docker.bash
|
||||||
|
#
|
||||||
|
# Note:
|
||||||
|
# Currently, the completions will not work if the docker daemon is not
|
||||||
|
# bound to the default communication port/socket
|
||||||
|
# If the docker daemon is using a unix socket for communication your user
|
||||||
|
# must have access to the socket for the completions to function correctly
|
||||||
|
|
||||||
|
__docker_containers_all()
|
||||||
|
{
|
||||||
|
local containers
|
||||||
|
containers="$( docker ps -a -q )"
|
||||||
|
COMPREPLY=( $( compgen -W "$containers" -- "$cur" ) )
|
||||||
|
}
|
||||||
|
|
||||||
|
__docker_containers_running()
|
||||||
|
{
|
||||||
|
local containers
|
||||||
|
containers="$( docker ps -q )"
|
||||||
|
COMPREPLY=( $( compgen -W "$containers" -- "$cur" ) )
|
||||||
|
}
|
||||||
|
|
||||||
|
__docker_containers_stopped()
|
||||||
|
{
|
||||||
|
local containers
|
||||||
|
containers="$( comm -13 <(docker ps -q | sort -u) <(docker ps -a -q | sort -u) )"
|
||||||
|
COMPREPLY=( $( compgen -W "$containers" -- "$cur" ) )
|
||||||
|
}
|
||||||
|
|
||||||
|
__docker_image_repos()
|
||||||
|
{
|
||||||
|
local repos
|
||||||
|
repos="$( docker images | awk 'NR>1{print $1}' )"
|
||||||
|
COMPREPLY=( $( compgen -W "$repos" -- "$cur" ) )
|
||||||
|
}
|
||||||
|
|
||||||
|
__docker_images()
|
||||||
|
{
|
||||||
|
local images
|
||||||
|
images="$( docker images | awk 'NR>1{print $1":"$2}' )"
|
||||||
|
COMPREPLY=( $( compgen -W "$images" -- "$cur" ) )
|
||||||
|
__ltrim_colon_completions "$cur"
|
||||||
|
}
|
||||||
|
|
||||||
|
__docker_image_repos_and_tags()
|
||||||
|
{
|
||||||
|
local repos images
|
||||||
|
repos="$( docker images | awk 'NR>1{print $1}' )"
|
||||||
|
images="$( docker images | awk 'NR>1{print $1":"$2}' )"
|
||||||
|
COMPREPLY=( $( compgen -W "$repos $images" -- "$cur" ) )
|
||||||
|
__ltrim_colon_completions "$cur"
|
||||||
|
}
|
||||||
|
|
||||||
|
__docker_containers_and_images()
|
||||||
|
{
|
||||||
|
local containers images
|
||||||
|
containers="$( docker ps -a -q )"
|
||||||
|
images="$( docker images | awk 'NR>1{print $1":"$2}' )"
|
||||||
|
COMPREPLY=( $( compgen -W "$images $containers" -- "$cur" ) )
|
||||||
|
__ltrim_colon_completions "$cur"
|
||||||
|
}
|
||||||
|
|
||||||
|
_docker_docker()
|
||||||
|
{
|
||||||
|
case "$prev" in
|
||||||
|
-H)
|
||||||
|
return
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
case "$cur" in
|
||||||
|
-*)
|
||||||
|
COMPREPLY=( $( compgen -W "-H" -- "$cur" ) )
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
COMPREPLY=( $( compgen -W "$commands help" -- "$cur" ) )
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
_docker_attach()
|
||||||
|
{
|
||||||
|
if [ $cpos -eq $cword ]; then
|
||||||
|
__docker_containers_running
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
_docker_build()
|
||||||
|
{
|
||||||
|
case "$prev" in
|
||||||
|
-t)
|
||||||
|
return
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
case "$cur" in
|
||||||
|
-*)
|
||||||
|
COMPREPLY=( $( compgen -W "-no-cache -t -q -rm" -- "$cur" ) )
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
_filedir
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
_docker_commit()
|
||||||
|
{
|
||||||
|
case "$prev" in
|
||||||
|
-author|-m|-run)
|
||||||
|
return
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
case "$cur" in
|
||||||
|
-*)
|
||||||
|
COMPREPLY=( $( compgen -W "-author -m -run" -- "$cur" ) )
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
local counter=$cpos
|
||||||
|
while [ $counter -le $cword ]; do
|
||||||
|
case "${words[$counter]}" in
|
||||||
|
-author|-m|-run)
|
||||||
|
(( counter++ ))
|
||||||
|
;;
|
||||||
|
-*)
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
(( counter++ ))
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ $counter -eq $cword ]; then
|
||||||
|
__docker_containers_all
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
_docker_cp()
|
||||||
|
{
|
||||||
|
if [ $cpos -eq $cword ]; then
|
||||||
|
__docker_containers_all
|
||||||
|
else
|
||||||
|
_filedir
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
_docker_diff()
|
||||||
|
{
|
||||||
|
if [ $cpos -eq $cword ]; then
|
||||||
|
__docker_containers_all
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
_docker_events()
|
||||||
|
{
|
||||||
|
case "$prev" in
|
||||||
|
-since)
|
||||||
|
return
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
case "$cur" in
|
||||||
|
-*)
|
||||||
|
COMPREPLY=( $( compgen -W "-since" -- "$cur" ) )
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
_docker_export()
|
||||||
|
{
|
||||||
|
if [ $cpos -eq $cword ]; then
|
||||||
|
__docker_containers_all
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
_docker_help()
|
||||||
|
{
|
||||||
|
if [ $cpos -eq $cword ]; then
|
||||||
|
COMPREPLY=( $( compgen -W "$commands" -- "$cur" ) )
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
_docker_history()
|
||||||
|
{
|
||||||
|
if [ $cpos -eq $cword ]; then
|
||||||
|
__docker_image_repos_and_tags
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
_docker_images()
|
||||||
|
{
|
||||||
|
case "$cur" in
|
||||||
|
-*)
|
||||||
|
COMPREPLY=( $( compgen -W "-a -notrunc -q -viz" -- "$cur" ) )
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
local counter=$cpos
|
||||||
|
while [ $counter -le $cword ]; do
|
||||||
|
case "${words[$counter]}" in
|
||||||
|
-*)
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
(( counter++ ))
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ $counter -eq $cword ]; then
|
||||||
|
__docker_image_repos
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
_docker_import()
|
||||||
|
{
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
_docker_info()
|
||||||
|
{
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
_docker_insert()
|
||||||
|
{
|
||||||
|
if [ $cpos -eq $cword ]; then
|
||||||
|
__docker_image_repos_and_tags
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
_docker_inspect()
|
||||||
|
{
|
||||||
|
__docker_containers_and_images
|
||||||
|
}
|
||||||
|
|
||||||
|
_docker_kill()
|
||||||
|
{
|
||||||
|
__docker_containers_running
|
||||||
|
}
|
||||||
|
|
||||||
|
_docker_login()
|
||||||
|
{
|
||||||
|
case "$prev" in
|
||||||
|
-e|-p|-u)
|
||||||
|
return
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
case "$cur" in
|
||||||
|
-*)
|
||||||
|
COMPREPLY=( $( compgen -W "-e -p -u" -- "$cur" ) )
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
_docker_logs()
|
||||||
|
{
|
||||||
|
if [ $cpos -eq $cword ]; then
|
||||||
|
__docker_containers_all
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
_docker_port()
|
||||||
|
{
|
||||||
|
if [ $cpos -eq $cword ]; then
|
||||||
|
__docker_containers_all
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
_docker_ps()
|
||||||
|
{
|
||||||
|
case "$prev" in
|
||||||
|
-beforeId|-n|-sinceId)
|
||||||
|
return
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
case "$cur" in
|
||||||
|
-*)
|
||||||
|
COMPREPLY=( $( compgen -W "-a -beforeId -l -n -notrunc -q -s -sinceId" -- "$cur" ) )
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
_docker_pull()
|
||||||
|
{
|
||||||
|
case "$prev" in
|
||||||
|
-t)
|
||||||
|
return
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
case "$cur" in
|
||||||
|
-*)
|
||||||
|
COMPREPLY=( $( compgen -W "-t" -- "$cur" ) )
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
_docker_push()
|
||||||
|
{
|
||||||
|
__docker_image_repos
|
||||||
|
}
|
||||||
|
|
||||||
|
_docker_restart()
|
||||||
|
{
|
||||||
|
case "$prev" in
|
||||||
|
-t)
|
||||||
|
return
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
case "$cur" in
|
||||||
|
-*)
|
||||||
|
COMPREPLY=( $( compgen -W "-t" -- "$cur" ) )
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
__docker_containers_all
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
_docker_rm()
|
||||||
|
{
|
||||||
|
case "$cur" in
|
||||||
|
-*)
|
||||||
|
COMPREPLY=( $( compgen -W "-v" -- "$cur" ) )
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
__docker_containers_stopped
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
_docker_rmi()
|
||||||
|
{
|
||||||
|
__docker_image_repos_and_tags
|
||||||
|
}
|
||||||
|
|
||||||
|
_docker_run()
|
||||||
|
{
|
||||||
|
case "$prev" in
|
||||||
|
-cidfile)
|
||||||
|
_filedir
|
||||||
|
;;
|
||||||
|
-volumes-from)
|
||||||
|
__docker_containers_all
|
||||||
|
;;
|
||||||
|
-a|-c|-dns|-e|-entrypoint|-h|-lxc-conf|-m|-p|-u|-v|-w)
|
||||||
|
return
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
case "$cur" in
|
||||||
|
-*)
|
||||||
|
COMPREPLY=( $( compgen -W "-a -c -cidfile -d -dns -e -entrypoint -h -i -lxc-conf -m -n -p -privileged -t -u -v -volumes-from -w" -- "$cur" ) )
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
local counter=$cpos
|
||||||
|
while [ $counter -le $cword ]; do
|
||||||
|
case "${words[$counter]}" in
|
||||||
|
-a|-c|-cidfile|-dns|-e|-entrypoint|-h|-lxc-conf|-m|-p|-u|-v|-volumes-from|-w)
|
||||||
|
(( counter++ ))
|
||||||
|
;;
|
||||||
|
-*)
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
(( counter++ ))
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ $counter -eq $cword ]; then
|
||||||
|
__docker_image_repos_and_tags
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
_docker_search()
|
||||||
|
{
|
||||||
|
COMPREPLY=( $( compgen -W "-notrunc" "-stars" "-trusted" -- "$cur" ) )
|
||||||
|
}
|
||||||
|
|
||||||
|
_docker_start()
|
||||||
|
{
|
||||||
|
__docker_containers_stopped
|
||||||
|
}
|
||||||
|
|
||||||
|
_docker_stop()
|
||||||
|
{
|
||||||
|
case "$prev" in
|
||||||
|
-t)
|
||||||
|
return
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
case "$cur" in
|
||||||
|
-*)
|
||||||
|
COMPREPLY=( $( compgen -W "-t" -- "$cur" ) )
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
__docker_containers_running
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
_docker_tag()
|
||||||
|
{
|
||||||
|
COMPREPLY=( $( compgen -W "-f" -- "$cur" ) )
|
||||||
|
}
|
||||||
|
|
||||||
|
_docker_top()
|
||||||
|
{
|
||||||
|
if [ $cpos -eq $cword ]; then
|
||||||
|
__docker_containers_running
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
_docker_version()
|
||||||
|
{
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
_docker_wait()
|
||||||
|
{
|
||||||
|
__docker_containers_all
|
||||||
|
}
|
||||||
|
|
||||||
|
_docker()
|
||||||
|
{
|
||||||
|
local cur prev words cword command="docker" counter=1 word cpos
|
||||||
|
local commands="
|
||||||
|
attach
|
||||||
|
build
|
||||||
|
commit
|
||||||
|
cp
|
||||||
|
diff
|
||||||
|
events
|
||||||
|
export
|
||||||
|
history
|
||||||
|
images
|
||||||
|
import
|
||||||
|
info
|
||||||
|
insert
|
||||||
|
inspect
|
||||||
|
kill
|
||||||
|
login
|
||||||
|
logs
|
||||||
|
port
|
||||||
|
ps
|
||||||
|
pull
|
||||||
|
push
|
||||||
|
restart
|
||||||
|
rm
|
||||||
|
rmi
|
||||||
|
run
|
||||||
|
search
|
||||||
|
start
|
||||||
|
stop
|
||||||
|
tag
|
||||||
|
top
|
||||||
|
version
|
||||||
|
wait
|
||||||
|
"
|
||||||
|
|
||||||
|
COMPREPLY=()
|
||||||
|
_get_comp_words_by_ref -n : cur prev words cword
|
||||||
|
|
||||||
|
while [ $counter -lt $cword ]; do
|
||||||
|
word="${words[$counter]}"
|
||||||
|
case "$word" in
|
||||||
|
-H)
|
||||||
|
(( counter++ ))
|
||||||
|
;;
|
||||||
|
-*)
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
command="$word"
|
||||||
|
cpos=$counter
|
||||||
|
(( cpos++ ))
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
(( counter++ ))
|
||||||
|
done
|
||||||
|
|
||||||
|
local completions_func=_docker_${command}
|
||||||
|
declare -F $completions_func >/dev/null && $completions_func
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
complete -F _docker docker
|
||||||
Executable
+242
@@ -0,0 +1,242 @@
|
|||||||
|
#compdef docker
|
||||||
|
#
|
||||||
|
# zsh completion for docker (http://docker.io)
|
||||||
|
#
|
||||||
|
# version: 0.2.2
|
||||||
|
# author: Felix Riedel
|
||||||
|
# license: BSD License
|
||||||
|
# github: https://github.com/felixr/docker-zsh-completion
|
||||||
|
#
|
||||||
|
|
||||||
|
__parse_docker_list() {
|
||||||
|
sed -e '/^ID/d' -e 's/[ ]\{2,\}/|/g' -e 's/ \([hdwm]\)\(inutes\|ays\|ours\|eeks\)/\1/' | awk ' BEGIN {FS="|"} { printf("%s:%7s, %s\n", $1, $4, $2)}'
|
||||||
|
}
|
||||||
|
|
||||||
|
__docker_stoppedcontainers() {
|
||||||
|
local expl
|
||||||
|
declare -a stoppedcontainers
|
||||||
|
stoppedcontainers=(${(f)"$(docker ps -a | grep --color=never 'Exit' | __parse_docker_list )"})
|
||||||
|
_describe -t containers-stopped "Stopped Containers" stoppedcontainers
|
||||||
|
}
|
||||||
|
|
||||||
|
__docker_runningcontainers() {
|
||||||
|
local expl
|
||||||
|
declare -a containers
|
||||||
|
|
||||||
|
containers=(${(f)"$(docker ps | __parse_docker_list)"})
|
||||||
|
_describe -t containers-active "Running Containers" containers
|
||||||
|
}
|
||||||
|
|
||||||
|
__docker_containers () {
|
||||||
|
__docker_stoppedcontainers
|
||||||
|
__docker_runningcontainers
|
||||||
|
}
|
||||||
|
|
||||||
|
__docker_images () {
|
||||||
|
local expl
|
||||||
|
declare -a images
|
||||||
|
images=(${(f)"$(docker images | awk '(NR > 1){printf("%s\\:%s\n", $1,$2)}')"})
|
||||||
|
images=($images ${(f)"$(docker images | awk '(NR > 1){printf("%s:%-15s in %s\n", $3,$2,$1)}')"})
|
||||||
|
_describe -t docker-images "Images" images
|
||||||
|
}
|
||||||
|
|
||||||
|
__docker_tags() {
|
||||||
|
local expl
|
||||||
|
declare -a tags
|
||||||
|
tags=(${(f)"$(docker images | awk '(NR>1){print $2}'| sort | uniq)"})
|
||||||
|
_describe -t docker-tags "tags" tags
|
||||||
|
}
|
||||||
|
|
||||||
|
__docker_search() {
|
||||||
|
# declare -a dockersearch
|
||||||
|
local cache_policy
|
||||||
|
zstyle -s ":completion:${curcontext}:" cache-policy cache_policy
|
||||||
|
if [[ -z "$cache_policy" ]]; then
|
||||||
|
zstyle ":completion:${curcontext}:" cache-policy __docker_caching_policy
|
||||||
|
fi
|
||||||
|
|
||||||
|
local searchterm cachename
|
||||||
|
searchterm="${words[$CURRENT]%/}"
|
||||||
|
cachename=_docker-search-$searchterm
|
||||||
|
|
||||||
|
local expl
|
||||||
|
local -a result
|
||||||
|
if ( [[ ${(P)+cachename} -eq 0 ]] || _cache_invalid ${cachename#_} ) \
|
||||||
|
&& ! _retrieve_cache ${cachename#_}; then
|
||||||
|
_message "Searching for ${searchterm}..."
|
||||||
|
result=(${(f)"$(docker search ${searchterm} | awk '(NR>2){print $1}')"})
|
||||||
|
_store_cache ${cachename#_} result
|
||||||
|
fi
|
||||||
|
_wanted dockersearch expl 'Available images' compadd -a result
|
||||||
|
}
|
||||||
|
|
||||||
|
__docker_caching_policy()
|
||||||
|
{
|
||||||
|
# oldp=( "$1"(Nmh+24) ) # 24 hour
|
||||||
|
oldp=( "$1"(Nmh+1) ) # 24 hour
|
||||||
|
(( $#oldp ))
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
__docker_repositories () {
|
||||||
|
local expl
|
||||||
|
declare -a repos
|
||||||
|
repos=(${(f)"$(docker images | sed -e '1d' -e 's/[ ].*//' | sort | uniq)"})
|
||||||
|
_describe -t docker-repos "Repositories" repos
|
||||||
|
}
|
||||||
|
|
||||||
|
__docker_commands () {
|
||||||
|
# local -a _docker_subcommands
|
||||||
|
local cache_policy
|
||||||
|
|
||||||
|
zstyle -s ":completion:${curcontext}:" cache-policy cache_policy
|
||||||
|
if [[ -z "$cache_policy" ]]; then
|
||||||
|
zstyle ":completion:${curcontext}:" cache-policy __docker_caching_policy
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ( [[ ${+_docker_subcommands} -eq 0 ]] || _cache_invalid docker_subcommands) \
|
||||||
|
&& ! _retrieve_cache docker_subcommands;
|
||||||
|
then
|
||||||
|
_docker_subcommands=(${${(f)"$(_call_program commands
|
||||||
|
docker 2>&1 | sed -e '1,6d' -e '/^[ ]*$/d' -e 's/[ ]*\([^ ]\+\)\s*\([^ ].*\)/\1:\2/' )"}})
|
||||||
|
_docker_subcommands=($_docker_subcommands 'help:Show help for a command')
|
||||||
|
_store_cache docker_subcommands _docker_subcommands
|
||||||
|
fi
|
||||||
|
_describe -t docker-commands "docker command" _docker_subcommands
|
||||||
|
}
|
||||||
|
|
||||||
|
__docker_subcommand () {
|
||||||
|
local -a _command_args
|
||||||
|
case "$words[1]" in
|
||||||
|
(attach|wait)
|
||||||
|
_arguments ':containers:__docker_runningcontainers'
|
||||||
|
;;
|
||||||
|
(build)
|
||||||
|
_arguments \
|
||||||
|
'-t=-:repository:__docker_repositories' \
|
||||||
|
':path or URL:_directories'
|
||||||
|
;;
|
||||||
|
(commit)
|
||||||
|
_arguments \
|
||||||
|
':container:__docker_containers' \
|
||||||
|
':repository:__docker_repositories' \
|
||||||
|
':tag: '
|
||||||
|
;;
|
||||||
|
(diff|export|logs)
|
||||||
|
_arguments '*:containers:__docker_containers'
|
||||||
|
;;
|
||||||
|
(history)
|
||||||
|
_arguments '*:images:__docker_images'
|
||||||
|
;;
|
||||||
|
(images)
|
||||||
|
_arguments \
|
||||||
|
'-a[Show all images]' \
|
||||||
|
':repository:__docker_repositories'
|
||||||
|
;;
|
||||||
|
(inspect)
|
||||||
|
_arguments '*:containers:__docker_containers'
|
||||||
|
;;
|
||||||
|
(history)
|
||||||
|
_arguments ':images:__docker_images'
|
||||||
|
;;
|
||||||
|
(insert)
|
||||||
|
_arguments '1:containers:__docker_containers' \
|
||||||
|
'2:URL:(http:// file://)' \
|
||||||
|
'3:file:_files'
|
||||||
|
;;
|
||||||
|
(kill)
|
||||||
|
_arguments '*:containers:__docker_runningcontainers'
|
||||||
|
;;
|
||||||
|
(port)
|
||||||
|
_arguments '1:containers:__docker_runningcontainers'
|
||||||
|
;;
|
||||||
|
(start)
|
||||||
|
_arguments '*:containers:__docker_stoppedcontainers'
|
||||||
|
;;
|
||||||
|
(rm)
|
||||||
|
_arguments '-v[Remove the volumes associated to the container]' \
|
||||||
|
'*:containers:__docker_stoppedcontainers'
|
||||||
|
;;
|
||||||
|
(rmi)
|
||||||
|
_arguments '-v[Remove the volumes associated to the container]' \
|
||||||
|
'*:images:__docker_images'
|
||||||
|
;;
|
||||||
|
(top)
|
||||||
|
_arguments '1:containers:__docker_runningcontainers'
|
||||||
|
;;
|
||||||
|
(restart|stop)
|
||||||
|
_arguments '-t=-[Number of seconds to try to stop for before killing the container]:seconds to before killing:(1 5 10 30 60)' \
|
||||||
|
'*:containers:__docker_runningcontainers'
|
||||||
|
;;
|
||||||
|
(top)
|
||||||
|
_arguments ':containers:__docker_runningcontainers'
|
||||||
|
;;
|
||||||
|
(ps)
|
||||||
|
_arguments '-a[Show all containers. Only running containers are shown by default]' \
|
||||||
|
'-h[Show help]' \
|
||||||
|
'-beforeId=-[Show only container created before Id, include non-running one]:containers:__docker_containers' \
|
||||||
|
'-n=-[Show n last created containers, include non-running one]:n:(1 5 10 25 50)'
|
||||||
|
;;
|
||||||
|
(tag)
|
||||||
|
_arguments \
|
||||||
|
'-f[force]'\
|
||||||
|
':image:__docker_images'\
|
||||||
|
':repository:__docker_repositories' \
|
||||||
|
':tag:__docker_tags'
|
||||||
|
;;
|
||||||
|
(run)
|
||||||
|
_arguments \
|
||||||
|
'-a=-[Attach to stdin, stdout or stderr]:toggle:(true false)' \
|
||||||
|
'-c=-[CPU shares (relative weight)]:CPU shares: ' \
|
||||||
|
'-d[Detached mode: leave the container running in the background]' \
|
||||||
|
'*-dns=[Set custom dns servers]:dns server: ' \
|
||||||
|
'*-e=[Set environment variables]:environment variable: ' \
|
||||||
|
'-entrypoint=-[Overwrite the default entrypoint of the image]:entry point: ' \
|
||||||
|
'-h=-[Container host name]:hostname:_hosts' \
|
||||||
|
'-i[Keep stdin open even if not attached]' \
|
||||||
|
'-m=-[Memory limit (in bytes)]:limit: ' \
|
||||||
|
'*-p=-[Expose a container''s port to the host]:port:_ports' \
|
||||||
|
'-t=-[Allocate a pseudo-tty]:toggle:(true false)' \
|
||||||
|
'-u=-[Username or UID]:user:_users' \
|
||||||
|
'*-v=-[Bind mount a volume (e.g. from the host: -v /host:/container, from docker: -v /container)]:volume: '\
|
||||||
|
'-volumes-from=-[Mount volumes from the specified container]:volume: ' \
|
||||||
|
'(-):images:__docker_images' \
|
||||||
|
'(-):command: _command_names -e' \
|
||||||
|
'*::arguments: _normal'
|
||||||
|
;;
|
||||||
|
(pull|search)
|
||||||
|
_arguments ':name:__docker_search'
|
||||||
|
;;
|
||||||
|
(help)
|
||||||
|
_arguments ':subcommand:__docker_commands'
|
||||||
|
;;
|
||||||
|
(*)
|
||||||
|
_message 'Unknown sub command'
|
||||||
|
esac
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
_docker () {
|
||||||
|
local curcontext="$curcontext" state line
|
||||||
|
typeset -A opt_args
|
||||||
|
|
||||||
|
_arguments -C \
|
||||||
|
'-H=-[tcp://host:port to bind/connect to]:socket: ' \
|
||||||
|
'(-): :->command' \
|
||||||
|
'(-)*:: :->option-or-argument'
|
||||||
|
|
||||||
|
if (( CURRENT == 1 )); then
|
||||||
|
|
||||||
|
fi
|
||||||
|
case $state in
|
||||||
|
(command)
|
||||||
|
__docker_commands
|
||||||
|
;;
|
||||||
|
(option-or-argument)
|
||||||
|
curcontext=${curcontext%:*:*}:docker-$words[1]:
|
||||||
|
__docker_subcommand
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
_docker "$@"
|
||||||
@@ -77,7 +77,7 @@ func crashTest() error {
|
|||||||
stop = false
|
stop = false
|
||||||
for i := 0; i < 100 && !stop; {
|
for i := 0; i < 100 && !stop; {
|
||||||
func() error {
|
func() error {
|
||||||
cmd := exec.Command(DOCKERPATH, "run", "base", "echo", fmt.Sprintf("%d", totalTestCount))
|
cmd := exec.Command(DOCKERPATH, "run", "ubuntu", "echo", fmt.Sprintf("%d", totalTestCount))
|
||||||
i++
|
i++
|
||||||
totalTestCount++
|
totalTestCount++
|
||||||
outPipe, err := cmd.StdoutPipe()
|
outPipe, err := cmd.StdoutPipe()
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
Desktop Integration
|
||||||
|
===================
|
||||||
|
|
||||||
|
The ./contrib/desktop-integration contains examples of typical dockerized
|
||||||
|
desktop applications.
|
||||||
|
|
||||||
|
Examples
|
||||||
|
========
|
||||||
|
|
||||||
|
* Data container: ./data/Dockerfile creates a data image sharing /data volume
|
||||||
|
* Firefox: ./firefox/Dockerfile shows a way to dockerize a common multimedia application
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
# VERSION: 0.1
|
||||||
|
# DESCRIPTION: Create data image sharing /data volume
|
||||||
|
# AUTHOR: Daniel Mizyrycki <daniel@dotcloud.com>
|
||||||
|
# COMMENTS:
|
||||||
|
# This image is used as base for all data containers.
|
||||||
|
# /data volume is owned by sysadmin.
|
||||||
|
# USAGE:
|
||||||
|
# # Download data Dockerfile
|
||||||
|
# wget http://raw.github.com/dotcloud/docker/master/contrib/desktop-integration/data/Dockerfile
|
||||||
|
#
|
||||||
|
# # Build data image
|
||||||
|
# docker build -t data -rm .
|
||||||
|
#
|
||||||
|
# # Create a data container. (eg: firefox-data)
|
||||||
|
# docker run -name firefox-data data true
|
||||||
|
#
|
||||||
|
# # List data from it
|
||||||
|
# docker run -volumes-from firefox-data busybox ls -al /data
|
||||||
|
|
||||||
|
docker-version 0.6.5
|
||||||
|
|
||||||
|
# Smallest base image, just to launch a container
|
||||||
|
from busybox
|
||||||
|
maintainer Daniel Mizyrycki <daniel@docker.com>
|
||||||
|
|
||||||
|
# Create a regular user
|
||||||
|
run echo 'sysadmin:x:1000:1000::/data:/bin/sh' >> /etc/passwd
|
||||||
|
run echo 'sysadmin:x:1000:' >> /etc/group
|
||||||
|
|
||||||
|
# Create directory for that user
|
||||||
|
run mkdir /data
|
||||||
|
run chown sysadmin.sysadmin /data
|
||||||
|
|
||||||
|
# Add content to /data. This will keep sysadmin ownership
|
||||||
|
run touch /data/init_volume
|
||||||
|
|
||||||
|
# Create /data volume
|
||||||
|
VOLUME /data
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
# VERSION: 0.7
|
||||||
|
# DESCRIPTION: Create firefox container with its dependencies
|
||||||
|
# AUTHOR: Daniel Mizyrycki <daniel@dotcloud.com>
|
||||||
|
# COMMENTS:
|
||||||
|
# This file describes how to build a Firefox container with all
|
||||||
|
# dependencies installed. It uses native X11 unix socket and alsa
|
||||||
|
# sound devices. Tested on Debian 7.2
|
||||||
|
# USAGE:
|
||||||
|
# # Download Firefox Dockerfile
|
||||||
|
# wget http://raw.github.com/dotcloud/docker/master/contrib/desktop-integration/firefox/Dockerfile
|
||||||
|
#
|
||||||
|
# # Build firefox image
|
||||||
|
# docker build -t firefox -rm .
|
||||||
|
#
|
||||||
|
# # Run stateful data-on-host firefox. For ephemeral, remove -v /data/firefox:/data
|
||||||
|
# docker run -v /data/firefox:/data -v /tmp/.X11-unix:/tmp/.X11-unix \
|
||||||
|
# -v /dev/snd:/dev/snd -lxc-conf='lxc.cgroup.devices.allow = c 116:* rwm' \
|
||||||
|
# -e DISPLAY=unix$DISPLAY firefox
|
||||||
|
#
|
||||||
|
# # To run stateful dockerized data containers
|
||||||
|
# docker run -volumes-from firefox-data -v /tmp/.X11-unix:/tmp/.X11-unix \
|
||||||
|
# -v /dev/snd:/dev/snd -lxc-conf='lxc.cgroup.devices.allow = c 116:* rwm' \
|
||||||
|
# -e DISPLAY=unix$DISPLAY firefox
|
||||||
|
|
||||||
|
docker-version 0.6.5
|
||||||
|
|
||||||
|
# Base docker image
|
||||||
|
from tianon/debian:wheezy
|
||||||
|
maintainer Daniel Mizyrycki <daniel@docker.com>
|
||||||
|
|
||||||
|
# Install firefox dependencies
|
||||||
|
run echo "deb http://ftp.debian.org/debian/ wheezy main contrib" > /etc/apt/sources.list
|
||||||
|
run apt-get update
|
||||||
|
run DEBIAN_FRONTEND=noninteractive apt-get install -y libXrender1 libasound2 \
|
||||||
|
libdbus-glib-1-2 libgtk2.0-0 libpango1.0-0 libxt6 wget bzip2 sudo
|
||||||
|
|
||||||
|
# Install Firefox
|
||||||
|
run mkdir /application
|
||||||
|
run cd /application; wget -O - \
|
||||||
|
http://ftp.mozilla.org/pub/mozilla.org/firefox/releases/25.0/linux-x86_64/en-US/firefox-25.0.tar.bz2 | tar jx
|
||||||
|
|
||||||
|
# create sysadmin account
|
||||||
|
run useradd -m -d /data -p saIVpsc0EVTwA sysadmin
|
||||||
|
run sed -Ei 's/sudo:x:27:/sudo:x:27:sysadmin/' /etc/group
|
||||||
|
run sed -Ei 's/(\%sudo\s+ALL=\(ALL\:ALL\) )ALL/\1 NOPASSWD:ALL/' /etc/sudoers
|
||||||
|
|
||||||
|
# Autorun firefox. -no-remote is necessary to create a new container, as firefox
|
||||||
|
# appears to communicate with itself through X11.
|
||||||
|
cmd ["/bin/sh", "-c", "/usr/bin/sudo -u sysadmin -H -E /application/firefox/firefox -no-remote"]
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
#
|
||||||
|
# This Dockerfile will create an image that allows to generate upstart and
|
||||||
|
# systemd scripts (more to come)
|
||||||
|
#
|
||||||
|
# docker-version 0.6.2
|
||||||
|
#
|
||||||
|
|
||||||
|
FROM ubuntu:12.10
|
||||||
|
MAINTAINER Guillaume J. Charmes <guillaume@dotcloud.com>
|
||||||
|
|
||||||
|
RUN apt-get update && apt-get install -y wget git mercurial
|
||||||
|
|
||||||
|
# Install Go
|
||||||
|
RUN wget --no-check-certificate https://go.googlecode.com/files/go1.1.2.linux-amd64.tar.gz -O go-1.1.2.tar.gz
|
||||||
|
RUN tar -xzvf go-1.1.2.tar.gz && mv /go /goroot
|
||||||
|
RUN mkdir /go
|
||||||
|
|
||||||
|
ENV GOROOT /goroot
|
||||||
|
ENV GOPATH /go
|
||||||
|
ENV PATH $GOROOT/bin:$PATH
|
||||||
|
|
||||||
|
RUN go get github.com/dotcloud/docker && cd /go/src/github.com/dotcloud/docker && git checkout v0.6.3
|
||||||
|
ADD manager.go /manager/
|
||||||
|
RUN cd /manager && go build -o /usr/bin/manager
|
||||||
|
|
||||||
|
ENTRYPOINT ["/usr/bin/manager"]
|
||||||
|
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
FROM busybox
|
||||||
|
MAINTAINER Guillaume J. Charmes <guillaume@dotcloud.com>
|
||||||
|
ADD manager /usr/bin/
|
||||||
|
ENTRYPOINT ["/usr/bin/manager"]
|
||||||
@@ -0,0 +1,130 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"github.com/dotcloud/docker"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
"text/template"
|
||||||
|
)
|
||||||
|
|
||||||
|
var templates = map[string]string{
|
||||||
|
|
||||||
|
"upstart": `description "{{.description}}"
|
||||||
|
author "{{.author}}"
|
||||||
|
start on filesystem and started lxc-net and started docker
|
||||||
|
stop on runlevel [!2345]
|
||||||
|
respawn
|
||||||
|
exec /home/vagrant/goroot/bin/docker start -a {{.container_id}}
|
||||||
|
`,
|
||||||
|
|
||||||
|
"systemd": `[Unit]
|
||||||
|
Description={{.description}}
|
||||||
|
Author={{.author}}
|
||||||
|
After=docker.service
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Restart=always
|
||||||
|
ExecStart=/usr/bin/docker start -a {{.container_id}}
|
||||||
|
ExecStop=/usr/bin/docker stop -t 2 {{.container_id}}
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=local.target
|
||||||
|
`,
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
// Parse command line for custom options
|
||||||
|
kind := flag.String("t", "upstart", "Type of manager requested")
|
||||||
|
author := flag.String("a", "<none>", "Author of the image")
|
||||||
|
description := flag.String("d", "<none>", "Description of the image")
|
||||||
|
flag.Usage = func() {
|
||||||
|
fmt.Fprintf(os.Stderr, "\nUsage: manager <container id>\n\n")
|
||||||
|
flag.PrintDefaults()
|
||||||
|
}
|
||||||
|
flag.Parse()
|
||||||
|
|
||||||
|
// We require at least the container ID
|
||||||
|
if flag.NArg() != 1 {
|
||||||
|
println(flag.NArg())
|
||||||
|
flag.Usage()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check that the requested process manager is supported
|
||||||
|
if _, exists := templates[*kind]; !exists {
|
||||||
|
panic("Unkown script template")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load the requested template
|
||||||
|
tpl, err := template.New("processManager").Parse(templates[*kind])
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create stdout/stderr buffers
|
||||||
|
bufOut := bytes.NewBuffer(nil)
|
||||||
|
bufErr := bytes.NewBuffer(nil)
|
||||||
|
|
||||||
|
// Instanciate the Docker CLI
|
||||||
|
cli := docker.NewDockerCli(nil, bufOut, bufErr, "unix", "/var/run/docker.sock")
|
||||||
|
// Retrieve the container info
|
||||||
|
if err := cli.CmdInspect(flag.Arg(0)); err != nil {
|
||||||
|
// As of docker v0.6.3, CmdInspect always returns nil
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// If there is nothing in the error buffer, then the Docker daemon is there and the container has been found
|
||||||
|
if bufErr.Len() == 0 {
|
||||||
|
// Unmarshall the resulting container data
|
||||||
|
c := []*docker.Container{{}}
|
||||||
|
if err := json.Unmarshal(bufOut.Bytes(), &c); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
// Reset the buffers
|
||||||
|
bufOut.Reset()
|
||||||
|
bufErr.Reset()
|
||||||
|
// Retrieve the info of the linked image
|
||||||
|
if err := cli.CmdInspect(c[0].Image); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
// If there is nothing in the error buffer, then the image has been found.
|
||||||
|
if bufErr.Len() == 0 {
|
||||||
|
// Unmarshall the resulting image data
|
||||||
|
img := []*docker.Image{{}}
|
||||||
|
if err := json.Unmarshal(bufOut.Bytes(), &img); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
// If no author has been set, use the one from the image
|
||||||
|
if *author == "<none>" && img[0].Author != "" {
|
||||||
|
*author = strings.Replace(img[0].Author, "\"", "", -1)
|
||||||
|
}
|
||||||
|
// If no description has been set, use the comment from the image
|
||||||
|
if *description == "<none>" && img[0].Comment != "" {
|
||||||
|
*description = strings.Replace(img[0].Comment, "\"", "", -1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Old version: Wrtie the resulting script to file
|
||||||
|
// f, err := os.OpenFile(kind, os.O_CREATE|os.O_WRONLY, 0755)
|
||||||
|
// if err != nil {
|
||||||
|
// panic(err)
|
||||||
|
// }
|
||||||
|
// defer f.Close()
|
||||||
|
|
||||||
|
// Create a map with needed data
|
||||||
|
data := map[string]string{
|
||||||
|
"author": *author,
|
||||||
|
"description": *description,
|
||||||
|
"container_id": flag.Arg(0),
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process the template and output it on Stdout
|
||||||
|
if err := tpl.Execute(os.Stdout, data); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
Executable
+53
@@ -0,0 +1,53 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
set -e
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
echo >&2 "usage: $0 [-a author] [-d description] container [manager]"
|
||||||
|
echo >&2 " ie: $0 -a 'John Smith' 4ec9612a37cd systemd"
|
||||||
|
echo >&2 " ie: $0 -d 'Super Cool System' 4ec9612a37cd # defaults to upstart"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
auth='<none>'
|
||||||
|
desc='<none>'
|
||||||
|
have_auth=
|
||||||
|
have_desc=
|
||||||
|
while getopts a:d: opt; do
|
||||||
|
case "$opt" in
|
||||||
|
a)
|
||||||
|
auth="$OPTARG"
|
||||||
|
have_auth=1
|
||||||
|
;;
|
||||||
|
d)
|
||||||
|
desc="$OPTARG"
|
||||||
|
have_desc=1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
shift $(($OPTIND - 1))
|
||||||
|
|
||||||
|
[ $# -ge 1 -a $# -le 2 ] || usage
|
||||||
|
|
||||||
|
cid="$1"
|
||||||
|
script="${2:-upstart}"
|
||||||
|
if [ ! -e "manager/$script" ]; then
|
||||||
|
echo >&2 "Error: manager type '$script' is unknown (PRs always welcome!)."
|
||||||
|
echo >&2 'The currently supported types are:'
|
||||||
|
echo >&2 " $(cd manager && echo *)"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# TODO https://github.com/dotcloud/docker/issues/734 (docker inspect formatting)
|
||||||
|
#if command -v docker > /dev/null 2>&1; then
|
||||||
|
# image="$(docker inspect -f '{{.Image}}' "$cid")"
|
||||||
|
# if [ "$image" ]; then
|
||||||
|
# if [ -z "$have_auth" ]; then
|
||||||
|
# auth="$(docker inspect -f '{{.Author}}' "$image")"
|
||||||
|
# fi
|
||||||
|
# if [ -z "$have_desc" ]; then
|
||||||
|
# desc="$(docker inspect -f '{{.Comment}}' "$image")"
|
||||||
|
# fi
|
||||||
|
# fi
|
||||||
|
#fi
|
||||||
|
|
||||||
|
exec "manager/$script" "$cid" "$auth" "$desc"
|
||||||
Executable
+20
@@ -0,0 +1,20 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
set -e
|
||||||
|
|
||||||
|
cid="$1"
|
||||||
|
auth="$2"
|
||||||
|
desc="$3"
|
||||||
|
|
||||||
|
cat <<-EOF
|
||||||
|
[Unit]
|
||||||
|
Description=$desc
|
||||||
|
Author=$auth
|
||||||
|
After=docker.service
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
ExecStart=/usr/bin/docker start -a $cid
|
||||||
|
ExecStop=/usr/bin/docker stop -t 2 $cid
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=local.target
|
||||||
|
EOF
|
||||||
Executable
+15
@@ -0,0 +1,15 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
set -e
|
||||||
|
|
||||||
|
cid="$1"
|
||||||
|
auth="$2"
|
||||||
|
desc="$3"
|
||||||
|
|
||||||
|
cat <<-EOF
|
||||||
|
description "$(echo "$desc" | sed 's/"/\\"/g')"
|
||||||
|
author "$(echo "$auth" | sed 's/"/\\"/g')"
|
||||||
|
start on filesystem and started lxc-net and started docker
|
||||||
|
stop on runlevel [!2345]
|
||||||
|
respawn
|
||||||
|
exec /usr/bin/docker start -a "$cid"
|
||||||
|
EOF
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
# /etc/conf.d/docker: config file for /etc/init.d/docker
|
||||||
|
|
||||||
|
# where the docker daemon output gets piped
|
||||||
|
#DOCKER_LOGFILE="/var/log/docker.log"
|
||||||
|
|
||||||
|
# where docker's pid get stored
|
||||||
|
#DOCKER_PIDFILE="/run/docker.pid"
|
||||||
|
|
||||||
|
# where the docker daemon itself is run from
|
||||||
|
#DOCKER_BINARY="/usr/bin/docker"
|
||||||
|
|
||||||
|
# any other random options you want to pass to docker
|
||||||
|
DOCKER_OPTS=""
|
||||||
Executable
+31
@@ -0,0 +1,31 @@
|
|||||||
|
#!/sbin/runscript
|
||||||
|
# Copyright 1999-2013 Gentoo Foundation
|
||||||
|
# Distributed under the terms of the GNU General Public License v2
|
||||||
|
# $Header: $
|
||||||
|
|
||||||
|
DOCKER_LOGFILE=${DOCKER_LOGFILE:-/var/log/${SVCNAME}.log}
|
||||||
|
DOCKER_PIDFILE=${DOCKER_PIDFILE:-/run/${SVCNAME}.pid}
|
||||||
|
DOCKER_BINARY=${DOCKER_BINARY:-/usr/bin/docker}
|
||||||
|
DOCKER_OPTS=${DOCKER_OPTS:-}
|
||||||
|
|
||||||
|
start() {
|
||||||
|
checkpath -f -m 0644 -o root:docker "$DOCKER_LOGFILE"
|
||||||
|
|
||||||
|
ebegin "Starting docker daemon"
|
||||||
|
start-stop-daemon --start --background \
|
||||||
|
--exec "$DOCKER_BINARY" \
|
||||||
|
--pidfile "$DOCKER_PIDFILE" \
|
||||||
|
--stdout "$DOCKER_LOGFILE" \
|
||||||
|
--stderr "$DOCKER_LOGFILE" \
|
||||||
|
-- -d -p "$DOCKER_PIDFILE" \
|
||||||
|
$DOCKER_OPTS
|
||||||
|
eend $?
|
||||||
|
}
|
||||||
|
|
||||||
|
stop() {
|
||||||
|
ebegin "Stopping docker daemon"
|
||||||
|
start-stop-daemon --stop \
|
||||||
|
--exec "$DOCKER_BINARY" \
|
||||||
|
--pidfile "$DOCKER_PIDFILE"
|
||||||
|
eend $?
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=Docker Application Container Engine
|
||||||
|
Documentation=http://docs.docker.io
|
||||||
|
Requires=network.target
|
||||||
|
After=multi-user.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
ExecStartPre=/bin/mount --make-rprivate /
|
||||||
|
ExecStart=/usr/bin/docker -d
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
Executable
+96
@@ -0,0 +1,96 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
### BEGIN INIT INFO
|
||||||
|
# Provides: docker
|
||||||
|
# Required-Start: $syslog $remote_fs
|
||||||
|
# Required-Stop: $syslog $remote_fs
|
||||||
|
# Default-Start: 2 3 4 5
|
||||||
|
# Default-Stop: 0 1 6
|
||||||
|
# Short-Description: Create lightweight, portable, self-sufficient containers.
|
||||||
|
# Description:
|
||||||
|
# Docker 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.
|
||||||
|
### END INIT INFO
|
||||||
|
|
||||||
|
BASE=$(basename $0)
|
||||||
|
|
||||||
|
DOCKER=/usr/bin/$BASE
|
||||||
|
DOCKER_PIDFILE=/var/run/$BASE.pid
|
||||||
|
DOCKER_OPTS=
|
||||||
|
|
||||||
|
PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin
|
||||||
|
|
||||||
|
# Get lsb functions
|
||||||
|
. /lib/lsb/init-functions
|
||||||
|
|
||||||
|
if [ -f /etc/default/$BASE ]; then
|
||||||
|
. /etc/default/$BASE
|
||||||
|
fi
|
||||||
|
|
||||||
|
# see also init_is_upstart in /lib/lsb/init-functions (which isn't available in Ubuntu 12.04, or we'd use it)
|
||||||
|
if [ -x /sbin/initctl ] && /sbin/initctl version 2>/dev/null | /bin/grep -q upstart; then
|
||||||
|
log_failure_msg "Docker is managed via upstart, try using service $BASE $1"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check docker is present
|
||||||
|
if [ ! -x $DOCKER ]; then
|
||||||
|
log_failure_msg "$DOCKER not present or not executable"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
fail_unless_root() {
|
||||||
|
if [ "$(id -u)" != '0' ]; then
|
||||||
|
log_failure_msg "Docker must be run as root"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
case "$1" in
|
||||||
|
start)
|
||||||
|
fail_unless_root
|
||||||
|
log_begin_msg "Starting Docker: $BASE"
|
||||||
|
mount | grep cgroup >/dev/null || mount -t cgroup none /sys/fs/cgroup 2>/dev/null
|
||||||
|
start-stop-daemon --start --background \
|
||||||
|
--exec "$DOCKER" \
|
||||||
|
--pidfile "$DOCKER_PIDFILE" \
|
||||||
|
-- -d -p "$DOCKER_PIDFILE" \
|
||||||
|
$DOCKER_OPTS
|
||||||
|
log_end_msg $?
|
||||||
|
;;
|
||||||
|
|
||||||
|
stop)
|
||||||
|
fail_unless_root
|
||||||
|
log_begin_msg "Stopping Docker: $BASE"
|
||||||
|
start-stop-daemon --stop \
|
||||||
|
--pidfile "$DOCKER_PIDFILE"
|
||||||
|
log_end_msg $?
|
||||||
|
;;
|
||||||
|
|
||||||
|
restart)
|
||||||
|
fail_unless_root
|
||||||
|
docker_pid=`cat "$DOCKER_PIDFILE" 2>/dev/null`
|
||||||
|
[ -n "$docker_pid" ] \
|
||||||
|
&& ps -p $docker_pid > /dev/null 2>&1 \
|
||||||
|
&& $0 stop
|
||||||
|
$0 start
|
||||||
|
;;
|
||||||
|
|
||||||
|
force-reload)
|
||||||
|
fail_unless_root
|
||||||
|
$0 restart
|
||||||
|
;;
|
||||||
|
|
||||||
|
status)
|
||||||
|
status_of_proc -p "$DOCKER_PIDFILE" "$DOCKER" docker
|
||||||
|
;;
|
||||||
|
|
||||||
|
*)
|
||||||
|
echo "Usage: $0 {start|stop|restart|status}"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
exit 0
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
description "Docker daemon"
|
||||||
|
|
||||||
|
start on filesystem and started lxc-net
|
||||||
|
stop on runlevel [!2345]
|
||||||
|
|
||||||
|
respawn
|
||||||
|
|
||||||
|
script
|
||||||
|
DOCKER=/usr/bin/$UPSTART_JOB
|
||||||
|
DOCKER_OPTS=
|
||||||
|
if [ -f /etc/default/$UPSTART_JOB ]; then
|
||||||
|
. /etc/default/$UPSTART_JOB
|
||||||
|
fi
|
||||||
|
"$DOCKER" -d $DOCKER_OPTS
|
||||||
|
end script
|
||||||
@@ -1,55 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
# This script is meant for quick & easy install via 'curl URL-OF-SCRIPT | sh'
|
|
||||||
# Original version by Jeff Lindsay <progrium@gmail.com>
|
|
||||||
# Revamped by Jerome Petazzoni <jerome@dotcloud.com>
|
|
||||||
#
|
|
||||||
# This script canonical location is http://get.docker.io/; to update it, run:
|
|
||||||
# s3cmd put -m text/x-shellscript -P install.sh s3://get.docker.io/index
|
|
||||||
|
|
||||||
echo "Ensuring basic dependencies are installed..."
|
|
||||||
apt-get -qq update
|
|
||||||
apt-get -qq install lxc wget
|
|
||||||
|
|
||||||
echo "Looking in /proc/filesystems to see if we have AUFS support..."
|
|
||||||
if grep -q aufs /proc/filesystems
|
|
||||||
then
|
|
||||||
echo "Found."
|
|
||||||
else
|
|
||||||
echo "Ahem, it looks like the current kernel does not support AUFS."
|
|
||||||
echo "Let's see if we can load the AUFS module with modprobe..."
|
|
||||||
if modprobe aufs
|
|
||||||
then
|
|
||||||
echo "Module loaded."
|
|
||||||
else
|
|
||||||
echo "Ahem, things didn't turn out as expected."
|
|
||||||
KPKG=linux-image-extra-$(uname -r)
|
|
||||||
echo "Trying to install $KPKG..."
|
|
||||||
if apt-get -qq install $KPKG
|
|
||||||
then
|
|
||||||
echo "Installed."
|
|
||||||
else
|
|
||||||
echo "Oops, we couldn't install the -extra kernel."
|
|
||||||
echo "Are you sure you are running a supported version of Ubuntu?"
|
|
||||||
echo "Proceeding anyway, but Docker will probably NOT WORK!"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "Downloading docker binary and uncompressing into /usr/local/bin..."
|
|
||||||
curl -s http://get.docker.io/builds/$(uname -s)/$(uname -m)/docker-latest.tgz |
|
|
||||||
tar -C /usr/local/bin --strip-components=1 -zxf- \
|
|
||||||
docker-latest/docker
|
|
||||||
|
|
||||||
if [ -f /etc/init/dockerd.conf ]
|
|
||||||
then
|
|
||||||
echo "Upstart script already exists."
|
|
||||||
else
|
|
||||||
echo "Creating /etc/init/dockerd.conf..."
|
|
||||||
echo "exec env LANG=\"en_US.UTF-8\" /usr/local/bin/docker -d" > /etc/init/dockerd.conf
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "Starting dockerd..."
|
|
||||||
start dockerd > /dev/null
|
|
||||||
|
|
||||||
echo "Done."
|
|
||||||
echo
|
|
||||||
Executable
+67
@@ -0,0 +1,67 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# Generate a minimal filesystem for archlinux and load it into the local
|
||||||
|
# docker as "archlinux"
|
||||||
|
# requires root
|
||||||
|
set -e
|
||||||
|
|
||||||
|
PACSTRAP=$(which pacstrap)
|
||||||
|
[ "$PACSTRAP" ] || {
|
||||||
|
echo "Could not find pacstrap. Run pacman -S arch-install-scripts"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
EXPECT=$(which expect)
|
||||||
|
[ "$EXPECT" ] || {
|
||||||
|
echo "Could not find expect. Run pacman -S expect"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
ROOTFS=~/rootfs-arch-$$-$RANDOM
|
||||||
|
mkdir $ROOTFS
|
||||||
|
|
||||||
|
#packages to ignore for space savings
|
||||||
|
PKGIGNORE=linux,jfsutils,lvm2,cryptsetup,groff,man-db,man-pages,mdadm,pciutils,pcmciautils,reiserfsprogs,s-nail,xfsprogs
|
||||||
|
|
||||||
|
expect <<EOF
|
||||||
|
set timeout 60
|
||||||
|
set send_slow {1 1}
|
||||||
|
spawn pacstrap -c -d -G -i $ROOTFS base haveged --ignore $PKGIGNORE
|
||||||
|
expect {
|
||||||
|
"Install anyway?" { send n\r; exp_continue }
|
||||||
|
"(default=all)" { send \r; exp_continue }
|
||||||
|
"Proceed with installation?" { send "\r"; exp_continue }
|
||||||
|
"skip the above package" {send "y\r"; exp_continue }
|
||||||
|
"checking" { exp_continue }
|
||||||
|
"loading" { exp_continue }
|
||||||
|
"installing" { exp_continue }
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
arch-chroot $ROOTFS /bin/sh -c "haveged -w 1024; pacman-key --init; pkill haveged; pacman -Rs --noconfirm haveged; pacman-key --populate archlinux"
|
||||||
|
arch-chroot $ROOTFS /bin/sh -c "ln -s /usr/share/zoneinfo/UTC /etc/localtime"
|
||||||
|
cat > $ROOTFS/etc/locale.gen <<DELIM
|
||||||
|
en_US.UTF-8 UTF-8
|
||||||
|
en_US ISO-8859-1
|
||||||
|
DELIM
|
||||||
|
arch-chroot $ROOTFS locale-gen
|
||||||
|
arch-chroot $ROOTFS /bin/sh -c 'echo "Server = http://mirrors.kernel.org/archlinux/\$repo/os/\$arch" > /etc/pacman.d/mirrorlist'
|
||||||
|
|
||||||
|
# udev doesn't work in containers, rebuild /dev
|
||||||
|
DEV=${ROOTFS}/dev
|
||||||
|
mv ${DEV} ${DEV}.old
|
||||||
|
mkdir -p ${DEV}
|
||||||
|
mknod -m 666 ${DEV}/null c 1 3
|
||||||
|
mknod -m 666 ${DEV}/zero c 1 5
|
||||||
|
mknod -m 666 ${DEV}/random c 1 8
|
||||||
|
mknod -m 666 ${DEV}/urandom c 1 9
|
||||||
|
mkdir -m 755 ${DEV}/pts
|
||||||
|
mkdir -m 1777 ${DEV}/shm
|
||||||
|
mknod -m 666 ${DEV}/tty c 5 0
|
||||||
|
mknod -m 600 ${DEV}/console c 5 1
|
||||||
|
mknod -m 666 ${DEV}/tty0 c 4 0
|
||||||
|
mknod -m 666 ${DEV}/full c 1 7
|
||||||
|
mknod -m 600 ${DEV}/initctl p
|
||||||
|
mknod -m 666 ${DEV}/ptmx c 5 2
|
||||||
|
|
||||||
|
tar --numeric-owner -C $ROOTFS -c . | docker import - archlinux
|
||||||
|
docker run -i -t archlinux echo Success.
|
||||||
|
rm -rf $ROOTFS
|
||||||
@@ -35,5 +35,5 @@ do
|
|||||||
cp -a /dev/$X dev
|
cp -a /dev/$X dev
|
||||||
done
|
done
|
||||||
|
|
||||||
tar -cf- . | docker import - busybox
|
tar --numeric-owner -cf- . | docker import - busybox
|
||||||
docker run -i -u root busybox /bin/echo Success.
|
docker run -i -u root busybox /bin/echo Success.
|
||||||
|
|||||||
Executable
+15
@@ -0,0 +1,15 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# Create a CentOS base image for Docker
|
||||||
|
# From unclejack https://github.com/dotcloud/docker/issues/290
|
||||||
|
set -e
|
||||||
|
|
||||||
|
MIRROR_URL="http://centos.netnitco.net/6.4/os/x86_64/"
|
||||||
|
MIRROR_URL_UPDATES="http://centos.netnitco.net/6.4/updates/x86_64/"
|
||||||
|
|
||||||
|
yum install -y febootstrap xz
|
||||||
|
|
||||||
|
febootstrap -i bash -i coreutils -i tar -i bzip2 -i gzip -i vim-minimal -i wget -i patch -i diffutils -i iproute -i yum centos centos64 $MIRROR_URL -u $MIRROR_URL_UPDATES
|
||||||
|
touch centos64/etc/resolv.conf
|
||||||
|
touch centos64/sbin/init
|
||||||
|
|
||||||
|
tar --numeric-owner -Jcpf centos-64.tar.xz -C centos64 .
|
||||||
@@ -1,55 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
set -e
|
|
||||||
|
|
||||||
# these should match the names found at http://www.debian.org/releases/
|
|
||||||
stableSuite='wheezy'
|
|
||||||
testingSuite='jessie'
|
|
||||||
unstableSuite='sid'
|
|
||||||
|
|
||||||
variant='minbase'
|
|
||||||
include='iproute,iputils-ping'
|
|
||||||
|
|
||||||
repo="$1"
|
|
||||||
suite="${2:-$stableSuite}"
|
|
||||||
mirror="${3:-}" # stick to the default debootstrap mirror if one is not provided
|
|
||||||
|
|
||||||
if [ ! "$repo" ]; then
|
|
||||||
echo >&2 "usage: $0 repo [suite [mirror]]"
|
|
||||||
echo >&2 " ie: $0 tianon/debian squeeze"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
target="/tmp/docker-rootfs-debian-$suite-$$-$RANDOM"
|
|
||||||
|
|
||||||
cd "$(dirname "$(readlink -f "$BASH_SOURCE")")"
|
|
||||||
returnTo="$(pwd -P)"
|
|
||||||
|
|
||||||
set -x
|
|
||||||
|
|
||||||
# bootstrap
|
|
||||||
mkdir -p "$target"
|
|
||||||
sudo debootstrap --verbose --variant="$variant" --include="$include" "$suite" "$target" "$mirror"
|
|
||||||
|
|
||||||
cd "$target"
|
|
||||||
|
|
||||||
# create the image
|
|
||||||
img=$(sudo tar -c . | docker import -)
|
|
||||||
|
|
||||||
# tag suite
|
|
||||||
docker tag $img $repo $suite
|
|
||||||
|
|
||||||
# test the image
|
|
||||||
docker run -i -t $repo:$suite echo success
|
|
||||||
|
|
||||||
if [ "$suite" = "$stableSuite" -o "$suite" = 'stable' ]; then
|
|
||||||
# tag latest
|
|
||||||
docker tag $img $repo latest
|
|
||||||
|
|
||||||
# tag the specific debian release version
|
|
||||||
ver=$(docker run $repo:$suite cat /etc/debian_version)
|
|
||||||
docker tag $img $repo $ver
|
|
||||||
fi
|
|
||||||
|
|
||||||
# cleanup
|
|
||||||
cd "$returnTo"
|
|
||||||
sudo rm -rf "$target"
|
|
||||||
Executable
+233
@@ -0,0 +1,233 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
variant='minbase'
|
||||||
|
include='iproute,iputils-ping'
|
||||||
|
arch='amd64' # intentionally undocumented for now
|
||||||
|
skipDetection=
|
||||||
|
strictDebootstrap=
|
||||||
|
justTar=
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
echo >&2
|
||||||
|
|
||||||
|
echo >&2 "usage: $0 [options] repo suite [mirror]"
|
||||||
|
|
||||||
|
echo >&2
|
||||||
|
echo >&2 'options: (not recommended)'
|
||||||
|
echo >&2 " -p set an http_proxy for debootstrap"
|
||||||
|
echo >&2 " -v $variant # change default debootstrap variant"
|
||||||
|
echo >&2 " -i $include # change default package includes"
|
||||||
|
echo >&2 " -d # strict debootstrap (do not apply any docker-specific tweaks)"
|
||||||
|
echo >&2 " -s # skip version detection and tagging (ie, precise also tagged as 12.04)"
|
||||||
|
echo >&2 " # note that this will also skip adding universe and/or security/updates to sources.list"
|
||||||
|
echo >&2 " -t # just create a tarball, especially for dockerbrew (uses repo as tarball name)"
|
||||||
|
|
||||||
|
echo >&2
|
||||||
|
echo >&2 " ie: $0 username/debian squeeze"
|
||||||
|
echo >&2 " $0 username/debian squeeze http://ftp.uk.debian.org/debian/"
|
||||||
|
|
||||||
|
echo >&2
|
||||||
|
echo >&2 " ie: $0 username/ubuntu precise"
|
||||||
|
echo >&2 " $0 username/ubuntu precise http://mirrors.melbourne.co.uk/ubuntu/"
|
||||||
|
|
||||||
|
echo >&2
|
||||||
|
echo >&2 " ie: $0 -t precise.tar.bz2 precise"
|
||||||
|
echo >&2 " $0 -t wheezy.tgz wheezy"
|
||||||
|
echo >&2 " $0 -t wheezy-uk.tar.xz wheezy http://ftp.uk.debian.org/debian/"
|
||||||
|
|
||||||
|
echo >&2
|
||||||
|
}
|
||||||
|
|
||||||
|
# these should match the names found at http://www.debian.org/releases/
|
||||||
|
debianStable=wheezy
|
||||||
|
debianUnstable=sid
|
||||||
|
# this should match the name found at http://releases.ubuntu.com/
|
||||||
|
ubuntuLatestLTS=precise
|
||||||
|
|
||||||
|
while getopts v:i:a:p:dst name; do
|
||||||
|
case "$name" in
|
||||||
|
p)
|
||||||
|
http_proxy="$OPTARG"
|
||||||
|
;;
|
||||||
|
v)
|
||||||
|
variant="$OPTARG"
|
||||||
|
;;
|
||||||
|
i)
|
||||||
|
include="$OPTARG"
|
||||||
|
;;
|
||||||
|
a)
|
||||||
|
arch="$OPTARG"
|
||||||
|
;;
|
||||||
|
d)
|
||||||
|
strictDebootstrap=1
|
||||||
|
;;
|
||||||
|
s)
|
||||||
|
skipDetection=1
|
||||||
|
;;
|
||||||
|
t)
|
||||||
|
justTar=1
|
||||||
|
;;
|
||||||
|
?)
|
||||||
|
usage
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
shift $(($OPTIND - 1))
|
||||||
|
|
||||||
|
repo="$1"
|
||||||
|
suite="$2"
|
||||||
|
mirror="${3:-}" # stick to the default debootstrap mirror if one is not provided
|
||||||
|
|
||||||
|
if [ ! "$repo" ] || [ ! "$suite" ]; then
|
||||||
|
usage
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# some rudimentary detection for whether we need to "sudo" our docker calls
|
||||||
|
docker=''
|
||||||
|
if docker version > /dev/null 2>&1; then
|
||||||
|
docker='docker'
|
||||||
|
elif sudo docker version > /dev/null 2>&1; then
|
||||||
|
docker='sudo docker'
|
||||||
|
elif command -v docker > /dev/null 2>&1; then
|
||||||
|
docker='docker'
|
||||||
|
else
|
||||||
|
echo >&2 "warning: either docker isn't installed, or your current user cannot run it;"
|
||||||
|
echo >&2 " this script is not likely to work as expected"
|
||||||
|
sleep 3
|
||||||
|
docker='docker' # give us a command-not-found later
|
||||||
|
fi
|
||||||
|
|
||||||
|
# make sure we have an absolute path to our final tarball so we can still reference it properly after we change directory
|
||||||
|
if [ "$justTar" ]; then
|
||||||
|
if [ ! -d "$(dirname "$repo")" ]; then
|
||||||
|
echo >&2 "error: $(dirname "$repo") does not exist"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
repo="$(cd "$(dirname "$repo")" && pwd -P)/$(basename "$repo")"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# will be filled in later, if [ -z "$skipDetection" ]
|
||||||
|
lsbDist=''
|
||||||
|
|
||||||
|
target="/tmp/docker-rootfs-debootstrap-$suite-$$-$RANDOM"
|
||||||
|
|
||||||
|
cd "$(dirname "$(readlink -f "$BASH_SOURCE")")"
|
||||||
|
returnTo="$(pwd -P)"
|
||||||
|
|
||||||
|
set -x
|
||||||
|
|
||||||
|
# bootstrap
|
||||||
|
mkdir -p "$target"
|
||||||
|
sudo http_proxy=$http_proxy debootstrap --verbose --variant="$variant" --include="$include" --arch="$arch" "$suite" "$target" "$mirror"
|
||||||
|
|
||||||
|
cd "$target"
|
||||||
|
|
||||||
|
if [ -z "$strictDebootstrap" ]; then
|
||||||
|
# prevent init scripts from running during install/update
|
||||||
|
# policy-rc.d (for most scripts)
|
||||||
|
echo $'#!/bin/sh\nexit 101' | sudo tee usr/sbin/policy-rc.d > /dev/null
|
||||||
|
sudo chmod +x usr/sbin/policy-rc.d
|
||||||
|
# initctl (for some pesky upstart scripts)
|
||||||
|
sudo chroot . dpkg-divert --local --rename --add /sbin/initctl
|
||||||
|
sudo ln -sf /bin/true sbin/initctl
|
||||||
|
# see https://github.com/dotcloud/docker/issues/446#issuecomment-16953173
|
||||||
|
|
||||||
|
# shrink the image, since apt makes us fat (wheezy: ~157.5MB vs ~120MB)
|
||||||
|
sudo chroot . apt-get clean
|
||||||
|
|
||||||
|
# while we're at it, apt is unnecessarily slow inside containers
|
||||||
|
# this forces dpkg not to call sync() after package extraction and speeds up install
|
||||||
|
# the benefit is huge on spinning disks, and the penalty is nonexistent on SSD or decent server virtualization
|
||||||
|
echo 'force-unsafe-io' | sudo tee etc/dpkg/dpkg.cfg.d/02apt-speedup > /dev/null
|
||||||
|
# we want to effectively run "apt-get clean" after every install to keep images small
|
||||||
|
echo 'DPkg::Post-Invoke {"/bin/rm -f /var/cache/apt/archives/*.deb || true";};' | sudo tee etc/apt/apt.conf.d/no-cache > /dev/null
|
||||||
|
|
||||||
|
# helpful undo lines for each the above tweaks (for lack of a better home to keep track of them):
|
||||||
|
# rm /usr/sbin/policy-rc.d
|
||||||
|
# rm /sbin/initctl; dpkg-divert --rename --remove /sbin/initctl
|
||||||
|
# rm /etc/dpkg/dpkg.cfg.d/02apt-speedup
|
||||||
|
# rm /etc/apt/apt.conf.d/no-cache
|
||||||
|
|
||||||
|
if [ -z "$skipDetection" ]; then
|
||||||
|
# see also rudimentary platform detection in hack/install.sh
|
||||||
|
lsbDist=''
|
||||||
|
if [ -r etc/lsb-release ]; then
|
||||||
|
lsbDist="$(. etc/lsb-release && echo "$DISTRIB_ID")"
|
||||||
|
fi
|
||||||
|
if [ -z "$lsbDist" ] && [ -r etc/debian_version ]; then
|
||||||
|
lsbDist='Debian'
|
||||||
|
fi
|
||||||
|
|
||||||
|
case "$lsbDist" in
|
||||||
|
Debian)
|
||||||
|
# add the updates and security repositories
|
||||||
|
if [ "$suite" != "$debianUnstable" -a "$suite" != 'unstable' ]; then
|
||||||
|
# ${suite}-updates only applies to non-unstable
|
||||||
|
sudo sed -i "p; s/ $suite main$/ ${suite}-updates main/" etc/apt/sources.list
|
||||||
|
|
||||||
|
# same for security updates
|
||||||
|
echo "deb http://security.debian.org/ $suite/updates main" | sudo tee -a etc/apt/sources.list > /dev/null
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
Ubuntu)
|
||||||
|
# add the universe, updates, and security repositories
|
||||||
|
sudo sed -i "
|
||||||
|
s/ $suite main$/ $suite main universe/; p;
|
||||||
|
s/ $suite main/ ${suite}-updates main/; p;
|
||||||
|
s/ $suite-updates main/ ${suite}-security main/
|
||||||
|
" etc/apt/sources.list
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$justTar" ]; then
|
||||||
|
# create the tarball file so it has the right permissions (ie, not root)
|
||||||
|
touch "$repo"
|
||||||
|
|
||||||
|
# fill the tarball
|
||||||
|
sudo tar --numeric-owner -caf "$repo" .
|
||||||
|
else
|
||||||
|
# create the image (and tag $repo:$suite)
|
||||||
|
sudo tar --numeric-owner -c . | $docker import - $repo:$suite
|
||||||
|
|
||||||
|
# test the image
|
||||||
|
$docker run -i -t $repo:$suite echo success
|
||||||
|
|
||||||
|
if [ -z "$skipDetection" ]; then
|
||||||
|
case "$lsbDist" in
|
||||||
|
Debian)
|
||||||
|
if [ "$suite" = "$debianStable" -o "$suite" = 'stable' ] && [ -r etc/debian_version ]; then
|
||||||
|
# tag latest
|
||||||
|
$docker tag $repo:$suite $repo:latest
|
||||||
|
|
||||||
|
if [ -r etc/debian_version ]; then
|
||||||
|
# tag the specific debian release version (which is only reasonable to tag on debian stable)
|
||||||
|
ver=$(cat etc/debian_version)
|
||||||
|
$docker tag $repo:$suite $repo:$ver
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
Ubuntu)
|
||||||
|
if [ "$suite" = "$ubuntuLatestLTS" ]; then
|
||||||
|
# tag latest
|
||||||
|
$docker tag $repo:$suite $repo:latest
|
||||||
|
fi
|
||||||
|
if [ -r etc/lsb-release ]; then
|
||||||
|
lsbRelease="$(. etc/lsb-release && echo "$DISTRIB_RELEASE")"
|
||||||
|
if [ "$lsbRelease" ]; then
|
||||||
|
# tag specific Ubuntu version number, if available (12.04, etc.)
|
||||||
|
$docker tag $repo:$suite $repo:$lsbRelease
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# cleanup
|
||||||
|
cd "$returnTo"
|
||||||
|
sudo rm -rf "$target"
|
||||||
@@ -44,6 +44,6 @@ do
|
|||||||
done
|
done
|
||||||
|
|
||||||
chmod 0755 $ROOTFS # See #486
|
chmod 0755 $ROOTFS # See #486
|
||||||
tar -cf- . | docker import - docker-ut
|
tar --numeric-owner -cf- . | docker import - docker-ut
|
||||||
docker run -i -u root docker-ut /bin/echo Success.
|
docker run -i -u root docker-ut /bin/echo Success.
|
||||||
rm -rf $ROOTFS
|
rm -rf $ROOTFS
|
||||||
|
|||||||
@@ -1,3 +1,19 @@
|
|||||||
# Vagrant-docker
|
# Vagrant integration
|
||||||
|
|
||||||
This is a placeholder for the official vagrant-docker, a plugin for Vagrant (http://vagrantup.com) which exposes Docker as a provider.
|
Currently there are at least 4 different projects that we are aware of that deals
|
||||||
|
with integration with [Vagrant](http://vagrantup.com/) at different levels. One
|
||||||
|
approach is to use Docker as a [provisioner](http://docs.vagrantup.com/v2/provisioning/index.html)
|
||||||
|
which means you can create containers and pull base images on VMs using Docker's
|
||||||
|
CLI and the other is to use Docker as a [provider](http://docs.vagrantup.com/v2/providers/index.html),
|
||||||
|
meaning you can use Vagrant to control Docker containers.
|
||||||
|
|
||||||
|
|
||||||
|
### Provisioners
|
||||||
|
|
||||||
|
* [Vocker](https://github.com/fgrehm/vocker)
|
||||||
|
* [Ventriloquist](https://github.com/fgrehm/ventriloquist)
|
||||||
|
|
||||||
|
### Providers
|
||||||
|
|
||||||
|
* [docker-provider](https://github.com/fgrehm/docker-provider)
|
||||||
|
* [vagrant-shell](https://github.com/destructuring/vagrant-shell)
|
||||||
|
|||||||
@@ -0,0 +1,22 @@
|
|||||||
|
Copyright (c) 2013 Honza Pokorny
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
dockerfile.vim
|
||||||
|
==============
|
||||||
|
|
||||||
|
Syntax highlighting for Dockerfiles
|
||||||
|
|
||||||
|
Installation
|
||||||
|
------------
|
||||||
|
|
||||||
|
Via pathogen, the usual way...
|
||||||
|
|
||||||
|
Features
|
||||||
|
--------
|
||||||
|
|
||||||
|
The syntax highlighting includes:
|
||||||
|
|
||||||
|
* The directives (e.g. `FROM`)
|
||||||
|
* Strings
|
||||||
|
* Comments
|
||||||
|
|
||||||
|
License
|
||||||
|
-------
|
||||||
|
|
||||||
|
BSD, short and sweet
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
*dockerfile.txt* Syntax highlighting for Dockerfiles
|
||||||
|
|
||||||
|
Author: Honza Pokorny <http://honza.ca>
|
||||||
|
License: BSD
|
||||||
|
|
||||||
|
INSTALLATION *installation*
|
||||||
|
|
||||||
|
Drop it on your Pathogen path and you're all set.
|
||||||
|
|
||||||
|
FEATURES *features*
|
||||||
|
|
||||||
|
The syntax highlighting includes:
|
||||||
|
|
||||||
|
* The directives (e.g. FROM)
|
||||||
|
* Strings
|
||||||
|
* Comments
|
||||||
|
|
||||||
|
vim:tw=78:et:ft=help:norl:
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
au BufNewFile,BufRead Dockerfile set filetype=dockerfile
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
" dockerfile.vim - Syntax highlighting for Dockerfiles
|
||||||
|
" Maintainer: Honza Pokorny <http://honza.ca>
|
||||||
|
" Version: 0.5
|
||||||
|
|
||||||
|
|
||||||
|
if exists("b:current_syntax")
|
||||||
|
finish
|
||||||
|
endif
|
||||||
|
|
||||||
|
let b:current_syntax = "dockerfile"
|
||||||
|
|
||||||
|
syntax case ignore
|
||||||
|
|
||||||
|
syntax match dockerfileKeyword /\v^\s*(FROM|MAINTAINER|RUN|CMD|EXPOSE|ENV|ADD)\s/
|
||||||
|
syntax match dockerfileKeyword /\v^\s*(ENTRYPOINT|VOLUME|USER|WORKDIR)\s/
|
||||||
|
highlight link dockerfileKeyword Keyword
|
||||||
|
|
||||||
|
syntax region dockerfileString start=/\v"/ skip=/\v\\./ end=/\v"/
|
||||||
|
highlight link dockerfileString String
|
||||||
|
|
||||||
|
syntax match dockerfileComment "\v^\s*#.*$"
|
||||||
|
highlight link dockerfileComment Comment
|
||||||
|
|
||||||
|
set commentstring=#\ %s
|
||||||
+53
-93
@@ -4,147 +4,107 @@ import (
|
|||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/dotcloud/docker"
|
"github.com/dotcloud/docker"
|
||||||
|
"github.com/dotcloud/docker/engine"
|
||||||
|
"github.com/dotcloud/docker/sysinit"
|
||||||
"github.com/dotcloud/docker/utils"
|
"github.com/dotcloud/docker/utils"
|
||||||
"io/ioutil"
|
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
GITCOMMIT string
|
GITCOMMIT string
|
||||||
|
VERSION string
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
if utils.SelfPath() == "/sbin/init" {
|
if selfPath := utils.SelfPath(); selfPath == "/sbin/init" || selfPath == "/.dockerinit" {
|
||||||
// Running in init mode
|
// Running in init mode
|
||||||
docker.SysInit()
|
sysinit.SysInit()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// FIXME: Switch d and D ? (to be more sshd like)
|
// FIXME: Switch d and D ? (to be more sshd like)
|
||||||
|
flVersion := flag.Bool("v", false, "Print version information and quit")
|
||||||
flDaemon := flag.Bool("d", false, "Daemon mode")
|
flDaemon := flag.Bool("d", false, "Daemon mode")
|
||||||
flDebug := flag.Bool("D", false, "Debug mode")
|
flDebug := flag.Bool("D", false, "Debug mode")
|
||||||
flAutoRestart := flag.Bool("r", false, "Restart previously running containers")
|
flAutoRestart := flag.Bool("r", true, "Restart previously running containers")
|
||||||
bridgeName := flag.String("b", "", "Attach containers to a pre-existing network bridge. Use 'none' to disable container networking")
|
bridgeName := flag.String("b", "", "Attach containers to a pre-existing network bridge. Use 'none' to disable container networking")
|
||||||
pidfile := flag.String("p", "/var/run/docker.pid", "File containing process PID")
|
pidfile := flag.String("p", "/var/run/docker.pid", "File containing process PID")
|
||||||
flGraphPath := flag.String("g", "/var/lib/docker", "Path to graph storage base dir.")
|
flRoot := flag.String("g", "/var/lib/docker", "Path to use as the root of the docker runtime.")
|
||||||
flEnableCors := flag.Bool("api-enable-cors", false, "Enable CORS requests in the remote api.")
|
flEnableCors := flag.Bool("api-enable-cors", false, "Enable CORS requests in the remote api.")
|
||||||
flDns := flag.String("dns", "", "Set custom dns servers")
|
flDns := flag.String("dns", "", "Set custom dns servers")
|
||||||
flHosts := docker.ListOpts{fmt.Sprintf("unix://%s", docker.DEFAULTUNIXSOCKET)}
|
flHosts := utils.ListOpts{fmt.Sprintf("unix://%s", docker.DEFAULTUNIXSOCKET)}
|
||||||
flag.Var(&flHosts, "H", "tcp://host:port to bind/connect to or unix://path/to/socket to use")
|
flag.Var(&flHosts, "H", "tcp://host:port to bind/connect to or unix://path/to/socket to use")
|
||||||
|
flEnableIptables := flag.Bool("iptables", true, "Disable iptables within docker")
|
||||||
|
flDefaultIp := flag.String("ip", "0.0.0.0", "Default ip address to use when binding a containers ports")
|
||||||
|
flInterContainerComm := flag.Bool("icc", true, "Enable inter-container communication")
|
||||||
|
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
|
if *flVersion {
|
||||||
|
showVersion()
|
||||||
|
return
|
||||||
|
}
|
||||||
if len(flHosts) > 1 {
|
if len(flHosts) > 1 {
|
||||||
flHosts = flHosts[1:] //trick to display a nice defaul value in the usage
|
flHosts = flHosts[1:] //trick to display a nice default value in the usage
|
||||||
}
|
}
|
||||||
for i, flHost := range flHosts {
|
for i, flHost := range flHosts {
|
||||||
flHosts[i] = utils.ParseHost(docker.DEFAULTHTTPHOST, docker.DEFAULTHTTPPORT, flHost)
|
host, err := utils.ParseHost(docker.DEFAULTHTTPHOST, docker.DEFAULTHTTPPORT, flHost)
|
||||||
|
if err == nil {
|
||||||
|
flHosts[i] = host
|
||||||
|
} else {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if *bridgeName != "" {
|
|
||||||
docker.NetworkBridgeIface = *bridgeName
|
|
||||||
} else {
|
|
||||||
docker.NetworkBridgeIface = docker.DefaultNetworkBridge
|
|
||||||
}
|
|
||||||
if *flDebug {
|
if *flDebug {
|
||||||
os.Setenv("DEBUG", "1")
|
os.Setenv("DEBUG", "1")
|
||||||
}
|
}
|
||||||
docker.GITCOMMIT = GITCOMMIT
|
docker.GITCOMMIT = GITCOMMIT
|
||||||
|
docker.VERSION = VERSION
|
||||||
if *flDaemon {
|
if *flDaemon {
|
||||||
if flag.NArg() != 0 {
|
if flag.NArg() != 0 {
|
||||||
flag.Usage()
|
flag.Usage()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if err := daemon(*pidfile, *flGraphPath, flHosts, *flAutoRestart, *flEnableCors, *flDns); err != nil {
|
eng, err := engine.New(*flRoot)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
// Load plugin: httpapi
|
||||||
|
job := eng.Job("initapi")
|
||||||
|
job.Setenv("Pidfile", *pidfile)
|
||||||
|
job.Setenv("Root", *flRoot)
|
||||||
|
job.SetenvBool("AutoRestart", *flAutoRestart)
|
||||||
|
job.SetenvBool("EnableCors", *flEnableCors)
|
||||||
|
job.Setenv("Dns", *flDns)
|
||||||
|
job.SetenvBool("EnableIptables", *flEnableIptables)
|
||||||
|
job.Setenv("BridgeIface", *bridgeName)
|
||||||
|
job.Setenv("DefaultIp", *flDefaultIp)
|
||||||
|
job.SetenvBool("InterContainerCommunication", *flInterContainerComm)
|
||||||
|
if err := job.Run(); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
// Serve api
|
||||||
|
job = eng.Job("serveapi", flHosts...)
|
||||||
|
job.SetenvBool("Logging", true)
|
||||||
|
if err := job.Run(); err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
os.Exit(-1)
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if len(flHosts) > 1 {
|
if len(flHosts) > 1 {
|
||||||
log.Fatal("Please specify only one -H")
|
log.Fatal("Please specify only one -H")
|
||||||
return
|
|
||||||
}
|
}
|
||||||
protoAddrParts := strings.SplitN(flHosts[0], "://", 2)
|
protoAddrParts := strings.SplitN(flHosts[0], "://", 2)
|
||||||
if err := docker.ParseCommands(protoAddrParts[0], protoAddrParts[1], flag.Args()...); err != nil {
|
if err := docker.ParseCommands(protoAddrParts[0], protoAddrParts[1], flag.Args()...); err != nil {
|
||||||
|
if sterr, ok := err.(*utils.StatusError); ok {
|
||||||
|
os.Exit(sterr.Status)
|
||||||
|
}
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
os.Exit(-1)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func createPidFile(pidfile string) error {
|
func showVersion() {
|
||||||
if pidString, err := ioutil.ReadFile(pidfile); err == nil {
|
fmt.Printf("Docker version %s, build %s\n", VERSION, GITCOMMIT)
|
||||||
pid, err := strconv.Atoi(string(pidString))
|
|
||||||
if err == nil {
|
|
||||||
if _, err := os.Stat(fmt.Sprintf("/proc/%d/", pid)); err == nil {
|
|
||||||
return fmt.Errorf("pid file found, ensure docker is not running or delete %s", pidfile)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
file, err := os.Create(pidfile)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
defer file.Close()
|
|
||||||
|
|
||||||
_, err = fmt.Fprintf(file, "%d", os.Getpid())
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func removePidFile(pidfile string) {
|
|
||||||
if err := os.Remove(pidfile); err != nil {
|
|
||||||
log.Printf("Error removing %s: %s", pidfile, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func daemon(pidfile string, flGraphPath string, protoAddrs []string, autoRestart, enableCors bool, flDns string) error {
|
|
||||||
if err := createPidFile(pidfile); err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
defer removePidFile(pidfile)
|
|
||||||
|
|
||||||
c := make(chan os.Signal, 1)
|
|
||||||
signal.Notify(c, os.Interrupt, os.Kill, os.Signal(syscall.SIGTERM))
|
|
||||||
go func() {
|
|
||||||
sig := <-c
|
|
||||||
log.Printf("Received signal '%v', exiting\n", sig)
|
|
||||||
removePidFile(pidfile)
|
|
||||||
os.Exit(0)
|
|
||||||
}()
|
|
||||||
var dns []string
|
|
||||||
if flDns != "" {
|
|
||||||
dns = []string{flDns}
|
|
||||||
}
|
|
||||||
server, err := docker.NewServer(flGraphPath, autoRestart, enableCors, dns)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
chErrors := make(chan error, len(protoAddrs))
|
|
||||||
for _, protoAddr := range protoAddrs {
|
|
||||||
protoAddrParts := strings.SplitN(protoAddr, "://", 2)
|
|
||||||
if protoAddrParts[0] == "unix" {
|
|
||||||
syscall.Unlink(protoAddrParts[1])
|
|
||||||
} else if protoAddrParts[0] == "tcp" {
|
|
||||||
if !strings.HasPrefix(protoAddrParts[1], "127.0.0.1") {
|
|
||||||
log.Println("/!\\ DON'T BIND ON ANOTHER IP ADDRESS THAN 127.0.0.1 IF YOU DON'T KNOW WHAT YOU'RE DOING /!\\")
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
log.Fatal("Invalid protocol format.")
|
|
||||||
os.Exit(-1)
|
|
||||||
}
|
|
||||||
go func() {
|
|
||||||
chErrors <- docker.ListenAndServe(protoAddrParts[0], protoAddrParts[1], server, true)
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
for i := 0; i < len(protoAddrs); i += 1 {
|
|
||||||
err := <-chErrors
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/dotcloud/docker/sysinit"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
GITCOMMIT string
|
||||||
|
VERSION string
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
// Running in init mode
|
||||||
|
sysinit.SysInit()
|
||||||
|
return
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
from ubuntu:12.04
|
||||||
|
maintainer Nick Stinemates
|
||||||
|
#
|
||||||
|
# docker build -t docker:docs . && docker run -p 8000:8000 docker:docs
|
||||||
|
#
|
||||||
|
|
||||||
|
run apt-get update
|
||||||
|
run apt-get install -y python-setuptools make
|
||||||
|
run easy_install pip
|
||||||
|
#from docs/requirements.txt, but here to increase cacheability
|
||||||
|
run pip install Sphinx==1.1.3
|
||||||
|
run pip install sphinxcontrib-httpdomain==1.1.8
|
||||||
|
add . /docs
|
||||||
|
run cd /docs; make docs
|
||||||
|
|
||||||
|
expose 8000
|
||||||
|
|
||||||
|
workdir /docs/_build/html
|
||||||
|
|
||||||
|
entrypoint ["python", "-m", "SimpleHTTPServer"]
|
||||||
+2
-2
@@ -1,2 +1,2 @@
|
|||||||
Andy Rothfusz <andy@dotcloud.com>
|
Andy Rothfusz <andy@dotcloud.com> (@metalivedev)
|
||||||
Ken Cochrane <ken@dotcloud.com>
|
Ken Cochrane <ken@dotcloud.com> (@kencochrane)
|
||||||
|
|||||||
+1
-1
@@ -31,7 +31,7 @@ help:
|
|||||||
# @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
|
# @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
|
||||||
# @echo " latexpdf to make LaTeX files and run them through pdflatex"
|
# @echo " latexpdf to make LaTeX files and run them through pdflatex"
|
||||||
# @echo " text to make text files"
|
# @echo " text to make text files"
|
||||||
# @echo " man to make manual pages"
|
@echo " man to make a manual page"
|
||||||
# @echo " texinfo to make Texinfo files"
|
# @echo " texinfo to make Texinfo files"
|
||||||
# @echo " info to make Texinfo files and run them through makeinfo"
|
# @echo " info to make Texinfo files and run them through makeinfo"
|
||||||
# @echo " gettext to make PO message catalogs"
|
# @echo " gettext to make PO message catalogs"
|
||||||
|
|||||||
+91
-25
@@ -1,53 +1,103 @@
|
|||||||
Docker documentation and website
|
Docker Documentation
|
||||||
================================
|
====================
|
||||||
|
|
||||||
Documentation
|
Overview
|
||||||
-------------
|
--------
|
||||||
This is your definite place to contribute to the docker documentation. The documentation is generated from the
|
|
||||||
.rst files under sources.
|
|
||||||
|
|
||||||
The folder also contains the other files to create the http://docker.io website, but you can generally ignore
|
The source for Docker documentation is here under ``sources/`` in the
|
||||||
most of those.
|
form of .rst files. These files use
|
||||||
|
[reStructuredText](http://docutils.sourceforge.net/rst.html)
|
||||||
|
formatting with [Sphinx](http://sphinx-doc.org/) extensions for
|
||||||
|
structure, cross-linking and indexing.
|
||||||
|
|
||||||
|
The HTML files are built and hosted on
|
||||||
|
[readthedocs.org](https://readthedocs.org/projects/docker/), appearing
|
||||||
|
via proxy on https://docs.docker.io. The HTML files update
|
||||||
|
automatically after each change to the master or release branch of the
|
||||||
|
[docker files on GitHub](https://github.com/dotcloud/docker) thanks to
|
||||||
|
post-commit hooks. The "release" branch maps to the "latest"
|
||||||
|
documentation and the "master" branch maps to the "master"
|
||||||
|
documentation.
|
||||||
|
|
||||||
Installation
|
**Warning**: The "master" documentation may include features not yet
|
||||||
------------
|
part of any official docker release. "Master" docs should be used only
|
||||||
|
for understanding bleeding-edge development and "latest" should be
|
||||||
|
used for the latest official release.
|
||||||
|
|
||||||
|
If you need to manually trigger a build of an existing branch, then
|
||||||
|
you can do that through the [readthedocs
|
||||||
|
interface](https://readthedocs.org/builds/docker/). If you would like
|
||||||
|
to add new build targets, including new branches or tags, then you
|
||||||
|
must contact one of the existing maintainers and get your
|
||||||
|
readthedocs.org account added to the maintainers list, or just file an
|
||||||
|
issue on GitHub describing the branch/tag and why it needs to be added
|
||||||
|
to the docs, and one of the maintainers will add it for you.
|
||||||
|
|
||||||
|
Getting Started
|
||||||
|
---------------
|
||||||
|
|
||||||
|
To edit and test the docs, you'll need to install the Sphinx tool and
|
||||||
|
its dependencies. There are two main ways to install this tool:
|
||||||
|
|
||||||
|
###Native Installation
|
||||||
|
|
||||||
* Work in your own fork of the code, we accept pull requests.
|
|
||||||
* Install sphinx: `pip install sphinx`
|
* Install sphinx: `pip install sphinx`
|
||||||
* Mac OS X: `[sudo] pip-2.7 install sphinx`)
|
* Mac OS X: `[sudo] pip-2.7 install sphinx`
|
||||||
* Install sphinx httpdomain contrib package: `pip install sphinxcontrib-httpdomain`
|
* Install sphinx httpdomain contrib package: `pip install sphinxcontrib-httpdomain`
|
||||||
* Mac OS X: `[sudo] pip-2.7 install sphinxcontrib-httpdomain`
|
* Mac OS X: `[sudo] pip-2.7 install sphinxcontrib-httpdomain`
|
||||||
* If pip is not available you can probably install it using your favorite package manager as **python-pip**
|
* If pip is not available you can probably install it using your favorite package manager as **python-pip**
|
||||||
|
|
||||||
|
###Alternative Installation: Docker Container
|
||||||
|
|
||||||
|
If you're running ``docker`` on your development machine then you may
|
||||||
|
find it easier and cleaner to use the Dockerfile. This installs Sphinx
|
||||||
|
in a container, adds the local ``docs/`` directory and builds the HTML
|
||||||
|
docs inside the container, even starting a simple HTTP server on port
|
||||||
|
8000 so that you can connect and see your changes. Just run ``docker
|
||||||
|
build .`` and run the resulting image. This is the equivalent to
|
||||||
|
``make clean server`` since each container starts clean.
|
||||||
|
|
||||||
|
In the ``docs/`` directory, run:
|
||||||
|
```docker build -t docker:docs . && docker run -p 8000:8000 docker:docs```
|
||||||
|
|
||||||
Usage
|
Usage
|
||||||
-----
|
-----
|
||||||
* Change the `.rst` files with your favorite editor to your liking.
|
* Follow the contribution guidelines (``../CONTRIBUTING.md``)
|
||||||
* Run `make docs` to clean up old files and generate new ones.
|
* Work in your own fork of the code, we accept pull requests.
|
||||||
* Your static website can now be found in the `_build` directory.
|
* Change the ``.rst`` files with your favorite editor -- try to keep the
|
||||||
* To preview what you have generated run `make server` and open <http://localhost:8000/> in your favorite browser.
|
lines short and respect RST and Sphinx conventions.
|
||||||
|
* Run ``make clean docs`` to clean up old files and generate new ones,
|
||||||
|
or just ``make docs`` to update after small changes.
|
||||||
|
* Your static website can now be found in the ``_build`` directory.
|
||||||
|
* To preview what you have generated run ``make server`` and open
|
||||||
|
http://localhost:8000/ in your favorite browser.
|
||||||
|
|
||||||
|
``make clean docs`` must complete without any warnings or errors.
|
||||||
|
|
||||||
Working using GitHub's file editor
|
Working using GitHub's file editor
|
||||||
----------------------------------
|
----------------------------------
|
||||||
Alternatively, for small changes and typo's you might want to use GitHub's built in file editor. It allows
|
|
||||||
you to preview your changes right online. Just be carefull not to create many commits.
|
Alternatively, for small changes and typos you might want to use
|
||||||
|
GitHub's built in file editor. It allows you to preview your changes
|
||||||
|
right online (though there can be some differences between GitHub
|
||||||
|
markdown and Sphinx RST). Just be careful not to create many commits.
|
||||||
|
|
||||||
Images
|
Images
|
||||||
------
|
------
|
||||||
When you need to add images, try to make them as small as possible (e.g. as gif).
|
|
||||||
|
|
||||||
|
When you need to add images, try to make them as small as possible
|
||||||
|
(e.g. as gif). Usually images should go in the same directory as the
|
||||||
|
.rst file which references them, or in a subdirectory if one already
|
||||||
|
exists.
|
||||||
|
|
||||||
Notes
|
Notes
|
||||||
-----
|
-----
|
||||||
* The index.html and gettingstarted.html files are copied from the source dir to the output dir without modification.
|
|
||||||
So changes to those pages should be made directly in html
|
|
||||||
* For the template the css is compiled from less. When changes are needed they can be compiled using
|
* For the template the css is compiled from less. When changes are needed they can be compiled using
|
||||||
lessc ``lessc main.less`` or watched using watch-lessc ``watch-lessc -i main.less -o main.css``
|
lessc ``lessc main.less`` or watched using watch-lessc ``watch-lessc -i main.less -o main.css``
|
||||||
|
|
||||||
|
|
||||||
Guides on using sphinx
|
Guides on using sphinx
|
||||||
----------------------
|
----------------------
|
||||||
* To make links to certain pages create a link target like so:
|
* To make links to certain sections create a link target like so:
|
||||||
|
|
||||||
```
|
```
|
||||||
.. _hello_world:
|
.. _hello_world:
|
||||||
@@ -58,7 +108,10 @@ Guides on using sphinx
|
|||||||
This is.. (etc.)
|
This is.. (etc.)
|
||||||
```
|
```
|
||||||
|
|
||||||
The ``_hello_world:`` will make it possible to link to this position (page and marker) from all other pages.
|
The ``_hello_world:`` will make it possible to link to this position
|
||||||
|
(page and section heading) from all other pages. See the [Sphinx
|
||||||
|
docs](http://sphinx-doc.org/markup/inline.html#role-ref) for more
|
||||||
|
information and examples.
|
||||||
|
|
||||||
* Notes, warnings and alarms
|
* Notes, warnings and alarms
|
||||||
|
|
||||||
@@ -74,4 +127,17 @@ Guides on using sphinx
|
|||||||
|
|
||||||
* Code examples
|
* Code examples
|
||||||
|
|
||||||
Start without $, so it's easy to copy and paste.
|
* Start without $, so it's easy to copy and paste.
|
||||||
|
* Use "sudo" with docker to ensure that your command is runnable
|
||||||
|
even if they haven't [used the *docker*
|
||||||
|
group](http://docs.docker.io/en/latest/use/basics/#why-sudo).
|
||||||
|
|
||||||
|
Manpages
|
||||||
|
--------
|
||||||
|
|
||||||
|
* To make the manpages, run ``make man``. Please note there is a bug
|
||||||
|
in spinx 1.1.3 which makes this fail. Upgrade to the latest version
|
||||||
|
of Sphinx.
|
||||||
|
* Then preview the manpage by running ``man _build/man/docker.1``,
|
||||||
|
where ``_build/man/docker.1`` is the path to the generated manfile
|
||||||
|
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
Sphinx==1.1.3
|
Sphinx==1.1.3
|
||||||
sphinxcontrib-httpdomain==1.1.8
|
sphinxcontrib-httpdomain==1.1.9
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
Solomon Hykes <solomon@dotcloud.com>
|
Solomon Hykes <solomon@dotcloud.com> (@shykes)
|
||||||
|
|||||||
@@ -9,13 +9,13 @@
|
|||||||
Docker Remote API
|
Docker Remote API
|
||||||
=================
|
=================
|
||||||
|
|
||||||
.. contents:: Table of Contents
|
|
||||||
|
|
||||||
1. Brief introduction
|
1. Brief introduction
|
||||||
=====================
|
=====================
|
||||||
|
|
||||||
- The Remote API is replacing rcli
|
- The Remote API is replacing rcli
|
||||||
- By default the Docker daemon listens on unix:///var/run/docker.sock and the client must have root access to interact with the daemon
|
- By default the Docker daemon listens on unix:///var/run/docker.sock and the client must have root access to interact with the daemon
|
||||||
|
- If a group named *docker* exists on your system, docker will apply ownership of the socket to the group
|
||||||
- The API tends to be REST, but for some complex commands, like attach
|
- The API tends to be REST, but for some complex commands, like attach
|
||||||
or pull, the HTTP connection is hijacked to transport stdout stdin
|
or pull, the HTTP connection is hijacked to transport stdout stdin
|
||||||
and stderr
|
and stderr
|
||||||
@@ -26,29 +26,198 @@ Docker Remote API
|
|||||||
2. Versions
|
2. Versions
|
||||||
===========
|
===========
|
||||||
|
|
||||||
The current verson of the API is 1.4
|
The current version of the API is 1.7
|
||||||
|
|
||||||
Calling /images/<name>/insert is the same as calling
|
Calling /images/<name>/insert is the same as calling
|
||||||
/v1.4/images/<name>/insert
|
/v1.7/images/<name>/insert
|
||||||
|
|
||||||
You can still call an old version of the api using
|
You can still call an old version of the api using
|
||||||
/v1.0/images/<name>/insert
|
/v1.0/images/<name>/insert
|
||||||
|
|
||||||
:doc:`docker_remote_api_v1.4`
|
v1.7
|
||||||
*****************************
|
****
|
||||||
|
|
||||||
|
Full Documentation
|
||||||
|
------------------
|
||||||
|
|
||||||
|
:doc:`docker_remote_api_v1.7`
|
||||||
|
|
||||||
What's new
|
What's new
|
||||||
----------
|
----------
|
||||||
|
|
||||||
|
.. http:get:: /images/json
|
||||||
|
|
||||||
|
The format of the json returned from this uri changed. Instead of an entry
|
||||||
|
for each repo/tag on an image, each image is only represented once, with a
|
||||||
|
nested attribute indicating the repo/tags that apply to that image.
|
||||||
|
|
||||||
|
Instead of:
|
||||||
|
|
||||||
|
.. sourcecode:: http
|
||||||
|
|
||||||
|
HTTP/1.1 200 OK
|
||||||
|
Content-Type: application/json
|
||||||
|
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"VirtualSize": 131506275,
|
||||||
|
"Size": 131506275,
|
||||||
|
"Created": 1365714795,
|
||||||
|
"Id": "8dbd9e392a964056420e5d58ca5cc376ef18e2de93b5cc90e868a1bbc8318c1c",
|
||||||
|
"Tag": "12.04",
|
||||||
|
"Repository": "ubuntu"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"VirtualSize": 131506275,
|
||||||
|
"Size": 131506275,
|
||||||
|
"Created": 1365714795,
|
||||||
|
"Id": "8dbd9e392a964056420e5d58ca5cc376ef18e2de93b5cc90e868a1bbc8318c1c",
|
||||||
|
"Tag": "latest",
|
||||||
|
"Repository": "ubuntu"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"VirtualSize": 131506275,
|
||||||
|
"Size": 131506275,
|
||||||
|
"Created": 1365714795,
|
||||||
|
"Id": "8dbd9e392a964056420e5d58ca5cc376ef18e2de93b5cc90e868a1bbc8318c1c",
|
||||||
|
"Tag": "precise",
|
||||||
|
"Repository": "ubuntu"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"VirtualSize": 180116135,
|
||||||
|
"Size": 24653,
|
||||||
|
"Created": 1364102658,
|
||||||
|
"Id": "b750fe79269d2ec9a3c593ef05b4332b1d1a02a62b4accb2c21d589ff2f5f2dc",
|
||||||
|
"Tag": "12.10",
|
||||||
|
"Repository": "ubuntu"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"VirtualSize": 180116135,
|
||||||
|
"Size": 24653,
|
||||||
|
"Created": 1364102658,
|
||||||
|
"Id": "b750fe79269d2ec9a3c593ef05b4332b1d1a02a62b4accb2c21d589ff2f5f2dc",
|
||||||
|
"Tag": "quantal",
|
||||||
|
"Repository": "ubuntu"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
The returned json looks like this:
|
||||||
|
|
||||||
|
.. sourcecode:: http
|
||||||
|
|
||||||
|
HTTP/1.1 200 OK
|
||||||
|
Content-Type: application/json
|
||||||
|
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"RepoTag": [
|
||||||
|
"ubuntu:12.04",
|
||||||
|
"ubuntu:precise",
|
||||||
|
"ubuntu:latest"
|
||||||
|
],
|
||||||
|
"Id": "8dbd9e392a964056420e5d58ca5cc376ef18e2de93b5cc90e868a1bbc8318c1c",
|
||||||
|
"Created": 1365714795,
|
||||||
|
"Size": 131506275,
|
||||||
|
"VirtualSize": 131506275
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"RepoTag": [
|
||||||
|
"ubuntu:12.10",
|
||||||
|
"ubuntu:quantal"
|
||||||
|
],
|
||||||
|
"ParentId": "27cf784147099545",
|
||||||
|
"Id": "b750fe79269d2ec9a3c593ef05b4332b1d1a02a62b4accb2c21d589ff2f5f2dc",
|
||||||
|
"Created": 1364102658,
|
||||||
|
"Size": 24653,
|
||||||
|
"VirtualSize": 180116135
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
.. http:get:: /images/viz
|
||||||
|
|
||||||
|
This URI no longer exists. The ``images -viz`` output is now generated in
|
||||||
|
the client, using the ``/images/json`` data.
|
||||||
|
|
||||||
|
v1.6
|
||||||
|
****
|
||||||
|
|
||||||
|
Full Documentation
|
||||||
|
------------------
|
||||||
|
|
||||||
|
:doc:`docker_remote_api_v1.6`
|
||||||
|
|
||||||
|
What's new
|
||||||
|
----------
|
||||||
|
|
||||||
|
.. http:post:: /containers/(id)/attach
|
||||||
|
|
||||||
|
**New!** You can now split stderr from stdout. This is done by prefixing
|
||||||
|
a header to each transmition. See :http:post:`/containers/(id)/attach`.
|
||||||
|
The WebSocket attach is unchanged.
|
||||||
|
Note that attach calls on the previous API version didn't change. Stdout and
|
||||||
|
stderr are merged.
|
||||||
|
|
||||||
|
|
||||||
|
v1.5
|
||||||
|
****
|
||||||
|
|
||||||
|
Full Documentation
|
||||||
|
------------------
|
||||||
|
|
||||||
|
:doc:`docker_remote_api_v1.5`
|
||||||
|
|
||||||
|
What's new
|
||||||
|
----------
|
||||||
|
|
||||||
|
.. http:post:: /images/create
|
||||||
|
|
||||||
|
**New!** You can now pass registry credentials (via an AuthConfig object)
|
||||||
|
through the `X-Registry-Auth` header
|
||||||
|
|
||||||
|
.. http:post:: /images/(name)/push
|
||||||
|
|
||||||
|
**New!** The AuthConfig object now needs to be passed through
|
||||||
|
the `X-Registry-Auth` header
|
||||||
|
|
||||||
|
.. http:get:: /containers/json
|
||||||
|
|
||||||
|
**New!** The format of the `Ports` entry has been changed to a list of
|
||||||
|
dicts each containing `PublicPort`, `PrivatePort` and `Type` describing a
|
||||||
|
port mapping.
|
||||||
|
|
||||||
|
v1.4
|
||||||
|
****
|
||||||
|
|
||||||
|
Full Documentation
|
||||||
|
------------------
|
||||||
|
|
||||||
|
:doc:`docker_remote_api_v1.4`
|
||||||
|
|
||||||
|
What's new
|
||||||
|
----------
|
||||||
|
|
||||||
|
.. http:post:: /images/create
|
||||||
|
|
||||||
|
**New!** When pulling a repo, all images are now downloaded in parallel.
|
||||||
|
|
||||||
.. http:get:: /containers/(id)/top
|
.. http:get:: /containers/(id)/top
|
||||||
|
|
||||||
**New!** You can now use ps args with docker top, like `docker top <container_id> aux`
|
**New!** You can now use ps args with docker top, like `docker top <container_id> aux`
|
||||||
|
|
||||||
:doc:`docker_remote_api_v1.3`
|
.. http:get:: /events:
|
||||||
*****************************
|
|
||||||
|
**New!** Image's name added in the events
|
||||||
|
|
||||||
|
v1.3
|
||||||
|
****
|
||||||
|
|
||||||
docker v0.5.0 51f6c4a_
|
docker v0.5.0 51f6c4a_
|
||||||
|
|
||||||
|
Full Documentation
|
||||||
|
------------------
|
||||||
|
|
||||||
|
:doc:`docker_remote_api_v1.3`
|
||||||
|
|
||||||
What's new
|
What's new
|
||||||
----------
|
----------
|
||||||
|
|
||||||
@@ -81,11 +250,16 @@ Start containers (/containers/<id>/start):
|
|||||||
- You can now pass host-specific configuration (e.g. bind mounts) in
|
- You can now pass host-specific configuration (e.g. bind mounts) in
|
||||||
the POST body for start calls
|
the POST body for start calls
|
||||||
|
|
||||||
:doc:`docker_remote_api_v1.2`
|
v1.2
|
||||||
*****************************
|
****
|
||||||
|
|
||||||
docker v0.4.2 2e7649b_
|
docker v0.4.2 2e7649b_
|
||||||
|
|
||||||
|
Full Documentation
|
||||||
|
------------------
|
||||||
|
|
||||||
|
:doc:`docker_remote_api_v1.2`
|
||||||
|
|
||||||
What's new
|
What's new
|
||||||
----------
|
----------
|
||||||
|
|
||||||
@@ -103,7 +277,7 @@ The client should send it's authConfig as POST on each call of
|
|||||||
Only checks the configuration but doesn't store it on the server
|
Only checks the configuration but doesn't store it on the server
|
||||||
|
|
||||||
Deleting an image is now improved, will only untag the image if it
|
Deleting an image is now improved, will only untag the image if it
|
||||||
has chidren and remove all the untagged parents if has any.
|
has children and remove all the untagged parents if has any.
|
||||||
|
|
||||||
.. http:post:: /images/<name>/delete
|
.. http:post:: /images/<name>/delete
|
||||||
|
|
||||||
@@ -111,11 +285,16 @@ The client should send it's authConfig as POST on each call of
|
|||||||
deleted/untagged.
|
deleted/untagged.
|
||||||
|
|
||||||
|
|
||||||
:doc:`docker_remote_api_v1.1`
|
v1.1
|
||||||
*****************************
|
****
|
||||||
|
|
||||||
docker v0.4.0 a8ae398_
|
docker v0.4.0 a8ae398_
|
||||||
|
|
||||||
|
Full Documentation
|
||||||
|
------------------
|
||||||
|
|
||||||
|
:doc:`docker_remote_api_v1.1`
|
||||||
|
|
||||||
What's new
|
What's new
|
||||||
----------
|
----------
|
||||||
|
|
||||||
@@ -135,12 +314,16 @@ What's new
|
|||||||
{"error":"Invalid..."}
|
{"error":"Invalid..."}
|
||||||
...
|
...
|
||||||
|
|
||||||
|
v1.0
|
||||||
:doc:`docker_remote_api_v1.0`
|
****
|
||||||
*****************************
|
|
||||||
|
|
||||||
docker v0.3.4 8d73740_
|
docker v0.3.4 8d73740_
|
||||||
|
|
||||||
|
Full Documentation
|
||||||
|
------------------
|
||||||
|
|
||||||
|
:doc:`docker_remote_api_v1.0`
|
||||||
|
|
||||||
What's new
|
What's new
|
||||||
----------
|
----------
|
||||||
|
|
||||||
@@ -151,32 +334,3 @@ Initial version
|
|||||||
.. _8d73740: https://github.com/dotcloud/docker/commit/8d73740343778651c09160cde9661f5f387b36f4
|
.. _8d73740: https://github.com/dotcloud/docker/commit/8d73740343778651c09160cde9661f5f387b36f4
|
||||||
.. _2e7649b: https://github.com/dotcloud/docker/commit/2e7649beda7c820793bd46766cbc2cfeace7b168
|
.. _2e7649b: https://github.com/dotcloud/docker/commit/2e7649beda7c820793bd46766cbc2cfeace7b168
|
||||||
.. _51f6c4a: https://github.com/dotcloud/docker/commit/51f6c4a7372450d164c61e0054daf0223ddbd909
|
.. _51f6c4a: https://github.com/dotcloud/docker/commit/51f6c4a7372450d164c61e0054daf0223ddbd909
|
||||||
|
|
||||||
==================================
|
|
||||||
Docker Remote API Client Libraries
|
|
||||||
==================================
|
|
||||||
|
|
||||||
These libraries have been not tested by the Docker Maintainers for
|
|
||||||
compatibility. Please file issues with the library owners. If you
|
|
||||||
find more library implementations, please list them in Docker doc bugs
|
|
||||||
and we will add the libraries here.
|
|
||||||
|
|
||||||
+----------------------+----------------+--------------------------------------------+
|
|
||||||
| Language/Framework | Name | Repository |
|
|
||||||
+======================+================+============================================+
|
|
||||||
| Python | docker-py | https://github.com/dotcloud/docker-py |
|
|
||||||
+----------------------+----------------+--------------------------------------------+
|
|
||||||
| Ruby | docker-ruby | https://github.com/ActiveState/docker-ruby |
|
|
||||||
+----------------------+----------------+--------------------------------------------+
|
|
||||||
| Ruby | docker-client | https://github.com/geku/docker-client |
|
|
||||||
+----------------------+----------------+--------------------------------------------+
|
|
||||||
| Ruby | docker-api | https://github.com/swipely/docker-api |
|
|
||||||
+----------------------+----------------+--------------------------------------------+
|
|
||||||
| Javascript | docker-js | https://github.com/dgoujard/docker-js |
|
|
||||||
+----------------------+----------------+--------------------------------------------+
|
|
||||||
| Javascript (Angular) | dockerui | https://github.com/crosbymichael/dockerui |
|
|
||||||
| **WebUI** | | |
|
|
||||||
+----------------------+----------------+--------------------------------------------+
|
|
||||||
| Java | docker-java | https://github.com/kpelykh/docker-java |
|
|
||||||
+----------------------+----------------+--------------------------------------------+
|
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ Docker Remote API v1.0
|
|||||||
=====================
|
=====================
|
||||||
|
|
||||||
- The Remote API is replacing rcli
|
- The Remote API is replacing rcli
|
||||||
- Default port in the docker deamon is 4243
|
- Default port in the docker daemon is 4243
|
||||||
- The API tends to be REST, but for some complex commands, like attach or pull, the HTTP connection is hijacked to transport stdout stdin and stderr
|
- The API tends to be REST, but for some complex commands, like attach or pull, the HTTP connection is hijacked to transport stdout stdin and stderr
|
||||||
|
|
||||||
2. Endpoints
|
2. Endpoints
|
||||||
@@ -49,28 +49,28 @@ List containers
|
|||||||
[
|
[
|
||||||
{
|
{
|
||||||
"Id": "8dfafdbc3a40",
|
"Id": "8dfafdbc3a40",
|
||||||
"Image": "base:latest",
|
"Image": "ubuntu:latest",
|
||||||
"Command": "echo 1",
|
"Command": "echo 1",
|
||||||
"Created": 1367854155,
|
"Created": 1367854155,
|
||||||
"Status": "Exit 0"
|
"Status": "Exit 0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Id": "9cd87474be90",
|
"Id": "9cd87474be90",
|
||||||
"Image": "base:latest",
|
"Image": "ubuntu:latest",
|
||||||
"Command": "echo 222222",
|
"Command": "echo 222222",
|
||||||
"Created": 1367854155,
|
"Created": 1367854155,
|
||||||
"Status": "Exit 0"
|
"Status": "Exit 0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Id": "3176a2479c92",
|
"Id": "3176a2479c92",
|
||||||
"Image": "base:latest",
|
"Image": "centos:latest",
|
||||||
"Command": "echo 3333333333333333",
|
"Command": "echo 3333333333333333",
|
||||||
"Created": 1367854154,
|
"Created": 1367854154,
|
||||||
"Status": "Exit 0"
|
"Status": "Exit 0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Id": "4cb07b47f9fb",
|
"Id": "4cb07b47f9fb",
|
||||||
"Image": "base:latest",
|
"Image": "fedora:latest",
|
||||||
"Command": "echo 444444444444444444444444444444444",
|
"Command": "echo 444444444444444444444444444444444",
|
||||||
"Created": 1367854152,
|
"Created": 1367854152,
|
||||||
"Status": "Exit 0"
|
"Status": "Exit 0"
|
||||||
@@ -117,7 +117,7 @@ Create a container
|
|||||||
"date"
|
"date"
|
||||||
],
|
],
|
||||||
"Dns":null,
|
"Dns":null,
|
||||||
"Image":"base",
|
"Image":"ubuntu",
|
||||||
"Volumes":{},
|
"Volumes":{},
|
||||||
"VolumesFrom":""
|
"VolumesFrom":""
|
||||||
}
|
}
|
||||||
@@ -183,7 +183,7 @@ Inspect a container
|
|||||||
"date"
|
"date"
|
||||||
],
|
],
|
||||||
"Dns": null,
|
"Dns": null,
|
||||||
"Image": "base",
|
"Image": "ubuntu",
|
||||||
"Volumes": {},
|
"Volumes": {},
|
||||||
"VolumesFrom": ""
|
"VolumesFrom": ""
|
||||||
},
|
},
|
||||||
@@ -490,14 +490,14 @@ List Images
|
|||||||
|
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
"Repository":"base",
|
"Repository":"ubuntu",
|
||||||
"Tag":"ubuntu-12.10",
|
"Tag":"precise",
|
||||||
"Id":"b750fe79269d",
|
"Id":"b750fe79269d",
|
||||||
"Created":1364102658
|
"Created":1364102658
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Repository":"base",
|
"Repository":"ubuntu",
|
||||||
"Tag":"ubuntu-quantal",
|
"Tag":"12.04",
|
||||||
"Id":"b750fe79269d",
|
"Id":"b750fe79269d",
|
||||||
"Created":1364102658
|
"Created":1364102658
|
||||||
}
|
}
|
||||||
@@ -529,9 +529,9 @@ List Images
|
|||||||
"d6434d954665" -> "d82cbacda43a"
|
"d6434d954665" -> "d82cbacda43a"
|
||||||
base -> "e9aa60c60128" [style=invis]
|
base -> "e9aa60c60128" [style=invis]
|
||||||
"074be284591f" -> "f71189fff3de"
|
"074be284591f" -> "f71189fff3de"
|
||||||
"b750fe79269d" [label="b750fe79269d\nbase",shape=box,fillcolor="paleturquoise",style="filled,rounded"];
|
"b750fe79269d" [label="b750fe79269d\nubuntu",shape=box,fillcolor="paleturquoise",style="filled,rounded"];
|
||||||
"e9aa60c60128" [label="e9aa60c60128\nbase2",shape=box,fillcolor="paleturquoise",style="filled,rounded"];
|
"e9aa60c60128" [label="e9aa60c60128\ncentos",shape=box,fillcolor="paleturquoise",style="filled,rounded"];
|
||||||
"9a33b36209ed" [label="9a33b36209ed\ntest",shape=box,fillcolor="paleturquoise",style="filled,rounded"];
|
"9a33b36209ed" [label="9a33b36209ed\nfedora",shape=box,fillcolor="paleturquoise",style="filled,rounded"];
|
||||||
base [style=invisible]
|
base [style=invisible]
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -552,7 +552,7 @@ Create an image
|
|||||||
|
|
||||||
.. sourcecode:: http
|
.. sourcecode:: http
|
||||||
|
|
||||||
POST /images/create?fromImage=base HTTP/1.1
|
POST /images/create?fromImage=ubuntu HTTP/1.1
|
||||||
|
|
||||||
**Example response**:
|
**Example response**:
|
||||||
|
|
||||||
@@ -572,8 +572,8 @@ Create an image
|
|||||||
:statuscode 500: server error
|
:statuscode 500: server error
|
||||||
|
|
||||||
|
|
||||||
Insert a file in a image
|
Insert a file in an image
|
||||||
************************
|
*************************
|
||||||
|
|
||||||
.. http:post:: /images/(name)/insert
|
.. http:post:: /images/(name)/insert
|
||||||
|
|
||||||
@@ -608,7 +608,7 @@ Inspect an image
|
|||||||
|
|
||||||
.. sourcecode:: http
|
.. sourcecode:: http
|
||||||
|
|
||||||
GET /images/base/json HTTP/1.1
|
GET /images/centos/json HTTP/1.1
|
||||||
|
|
||||||
**Example response**:
|
**Example response**:
|
||||||
|
|
||||||
@@ -638,7 +638,7 @@ Inspect an image
|
|||||||
"Env":null,
|
"Env":null,
|
||||||
"Cmd": ["/bin/bash"]
|
"Cmd": ["/bin/bash"]
|
||||||
,"Dns":null,
|
,"Dns":null,
|
||||||
"Image":"base",
|
"Image":"centos",
|
||||||
"Volumes":null,
|
"Volumes":null,
|
||||||
"VolumesFrom":""
|
"VolumesFrom":""
|
||||||
}
|
}
|
||||||
@@ -660,7 +660,7 @@ Get the history of an image
|
|||||||
|
|
||||||
.. sourcecode:: http
|
.. sourcecode:: http
|
||||||
|
|
||||||
GET /images/base/history HTTP/1.1
|
GET /images/fedora/history HTTP/1.1
|
||||||
|
|
||||||
**Example response**:
|
**Example response**:
|
||||||
|
|
||||||
@@ -832,7 +832,7 @@ Build an image from Dockerfile via stdin
|
|||||||
|
|
||||||
{{ STREAM }}
|
{{ STREAM }}
|
||||||
|
|
||||||
:query t: tag to be applied to the resulting image in case of success
|
:query t: repository name to be applied to the resulting image in case of success
|
||||||
:statuscode 200: no error
|
:statuscode 200: no error
|
||||||
:statuscode 500: server error
|
:statuscode 500: server error
|
||||||
|
|
||||||
@@ -970,28 +970,33 @@ Create a new image from a container's changes
|
|||||||
|
|
||||||
**Example request**:
|
**Example request**:
|
||||||
|
|
||||||
.. sourcecode:: http
|
.. sourcecode:: http
|
||||||
|
|
||||||
POST /commit?container=44c004db4b17&m=message&repo=myrepo HTTP/1.1
|
POST /commit?container=44c004db4b17&m=message&repo=myrepo HTTP/1.1
|
||||||
|
Content-Type: application/json
|
||||||
|
|
||||||
|
{
|
||||||
|
"Cmd": ["cat", "/world"],
|
||||||
|
"PortSpecs":["22"]
|
||||||
|
}
|
||||||
|
|
||||||
**Example response**:
|
**Example response**:
|
||||||
|
|
||||||
.. sourcecode:: http
|
.. sourcecode:: http
|
||||||
|
|
||||||
HTTP/1.1 201 OK
|
HTTP/1.1 201 OK
|
||||||
Content-Type: application/vnd.docker.raw-stream
|
Content-Type: application/vnd.docker.raw-stream
|
||||||
|
|
||||||
{"Id":"596069db4bf5"}
|
{"Id":"596069db4bf5"}
|
||||||
|
|
||||||
:query container: source container
|
:query container: source container
|
||||||
:query repo: repository
|
:query repo: repository
|
||||||
:query tag: tag
|
:query tag: tag
|
||||||
:query m: commit message
|
:query m: commit message
|
||||||
:query author: author (eg. "John Hannibal Smith <hannibal@a-team.com>")
|
:query author: author (eg. "John Hannibal Smith <hannibal@a-team.com>")
|
||||||
:query run: config automatically applied when the image is run. (ex: {"Cmd": ["cat", "/world"], "PortSpecs":["22"]})
|
:statuscode 201: no error
|
||||||
:statuscode 201: no error
|
:statuscode 404: no such container
|
||||||
:statuscode 404: no such container
|
:statuscode 500: server error
|
||||||
:statuscode 500: server error
|
|
||||||
|
|
||||||
|
|
||||||
3. Going further
|
3. Going further
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ Docker Remote API v1.1
|
|||||||
=====================
|
=====================
|
||||||
|
|
||||||
- The Remote API is replacing rcli
|
- The Remote API is replacing rcli
|
||||||
- Default port in the docker deamon is 4243
|
- Default port in the docker daemon is 4243
|
||||||
- The API tends to be REST, but for some complex commands, like attach or pull, the HTTP connection is hijacked to transport stdout stdin and stderr
|
- The API tends to be REST, but for some complex commands, like attach or pull, the HTTP connection is hijacked to transport stdout stdin and stderr
|
||||||
|
|
||||||
2. Endpoints
|
2. Endpoints
|
||||||
@@ -49,28 +49,28 @@ List containers
|
|||||||
[
|
[
|
||||||
{
|
{
|
||||||
"Id": "8dfafdbc3a40",
|
"Id": "8dfafdbc3a40",
|
||||||
"Image": "base:latest",
|
"Image": "ubuntu:latest",
|
||||||
"Command": "echo 1",
|
"Command": "echo 1",
|
||||||
"Created": 1367854155,
|
"Created": 1367854155,
|
||||||
"Status": "Exit 0"
|
"Status": "Exit 0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Id": "9cd87474be90",
|
"Id": "9cd87474be90",
|
||||||
"Image": "base:latest",
|
"Image": "ubuntu:latest",
|
||||||
"Command": "echo 222222",
|
"Command": "echo 222222",
|
||||||
"Created": 1367854155,
|
"Created": 1367854155,
|
||||||
"Status": "Exit 0"
|
"Status": "Exit 0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Id": "3176a2479c92",
|
"Id": "3176a2479c92",
|
||||||
"Image": "base:latest",
|
"Image": "centos:latest",
|
||||||
"Command": "echo 3333333333333333",
|
"Command": "echo 3333333333333333",
|
||||||
"Created": 1367854154,
|
"Created": 1367854154,
|
||||||
"Status": "Exit 0"
|
"Status": "Exit 0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Id": "4cb07b47f9fb",
|
"Id": "4cb07b47f9fb",
|
||||||
"Image": "base:latest",
|
"Image": "fedora:latest",
|
||||||
"Command": "echo 444444444444444444444444444444444",
|
"Command": "echo 444444444444444444444444444444444",
|
||||||
"Created": 1367854152,
|
"Created": 1367854152,
|
||||||
"Status": "Exit 0"
|
"Status": "Exit 0"
|
||||||
@@ -117,7 +117,7 @@ Create a container
|
|||||||
"date"
|
"date"
|
||||||
],
|
],
|
||||||
"Dns":null,
|
"Dns":null,
|
||||||
"Image":"base",
|
"Image":"ubuntu",
|
||||||
"Volumes":{},
|
"Volumes":{},
|
||||||
"VolumesFrom":""
|
"VolumesFrom":""
|
||||||
}
|
}
|
||||||
@@ -183,7 +183,7 @@ Inspect a container
|
|||||||
"date"
|
"date"
|
||||||
],
|
],
|
||||||
"Dns": null,
|
"Dns": null,
|
||||||
"Image": "base",
|
"Image": "ubuntu",
|
||||||
"Volumes": {},
|
"Volumes": {},
|
||||||
"VolumesFrom": ""
|
"VolumesFrom": ""
|
||||||
},
|
},
|
||||||
@@ -305,8 +305,8 @@ Start a container
|
|||||||
:statuscode 500: server error
|
:statuscode 500: server error
|
||||||
|
|
||||||
|
|
||||||
Stop a contaier
|
Stop a container
|
||||||
***************
|
****************
|
||||||
|
|
||||||
.. http:post:: /containers/(id)/stop
|
.. http:post:: /containers/(id)/stop
|
||||||
|
|
||||||
@@ -490,14 +490,14 @@ List Images
|
|||||||
|
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
"Repository":"base",
|
"Repository":"ubuntu",
|
||||||
"Tag":"ubuntu-12.10",
|
"Tag":"precise",
|
||||||
"Id":"b750fe79269d",
|
"Id":"b750fe79269d",
|
||||||
"Created":1364102658
|
"Created":1364102658
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Repository":"base",
|
"Repository":"ubuntu",
|
||||||
"Tag":"ubuntu-quantal",
|
"Tag":"12.04",
|
||||||
"Id":"b750fe79269d",
|
"Id":"b750fe79269d",
|
||||||
"Created":1364102658
|
"Created":1364102658
|
||||||
}
|
}
|
||||||
@@ -529,9 +529,9 @@ List Images
|
|||||||
"d6434d954665" -> "d82cbacda43a"
|
"d6434d954665" -> "d82cbacda43a"
|
||||||
base -> "e9aa60c60128" [style=invis]
|
base -> "e9aa60c60128" [style=invis]
|
||||||
"074be284591f" -> "f71189fff3de"
|
"074be284591f" -> "f71189fff3de"
|
||||||
"b750fe79269d" [label="b750fe79269d\nbase",shape=box,fillcolor="paleturquoise",style="filled,rounded"];
|
"b750fe79269d" [label="b750fe79269d\nubuntu",shape=box,fillcolor="paleturquoise",style="filled,rounded"];
|
||||||
"e9aa60c60128" [label="e9aa60c60128\nbase2",shape=box,fillcolor="paleturquoise",style="filled,rounded"];
|
"e9aa60c60128" [label="e9aa60c60128\ncentos",shape=box,fillcolor="paleturquoise",style="filled,rounded"];
|
||||||
"9a33b36209ed" [label="9a33b36209ed\ntest",shape=box,fillcolor="paleturquoise",style="filled,rounded"];
|
"9a33b36209ed" [label="9a33b36209ed\nfedora",shape=box,fillcolor="paleturquoise",style="filled,rounded"];
|
||||||
base [style=invisible]
|
base [style=invisible]
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -552,7 +552,7 @@ Create an image
|
|||||||
|
|
||||||
.. sourcecode:: http
|
.. sourcecode:: http
|
||||||
|
|
||||||
POST /images/create?fromImage=base HTTP/1.1
|
POST /images/create?fromImage=ubuntu HTTP/1.1
|
||||||
|
|
||||||
**Example response**:
|
**Example response**:
|
||||||
|
|
||||||
@@ -575,8 +575,8 @@ Create an image
|
|||||||
:statuscode 500: server error
|
:statuscode 500: server error
|
||||||
|
|
||||||
|
|
||||||
Insert a file in a image
|
Insert a file in an image
|
||||||
************************
|
*************************
|
||||||
|
|
||||||
.. http:post:: /images/(name)/insert
|
.. http:post:: /images/(name)/insert
|
||||||
|
|
||||||
@@ -615,7 +615,7 @@ Inspect an image
|
|||||||
|
|
||||||
.. sourcecode:: http
|
.. sourcecode:: http
|
||||||
|
|
||||||
GET /images/base/json HTTP/1.1
|
GET /images/centos/json HTTP/1.1
|
||||||
|
|
||||||
**Example response**:
|
**Example response**:
|
||||||
|
|
||||||
@@ -645,7 +645,7 @@ Inspect an image
|
|||||||
"Env":null,
|
"Env":null,
|
||||||
"Cmd": ["/bin/bash"]
|
"Cmd": ["/bin/bash"]
|
||||||
,"Dns":null,
|
,"Dns":null,
|
||||||
"Image":"base",
|
"Image":"centos",
|
||||||
"Volumes":null,
|
"Volumes":null,
|
||||||
"VolumesFrom":""
|
"VolumesFrom":""
|
||||||
}
|
}
|
||||||
@@ -667,7 +667,7 @@ Get the history of an image
|
|||||||
|
|
||||||
.. sourcecode:: http
|
.. sourcecode:: http
|
||||||
|
|
||||||
GET /images/base/history HTTP/1.1
|
GET /images/fedora/history HTTP/1.1
|
||||||
|
|
||||||
**Example response**:
|
**Example response**:
|
||||||
|
|
||||||
@@ -977,32 +977,37 @@ Create a new image from a container's changes
|
|||||||
|
|
||||||
.. http:post:: /commit
|
.. http:post:: /commit
|
||||||
|
|
||||||
Create a new image from a container's changes
|
Create a new image from a container's changes
|
||||||
|
|
||||||
**Example request**:
|
**Example request**:
|
||||||
|
|
||||||
|
.. sourcecode:: http
|
||||||
|
|
||||||
|
POST /commit?container=44c004db4b17&m=message&repo=myrepo HTTP/1.1
|
||||||
|
Content-Type: application/json
|
||||||
|
|
||||||
|
{
|
||||||
|
"Cmd": ["cat", "/world"],
|
||||||
|
"PortSpecs":["22"]
|
||||||
|
}
|
||||||
|
|
||||||
|
**Example response**:
|
||||||
|
|
||||||
|
.. sourcecode:: http
|
||||||
|
|
||||||
|
HTTP/1.1 201 OK
|
||||||
|
Content-Type: application/vnd.docker.raw-stream
|
||||||
|
|
||||||
.. sourcecode:: http
|
{"Id":"596069db4bf5"}
|
||||||
|
|
||||||
POST /commit?container=44c004db4b17&m=message&repo=myrepo HTTP/1.1
|
:query container: source container
|
||||||
|
:query repo: repository
|
||||||
**Example response**:
|
:query tag: tag
|
||||||
|
:query m: commit message
|
||||||
.. sourcecode:: http
|
:query author: author (eg. "John Hannibal Smith <hannibal@a-team.com>")
|
||||||
|
:statuscode 201: no error
|
||||||
HTTP/1.1 201 OK
|
:statuscode 404: no such container
|
||||||
Content-Type: application/vnd.docker.raw-stream
|
:statuscode 500: server error
|
||||||
|
|
||||||
{"Id":"596069db4bf5"}
|
|
||||||
|
|
||||||
:query container: source container
|
|
||||||
:query repo: repository
|
|
||||||
:query tag: tag
|
|
||||||
:query m: commit message
|
|
||||||
:query author: author (eg. "John Hannibal Smith <hannibal@a-team.com>")
|
|
||||||
:query run: config automatically applied when the image is run. (ex: {"Cmd": ["cat", "/world"], "PortSpecs":["22"]})
|
|
||||||
:statuscode 201: no error
|
|
||||||
:statuscode 404: no such container
|
|
||||||
:statuscode 500: server error
|
|
||||||
|
|
||||||
|
|
||||||
3. Going further
|
3. Going further
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ Docker Remote API v1.2
|
|||||||
=====================
|
=====================
|
||||||
|
|
||||||
- The Remote API is replacing rcli
|
- The Remote API is replacing rcli
|
||||||
- Default port in the docker deamon is 4243
|
- Default port in the docker daemon is 4243
|
||||||
- The API tends to be REST, but for some complex commands, like attach or pull, the HTTP connection is hijacked to transport stdout stdin and stderr
|
- The API tends to be REST, but for some complex commands, like attach or pull, the HTTP connection is hijacked to transport stdout stdin and stderr
|
||||||
|
|
||||||
2. Endpoints
|
2. Endpoints
|
||||||
@@ -49,7 +49,7 @@ List containers
|
|||||||
[
|
[
|
||||||
{
|
{
|
||||||
"Id": "8dfafdbc3a40",
|
"Id": "8dfafdbc3a40",
|
||||||
"Image": "base:latest",
|
"Image": "ubuntu:latest",
|
||||||
"Command": "echo 1",
|
"Command": "echo 1",
|
||||||
"Created": 1367854155,
|
"Created": 1367854155,
|
||||||
"Status": "Exit 0",
|
"Status": "Exit 0",
|
||||||
@@ -59,7 +59,7 @@ List containers
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Id": "9cd87474be90",
|
"Id": "9cd87474be90",
|
||||||
"Image": "base:latest",
|
"Image": "ubuntu:latest",
|
||||||
"Command": "echo 222222",
|
"Command": "echo 222222",
|
||||||
"Created": 1367854155,
|
"Created": 1367854155,
|
||||||
"Status": "Exit 0",
|
"Status": "Exit 0",
|
||||||
@@ -69,7 +69,7 @@ List containers
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Id": "3176a2479c92",
|
"Id": "3176a2479c92",
|
||||||
"Image": "base:latest",
|
"Image": "centos:latest",
|
||||||
"Command": "echo 3333333333333333",
|
"Command": "echo 3333333333333333",
|
||||||
"Created": 1367854154,
|
"Created": 1367854154,
|
||||||
"Status": "Exit 0",
|
"Status": "Exit 0",
|
||||||
@@ -79,7 +79,7 @@ List containers
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Id": "4cb07b47f9fb",
|
"Id": "4cb07b47f9fb",
|
||||||
"Image": "base:latest",
|
"Image": "fedora:latest",
|
||||||
"Command": "echo 444444444444444444444444444444444",
|
"Command": "echo 444444444444444444444444444444444",
|
||||||
"Created": 1367854152,
|
"Created": 1367854152,
|
||||||
"Status": "Exit 0",
|
"Status": "Exit 0",
|
||||||
@@ -129,7 +129,7 @@ Create a container
|
|||||||
"date"
|
"date"
|
||||||
],
|
],
|
||||||
"Dns":null,
|
"Dns":null,
|
||||||
"Image":"base",
|
"Image":"ubuntu",
|
||||||
"Volumes":{},
|
"Volumes":{},
|
||||||
"VolumesFrom":""
|
"VolumesFrom":""
|
||||||
}
|
}
|
||||||
@@ -195,7 +195,7 @@ Inspect a container
|
|||||||
"date"
|
"date"
|
||||||
],
|
],
|
||||||
"Dns": null,
|
"Dns": null,
|
||||||
"Image": "base",
|
"Image": "ubuntu",
|
||||||
"Volumes": {},
|
"Volumes": {},
|
||||||
"VolumesFrom": ""
|
"VolumesFrom": ""
|
||||||
},
|
},
|
||||||
@@ -317,8 +317,8 @@ Start a container
|
|||||||
:statuscode 500: server error
|
:statuscode 500: server error
|
||||||
|
|
||||||
|
|
||||||
Stop a contaier
|
Stop a container
|
||||||
***************
|
****************
|
||||||
|
|
||||||
.. http:post:: /containers/(id)/stop
|
.. http:post:: /containers/(id)/stop
|
||||||
|
|
||||||
@@ -502,16 +502,16 @@ List Images
|
|||||||
|
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
"Repository":"base",
|
"Repository":"ubuntu",
|
||||||
"Tag":"ubuntu-12.10",
|
"Tag":"precise",
|
||||||
"Id":"b750fe79269d",
|
"Id":"b750fe79269d",
|
||||||
"Created":1364102658,
|
"Created":1364102658,
|
||||||
"Size":24653,
|
"Size":24653,
|
||||||
"VirtualSize":180116135
|
"VirtualSize":180116135
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Repository":"base",
|
"Repository":"ubuntu",
|
||||||
"Tag":"ubuntu-quantal",
|
"Tag":"12.04",
|
||||||
"Id":"b750fe79269d",
|
"Id":"b750fe79269d",
|
||||||
"Created":1364102658,
|
"Created":1364102658,
|
||||||
"Size":24653,
|
"Size":24653,
|
||||||
@@ -545,9 +545,9 @@ List Images
|
|||||||
"d6434d954665" -> "d82cbacda43a"
|
"d6434d954665" -> "d82cbacda43a"
|
||||||
base -> "e9aa60c60128" [style=invis]
|
base -> "e9aa60c60128" [style=invis]
|
||||||
"074be284591f" -> "f71189fff3de"
|
"074be284591f" -> "f71189fff3de"
|
||||||
"b750fe79269d" [label="b750fe79269d\nbase",shape=box,fillcolor="paleturquoise",style="filled,rounded"];
|
"b750fe79269d" [label="b750fe79269d\nubuntu",shape=box,fillcolor="paleturquoise",style="filled,rounded"];
|
||||||
"e9aa60c60128" [label="e9aa60c60128\nbase2",shape=box,fillcolor="paleturquoise",style="filled,rounded"];
|
"e9aa60c60128" [label="e9aa60c60128\ncentos",shape=box,fillcolor="paleturquoise",style="filled,rounded"];
|
||||||
"9a33b36209ed" [label="9a33b36209ed\ntest",shape=box,fillcolor="paleturquoise",style="filled,rounded"];
|
"9a33b36209ed" [label="9a33b36209ed\nfedora",shape=box,fillcolor="paleturquoise",style="filled,rounded"];
|
||||||
base [style=invisible]
|
base [style=invisible]
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -568,7 +568,7 @@ Create an image
|
|||||||
|
|
||||||
.. sourcecode:: http
|
.. sourcecode:: http
|
||||||
|
|
||||||
POST /images/create?fromImage=base HTTP/1.1
|
POST /images/create?fromImage=ubuntu HTTP/1.1
|
||||||
|
|
||||||
**Example response**:
|
**Example response**:
|
||||||
|
|
||||||
@@ -591,8 +591,8 @@ Create an image
|
|||||||
:statuscode 500: server error
|
:statuscode 500: server error
|
||||||
|
|
||||||
|
|
||||||
Insert a file in a image
|
Insert a file in an image
|
||||||
************************
|
*************************
|
||||||
|
|
||||||
.. http:post:: /images/(name)/insert
|
.. http:post:: /images/(name)/insert
|
||||||
|
|
||||||
@@ -631,7 +631,7 @@ Inspect an image
|
|||||||
|
|
||||||
.. sourcecode:: http
|
.. sourcecode:: http
|
||||||
|
|
||||||
GET /images/base/json HTTP/1.1
|
GET /images/centos/json HTTP/1.1
|
||||||
|
|
||||||
**Example response**:
|
**Example response**:
|
||||||
|
|
||||||
@@ -661,7 +661,7 @@ Inspect an image
|
|||||||
"Env":null,
|
"Env":null,
|
||||||
"Cmd": ["/bin/bash"]
|
"Cmd": ["/bin/bash"]
|
||||||
,"Dns":null,
|
,"Dns":null,
|
||||||
"Image":"base",
|
"Image":"centos",
|
||||||
"Volumes":null,
|
"Volumes":null,
|
||||||
"VolumesFrom":""
|
"VolumesFrom":""
|
||||||
},
|
},
|
||||||
@@ -684,7 +684,7 @@ Get the history of an image
|
|||||||
|
|
||||||
.. sourcecode:: http
|
.. sourcecode:: http
|
||||||
|
|
||||||
GET /images/base/history HTTP/1.1
|
GET /images/fedora/history HTTP/1.1
|
||||||
|
|
||||||
**Example response**:
|
**Example response**:
|
||||||
|
|
||||||
@@ -696,7 +696,7 @@ Get the history of an image
|
|||||||
[
|
[
|
||||||
{
|
{
|
||||||
"Id":"b750fe79269d",
|
"Id":"b750fe79269d",
|
||||||
"Tag":["base:latest"],
|
"Tag":["ubuntu:latest"],
|
||||||
"Created":1364102658,
|
"Created":1364102658,
|
||||||
"CreatedBy":"/bin/bash"
|
"CreatedBy":"/bin/bash"
|
||||||
},
|
},
|
||||||
@@ -870,7 +870,7 @@ Build an image from Dockerfile via stdin
|
|||||||
|
|
||||||
{{ STREAM }}
|
{{ STREAM }}
|
||||||
|
|
||||||
:query t: tag to be applied to the resulting image in case of success
|
:query t: repository name to be applied to the resulting image in case of success
|
||||||
:query remote: resource to fetch, as URI
|
:query remote: resource to fetch, as URI
|
||||||
:statuscode 200: no error
|
:statuscode 200: no error
|
||||||
:statuscode 500: server error
|
:statuscode 500: server error
|
||||||
@@ -985,32 +985,37 @@ Create a new image from a container's changes
|
|||||||
|
|
||||||
.. http:post:: /commit
|
.. http:post:: /commit
|
||||||
|
|
||||||
Create a new image from a container's changes
|
Create a new image from a container's changes
|
||||||
|
|
||||||
**Example request**:
|
**Example request**:
|
||||||
|
|
||||||
.. sourcecode:: http
|
.. sourcecode:: http
|
||||||
|
|
||||||
POST /commit?container=44c004db4b17&m=message&repo=myrepo HTTP/1.1
|
POST /commit?container=44c004db4b17&m=message&repo=myrepo HTTP/1.1
|
||||||
|
Content-Type: application/json
|
||||||
|
|
||||||
|
{
|
||||||
|
"Cmd": ["cat", "/world"],
|
||||||
|
"PortSpecs":["22"]
|
||||||
|
}
|
||||||
|
|
||||||
**Example response**:
|
**Example response**:
|
||||||
|
|
||||||
.. sourcecode:: http
|
.. sourcecode:: http
|
||||||
|
|
||||||
HTTP/1.1 201 OK
|
HTTP/1.1 201 OK
|
||||||
Content-Type: application/vnd.docker.raw-stream
|
Content-Type: application/vnd.docker.raw-stream
|
||||||
|
|
||||||
{"Id":"596069db4bf5"}
|
{"Id":"596069db4bf5"}
|
||||||
|
|
||||||
:query container: source container
|
:query container: source container
|
||||||
:query repo: repository
|
:query repo: repository
|
||||||
:query tag: tag
|
:query tag: tag
|
||||||
:query m: commit message
|
:query m: commit message
|
||||||
:query author: author (eg. "John Hannibal Smith <hannibal@a-team.com>")
|
:query author: author (eg. "John Hannibal Smith <hannibal@a-team.com>")
|
||||||
:query run: config automatically applied when the image is run. (ex: {"Cmd": ["cat", "/world"], "PortSpecs":["22"]})
|
:statuscode 201: no error
|
||||||
:statuscode 201: no error
|
:statuscode 404: no such container
|
||||||
:statuscode 404: no such container
|
:statuscode 500: server error
|
||||||
:statuscode 500: server error
|
|
||||||
|
|
||||||
|
|
||||||
3. Going further
|
3. Going further
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ Docker Remote API v1.3
|
|||||||
=====================
|
=====================
|
||||||
|
|
||||||
- The Remote API is replacing rcli
|
- The Remote API is replacing rcli
|
||||||
- Default port in the docker deamon is 4243
|
- Default port in the docker daemon is 4243
|
||||||
- The API tends to be REST, but for some complex commands, like attach or pull, the HTTP connection is hijacked to transport stdout stdin and stderr
|
- The API tends to be REST, but for some complex commands, like attach or pull, the HTTP connection is hijacked to transport stdout stdin and stderr
|
||||||
|
|
||||||
2. Endpoints
|
2. Endpoints
|
||||||
@@ -49,7 +49,7 @@ List containers
|
|||||||
[
|
[
|
||||||
{
|
{
|
||||||
"Id": "8dfafdbc3a40",
|
"Id": "8dfafdbc3a40",
|
||||||
"Image": "base:latest",
|
"Image": "ubuntu:latest",
|
||||||
"Command": "echo 1",
|
"Command": "echo 1",
|
||||||
"Created": 1367854155,
|
"Created": 1367854155,
|
||||||
"Status": "Exit 0",
|
"Status": "Exit 0",
|
||||||
@@ -59,7 +59,7 @@ List containers
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Id": "9cd87474be90",
|
"Id": "9cd87474be90",
|
||||||
"Image": "base:latest",
|
"Image": "ubuntu:latest",
|
||||||
"Command": "echo 222222",
|
"Command": "echo 222222",
|
||||||
"Created": 1367854155,
|
"Created": 1367854155,
|
||||||
"Status": "Exit 0",
|
"Status": "Exit 0",
|
||||||
@@ -69,7 +69,7 @@ List containers
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Id": "3176a2479c92",
|
"Id": "3176a2479c92",
|
||||||
"Image": "base:latest",
|
"Image": "centos:latest",
|
||||||
"Command": "echo 3333333333333333",
|
"Command": "echo 3333333333333333",
|
||||||
"Created": 1367854154,
|
"Created": 1367854154,
|
||||||
"Status": "Exit 0",
|
"Status": "Exit 0",
|
||||||
@@ -79,7 +79,7 @@ List containers
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Id": "4cb07b47f9fb",
|
"Id": "4cb07b47f9fb",
|
||||||
"Image": "base:latest",
|
"Image": "fedora:latest",
|
||||||
"Command": "echo 444444444444444444444444444444444",
|
"Command": "echo 444444444444444444444444444444444",
|
||||||
"Created": 1367854152,
|
"Created": 1367854152,
|
||||||
"Status": "Exit 0",
|
"Status": "Exit 0",
|
||||||
@@ -130,7 +130,7 @@ Create a container
|
|||||||
"date"
|
"date"
|
||||||
],
|
],
|
||||||
"Dns":null,
|
"Dns":null,
|
||||||
"Image":"base",
|
"Image":"ubuntu",
|
||||||
"Volumes":{},
|
"Volumes":{},
|
||||||
"VolumesFrom":""
|
"VolumesFrom":""
|
||||||
}
|
}
|
||||||
@@ -196,7 +196,7 @@ Inspect a container
|
|||||||
"date"
|
"date"
|
||||||
],
|
],
|
||||||
"Dns": null,
|
"Dns": null,
|
||||||
"Image": "base",
|
"Image": "ubuntu",
|
||||||
"Volumes": {},
|
"Volumes": {},
|
||||||
"VolumesFrom": ""
|
"VolumesFrom": ""
|
||||||
},
|
},
|
||||||
@@ -365,8 +365,8 @@ Start a container
|
|||||||
:statuscode 500: server error
|
:statuscode 500: server error
|
||||||
|
|
||||||
|
|
||||||
Stop a contaier
|
Stop a container
|
||||||
***************
|
****************
|
||||||
|
|
||||||
.. http:post:: /containers/(id)/stop
|
.. http:post:: /containers/(id)/stop
|
||||||
|
|
||||||
@@ -550,16 +550,16 @@ List Images
|
|||||||
|
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
"Repository":"base",
|
"Repository":"ubuntu",
|
||||||
"Tag":"ubuntu-12.10",
|
"Tag":"precise",
|
||||||
"Id":"b750fe79269d",
|
"Id":"b750fe79269d",
|
||||||
"Created":1364102658,
|
"Created":1364102658,
|
||||||
"Size":24653,
|
"Size":24653,
|
||||||
"VirtualSize":180116135
|
"VirtualSize":180116135
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Repository":"base",
|
"Repository":"ubuntu",
|
||||||
"Tag":"ubuntu-quantal",
|
"Tag":"12.04",
|
||||||
"Id":"b750fe79269d",
|
"Id":"b750fe79269d",
|
||||||
"Created":1364102658,
|
"Created":1364102658,
|
||||||
"Size":24653,
|
"Size":24653,
|
||||||
@@ -593,9 +593,9 @@ List Images
|
|||||||
"d6434d954665" -> "d82cbacda43a"
|
"d6434d954665" -> "d82cbacda43a"
|
||||||
base -> "e9aa60c60128" [style=invis]
|
base -> "e9aa60c60128" [style=invis]
|
||||||
"074be284591f" -> "f71189fff3de"
|
"074be284591f" -> "f71189fff3de"
|
||||||
"b750fe79269d" [label="b750fe79269d\nbase",shape=box,fillcolor="paleturquoise",style="filled,rounded"];
|
"b750fe79269d" [label="b750fe79269d\nubuntu",shape=box,fillcolor="paleturquoise",style="filled,rounded"];
|
||||||
"e9aa60c60128" [label="e9aa60c60128\nbase2",shape=box,fillcolor="paleturquoise",style="filled,rounded"];
|
"e9aa60c60128" [label="e9aa60c60128\ncentos",shape=box,fillcolor="paleturquoise",style="filled,rounded"];
|
||||||
"9a33b36209ed" [label="9a33b36209ed\ntest",shape=box,fillcolor="paleturquoise",style="filled,rounded"];
|
"9a33b36209ed" [label="9a33b36209ed\nfedora",shape=box,fillcolor="paleturquoise",style="filled,rounded"];
|
||||||
base [style=invisible]
|
base [style=invisible]
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -616,7 +616,7 @@ Create an image
|
|||||||
|
|
||||||
.. sourcecode:: http
|
.. sourcecode:: http
|
||||||
|
|
||||||
POST /images/create?fromImage=base HTTP/1.1
|
POST /images/create?fromImage=ubuntu HTTP/1.1
|
||||||
|
|
||||||
**Example response**:
|
**Example response**:
|
||||||
|
|
||||||
@@ -639,8 +639,8 @@ Create an image
|
|||||||
:statuscode 500: server error
|
:statuscode 500: server error
|
||||||
|
|
||||||
|
|
||||||
Insert a file in a image
|
Insert a file in an image
|
||||||
************************
|
*************************
|
||||||
|
|
||||||
.. http:post:: /images/(name)/insert
|
.. http:post:: /images/(name)/insert
|
||||||
|
|
||||||
@@ -679,7 +679,7 @@ Inspect an image
|
|||||||
|
|
||||||
.. sourcecode:: http
|
.. sourcecode:: http
|
||||||
|
|
||||||
GET /images/base/json HTTP/1.1
|
GET /images/centos/json HTTP/1.1
|
||||||
|
|
||||||
**Example response**:
|
**Example response**:
|
||||||
|
|
||||||
@@ -709,7 +709,7 @@ Inspect an image
|
|||||||
"Env":null,
|
"Env":null,
|
||||||
"Cmd": ["/bin/bash"]
|
"Cmd": ["/bin/bash"]
|
||||||
,"Dns":null,
|
,"Dns":null,
|
||||||
"Image":"base",
|
"Image":"centos",
|
||||||
"Volumes":null,
|
"Volumes":null,
|
||||||
"VolumesFrom":""
|
"VolumesFrom":""
|
||||||
},
|
},
|
||||||
@@ -732,7 +732,7 @@ Get the history of an image
|
|||||||
|
|
||||||
.. sourcecode:: http
|
.. sourcecode:: http
|
||||||
|
|
||||||
GET /images/base/history HTTP/1.1
|
GET /images/fedora/history HTTP/1.1
|
||||||
|
|
||||||
**Example response**:
|
**Example response**:
|
||||||
|
|
||||||
@@ -925,7 +925,7 @@ Build an image from Dockerfile via stdin
|
|||||||
|
|
||||||
The Content-type header should be set to "application/tar".
|
The Content-type header should be set to "application/tar".
|
||||||
|
|
||||||
:query t: tag to be applied to the resulting image in case of success
|
:query t: repository name (and optionally a tag) to be applied to the resulting image in case of success
|
||||||
:query q: suppress verbose build output
|
:query q: suppress verbose build output
|
||||||
:statuscode 200: no error
|
:statuscode 200: no error
|
||||||
:statuscode 500: server error
|
:statuscode 500: server error
|
||||||
@@ -1034,32 +1034,37 @@ Create a new image from a container's changes
|
|||||||
|
|
||||||
.. http:post:: /commit
|
.. http:post:: /commit
|
||||||
|
|
||||||
Create a new image from a container's changes
|
Create a new image from a container's changes
|
||||||
|
|
||||||
**Example request**:
|
**Example request**:
|
||||||
|
|
||||||
.. sourcecode:: http
|
.. sourcecode:: http
|
||||||
|
|
||||||
POST /commit?container=44c004db4b17&m=message&repo=myrepo HTTP/1.1
|
POST /commit?container=44c004db4b17&m=message&repo=myrepo HTTP/1.1
|
||||||
|
Content-Type: application/json
|
||||||
|
|
||||||
|
{
|
||||||
|
"Cmd": ["cat", "/world"],
|
||||||
|
"PortSpecs":["22"]
|
||||||
|
}
|
||||||
|
|
||||||
**Example response**:
|
**Example response**:
|
||||||
|
|
||||||
.. sourcecode:: http
|
.. sourcecode:: http
|
||||||
|
|
||||||
HTTP/1.1 201 OK
|
HTTP/1.1 201 OK
|
||||||
Content-Type: application/vnd.docker.raw-stream
|
Content-Type: application/vnd.docker.raw-stream
|
||||||
|
|
||||||
{"Id":"596069db4bf5"}
|
{"Id":"596069db4bf5"}
|
||||||
|
|
||||||
:query container: source container
|
:query container: source container
|
||||||
:query repo: repository
|
:query repo: repository
|
||||||
:query tag: tag
|
:query tag: tag
|
||||||
:query m: commit message
|
:query m: commit message
|
||||||
:query author: author (eg. "John Hannibal Smith <hannibal@a-team.com>")
|
:query author: author (eg. "John Hannibal Smith <hannibal@a-team.com>")
|
||||||
:query run: config automatically applied when the image is run. (ex: {"Cmd": ["cat", "/world"], "PortSpecs":["22"]})
|
:statuscode 201: no error
|
||||||
:statuscode 201: no error
|
:statuscode 404: no such container
|
||||||
:statuscode 404: no such container
|
:statuscode 500: server error
|
||||||
:statuscode 500: server error
|
|
||||||
|
|
||||||
|
|
||||||
Monitor Docker's events
|
Monitor Docker's events
|
||||||
|
|||||||
@@ -2,6 +2,8 @@
|
|||||||
:description: API Documentation for Docker
|
:description: API Documentation for Docker
|
||||||
:keywords: API, Docker, rcli, REST, documentation
|
:keywords: API, Docker, rcli, REST, documentation
|
||||||
|
|
||||||
|
:orphan:
|
||||||
|
|
||||||
======================
|
======================
|
||||||
Docker Remote API v1.4
|
Docker Remote API v1.4
|
||||||
======================
|
======================
|
||||||
@@ -12,7 +14,7 @@ Docker Remote API v1.4
|
|||||||
=====================
|
=====================
|
||||||
|
|
||||||
- The Remote API is replacing rcli
|
- The Remote API is replacing rcli
|
||||||
- Default port in the docker deamon is 4243
|
- Default port in the docker daemon is 4243
|
||||||
- The API tends to be REST, but for some complex commands, like attach or pull, the HTTP connection is hijacked to transport stdout stdin and stderr
|
- The API tends to be REST, but for some complex commands, like attach or pull, the HTTP connection is hijacked to transport stdout stdin and stderr
|
||||||
|
|
||||||
2. Endpoints
|
2. Endpoints
|
||||||
@@ -44,7 +46,7 @@ List containers
|
|||||||
[
|
[
|
||||||
{
|
{
|
||||||
"Id": "8dfafdbc3a40",
|
"Id": "8dfafdbc3a40",
|
||||||
"Image": "base:latest",
|
"Image": "ubuntu:latest",
|
||||||
"Command": "echo 1",
|
"Command": "echo 1",
|
||||||
"Created": 1367854155,
|
"Created": 1367854155,
|
||||||
"Status": "Exit 0",
|
"Status": "Exit 0",
|
||||||
@@ -54,7 +56,7 @@ List containers
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Id": "9cd87474be90",
|
"Id": "9cd87474be90",
|
||||||
"Image": "base:latest",
|
"Image": "ubuntu:latest",
|
||||||
"Command": "echo 222222",
|
"Command": "echo 222222",
|
||||||
"Created": 1367854155,
|
"Created": 1367854155,
|
||||||
"Status": "Exit 0",
|
"Status": "Exit 0",
|
||||||
@@ -64,7 +66,7 @@ List containers
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Id": "3176a2479c92",
|
"Id": "3176a2479c92",
|
||||||
"Image": "base:latest",
|
"Image": "centos:latest",
|
||||||
"Command": "echo 3333333333333333",
|
"Command": "echo 3333333333333333",
|
||||||
"Created": 1367854154,
|
"Created": 1367854154,
|
||||||
"Status": "Exit 0",
|
"Status": "Exit 0",
|
||||||
@@ -74,7 +76,7 @@ List containers
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Id": "4cb07b47f9fb",
|
"Id": "4cb07b47f9fb",
|
||||||
"Image": "base:latest",
|
"Image": "fedora:latest",
|
||||||
"Command": "echo 444444444444444444444444444444444",
|
"Command": "echo 444444444444444444444444444444444",
|
||||||
"Created": 1367854152,
|
"Created": 1367854152,
|
||||||
"Status": "Exit 0",
|
"Status": "Exit 0",
|
||||||
@@ -117,6 +119,7 @@ Create a container
|
|||||||
"AttachStdout":true,
|
"AttachStdout":true,
|
||||||
"AttachStderr":true,
|
"AttachStderr":true,
|
||||||
"PortSpecs":null,
|
"PortSpecs":null,
|
||||||
|
"Privileged": false,
|
||||||
"Tty":false,
|
"Tty":false,
|
||||||
"OpenStdin":false,
|
"OpenStdin":false,
|
||||||
"StdinOnce":false,
|
"StdinOnce":false,
|
||||||
@@ -125,9 +128,11 @@ Create a container
|
|||||||
"date"
|
"date"
|
||||||
],
|
],
|
||||||
"Dns":null,
|
"Dns":null,
|
||||||
"Image":"base",
|
"Image":"ubuntu",
|
||||||
"Volumes":{},
|
"Volumes":{},
|
||||||
"VolumesFrom":""
|
"VolumesFrom":"",
|
||||||
|
"WorkingDir":""
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
**Example response**:
|
**Example response**:
|
||||||
@@ -191,9 +196,11 @@ Inspect a container
|
|||||||
"date"
|
"date"
|
||||||
],
|
],
|
||||||
"Dns": null,
|
"Dns": null,
|
||||||
"Image": "base",
|
"Image": "ubuntu",
|
||||||
"Volumes": {},
|
"Volumes": {},
|
||||||
"VolumesFrom": ""
|
"VolumesFrom": "",
|
||||||
|
"WorkingDir":""
|
||||||
|
|
||||||
},
|
},
|
||||||
"State": {
|
"State": {
|
||||||
"Running": false,
|
"Running": false,
|
||||||
@@ -217,6 +224,7 @@ Inspect a container
|
|||||||
|
|
||||||
:statuscode 200: no error
|
:statuscode 200: no error
|
||||||
:statuscode 404: no such container
|
:statuscode 404: no such container
|
||||||
|
:statuscode 409: conflict between containers and images
|
||||||
:statuscode 500: server error
|
:statuscode 500: server error
|
||||||
|
|
||||||
|
|
||||||
@@ -350,7 +358,8 @@ Start a container
|
|||||||
Content-Type: application/json
|
Content-Type: application/json
|
||||||
|
|
||||||
{
|
{
|
||||||
"Binds":["/tmp:/tmp"]
|
"Binds":["/tmp:/tmp"],
|
||||||
|
"LxcConf":[{"Key":"lxc.utsname","Value":"docker"}]
|
||||||
}
|
}
|
||||||
|
|
||||||
**Example response**:
|
**Example response**:
|
||||||
@@ -361,13 +370,13 @@ Start a container
|
|||||||
Content-Type: text/plain
|
Content-Type: text/plain
|
||||||
|
|
||||||
:jsonparam hostConfig: the container's host configuration (optional)
|
:jsonparam hostConfig: the container's host configuration (optional)
|
||||||
:statuscode 200: no error
|
:statuscode 204: no error
|
||||||
:statuscode 404: no such container
|
:statuscode 404: no such container
|
||||||
:statuscode 500: server error
|
:statuscode 500: server error
|
||||||
|
|
||||||
|
|
||||||
Stop a contaier
|
Stop a container
|
||||||
***************
|
****************
|
||||||
|
|
||||||
.. http:post:: /containers/(id)/stop
|
.. http:post:: /containers/(id)/stop
|
||||||
|
|
||||||
@@ -526,6 +535,38 @@ Remove a container
|
|||||||
:statuscode 500: server error
|
:statuscode 500: server error
|
||||||
|
|
||||||
|
|
||||||
|
Copy files or folders from a container
|
||||||
|
**************************************
|
||||||
|
|
||||||
|
.. http:post:: /containers/(id)/copy
|
||||||
|
|
||||||
|
Copy files or folders of container ``id``
|
||||||
|
|
||||||
|
**Example request**:
|
||||||
|
|
||||||
|
.. sourcecode:: http
|
||||||
|
|
||||||
|
POST /containers/4fa6e0f0c678/copy HTTP/1.1
|
||||||
|
Content-Type: application/json
|
||||||
|
|
||||||
|
{
|
||||||
|
"Resource":"test.txt"
|
||||||
|
}
|
||||||
|
|
||||||
|
**Example response**:
|
||||||
|
|
||||||
|
.. sourcecode:: http
|
||||||
|
|
||||||
|
HTTP/1.1 200 OK
|
||||||
|
Content-Type: application/octet-stream
|
||||||
|
|
||||||
|
{{ STREAM }}
|
||||||
|
|
||||||
|
:statuscode 200: no error
|
||||||
|
:statuscode 404: no such container
|
||||||
|
:statuscode 500: server error
|
||||||
|
|
||||||
|
|
||||||
2.2 Images
|
2.2 Images
|
||||||
----------
|
----------
|
||||||
|
|
||||||
@@ -551,16 +592,16 @@ List Images
|
|||||||
|
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
"Repository":"base",
|
"Repository":"ubuntu",
|
||||||
"Tag":"ubuntu-12.10",
|
"Tag":"precise",
|
||||||
"Id":"b750fe79269d",
|
"Id":"b750fe79269d",
|
||||||
"Created":1364102658,
|
"Created":1364102658,
|
||||||
"Size":24653,
|
"Size":24653,
|
||||||
"VirtualSize":180116135
|
"VirtualSize":180116135
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Repository":"base",
|
"Repository":"ubuntu",
|
||||||
"Tag":"ubuntu-quantal",
|
"Tag":"12.04",
|
||||||
"Id":"b750fe79269d",
|
"Id":"b750fe79269d",
|
||||||
"Created":1364102658,
|
"Created":1364102658,
|
||||||
"Size":24653,
|
"Size":24653,
|
||||||
@@ -594,9 +635,9 @@ List Images
|
|||||||
"d6434d954665" -> "d82cbacda43a"
|
"d6434d954665" -> "d82cbacda43a"
|
||||||
base -> "e9aa60c60128" [style=invis]
|
base -> "e9aa60c60128" [style=invis]
|
||||||
"074be284591f" -> "f71189fff3de"
|
"074be284591f" -> "f71189fff3de"
|
||||||
"b750fe79269d" [label="b750fe79269d\nbase",shape=box,fillcolor="paleturquoise",style="filled,rounded"];
|
"b750fe79269d" [label="b750fe79269d\nubuntu",shape=box,fillcolor="paleturquoise",style="filled,rounded"];
|
||||||
"e9aa60c60128" [label="e9aa60c60128\nbase2",shape=box,fillcolor="paleturquoise",style="filled,rounded"];
|
"e9aa60c60128" [label="e9aa60c60128\ncentos",shape=box,fillcolor="paleturquoise",style="filled,rounded"];
|
||||||
"9a33b36209ed" [label="9a33b36209ed\ntest",shape=box,fillcolor="paleturquoise",style="filled,rounded"];
|
"9a33b36209ed" [label="9a33b36209ed\nfedora",shape=box,fillcolor="paleturquoise",style="filled,rounded"];
|
||||||
base [style=invisible]
|
base [style=invisible]
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -617,7 +658,7 @@ Create an image
|
|||||||
|
|
||||||
.. sourcecode:: http
|
.. sourcecode:: http
|
||||||
|
|
||||||
POST /images/create?fromImage=base HTTP/1.1
|
POST /images/create?fromImage=ubuntu HTTP/1.1
|
||||||
|
|
||||||
**Example response**:
|
**Example response**:
|
||||||
|
|
||||||
@@ -640,8 +681,8 @@ Create an image
|
|||||||
:statuscode 500: server error
|
:statuscode 500: server error
|
||||||
|
|
||||||
|
|
||||||
Insert a file in a image
|
Insert a file in an image
|
||||||
************************
|
*************************
|
||||||
|
|
||||||
.. http:post:: /images/(name)/insert
|
.. http:post:: /images/(name)/insert
|
||||||
|
|
||||||
@@ -680,7 +721,7 @@ Inspect an image
|
|||||||
|
|
||||||
.. sourcecode:: http
|
.. sourcecode:: http
|
||||||
|
|
||||||
GET /images/base/json HTTP/1.1
|
GET /images/centos/json HTTP/1.1
|
||||||
|
|
||||||
**Example response**:
|
**Example response**:
|
||||||
|
|
||||||
@@ -710,16 +751,18 @@ Inspect an image
|
|||||||
"Env":null,
|
"Env":null,
|
||||||
"Cmd": ["/bin/bash"]
|
"Cmd": ["/bin/bash"]
|
||||||
,"Dns":null,
|
,"Dns":null,
|
||||||
"Image":"base",
|
"Image":"centos",
|
||||||
"Volumes":null,
|
"Volumes":null,
|
||||||
"VolumesFrom":""
|
"VolumesFrom":"",
|
||||||
|
"WorkingDir":""
|
||||||
},
|
},
|
||||||
"Size": 6824592
|
"Size": 6824592
|
||||||
}
|
}
|
||||||
|
|
||||||
:statuscode 200: no error
|
:statuscode 200: no error
|
||||||
:statuscode 404: no such image
|
:statuscode 404: no such image
|
||||||
:statuscode 500: server error
|
:statuscode 409: conflict between containers and images
|
||||||
|
:statuscode 500: server error
|
||||||
|
|
||||||
|
|
||||||
Get the history of an image
|
Get the history of an image
|
||||||
@@ -733,7 +776,7 @@ Get the history of an image
|
|||||||
|
|
||||||
.. sourcecode:: http
|
.. sourcecode:: http
|
||||||
|
|
||||||
GET /images/base/history HTTP/1.1
|
GET /images/fedora/history HTTP/1.1
|
||||||
|
|
||||||
**Example response**:
|
**Example response**:
|
||||||
|
|
||||||
@@ -765,29 +808,29 @@ Push an image on the registry
|
|||||||
|
|
||||||
.. http:post:: /images/(name)/push
|
.. http:post:: /images/(name)/push
|
||||||
|
|
||||||
Push the image ``name`` on the registry
|
Push the image ``name`` on the registry
|
||||||
|
|
||||||
**Example request**:
|
**Example request**:
|
||||||
|
|
||||||
.. sourcecode:: http
|
.. sourcecode:: http
|
||||||
|
|
||||||
POST /images/test/push HTTP/1.1
|
POST /images/test/push HTTP/1.1
|
||||||
{{ authConfig }}
|
{{ authConfig }}
|
||||||
|
|
||||||
**Example response**:
|
**Example response**:
|
||||||
|
|
||||||
.. sourcecode:: http
|
.. sourcecode:: http
|
||||||
|
|
||||||
HTTP/1.1 200 OK
|
HTTP/1.1 200 OK
|
||||||
Content-Type: application/json
|
Content-Type: application/json
|
||||||
|
|
||||||
{"status":"Pushing..."}
|
{"status":"Pushing..."}
|
||||||
{"status":"Pushing", "progress":"1/? (n/a)"}
|
{"status":"Pushing", "progress":"1/? (n/a)"}
|
||||||
{"error":"Invalid..."}
|
{"error":"Invalid..."}
|
||||||
...
|
...
|
||||||
|
|
||||||
:query registry: the registry you wan to push, optional
|
:query registry: the registry you wan to push, optional
|
||||||
:statuscode 200: no error
|
:statuscode 200: no error
|
||||||
:statuscode 404: no such image
|
:statuscode 404: no such image
|
||||||
:statuscode 500: server error
|
:statuscode 500: server error
|
||||||
|
|
||||||
@@ -900,36 +943,37 @@ Build an image from Dockerfile via stdin
|
|||||||
|
|
||||||
.. http:post:: /build
|
.. http:post:: /build
|
||||||
|
|
||||||
Build an image from Dockerfile via stdin
|
Build an image from Dockerfile via stdin
|
||||||
|
|
||||||
**Example request**:
|
**Example request**:
|
||||||
|
|
||||||
.. sourcecode:: http
|
.. sourcecode:: http
|
||||||
|
|
||||||
POST /build HTTP/1.1
|
POST /build HTTP/1.1
|
||||||
|
|
||||||
{{ STREAM }}
|
|
||||||
|
|
||||||
**Example response**:
|
{{ STREAM }}
|
||||||
|
|
||||||
.. sourcecode:: http
|
**Example response**:
|
||||||
|
|
||||||
HTTP/1.1 200 OK
|
.. sourcecode:: http
|
||||||
|
|
||||||
{{ STREAM }}
|
HTTP/1.1 200 OK
|
||||||
|
|
||||||
|
{{ STREAM }}
|
||||||
|
|
||||||
|
|
||||||
The stream must be a tar archive compressed with one of the following algorithms:
|
The stream must be a tar archive compressed with one of the following algorithms:
|
||||||
identity (no compression), gzip, bzip2, xz. The archive must include a file called
|
identity (no compression), gzip, bzip2, xz. The archive must include a file called
|
||||||
`Dockerfile` at its root. It may include any number of other files, which will be
|
`Dockerfile` at its root. It may include any number of other files, which will be
|
||||||
accessible in the build context (See the ADD build command).
|
accessible in the build context (See the ADD build command).
|
||||||
|
|
||||||
The Content-type header should be set to "application/tar".
|
The Content-type header should be set to "application/tar".
|
||||||
|
|
||||||
:query t: tag to be applied to the resulting image in case of success
|
:query t: repository name (and optionally a tag) to be applied to the resulting image in case of success
|
||||||
:query q: suppress verbose build output
|
:query q: suppress verbose build output
|
||||||
:statuscode 200: no error
|
:query nocache: do not use the cache when building the image
|
||||||
:statuscode 500: server error
|
:statuscode 200: no error
|
||||||
|
:statuscode 500: server error
|
||||||
|
|
||||||
|
|
||||||
Check auth configuration
|
Check auth configuration
|
||||||
@@ -949,7 +993,8 @@ Check auth configuration
|
|||||||
{
|
{
|
||||||
"username":"hannibal",
|
"username":"hannibal",
|
||||||
"password:"xxxx",
|
"password:"xxxx",
|
||||||
"email":"hannibal@a-team.com"
|
"email":"hannibal@a-team.com",
|
||||||
|
"serveraddress":"https://index.docker.io/v1/"
|
||||||
}
|
}
|
||||||
|
|
||||||
**Example response**:
|
**Example response**:
|
||||||
@@ -990,7 +1035,8 @@ Display system-wide information
|
|||||||
"NFd": 11,
|
"NFd": 11,
|
||||||
"NGoroutines":21,
|
"NGoroutines":21,
|
||||||
"MemoryLimit":true,
|
"MemoryLimit":true,
|
||||||
"SwapLimit":false
|
"SwapLimit":false,
|
||||||
|
"IPv4Forwarding":true
|
||||||
}
|
}
|
||||||
|
|
||||||
:statuscode 200: no error
|
:statuscode 200: no error
|
||||||
@@ -1023,8 +1069,8 @@ Show the docker version information
|
|||||||
"GoVersion":"go1.0.3"
|
"GoVersion":"go1.0.3"
|
||||||
}
|
}
|
||||||
|
|
||||||
:statuscode 200: no error
|
:statuscode 200: no error
|
||||||
:statuscode 500: server error
|
:statuscode 500: server error
|
||||||
|
|
||||||
|
|
||||||
Create a new image from a container's changes
|
Create a new image from a container's changes
|
||||||
@@ -1032,31 +1078,66 @@ Create a new image from a container's changes
|
|||||||
|
|
||||||
.. http:post:: /commit
|
.. http:post:: /commit
|
||||||
|
|
||||||
Create a new image from a container's changes
|
Create a new image from a container's changes
|
||||||
|
|
||||||
|
**Example request**:
|
||||||
|
|
||||||
|
.. sourcecode:: http
|
||||||
|
|
||||||
|
POST /commit?container=44c004db4b17&m=message&repo=myrepo HTTP/1.1
|
||||||
|
Content-Type: application/json
|
||||||
|
|
||||||
|
{
|
||||||
|
"Cmd": ["cat", "/world"],
|
||||||
|
"PortSpecs":["22"]
|
||||||
|
}
|
||||||
|
|
||||||
|
**Example response**:
|
||||||
|
|
||||||
|
.. sourcecode:: http
|
||||||
|
|
||||||
|
HTTP/1.1 201 OK
|
||||||
|
Content-Type: application/vnd.docker.raw-stream
|
||||||
|
|
||||||
|
{"Id":"596069db4bf5"}
|
||||||
|
|
||||||
|
:query container: source container
|
||||||
|
:query repo: repository
|
||||||
|
:query tag: tag
|
||||||
|
:query m: commit message
|
||||||
|
:query author: author (eg. "John Hannibal Smith <hannibal@a-team.com>")
|
||||||
|
:statuscode 201: no error
|
||||||
|
:statuscode 404: no such container
|
||||||
|
:statuscode 500: server error
|
||||||
|
|
||||||
|
|
||||||
|
Monitor Docker's events
|
||||||
|
***********************
|
||||||
|
|
||||||
|
.. http:get:: /events
|
||||||
|
|
||||||
|
Get events from docker, either in real time via streaming, or via polling (using `since`)
|
||||||
|
|
||||||
**Example request**:
|
**Example request**:
|
||||||
|
|
||||||
.. sourcecode:: http
|
.. sourcecode:: http
|
||||||
|
|
||||||
POST /commit?container=44c004db4b17&m=message&repo=myrepo HTTP/1.1
|
POST /events?since=1374067924
|
||||||
|
|
||||||
**Example response**:
|
**Example response**:
|
||||||
|
|
||||||
.. sourcecode:: http
|
.. sourcecode:: http
|
||||||
|
|
||||||
HTTP/1.1 201 OK
|
HTTP/1.1 200 OK
|
||||||
Content-Type: application/vnd.docker.raw-stream
|
Content-Type: application/json
|
||||||
|
|
||||||
{"Id":"596069db4bf5"}
|
{"status":"create","id":"dfdf82bd3881","from":"ubuntu:latest","time":1374067924}
|
||||||
|
{"status":"start","id":"dfdf82bd3881","from":"ubuntu:latest","time":1374067924}
|
||||||
|
{"status":"stop","id":"dfdf82bd3881","from":"ubuntu:latest","time":1374067966}
|
||||||
|
{"status":"destroy","id":"dfdf82bd3881","from":"ubuntu:latest","time":1374067970}
|
||||||
|
|
||||||
:query container: source container
|
:query since: timestamp used for polling
|
||||||
:query repo: repository
|
:statuscode 200: no error
|
||||||
:query tag: tag
|
|
||||||
:query m: commit message
|
|
||||||
:query author: author (eg. "John Hannibal Smith <hannibal@a-team.com>")
|
|
||||||
:query run: config automatically applied when the image is run. (ex: {"Cmd": ["cat", "/world"], "PortSpecs":["22"]})
|
|
||||||
:statuscode 201: no error
|
|
||||||
:statuscode 404: no such container
|
|
||||||
:statuscode 500: server error
|
:statuscode 500: server error
|
||||||
|
|
||||||
|
|
||||||
@@ -1088,6 +1169,8 @@ In this version of the API, /attach, uses hijacking to transport stdin, stdout a
|
|||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
To enable cross origin requests to the remote api add the flag "-api-enable-cors" when running docker in daemon mode.
|
To enable cross origin requests to the remote api add the flag "-api-enable-cors" when running docker in daemon mode.
|
||||||
|
|
||||||
docker -d -H="192.168.1.9:4243" -api-enable-cors
|
.. code-block:: bash
|
||||||
|
|
||||||
|
docker -d -H="192.168.1.9:4243" -api-enable-cors
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -14,5 +14,5 @@ Your programs and scripts can access Docker's functionality via these interfaces
|
|||||||
registry_api
|
registry_api
|
||||||
index_api
|
index_api
|
||||||
docker_remote_api
|
docker_remote_api
|
||||||
|
remote_api_client_libraries
|
||||||
|
|
||||||
|
|||||||
@@ -6,8 +6,6 @@
|
|||||||
Docker Index API
|
Docker Index API
|
||||||
=================
|
=================
|
||||||
|
|
||||||
.. contents:: Table of Contents
|
|
||||||
|
|
||||||
1. Brief introduction
|
1. Brief introduction
|
||||||
=====================
|
=====================
|
||||||
|
|
||||||
@@ -42,7 +40,7 @@ User Repo
|
|||||||
Authorization: Basic akmklmasadalkm==
|
Authorization: Basic akmklmasadalkm==
|
||||||
X-Docker-Token: true
|
X-Docker-Token: true
|
||||||
|
|
||||||
[{“id”: “9e89cc6f0bc3c38722009fe6857087b486531f9a779a0c17e3ed29dae8f12c4f”}]
|
[{"id": "9e89cc6f0bc3c38722009fe6857087b486531f9a779a0c17e3ed29dae8f12c4f"}]
|
||||||
|
|
||||||
:parameter namespace: the namespace for the repo
|
:parameter namespace: the namespace for the repo
|
||||||
:parameter repo_name: the name for the repo
|
:parameter repo_name: the name for the repo
|
||||||
@@ -54,7 +52,8 @@ User Repo
|
|||||||
HTTP/1.1 200
|
HTTP/1.1 200
|
||||||
Vary: Accept
|
Vary: Accept
|
||||||
Content-Type: application/json
|
Content-Type: application/json
|
||||||
WWW-Authenticate: Token signature=123abc,repository=”foo/bar”,access=write
|
WWW-Authenticate: Token signature=123abc,repository="foo/bar",access=write
|
||||||
|
X-Docker-Token: signature=123abc,repository="foo/bar",access=write
|
||||||
X-Docker-Endpoints: registry-1.docker.io [, registry-2.docker.io]
|
X-Docker-Endpoints: registry-1.docker.io [, registry-2.docker.io]
|
||||||
|
|
||||||
""
|
""
|
||||||
@@ -92,7 +91,8 @@ User Repo
|
|||||||
HTTP/1.1 202
|
HTTP/1.1 202
|
||||||
Vary: Accept
|
Vary: Accept
|
||||||
Content-Type: application/json
|
Content-Type: application/json
|
||||||
WWW-Authenticate: Token signature=123abc,repository=”foo/bar”,access=delete
|
WWW-Authenticate: Token signature=123abc,repository="foo/bar",access=delete
|
||||||
|
X-Docker-Token: signature=123abc,repository="foo/bar",access=delete
|
||||||
X-Docker-Endpoints: registry-1.docker.io [, registry-2.docker.io]
|
X-Docker-Endpoints: registry-1.docker.io [, registry-2.docker.io]
|
||||||
|
|
||||||
""
|
""
|
||||||
@@ -124,7 +124,7 @@ Library Repo
|
|||||||
Authorization: Basic akmklmasadalkm==
|
Authorization: Basic akmklmasadalkm==
|
||||||
X-Docker-Token: true
|
X-Docker-Token: true
|
||||||
|
|
||||||
[{“id”: “9e89cc6f0bc3c38722009fe6857087b486531f9a779a0c17e3ed29dae8f12c4f”}]
|
[{"id": "9e89cc6f0bc3c38722009fe6857087b486531f9a779a0c17e3ed29dae8f12c4f"}]
|
||||||
|
|
||||||
:parameter repo_name: the library name for the repo
|
:parameter repo_name: the library name for the repo
|
||||||
|
|
||||||
@@ -135,7 +135,8 @@ Library Repo
|
|||||||
HTTP/1.1 200
|
HTTP/1.1 200
|
||||||
Vary: Accept
|
Vary: Accept
|
||||||
Content-Type: application/json
|
Content-Type: application/json
|
||||||
WWW-Authenticate: Token signature=123abc,repository=”library/foobar”,access=write
|
WWW-Authenticate: Token signature=123abc,repository="library/foobar",access=write
|
||||||
|
X-Docker-Token: signature=123abc,repository="foo/bar",access=write
|
||||||
X-Docker-Endpoints: registry-1.docker.io [, registry-2.docker.io]
|
X-Docker-Endpoints: registry-1.docker.io [, registry-2.docker.io]
|
||||||
|
|
||||||
""
|
""
|
||||||
@@ -174,7 +175,8 @@ Library Repo
|
|||||||
HTTP/1.1 202
|
HTTP/1.1 202
|
||||||
Vary: Accept
|
Vary: Accept
|
||||||
Content-Type: application/json
|
Content-Type: application/json
|
||||||
WWW-Authenticate: Token signature=123abc,repository=”library/foobar”,access=delete
|
WWW-Authenticate: Token signature=123abc,repository="library/foobar",access=delete
|
||||||
|
X-Docker-Token: signature=123abc,repository="foo/bar",access=delete
|
||||||
X-Docker-Endpoints: registry-1.docker.io [, registry-2.docker.io]
|
X-Docker-Endpoints: registry-1.docker.io [, registry-2.docker.io]
|
||||||
|
|
||||||
""
|
""
|
||||||
@@ -205,8 +207,8 @@ User Repo Images
|
|||||||
Content-Type: application/json
|
Content-Type: application/json
|
||||||
Authorization: Basic akmklmasadalkm==
|
Authorization: Basic akmklmasadalkm==
|
||||||
|
|
||||||
[{“id”: “9e89cc6f0bc3c38722009fe6857087b486531f9a779a0c17e3ed29dae8f12c4f”,
|
[{"id": "9e89cc6f0bc3c38722009fe6857087b486531f9a779a0c17e3ed29dae8f12c4f",
|
||||||
“checksum”: “b486531f9a779a0c17e3ed29dae8f12c4f9e89cc6f0bc3c38722009fe6857087”}]
|
"checksum": "b486531f9a779a0c17e3ed29dae8f12c4f9e89cc6f0bc3c38722009fe6857087"}]
|
||||||
|
|
||||||
:parameter namespace: the namespace for the repo
|
:parameter namespace: the namespace for the repo
|
||||||
:parameter repo_name: the name for the repo
|
:parameter repo_name: the name for the repo
|
||||||
@@ -250,10 +252,10 @@ User Repo Images
|
|||||||
Vary: Accept
|
Vary: Accept
|
||||||
Content-Type: application/json
|
Content-Type: application/json
|
||||||
|
|
||||||
[{“id”: “9e89cc6f0bc3c38722009fe6857087b486531f9a779a0c17e3ed29dae8f12c4f”,
|
[{"id": "9e89cc6f0bc3c38722009fe6857087b486531f9a779a0c17e3ed29dae8f12c4f",
|
||||||
“checksum”: “b486531f9a779a0c17e3ed29dae8f12c4f9e89cc6f0bc3c38722009fe6857087”},
|
"checksum": "b486531f9a779a0c17e3ed29dae8f12c4f9e89cc6f0bc3c38722009fe6857087"},
|
||||||
{“id”: “ertwetewtwe38722009fe6857087b486531f9a779a0c1dfddgfgsdgdsgds”,
|
{"id": "ertwetewtwe38722009fe6857087b486531f9a779a0c1dfddgfgsdgdsgds",
|
||||||
“checksum”: “34t23f23fc17e3ed29dae8f12c4f9e89cc6f0bsdfgfsdgdsgdsgerwgew”}]
|
"checksum": "34t23f23fc17e3ed29dae8f12c4f9e89cc6f0bsdfgfsdgdsgdsgerwgew"}]
|
||||||
|
|
||||||
:statuscode 200: OK
|
:statuscode 200: OK
|
||||||
:statuscode 404: Not found
|
:statuscode 404: Not found
|
||||||
@@ -275,8 +277,8 @@ Library Repo Images
|
|||||||
Content-Type: application/json
|
Content-Type: application/json
|
||||||
Authorization: Basic akmklmasadalkm==
|
Authorization: Basic akmklmasadalkm==
|
||||||
|
|
||||||
[{“id”: “9e89cc6f0bc3c38722009fe6857087b486531f9a779a0c17e3ed29dae8f12c4f”,
|
[{"id": "9e89cc6f0bc3c38722009fe6857087b486531f9a779a0c17e3ed29dae8f12c4f",
|
||||||
“checksum”: “b486531f9a779a0c17e3ed29dae8f12c4f9e89cc6f0bc3c38722009fe6857087”}]
|
"checksum": "b486531f9a779a0c17e3ed29dae8f12c4f9e89cc6f0bc3c38722009fe6857087"}]
|
||||||
|
|
||||||
:parameter repo_name: the library name for the repo
|
:parameter repo_name: the library name for the repo
|
||||||
|
|
||||||
@@ -318,10 +320,10 @@ Library Repo Images
|
|||||||
Vary: Accept
|
Vary: Accept
|
||||||
Content-Type: application/json
|
Content-Type: application/json
|
||||||
|
|
||||||
[{“id”: “9e89cc6f0bc3c38722009fe6857087b486531f9a779a0c17e3ed29dae8f12c4f”,
|
[{"id": "9e89cc6f0bc3c38722009fe6857087b486531f9a779a0c17e3ed29dae8f12c4f",
|
||||||
“checksum”: “b486531f9a779a0c17e3ed29dae8f12c4f9e89cc6f0bc3c38722009fe6857087”},
|
"checksum": "b486531f9a779a0c17e3ed29dae8f12c4f9e89cc6f0bc3c38722009fe6857087"},
|
||||||
{“id”: “ertwetewtwe38722009fe6857087b486531f9a779a0c1dfddgfgsdgdsgds”,
|
{"id": "ertwetewtwe38722009fe6857087b486531f9a779a0c1dfddgfgsdgdsgds",
|
||||||
“checksum”: “34t23f23fc17e3ed29dae8f12c4f9e89cc6f0bsdfgfsdgdsgdsgerwgew”}]
|
"checksum": "34t23f23fc17e3ed29dae8f12c4f9e89cc6f0bsdfgfsdgdsgdsgerwgew"}]
|
||||||
|
|
||||||
:statuscode 200: OK
|
:statuscode 200: OK
|
||||||
:statuscode 404: Not found
|
:statuscode 404: Not found
|
||||||
@@ -541,10 +543,11 @@ Search
|
|||||||
Content-Type: application/json
|
Content-Type: application/json
|
||||||
|
|
||||||
{"query":"search_term",
|
{"query":"search_term",
|
||||||
"num_results": 2,
|
"num_results": 3,
|
||||||
"results" : [
|
"results" : [
|
||||||
{"name": "dotcloud/base", "description": "A base ubuntu64 image..."},
|
{"name": "ubuntu", "description": "An ubuntu image..."},
|
||||||
{"name": "base2", "description": "A base ubuntu64 image..."},
|
{"name": "centos", "description": "A centos image..."},
|
||||||
|
{"name": "fedora", "description": "A fedora image..."}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,6 @@
|
|||||||
Docker Registry API
|
Docker Registry API
|
||||||
===================
|
===================
|
||||||
|
|
||||||
.. contents:: Table of Contents
|
|
||||||
|
|
||||||
1. Brief introduction
|
1. Brief introduction
|
||||||
=====================
|
=====================
|
||||||
@@ -61,7 +60,7 @@ Layer
|
|||||||
Host: registry-1.docker.io
|
Host: registry-1.docker.io
|
||||||
Accept: application/json
|
Accept: application/json
|
||||||
Content-Type: application/json
|
Content-Type: application/json
|
||||||
Authorization: Token akmklmasadalkmsdfgsdgdge33
|
Authorization: Token signature=123abc,repository="foo/bar",access=read
|
||||||
|
|
||||||
:parameter image_id: the id for the layer you want to get
|
:parameter image_id: the id for the layer you want to get
|
||||||
|
|
||||||
@@ -71,39 +70,10 @@ Layer
|
|||||||
|
|
||||||
HTTP/1.1 200
|
HTTP/1.1 200
|
||||||
Vary: Accept
|
Vary: Accept
|
||||||
Content-Type: application/json
|
X-Docker-Registry-Version: 0.6.0
|
||||||
Cookie: (Cookie provided by the Registry)
|
Cookie: (Cookie provided by the Registry)
|
||||||
|
|
||||||
{
|
{layer binary data stream}
|
||||||
id: "088b4505aa3adc3d35e79c031fa126b403200f02f51920fbd9b7c503e87c7a2c",
|
|
||||||
parent: "aeee6396d62273d180a49c96c62e45438d87c7da4a5cf5d2be6bee4e21bc226f",
|
|
||||||
created: "2013-04-30T17:46:10.843673+03:00",
|
|
||||||
container: "8305672a76cc5e3d168f97221106ced35a76ec7ddbb03209b0f0d96bf74f6ef7",
|
|
||||||
container_config: {
|
|
||||||
Hostname: "host-test",
|
|
||||||
User: "",
|
|
||||||
Memory: 0,
|
|
||||||
MemorySwap: 0,
|
|
||||||
AttachStdin: false,
|
|
||||||
AttachStdout: false,
|
|
||||||
AttachStderr: false,
|
|
||||||
PortSpecs: null,
|
|
||||||
Tty: false,
|
|
||||||
OpenStdin: false,
|
|
||||||
StdinOnce: false,
|
|
||||||
Env: null,
|
|
||||||
Cmd: [
|
|
||||||
"/bin/bash",
|
|
||||||
"-c",
|
|
||||||
"apt-get -q -yy -f install libevent-dev"
|
|
||||||
],
|
|
||||||
Dns: null,
|
|
||||||
Image: "imagename/blah",
|
|
||||||
Volumes: { },
|
|
||||||
VolumesFrom: ""
|
|
||||||
},
|
|
||||||
docker_version: "0.1.7"
|
|
||||||
}
|
|
||||||
|
|
||||||
:statuscode 200: OK
|
:statuscode 200: OK
|
||||||
:statuscode 401: Requires authorization
|
:statuscode 401: Requires authorization
|
||||||
@@ -120,40 +90,10 @@ Layer
|
|||||||
|
|
||||||
PUT /v1/images/088b4505aa3adc3d35e79c031fa126b403200f02f51920fbd9b7c503e87c7a2c/layer HTTP/1.1
|
PUT /v1/images/088b4505aa3adc3d35e79c031fa126b403200f02f51920fbd9b7c503e87c7a2c/layer HTTP/1.1
|
||||||
Host: registry-1.docker.io
|
Host: registry-1.docker.io
|
||||||
Accept: application/json
|
Transfer-Encoding: chunked
|
||||||
Content-Type: application/json
|
Authorization: Token signature=123abc,repository="foo/bar",access=write
|
||||||
Authorization: Token akmklmasadalkmsdfgsdgdge33
|
|
||||||
|
|
||||||
{
|
{layer binary data stream}
|
||||||
id: "088b4505aa3adc3d35e79c031fa126b403200f02f51920fbd9b7c503e87c7a2c",
|
|
||||||
parent: "aeee6396d62273d180a49c96c62e45438d87c7da4a5cf5d2be6bee4e21bc226f",
|
|
||||||
created: "2013-04-30T17:46:10.843673+03:00",
|
|
||||||
container: "8305672a76cc5e3d168f97221106ced35a76ec7ddbb03209b0f0d96bf74f6ef7",
|
|
||||||
container_config: {
|
|
||||||
Hostname: "host-test",
|
|
||||||
User: "",
|
|
||||||
Memory: 0,
|
|
||||||
MemorySwap: 0,
|
|
||||||
AttachStdin: false,
|
|
||||||
AttachStdout: false,
|
|
||||||
AttachStderr: false,
|
|
||||||
PortSpecs: null,
|
|
||||||
Tty: false,
|
|
||||||
OpenStdin: false,
|
|
||||||
StdinOnce: false,
|
|
||||||
Env: null,
|
|
||||||
Cmd: [
|
|
||||||
"/bin/bash",
|
|
||||||
"-c",
|
|
||||||
"apt-get -q -yy -f install libevent-dev"
|
|
||||||
],
|
|
||||||
Dns: null,
|
|
||||||
Image: "imagename/blah",
|
|
||||||
Volumes: { },
|
|
||||||
VolumesFrom: ""
|
|
||||||
},
|
|
||||||
docker_version: "0.1.7"
|
|
||||||
}
|
|
||||||
|
|
||||||
:parameter image_id: the id for the layer you want to get
|
:parameter image_id: the id for the layer you want to get
|
||||||
|
|
||||||
@@ -165,6 +105,7 @@ Layer
|
|||||||
HTTP/1.1 200
|
HTTP/1.1 200
|
||||||
Vary: Accept
|
Vary: Accept
|
||||||
Content-Type: application/json
|
Content-Type: application/json
|
||||||
|
X-Docker-Registry-Version: 0.6.0
|
||||||
|
|
||||||
""
|
""
|
||||||
|
|
||||||
@@ -191,13 +132,38 @@ Image
|
|||||||
Cookie: (Cookie provided by the Registry)
|
Cookie: (Cookie provided by the Registry)
|
||||||
|
|
||||||
{
|
{
|
||||||
“id”: “088b4505aa3adc3d35e79c031fa126b403200f02f51920fbd9b7c503e87c7a2c”,
|
id: "088b4505aa3adc3d35e79c031fa126b403200f02f51920fbd9b7c503e87c7a2c",
|
||||||
“checksum”: “sha256:b486531f9a779a0c17e3ed29dae8f12c4f9e89cc6f0bc3c38722009fe6857087”
|
parent: "aeee6396d62273d180a49c96c62e45438d87c7da4a5cf5d2be6bee4e21bc226f",
|
||||||
}
|
created: "2013-04-30T17:46:10.843673+03:00",
|
||||||
|
container: "8305672a76cc5e3d168f97221106ced35a76ec7ddbb03209b0f0d96bf74f6ef7",
|
||||||
|
container_config: {
|
||||||
|
Hostname: "host-test",
|
||||||
|
User: "",
|
||||||
|
Memory: 0,
|
||||||
|
MemorySwap: 0,
|
||||||
|
AttachStdin: false,
|
||||||
|
AttachStdout: false,
|
||||||
|
AttachStderr: false,
|
||||||
|
PortSpecs: null,
|
||||||
|
Tty: false,
|
||||||
|
OpenStdin: false,
|
||||||
|
StdinOnce: false,
|
||||||
|
Env: null,
|
||||||
|
Cmd: [
|
||||||
|
"/bin/bash",
|
||||||
|
"-c",
|
||||||
|
"apt-get -q -yy -f install libevent-dev"
|
||||||
|
],
|
||||||
|
Dns: null,
|
||||||
|
Image: "imagename/blah",
|
||||||
|
Volumes: { },
|
||||||
|
VolumesFrom: ""
|
||||||
|
},
|
||||||
|
docker_version: "0.1.7"
|
||||||
|
}
|
||||||
|
|
||||||
:parameter image_id: the id for the layer you want to get
|
:parameter image_id: the id for the layer you want to get
|
||||||
|
|
||||||
|
|
||||||
**Example Response**:
|
**Example Response**:
|
||||||
|
|
||||||
.. sourcecode:: http
|
.. sourcecode:: http
|
||||||
@@ -205,6 +171,7 @@ Image
|
|||||||
HTTP/1.1 200
|
HTTP/1.1 200
|
||||||
Vary: Accept
|
Vary: Accept
|
||||||
Content-Type: application/json
|
Content-Type: application/json
|
||||||
|
X-Docker-Registry-Version: 0.6.0
|
||||||
|
|
||||||
""
|
""
|
||||||
|
|
||||||
@@ -234,11 +201,40 @@ Image
|
|||||||
HTTP/1.1 200
|
HTTP/1.1 200
|
||||||
Vary: Accept
|
Vary: Accept
|
||||||
Content-Type: application/json
|
Content-Type: application/json
|
||||||
|
X-Docker-Registry-Version: 0.6.0
|
||||||
|
X-Docker-Size: 456789
|
||||||
|
X-Docker-Checksum: b486531f9a779a0c17e3ed29dae8f12c4f9e89cc6f0bc3c38722009fe6857087
|
||||||
|
|
||||||
{
|
{
|
||||||
“id”: “088b4505aa3adc3d35e79c031fa126b403200f02f51920fbd9b7c503e87c7a2c”,
|
id: "088b4505aa3adc3d35e79c031fa126b403200f02f51920fbd9b7c503e87c7a2c",
|
||||||
“checksum”: “sha256:b486531f9a779a0c17e3ed29dae8f12c4f9e89cc6f0bc3c38722009fe6857087”
|
parent: "aeee6396d62273d180a49c96c62e45438d87c7da4a5cf5d2be6bee4e21bc226f",
|
||||||
}
|
created: "2013-04-30T17:46:10.843673+03:00",
|
||||||
|
container: "8305672a76cc5e3d168f97221106ced35a76ec7ddbb03209b0f0d96bf74f6ef7",
|
||||||
|
container_config: {
|
||||||
|
Hostname: "host-test",
|
||||||
|
User: "",
|
||||||
|
Memory: 0,
|
||||||
|
MemorySwap: 0,
|
||||||
|
AttachStdin: false,
|
||||||
|
AttachStdout: false,
|
||||||
|
AttachStderr: false,
|
||||||
|
PortSpecs: null,
|
||||||
|
Tty: false,
|
||||||
|
OpenStdin: false,
|
||||||
|
StdinOnce: false,
|
||||||
|
Env: null,
|
||||||
|
Cmd: [
|
||||||
|
"/bin/bash",
|
||||||
|
"-c",
|
||||||
|
"apt-get -q -yy -f install libevent-dev"
|
||||||
|
],
|
||||||
|
Dns: null,
|
||||||
|
Image: "imagename/blah",
|
||||||
|
Volumes: { },
|
||||||
|
VolumesFrom: ""
|
||||||
|
},
|
||||||
|
docker_version: "0.1.7"
|
||||||
|
}
|
||||||
|
|
||||||
:statuscode 200: OK
|
:statuscode 200: OK
|
||||||
:statuscode 401: Requires authorization
|
:statuscode 401: Requires authorization
|
||||||
@@ -271,6 +267,7 @@ Ancestry
|
|||||||
HTTP/1.1 200
|
HTTP/1.1 200
|
||||||
Vary: Accept
|
Vary: Accept
|
||||||
Content-Type: application/json
|
Content-Type: application/json
|
||||||
|
X-Docker-Registry-Version: 0.6.0
|
||||||
|
|
||||||
["088b4502f51920fbd9b7c503e87c7a2c05aa3adc3d35e79c031fa126b403200f",
|
["088b4502f51920fbd9b7c503e87c7a2c05aa3adc3d35e79c031fa126b403200f",
|
||||||
"aeee63968d87c7da4a5cf5d2be6bee4e21bc226fd62273d180a49c96c62e4543",
|
"aeee63968d87c7da4a5cf5d2be6bee4e21bc226fd62273d180a49c96c62e4543",
|
||||||
@@ -297,6 +294,7 @@ Ancestry
|
|||||||
Host: registry-1.docker.io
|
Host: registry-1.docker.io
|
||||||
Accept: application/json
|
Accept: application/json
|
||||||
Content-Type: application/json
|
Content-Type: application/json
|
||||||
|
X-Docker-Registry-Version: 0.6.0
|
||||||
Cookie: (Cookie provided by the Registry)
|
Cookie: (Cookie provided by the Registry)
|
||||||
|
|
||||||
:parameter namespace: namespace for the repo
|
:parameter namespace: namespace for the repo
|
||||||
@@ -309,10 +307,11 @@ Ancestry
|
|||||||
HTTP/1.1 200
|
HTTP/1.1 200
|
||||||
Vary: Accept
|
Vary: Accept
|
||||||
Content-Type: application/json
|
Content-Type: application/json
|
||||||
|
X-Docker-Registry-Version: 0.6.0
|
||||||
|
|
||||||
{
|
{
|
||||||
"latest": "9e89cc6f0bc3c38722009fe6857087b486531f9a779a0c17e3ed29dae8f12c4f",
|
"latest": "9e89cc6f0bc3c38722009fe6857087b486531f9a779a0c17e3ed29dae8f12c4f",
|
||||||
“0.1.1”: “b486531f9a779a0c17e3ed29dae8f12c4f9e89cc6f0bc3c38722009fe6857087”
|
"0.1.1": "b486531f9a779a0c17e3ed29dae8f12c4f9e89cc6f0bc3c38722009fe6857087"
|
||||||
}
|
}
|
||||||
|
|
||||||
:statuscode 200: OK
|
:statuscode 200: OK
|
||||||
@@ -332,6 +331,7 @@ Ancestry
|
|||||||
Host: registry-1.docker.io
|
Host: registry-1.docker.io
|
||||||
Accept: application/json
|
Accept: application/json
|
||||||
Content-Type: application/json
|
Content-Type: application/json
|
||||||
|
X-Docker-Registry-Version: 0.6.0
|
||||||
Cookie: (Cookie provided by the Registry)
|
Cookie: (Cookie provided by the Registry)
|
||||||
|
|
||||||
:parameter namespace: namespace for the repo
|
:parameter namespace: namespace for the repo
|
||||||
@@ -345,6 +345,7 @@ Ancestry
|
|||||||
HTTP/1.1 200
|
HTTP/1.1 200
|
||||||
Vary: Accept
|
Vary: Accept
|
||||||
Content-Type: application/json
|
Content-Type: application/json
|
||||||
|
X-Docker-Registry-Version: 0.6.0
|
||||||
|
|
||||||
"9e89cc6f0bc3c38722009fe6857087b486531f9a779a0c17e3ed29dae8f12c4f"
|
"9e89cc6f0bc3c38722009fe6857087b486531f9a779a0c17e3ed29dae8f12c4f"
|
||||||
|
|
||||||
@@ -377,6 +378,7 @@ Ancestry
|
|||||||
HTTP/1.1 200
|
HTTP/1.1 200
|
||||||
Vary: Accept
|
Vary: Accept
|
||||||
Content-Type: application/json
|
Content-Type: application/json
|
||||||
|
X-Docker-Registry-Version: 0.6.0
|
||||||
|
|
||||||
""
|
""
|
||||||
|
|
||||||
@@ -399,7 +401,7 @@ Ancestry
|
|||||||
Content-Type: application/json
|
Content-Type: application/json
|
||||||
Cookie: (Cookie provided by the Registry)
|
Cookie: (Cookie provided by the Registry)
|
||||||
|
|
||||||
“9e89cc6f0bc3c38722009fe6857087b486531f9a779a0c17e3ed29dae8f12c4f”
|
"9e89cc6f0bc3c38722009fe6857087b486531f9a779a0c17e3ed29dae8f12c4f"
|
||||||
|
|
||||||
:parameter namespace: namespace for the repo
|
:parameter namespace: namespace for the repo
|
||||||
:parameter repository: name for the repo
|
:parameter repository: name for the repo
|
||||||
@@ -412,6 +414,7 @@ Ancestry
|
|||||||
HTTP/1.1 200
|
HTTP/1.1 200
|
||||||
Vary: Accept
|
Vary: Accept
|
||||||
Content-Type: application/json
|
Content-Type: application/json
|
||||||
|
X-Docker-Registry-Version: 0.6.0
|
||||||
|
|
||||||
""
|
""
|
||||||
|
|
||||||
@@ -449,6 +452,7 @@ Ancestry
|
|||||||
HTTP/1.1 200
|
HTTP/1.1 200
|
||||||
Vary: Accept
|
Vary: Accept
|
||||||
Content-Type: application/json
|
Content-Type: application/json
|
||||||
|
X-Docker-Registry-Version: 0.6.0
|
||||||
|
|
||||||
""
|
""
|
||||||
|
|
||||||
@@ -456,8 +460,41 @@ Ancestry
|
|||||||
:statuscode 401: Requires authorization
|
:statuscode 401: Requires authorization
|
||||||
:statuscode 404: Repository not found
|
:statuscode 404: Repository not found
|
||||||
|
|
||||||
3.0 Authorization
|
2.4 Status
|
||||||
=================
|
----------
|
||||||
|
|
||||||
|
.. http:get:: /v1/_ping
|
||||||
|
|
||||||
|
Check status of the registry. This endpoint is also used to determine if
|
||||||
|
the registry supports SSL.
|
||||||
|
|
||||||
|
**Example Request**:
|
||||||
|
|
||||||
|
.. sourcecode:: http
|
||||||
|
|
||||||
|
GET /v1/_ping HTTP/1.1
|
||||||
|
Host: registry-1.docker.io
|
||||||
|
Accept: application/json
|
||||||
|
Content-Type: application/json
|
||||||
|
|
||||||
|
""
|
||||||
|
|
||||||
|
**Example Response**:
|
||||||
|
|
||||||
|
.. sourcecode:: http
|
||||||
|
|
||||||
|
HTTP/1.1 200
|
||||||
|
Vary: Accept
|
||||||
|
Content-Type: application/json
|
||||||
|
X-Docker-Registry-Version: 0.6.0
|
||||||
|
|
||||||
|
""
|
||||||
|
|
||||||
|
:statuscode 200: OK
|
||||||
|
|
||||||
|
|
||||||
|
3 Authorization
|
||||||
|
===============
|
||||||
This is where we describe the authorization process, including the tokens and cookies.
|
This is where we describe the authorization process, including the tokens and cookies.
|
||||||
|
|
||||||
TODO: add more info.
|
TODO: add more info.
|
||||||
|
|||||||
@@ -2,13 +2,12 @@
|
|||||||
:description: Documentation for docker Registry and Registry API
|
:description: Documentation for docker Registry and Registry API
|
||||||
:keywords: docker, registry, api, index
|
:keywords: docker, registry, api, index
|
||||||
|
|
||||||
|
.. _registryindexspec:
|
||||||
|
|
||||||
=====================
|
=====================
|
||||||
Registry & index Spec
|
Registry & Index Spec
|
||||||
=====================
|
=====================
|
||||||
|
|
||||||
.. contents:: Table of Contents
|
|
||||||
|
|
||||||
1. The 3 roles
|
1. The 3 roles
|
||||||
===============
|
===============
|
||||||
|
|
||||||
@@ -154,7 +153,7 @@ API (pulling repository foo/bar):
|
|||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
**It’s possible not to use the Index at all!** In this case, a deployed version of the Registry is deployed to store and serve images. Those images are not authentified and the security is not guaranteed.
|
**It’s possible not to use the Index at all!** In this case, a deployed version of the Registry is deployed to store and serve images. Those images are not authenticated and the security is not guaranteed.
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
@@ -563,8 +562,8 @@ Next request::
|
|||||||
Cookie: session="wD/J7LqL5ctqw8haL10vgfhrb2Q=?foo=UydiYXInCnAxCi4=×tamp=RjEzNjYzMTQ5NDcuNDc0NjQzCi4="
|
Cookie: session="wD/J7LqL5ctqw8haL10vgfhrb2Q=?foo=UydiYXInCnAxCi4=×tamp=RjEzNjYzMTQ5NDcuNDc0NjQzCi4="
|
||||||
|
|
||||||
|
|
||||||
7.0 Document Version
|
7 Document Version
|
||||||
---------------------
|
====================
|
||||||
|
|
||||||
- 1.0 : May 6th 2013 : initial release
|
- 1.0 : May 6th 2013 : initial release
|
||||||
- 1.1 : June 1st 2013 : Added Delete Repository and way to handle new source namespace.
|
- 1.1 : June 1st 2013 : Added Delete Repository and way to handle new source namespace.
|
||||||
|
|||||||
@@ -0,0 +1,39 @@
|
|||||||
|
:title: Remote API Client Libraries
|
||||||
|
:description: Various client libraries available to use with the Docker remote API
|
||||||
|
:keywords: API, Docker, index, registry, REST, documentation, clients, Python, Ruby, Javascript, Erlang, Go
|
||||||
|
|
||||||
|
|
||||||
|
==================================
|
||||||
|
Docker Remote API Client Libraries
|
||||||
|
==================================
|
||||||
|
|
||||||
|
These libraries have not been tested by the Docker Maintainers for
|
||||||
|
compatibility. Please file issues with the library owners. If you
|
||||||
|
find more library implementations, please list them in Docker doc bugs
|
||||||
|
and we will add the libraries here.
|
||||||
|
|
||||||
|
+----------------------+----------------+--------------------------------------------+----------+
|
||||||
|
| Language/Framework | Name | Repository | Status |
|
||||||
|
+======================+================+============================================+==========+
|
||||||
|
| Python | docker-py | https://github.com/dotcloud/docker-py | Active |
|
||||||
|
+----------------------+----------------+--------------------------------------------+----------+
|
||||||
|
| Ruby | docker-client | https://github.com/geku/docker-client | Outdated |
|
||||||
|
+----------------------+----------------+--------------------------------------------+----------+
|
||||||
|
| Ruby | docker-api | https://github.com/swipely/docker-api | Active |
|
||||||
|
+----------------------+----------------+--------------------------------------------+----------+
|
||||||
|
| Javascript (NodeJS) | docker.io | https://github.com/appersonlabs/docker.io | Active |
|
||||||
|
| | | Install via NPM: `npm install docker.io` | |
|
||||||
|
+----------------------+----------------+--------------------------------------------+----------+
|
||||||
|
| Javascript | docker-js | https://github.com/dgoujard/docker-js | Active |
|
||||||
|
+----------------------+----------------+--------------------------------------------+----------+
|
||||||
|
| Javascript (Angular) | dockerui | https://github.com/crosbymichael/dockerui | Active |
|
||||||
|
| **WebUI** | | | |
|
||||||
|
+----------------------+----------------+--------------------------------------------+----------+
|
||||||
|
| Java | docker-java | https://github.com/kpelykh/docker-java | Active |
|
||||||
|
+----------------------+----------------+--------------------------------------------+----------+
|
||||||
|
| Erlang | erldocker | https://github.com/proger/erldocker | Active |
|
||||||
|
+----------------------+----------------+--------------------------------------------+----------+
|
||||||
|
| Go | go-dockerclient| https://github.com/fsouza/go-dockerclient | Active |
|
||||||
|
+----------------------+----------------+--------------------------------------------+----------+
|
||||||
|
| PHP | Alvine | http://pear.alvine.io/ (alpha) | Active |
|
||||||
|
+----------------------+----------------+--------------------------------------------+----------+
|
||||||
+1017
-39
File diff suppressed because it is too large
Load Diff
@@ -1,13 +0,0 @@
|
|||||||
:title: Attach Command
|
|
||||||
:description: Attach to a running container
|
|
||||||
:keywords: attach, container, docker, documentation
|
|
||||||
|
|
||||||
===========================================
|
|
||||||
``attach`` -- Attach to a running container
|
|
||||||
===========================================
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
Usage: docker attach CONTAINER
|
|
||||||
|
|
||||||
Attach to a running container
|
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
:title: Build Command
|
|
||||||
:description: Build a new image from the Dockerfile passed via stdin
|
|
||||||
:keywords: build, docker, container, documentation
|
|
||||||
|
|
||||||
================================================
|
|
||||||
``build`` -- Build a container from a Dockerfile
|
|
||||||
================================================
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
Usage: docker build [OPTIONS] PATH | URL | -
|
|
||||||
Build a new container image from the source code at PATH
|
|
||||||
-t="": Tag to be applied to the resulting image in case of success.
|
|
||||||
-q=false: Suppress verbose build output.
|
|
||||||
When a single Dockerfile is given as URL, then no context is set. When a git repository is set as URL, the repository is used as context
|
|
||||||
|
|
||||||
|
|
||||||
Examples
|
|
||||||
--------
|
|
||||||
|
|
||||||
.. code-block:: bash
|
|
||||||
|
|
||||||
docker build .
|
|
||||||
|
|
||||||
| This will read the Dockerfile from the current directory. It will also send any other files and directories found in the current directory to the docker daemon.
|
|
||||||
| The contents of this directory would be used by ADD commands found within the Dockerfile.
|
|
||||||
| This will send a lot of data to the docker daemon if the current directory contains a lot of data.
|
|
||||||
| If the absolute path is provided instead of '.', only the files and directories required by the ADD commands from the Dockerfile will be added to the context and transferred to the docker daemon.
|
|
||||||
|
|
|
||||||
|
|
||||||
.. code-block:: bash
|
|
||||||
|
|
||||||
docker build - < Dockerfile
|
|
||||||
|
|
||||||
| This will read a Dockerfile from Stdin without context. Due to the lack of a context, no contents of any local directory will be sent to the docker daemon.
|
|
||||||
| ADD doesn't work when running in this mode due to the absence of the context, thus having no source files to copy to the container.
|
|
||||||
|
|
||||||
|
|
||||||
.. code-block:: bash
|
|
||||||
|
|
||||||
docker build github.com/creack/docker-firefox
|
|
||||||
|
|
||||||
| This will clone the github repository and use it as context. The Dockerfile at the root of the repository is used as Dockerfile.
|
|
||||||
| Note that you can specify an arbitrary git repository by using the 'git://' schema.
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
:title: Commit Command
|
|
||||||
:description: Create a new image from a container's changes
|
|
||||||
:keywords: commit, docker, container, documentation
|
|
||||||
|
|
||||||
===========================================================
|
|
||||||
``commit`` -- Create a new image from a container's changes
|
|
||||||
===========================================================
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
Usage: docker commit [OPTIONS] CONTAINER [REPOSITORY [TAG]]
|
|
||||||
|
|
||||||
Create a new image from a container's changes
|
|
||||||
|
|
||||||
-m="": Commit message
|
|
||||||
-author="": Author (eg. "John Hannibal Smith <hannibal@a-team.com>"
|
|
||||||
-run="": Config automatically applied when the image is run. "+`(ex: {"Cmd": ["cat", "/world"], "PortSpecs": ["22"]}')
|
|
||||||
|
|
||||||
Full -run example::
|
|
||||||
|
|
||||||
{"Hostname": "",
|
|
||||||
"User": "",
|
|
||||||
"CpuShares": 0,
|
|
||||||
"Memory": 0,
|
|
||||||
"MemorySwap": 0,
|
|
||||||
"PortSpecs": ["22", "80", "443"],
|
|
||||||
"Tty": true,
|
|
||||||
"OpenStdin": true,
|
|
||||||
"StdinOnce": true,
|
|
||||||
"Env": ["FOO=BAR", "FOO2=BAR2"],
|
|
||||||
"Cmd": ["cat", "-e", "/etc/resolv.conf"],
|
|
||||||
"Dns": ["8.8.8.8", "8.8.4.4"]}
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
:title: Diff Command
|
|
||||||
:description: Inspect changes on a container's filesystem
|
|
||||||
:keywords: diff, docker, container, documentation
|
|
||||||
|
|
||||||
=======================================================
|
|
||||||
``diff`` -- Inspect changes on a container's filesystem
|
|
||||||
=======================================================
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
Usage: docker diff CONTAINER [OPTIONS]
|
|
||||||
|
|
||||||
Inspect changes on a container's filesystem
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
:title: Export Command
|
|
||||||
:description: Export the contents of a filesystem as a tar archive
|
|
||||||
:keywords: export, docker, container, documentation
|
|
||||||
|
|
||||||
=================================================================
|
|
||||||
``export`` -- Stream the contents of a container as a tar archive
|
|
||||||
=================================================================
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
Usage: docker export CONTAINER
|
|
||||||
|
|
||||||
Export the contents of a filesystem as a tar archive
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
:title: History Command
|
|
||||||
:description: Show the history of an image
|
|
||||||
:keywords: history, docker, container, documentation
|
|
||||||
|
|
||||||
===========================================
|
|
||||||
``history`` -- Show the history of an image
|
|
||||||
===========================================
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
Usage: docker history [OPTIONS] IMAGE
|
|
||||||
|
|
||||||
Show the history of an image
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
:title: Images Command
|
|
||||||
:description: List images
|
|
||||||
:keywords: images, docker, container, documentation
|
|
||||||
|
|
||||||
=========================
|
|
||||||
``images`` -- List images
|
|
||||||
=========================
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
Usage: docker images [OPTIONS] [NAME]
|
|
||||||
|
|
||||||
List images
|
|
||||||
|
|
||||||
-a=false: show all images
|
|
||||||
-q=false: only show numeric IDs
|
|
||||||
-viz=false: output in graphviz format
|
|
||||||
|
|
||||||
Displaying images visually
|
|
||||||
--------------------------
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
docker images -viz | dot -Tpng -o docker.png
|
|
||||||
|
|
||||||
.. image:: images/docker_images.gif
|
|
||||||
@@ -1,41 +0,0 @@
|
|||||||
:title: Import Command
|
|
||||||
:description: Create a new filesystem image from the contents of a tarball
|
|
||||||
:keywords: import, tarball, docker, url, documentation
|
|
||||||
|
|
||||||
==========================================================================
|
|
||||||
``import`` -- Create a new filesystem image from the contents of a tarball
|
|
||||||
==========================================================================
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
Usage: docker import URL|- [REPOSITORY [TAG]]
|
|
||||||
|
|
||||||
Create a new filesystem image from the contents of a tarball
|
|
||||||
|
|
||||||
At this time, the URL must start with ``http`` and point to a single file archive
|
|
||||||
(.tar, .tar.gz, .tgz, .bzip, .tar.xz, .txz)
|
|
||||||
containing a root filesystem. If you would like to import from a local directory or archive,
|
|
||||||
you can use the ``-`` parameter to take the data from standard in.
|
|
||||||
|
|
||||||
Examples
|
|
||||||
--------
|
|
||||||
|
|
||||||
Import from a remote location
|
|
||||||
.............................
|
|
||||||
|
|
||||||
``$ docker import http://example.com/exampleimage.tgz exampleimagerepo``
|
|
||||||
|
|
||||||
Import from a local file
|
|
||||||
........................
|
|
||||||
|
|
||||||
Import to docker via pipe and standard in
|
|
||||||
|
|
||||||
``$ cat exampleimage.tgz | docker import - exampleimagelocal``
|
|
||||||
|
|
||||||
Import from a local directory
|
|
||||||
.............................
|
|
||||||
|
|
||||||
``$ sudo tar -c . | docker import - exampleimagedir``
|
|
||||||
|
|
||||||
Note the ``sudo`` in this example -- you must preserve the ownership of the files (especially root ownership)
|
|
||||||
during the archiving with tar. If you are not root (or sudo) when you tar, then the ownerships might not get preserved.
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
:title: Info Command
|
|
||||||
:description: Display system-wide information.
|
|
||||||
:keywords: info, docker, information, documentation
|
|
||||||
|
|
||||||
===========================================
|
|
||||||
``info`` -- Display system-wide information
|
|
||||||
===========================================
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
Usage: docker info
|
|
||||||
|
|
||||||
Display system-wide information.
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user