mirror of
https://github.com/moby/moby.git
synced 2026-01-12 03:01:38 +00:00
Compare commits
214 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b9f10c9518 | ||
|
|
85ebf9ba07 | ||
|
|
4251e1e99e | ||
|
|
9810988fb5 | ||
|
|
dacb55f979 | ||
|
|
e74e3840b0 | ||
|
|
a3f0e6fe9f | ||
|
|
a8947b35de | ||
|
|
11795730f1 | ||
|
|
956ba4ee06 | ||
|
|
a75a949876 | ||
|
|
08ecb29017 | ||
|
|
c9dd46ca5c | ||
|
|
276a8d3aa2 | ||
|
|
e24f320dd1 | ||
|
|
bde0bcf2d8 | ||
|
|
6d17d5bf9e | ||
|
|
a8dc0ba83a | ||
|
|
966e9126bb | ||
|
|
4a26a65799 | ||
|
|
d84150ab38 | ||
|
|
271ac412b5 | ||
|
|
8bc3da5420 | ||
|
|
b4cea1581f | ||
|
|
1e36e346db | ||
|
|
3886d02027 | ||
|
|
58a780f210 | ||
|
|
1690dba063 | ||
|
|
c3e391f777 | ||
|
|
5604cbed50 | ||
|
|
7ef1cfd696 | ||
|
|
61c0f4bc3e | ||
|
|
ab1be6f667 | ||
|
|
c06a4c22bb | ||
|
|
3b8c11b1b3 | ||
|
|
0c8c9bada9 | ||
|
|
dc984199eb | ||
|
|
f503494769 | ||
|
|
91880b45a7 | ||
|
|
75d6341d56 | ||
|
|
2735744cb5 | ||
|
|
45730a4584 | ||
|
|
ce9e2d800a | ||
|
|
c3348d02d5 | ||
|
|
8c1d8025f2 | ||
|
|
e04dca2bd6 | ||
|
|
9d68491978 | ||
|
|
ccfb894e6c | ||
|
|
c9417489a2 | ||
|
|
044398a7ad | ||
|
|
41130fb9bc | ||
|
|
9d99e360ba | ||
|
|
25f42443f1 | ||
|
|
4146b8b69b | ||
|
|
0344639420 | ||
|
|
2bebacef5f | ||
|
|
b599a07911 | ||
|
|
456ae2f1e2 | ||
|
|
4dc5990d75 | ||
|
|
365d80b3e1 | ||
|
|
2535db8678 | ||
|
|
54edfc41c6 | ||
|
|
4a6f2274be | ||
|
|
db08f19e36 | ||
|
|
af370ff997 | ||
|
|
645836f250 | ||
|
|
3d85e51ef4 | ||
|
|
5618fbf18c | ||
|
|
bf312aca9c | ||
|
|
4172802d68 | ||
|
|
fb06ddf4db | ||
|
|
d126e2fb72 | ||
|
|
3130169eb2 | ||
|
|
260a835cb4 | ||
|
|
d42b3f6765 | ||
|
|
134990dd07 | ||
|
|
aa7da70459 | ||
|
|
8ff913e45f | ||
|
|
642c4a7814 | ||
|
|
3522bdfc99 | ||
|
|
490c26524c | ||
|
|
7ae170ddab | ||
|
|
b4f0d68843 | ||
|
|
cbd50baf8b | ||
|
|
0b25417cce | ||
|
|
eb405d2b73 | ||
|
|
133773a4d0 | ||
|
|
9cdfce68f8 | ||
|
|
716b5b2547 | ||
|
|
52b8adea4d | ||
|
|
b1b86e9166 | ||
|
|
35d6def3aa | ||
|
|
2153d9ec9d | ||
|
|
b45be307a3 | ||
|
|
f75a21ef32 | ||
|
|
dae909fb3e | ||
|
|
99589731ac | ||
|
|
fd018754e2 | ||
|
|
a573ab1f81 | ||
|
|
c774c390b1 | ||
|
|
896f8b337e | ||
|
|
40ff845220 | ||
|
|
60be8487c1 | ||
|
|
5e5e07e106 | ||
|
|
9e4c6c75f5 | ||
|
|
5d1b0aecd0 | ||
|
|
f685fe1a99 | ||
|
|
9e62a2aad2 | ||
|
|
460806241c | ||
|
|
651cace5ee | ||
|
|
e941f698da | ||
|
|
cc5c9013d9 | ||
|
|
c17ee39d12 | ||
|
|
eeb30821ea | ||
|
|
38c206f97b | ||
|
|
346c5297b0 | ||
|
|
e66633c39e | ||
|
|
2f69842afa | ||
|
|
c5d179891f | ||
|
|
4d7d1736bd | ||
|
|
a5b5bdbbb4 | ||
|
|
9e3bfd5864 | ||
|
|
bab77d4991 | ||
|
|
4e1ff10d60 | ||
|
|
2936442f9d | ||
|
|
c5769cf53b | ||
|
|
b84d18ec21 | ||
|
|
2e92a84fa8 | ||
|
|
deb08a1012 | ||
|
|
4b21fdc96a | ||
|
|
1818ca9d75 | ||
|
|
9db0bd88f5 | ||
|
|
b98f05b4f4 | ||
|
|
ed2fcd9a2a | ||
|
|
1e67fdf3e4 | ||
|
|
2a60e5cac6 | ||
|
|
c319887dbb | ||
|
|
3fd08cc5e6 | ||
|
|
cd062fd3b3 | ||
|
|
55186eae32 | ||
|
|
76215b3268 | ||
|
|
f97f3e98fc | ||
|
|
7500c8cc72 | ||
|
|
c3eed8430c | ||
|
|
073d7841b4 | ||
|
|
8b0179c771 | ||
|
|
85d1517184 | ||
|
|
b59dced332 | ||
|
|
89ede3ae23 | ||
|
|
8facb73a8f | ||
|
|
c4fa814ecd | ||
|
|
e9279d57f7 | ||
|
|
01c531a72e | ||
|
|
a17e61c020 | ||
|
|
19b22712c0 | ||
|
|
e6629d4c10 | ||
|
|
0c598f34b6 | ||
|
|
e799da7e6a | ||
|
|
50552642ca | ||
|
|
474631498c | ||
|
|
08ccfd36e1 | ||
|
|
c3b3f8201a | ||
|
|
81a3a72727 | ||
|
|
70c594508f | ||
|
|
1fa9574e2b | ||
|
|
4a59dc5a41 | ||
|
|
c4b33d5334 | ||
|
|
197d61d01a | ||
|
|
abe8c11e36 | ||
|
|
08d09e7733 | ||
|
|
e23f622d38 | ||
|
|
73f7f515be | ||
|
|
501b0c387d | ||
|
|
cf1d012fda | ||
|
|
ad37aac45b | ||
|
|
f66010ad31 | ||
|
|
34fca93daf | ||
|
|
048db1da22 | ||
|
|
e768fc8468 | ||
|
|
31755449e1 | ||
|
|
fef9c5b432 | ||
|
|
519ac1252c | ||
|
|
89276c679e | ||
|
|
5a71ca6739 | ||
|
|
92c9bab6ab | ||
|
|
f04334ea04 | ||
|
|
ea799625bd | ||
|
|
3ef31215f4 | ||
|
|
4b03e857de | ||
|
|
c5e8051c81 | ||
|
|
6d324b4192 | ||
|
|
060330bf46 | ||
|
|
413155df6e | ||
|
|
48ce060e8c | ||
|
|
6106313b20 | ||
|
|
ae4f265053 | ||
|
|
4fc85b47fc | ||
|
|
3e890411bc | ||
|
|
1987d6e5df | ||
|
|
e4995d1517 | ||
|
|
6558158dc3 | ||
|
|
c985e2b84b | ||
|
|
6be088a3eb | ||
|
|
8c390f0987 | ||
|
|
d8ba21d07d | ||
|
|
b9d6c87592 | ||
|
|
03238022c8 | ||
|
|
1f8ea55c3d | ||
|
|
6fa49df0d9 | ||
|
|
32a5308237 | ||
|
|
76489af40f | ||
|
|
fad79467dd | ||
|
|
e651c1b2b9 | ||
|
|
b6f3c16ddc |
82
.mailmap
82
.mailmap
@@ -93,7 +93,8 @@ Sven Dowideit <SvenDowideit@home.org.au> <¨SvenDowideit@home.org.au¨>
|
||||
Sven Dowideit <SvenDowideit@home.org.au> <SvenDowideit@users.noreply.github.com>
|
||||
Sven Dowideit <SvenDowideit@home.org.au> <sven@t440s.home.gateway>
|
||||
<alexl@redhat.com> <alexander.larsson@gmail.com>
|
||||
Alexandr Morozov <lk4d4math@gmail.com>
|
||||
Alexander Morozov <lk4d4@docker.com> <lk4d4math@gmail.com>
|
||||
Alexander Morozov <lk4d4@docker.com>
|
||||
<git.nivoc@neverbox.com> <kuehnle@online.de>
|
||||
O.S. Tezer <ostezer@gmail.com>
|
||||
<ostezer@gmail.com> <ostezer@users.noreply.github.com>
|
||||
@@ -106,7 +107,9 @@ Roberto G. Hashioka <roberto.hashioka@docker.com> <roberto_hashioka@hotmail.com>
|
||||
Sridhar Ratnakumar <sridharr@activestate.com>
|
||||
Sridhar Ratnakumar <sridharr@activestate.com> <github@srid.name>
|
||||
Liang-Chi Hsieh <viirya@gmail.com>
|
||||
Aleksa Sarai <cyphar@cyphar.com>
|
||||
Aleksa Sarai <asarai@suse.de>
|
||||
Aleksa Sarai <asarai@suse.de> <asarai@suse.com>
|
||||
Aleksa Sarai <asarai@suse.de> <cyphar@cyphar.com>
|
||||
Will Weaver <monkey@buildingbananas.com>
|
||||
Timothy Hobbs <timothyhobbs@seznam.cz>
|
||||
Nathan LeClaire <nathan.leclaire@docker.com> <nathan.leclaire@gmail.com>
|
||||
@@ -117,24 +120,27 @@ Nathan LeClaire <nathan.leclaire@docker.com> <nathanleclaire@gmail.com>
|
||||
<marc@marc-abramowitz.com> <msabramo@gmail.com>
|
||||
Matthew Heon <mheon@redhat.com> <mheon@mheonlaptop.redhat.com>
|
||||
<bernat@luffy.cx> <vincent@bernat.im>
|
||||
<bernat@luffy.cx> <Vincent.Bernat@exoscale.ch>
|
||||
<p@pwaller.net> <peter@scraperwiki.com>
|
||||
<andrew.weiss@outlook.com> <andrew.weiss@microsoft.com>
|
||||
Francisco Carriedo <fcarriedo@gmail.com>
|
||||
<julienbordellier@gmail.com> <git@julienbordellier.com>
|
||||
<ahmetb@microsoft.com> <ahmetalpbalkan@gmail.com>
|
||||
<lk4d4@docker.com> <lk4d4math@gmail.com>
|
||||
<arnaud.porterie@docker.com> <icecrime@gmail.com>
|
||||
<baloo@gandi.net> <superbaloo+registrations.github@superbaloo.net>
|
||||
Brian Goff <cpuguy83@gmail.com>
|
||||
<cpuguy83@gmail.com> <bgoff@cpuguy83-mbp.home>
|
||||
<ewindisch@docker.com> <eric@windisch.us>
|
||||
<eric@windisch.us> <ewindisch@docker.com>
|
||||
<frank.rosquin+github@gmail.com> <frank.rosquin@gmail.com>
|
||||
Hollie Teal <hollie@docker.com>
|
||||
<hollie@docker.com> <hollie.teal@docker.com>
|
||||
<hollie@docker.com> <hollietealok@users.noreply.github.com>
|
||||
<huu@prismskylabs.com> <whoshuu@gmail.com>
|
||||
Jessica Frazelle <jess@docker.com> Jessie Frazelle <jfrazelle@users.noreply.github.com>
|
||||
<jess@docker.com> <jfrazelle@users.noreply.github.com>
|
||||
Jessica Frazelle <jess@mesosphere.com>
|
||||
Jessica Frazelle <jess@mesosphere.com> <jfrazelle@users.noreply.github.com>
|
||||
Jessica Frazelle <jess@mesosphere.com> <acidburn@docker.com>
|
||||
Jessica Frazelle <jess@mesosphere.com> <jess@docker.com>
|
||||
Jessica Frazelle <jess@mesosphere.com> <princess@docker.com>
|
||||
<konrad.wilhelm.kleine@gmail.com> <kwk@users.noreply.github.com>
|
||||
<tintypemolly@gmail.com> <tintypemolly@Ohui-MacBook-Pro.local>
|
||||
<estesp@linux.vnet.ibm.com> <estesp@gmail.com>
|
||||
@@ -142,6 +148,8 @@ Jessica Frazelle <jess@docker.com> Jessie Frazelle <jfrazelle@users.noreply.gith
|
||||
Thomas LEVEIL <thomasleveil@gmail.com> Thomas LÉVEIL <thomasleveil@users.noreply.github.com>
|
||||
<oi@truffles.me.uk> <timruffles@googlemail.com>
|
||||
<Vincent.Bernat@exoscale.ch> <bernat@luffy.cx>
|
||||
Antonio Murdaca <antonio.murdaca@gmail.com> <amurdaca@redhat.com>
|
||||
Antonio Murdaca <antonio.murdaca@gmail.com> <runcom@redhat.com>
|
||||
Antonio Murdaca <antonio.murdaca@gmail.com> <me@runcom.ninja>
|
||||
Antonio Murdaca <antonio.murdaca@gmail.com> <runcom@linux.com>
|
||||
Antonio Murdaca <antonio.murdaca@gmail.com> <runcom@users.noreply.github.com>
|
||||
@@ -151,8 +159,9 @@ Deshi Xiao <dxiao@redhat.com> <xiaods@gmail.com>
|
||||
Doug Davis <dug@us.ibm.com> <duglin@users.noreply.github.com>
|
||||
Jacob Atzen <jacob@jacobatzen.dk> <jatzen@gmail.com>
|
||||
Jeff Nickoloff <jeff.nickoloff@gmail.com> <jeff@allingeek.com>
|
||||
<jess@docker.com> <princess@docker.com>
|
||||
John Howard (VM) <John.Howard@microsoft.com> John Howard <jhoward@microsoft.com>
|
||||
John Howard (VM) <John.Howard@microsoft.com>
|
||||
John Howard (VM) <John.Howard@microsoft.com> <john.howard@microsoft.com>
|
||||
John Howard (VM) <John.Howard@microsoft.com> <jhoward@microsoft.com>
|
||||
Madhu Venugopal <madhu@socketplane.io> <madhu@docker.com>
|
||||
Mary Anthony <mary.anthony@docker.com> <mary@docker.com>
|
||||
Mary Anthony <mary.anthony@docker.com> moxiegirl <mary@docker.com>
|
||||
@@ -169,3 +178,60 @@ bin liu <liubin0329@users.noreply.github.com> <liubin0329@gmail.com>
|
||||
John Howard (VM) <John.Howard@microsoft.com> jhowardmsft <jhoward@microsoft.com>
|
||||
Ankush Agarwal <ankushagarwal11@gmail.com> <ankushagarwal@users.noreply.github.com>
|
||||
Tangi COLIN <tangicolin@gmail.com> tangicolin <tangicolin@gmail.com>
|
||||
Allen Sun <allen.sun@daocloud.io>
|
||||
Adrien Gallouët <adrien@gallouet.fr> <angt@users.noreply.github.com>
|
||||
<aanm90@gmail.com> <martins@noironetworks.com>
|
||||
Anuj Bahuguna <anujbahuguna.dev@gmail.com>
|
||||
Anusha Ragunathan <anusha.ragunathan@docker.com> <anusha@docker.com>
|
||||
Avi Miller <avi.miller@oracle.com> <avi.miller@gmail.com>
|
||||
Brent Salisbury <brent.salisbury@docker.com> <brent@docker.com>
|
||||
Chander G <chandergovind@gmail.com>
|
||||
Chun Chen <ramichen@tencent.com> <chenchun.feed@gmail.com>
|
||||
Ying Li <cyli@twistedmatrix.com>
|
||||
Daehyeok Mun <daehyeok@gmail.com> <daehyeok@daehyeok-ui-MacBook-Air.local>
|
||||
<dqminh@cloudflare.com> <dqminh89@gmail.com>
|
||||
Daniel, Dao Quang Minh <dqminh@cloudflare.com>
|
||||
Daniel Nephin <dnephin@docker.com> <dnephin@gmail.com>
|
||||
Dave Tucker <dt@docker.com> <dave@dtucker.co.uk>
|
||||
Doug Tangren <d.tangren@gmail.com>
|
||||
Frederick F. Kautz IV <fkautz@redhat.com> <fkautz@alumni.cmu.edu>
|
||||
Ben Golub <ben.golub@dotcloud.com>
|
||||
Harold Cooper <hrldcpr@gmail.com>
|
||||
hsinko <21551195@zju.edu.cn> <hsinko@users.noreply.github.com>
|
||||
Josh Hawn <josh.hawn@docker.com> <jlhawn@berkeley.edu>
|
||||
Justin Cormack <justin.cormack@docker.com>
|
||||
<justin.cormack@docker.com> <justin.cormack@unikernel.com>
|
||||
<justin.cormack@docker.com> <justin@specialbusservice.com>
|
||||
Kamil Domański <kamil@domanski.co>
|
||||
Lei Jitang <leijitang@huawei.com>
|
||||
<leijitang@huawei.com> <leijitang@gmail.com>
|
||||
Linus Heckemann <lheckemann@twig-world.com>
|
||||
<lheckemann@twig-world.com> <anonymouse2048@gmail.com>
|
||||
Lynda O'Leary <lyndaoleary29@gmail.com>
|
||||
<lyndaoleary29@gmail.com> <lyndaoleary@hotmail.com>
|
||||
Marianna Tessel <mtesselh@gmail.com>
|
||||
Michael Huettermann <michael@huettermann.net>
|
||||
Moysés Borges <moysesb@gmail.com>
|
||||
<moysesb@gmail.com> <moyses.furtado@wplex.com.br>
|
||||
Nigel Poulton <nigelpoulton@hotmail.com>
|
||||
Qiang Huang <h.huangqiang@huawei.com>
|
||||
<h.huangqiang@huawei.com> <qhuang@10.0.2.15>
|
||||
Boaz Shuster <ripcurld.github@gmail.com>
|
||||
Shuwei Hao <haosw@cn.ibm.com>
|
||||
<haosw@cn.ibm.com> <haoshuwei24@gmail.com>
|
||||
Soshi Katsuta <soshi.katsuta@gmail.com>
|
||||
<soshi.katsuta@gmail.com> <katsuta_soshi@cyberagent.co.jp>
|
||||
Stefan Berger <stefanb@linux.vnet.ibm.com>
|
||||
<stefanb@linux.vnet.ibm.com> <stefanb@us.ibm.com>
|
||||
Stephen Day <stephen.day@docker.com>
|
||||
<stephen.day@docker.com> <stevvooe@users.noreply.github.com>
|
||||
Toli Kuznets <toli@docker.com>
|
||||
Tristan Carel <tristan@cogniteev.com>
|
||||
<tristan@cogniteev.com> <tristan.carel@gmail.com>
|
||||
Vincent Demeester <vincent@sbr.pm>
|
||||
<vincent@sbr.pm> <vincent+github@demeester.fr>
|
||||
Vishnu Kannan <vishnuk@google.com>
|
||||
xlgao-zju <xlgao@zju.edu.cn> xlgao <xlgao@zju.edu.cn>
|
||||
yuchangchun <yuchangchun1@huawei.com> y00277921 <yuchangchun1@huawei.com>
|
||||
<zij@case.edu> <zjaffee@us.ibm.com>
|
||||
|
||||
|
||||
234
CHANGELOG.md
234
CHANGELOG.md
@@ -2,9 +2,219 @@
|
||||
|
||||
Items starting with `DEPRECATE` are important deprecation notices. For more
|
||||
information on the list of deprecated flags and APIs please have a look at
|
||||
https://docs.docker.com/misc/deprecated/ where target removal dates can also
|
||||
https://docs.docker.com/engine/deprecated/ where target removal dates can also
|
||||
be found.
|
||||
|
||||
## 1.11.2 (2016-05-31)
|
||||
|
||||
### Networking
|
||||
|
||||
- Fix a stale endpoint issue on overlay networks during ungraceful restart ([#23015](https://github.com/docker/docker/pull/23015))
|
||||
- Fix an issue where the wrong port could be reported by `docker inspect/ps/port` ([#22997](https://github.com/docker/docker/pull/22997))
|
||||
|
||||
### Runtime
|
||||
|
||||
- Fix a potential panic when running `docker build` ([#23032](https://github.com/docker/docker/pull/23032))
|
||||
- Fix interpretation of `--user` parameter ([#22998](https://github.com/docker/docker/pull/22998))
|
||||
- Fix a bug preventing container statistics to be correctly reported ([#22955](https://github.com/docker/docker/pull/22955))
|
||||
- Fix an issue preventing container to be restarted after daemon restart ([#22947](https://github.com/docker/docker/pull/22947))
|
||||
- Fix issues when running 32 bit binaries on Ubuntu 16.04 ([#22922](https://github.com/docker/docker/pull/22922))
|
||||
- Fix a possible deadlock on image deletion and container attach ([#22918](https://github.com/docker/docker/pull/22918))
|
||||
- Fix an issue where containers fail to start after a daemon restart if they depend on a containerized cluster store ([#22561](https://github.com/docker/docker/pull/22561))
|
||||
- Fix an issue causing `docker ps` to hang on CentOS when using devicemapper ([#22168](https://github.com/docker/docker/pull/22168), [#23067](https://github.com/docker/docker/pull/23067))
|
||||
- Fix a bug preventing to `docker exec` into a container when using devicemapper ([#22168](https://github.com/docker/docker/pull/22168), [#23067](https://github.com/docker/docker/pull/23067))
|
||||
|
||||
|
||||
## 1.11.1 (2016-04-26)
|
||||
|
||||
### Distribution
|
||||
|
||||
- Fix schema2 manifest media type to be of type `application/vnd.docker.container.image.v1+json` ([#21949](https://github.com/docker/docker/pull/21949))
|
||||
|
||||
### Documentation
|
||||
|
||||
+ Add missing API documentation for changes introduced with 1.11.0 ([#22048](https://github.com/docker/docker/pull/22048))
|
||||
|
||||
### Builder
|
||||
|
||||
* Append label passed to `docker build` as arguments as an implicit `LABEL` command at the end of the processed `Dockerfile` ([#22184](https://github.com/docker/docker/pull/22184))
|
||||
|
||||
### Networking
|
||||
|
||||
- Fix a panic that would occur when forwarding DNS query ([#22261](https://github.com/docker/docker/pull/22261))
|
||||
- Fix an issue where OS threads could end up within an incorrect network namespace when using user defined networks ([#22261](https://github.com/docker/docker/pull/22261))
|
||||
|
||||
### Runtime
|
||||
|
||||
- Fix a bug preventing labels configuration to be reloaded via the config file ([#22299](https://github.com/docker/docker/pull/22299))
|
||||
- Fix a regression where container mounting `/var/run` would prevent other containers from being removed ([#22256](https://github.com/docker/docker/pull/22256))
|
||||
- Fix an issue where it would be impossible to update both `memory-swap` and `memory` value together ([#22255](https://github.com/docker/docker/pull/22255))
|
||||
- Fix a regression from 1.11.0 where the `/auth` endpoint would not initialize `serveraddress` if it is not provided ([#22254](https://github.com/docker/docker/pull/22254))
|
||||
- Add missing cleanup of container temporary files when cancelling a schedule restart ([#22237](https://github.com/docker/docker/pull/22237))
|
||||
- Removed scary error message when no restart policy is specified ([#21993](https://github.com/docker/docker/pull/21993))
|
||||
- Fix a panic that would occur when the plugins were activated via the json spec ([#22191](https://github.com/docker/docker/pull/22191))
|
||||
- Fix restart backoff logic to correctly reset delay if container ran for at least 10secs ([#22125](https://github.com/docker/docker/pull/22125))
|
||||
- Remove error message when a container restart get cancelled ([#22123](https://github.com/docker/docker/pull/22123))
|
||||
- Fix an issue where `docker` would not correcly clean up after `docker exec` ([#22121](https://github.com/docker/docker/pull/22121))
|
||||
- Fix a panic that could occur when servicing concurrent `docker stats` commands ([#22120](https://github.com/docker/docker/pull/22120))`
|
||||
- Revert deprecation of non-existing host directories auto-creation ([#22065](https://github.com/docker/docker/pull/22065))
|
||||
- Hide misleading rpc error on daemon shutdown ([#22058](https://github.com/docker/docker/pull/22058))
|
||||
|
||||
## 1.11.0 (2016-04-13)
|
||||
|
||||
**IMPORTANT**: With Docker 1.11, a Linux docker installation is now made of 4 binaries (`docker`, [`docker-containerd`](https://github.com/docker/containerd), [`docker-containerd-shim`](https://github.com/docker/containerd) and [`docker-runc`](https://github.com/opencontainers/runc)). If you have scripts relying on docker being a single static binaries, please make sure to update them. Interaction with the daemon stay the same otherwise, the usage of the other binaries should be transparent. A Windows docker installation remains a single binary, `docker.exe`.
|
||||
|
||||
### Builder
|
||||
|
||||
- Fix a bug where Docker would not used the correct uid/gid when processing the `WORKDIR` command ([#21033](https://github.com/docker/docker/pull/21033))
|
||||
- Fix a bug where copy operations with userns would not use the proper uid/gid ([#20782](https://github.com/docker/docker/pull/20782), [#21162](https://github.com/docker/docker/pull/21162))
|
||||
|
||||
### Client
|
||||
|
||||
* Usage of the `:` separator for security option has been deprecated. `=` should be used instead ([#21232](https://github.com/docker/docker/pull/21232))
|
||||
+ The client user agent is now passed to the registry on `pull`, `build`, `push`, `login` and `search` operations ([#21306](https://github.com/docker/docker/pull/21306), [#21373](https://github.com/docker/docker/pull/21373))
|
||||
* Allow setting the Domainname and Hostname separately through the API ([#20200](https://github.com/docker/docker/pull/20200))
|
||||
* Docker info will now warn users if it can not detect the kernel version or the operating system ([#21128](https://github.com/docker/docker/pull/21128))
|
||||
- Fix an issue where `docker stats --no-stream` output could be all 0s ([#20803](https://github.com/docker/docker/pull/20803))
|
||||
- Fix a bug where some newly started container would not appear in a running `docker stats` command ([#20792](https://github.com/docker/docker/pull/20792))
|
||||
* Post processing is no longer enabled for linux-cgo terminals ([#20587](https://github.com/docker/docker/pull/20587))
|
||||
- Values to `--hostname` are now refused if they do not comply with [RFC1123](https://tools.ietf.org/html/rfc1123) ([#20566](https://github.com/docker/docker/pull/20566))
|
||||
+ Docker learned how to use a SOCKS proxy ([#20366](https://github.com/docker/docker/pull/20366), [#18373](https://github.com/docker/docker/pull/18373))
|
||||
+ Docker now supports external credential stores ([#20107](https://github.com/docker/docker/pull/20107))
|
||||
* `docker ps` now supports displaying the list of volumes mounted inside a container ([#20017](https://github.com/docker/docker/pull/20017))
|
||||
* `docker info` now also report Docker's root directory location ([#19986](https://github.com/docker/docker/pull/19986))
|
||||
- Docker now prohibits login in with an empty username (spaces are trimmed) ([#19806](https://github.com/docker/docker/pull/19806))
|
||||
* Docker events attributes are now sorted by key ([#19761](https://github.com/docker/docker/pull/19761))
|
||||
* `docker ps` no longer show exported port for stopped containers ([#19483](https://github.com/docker/docker/pull/19483))
|
||||
- Docker now cleans after itself if a save/export command fails ([#17849](https://github.com/docker/docker/pull/17849))
|
||||
* Docker load learned how to display a progress bar ([#17329](https://github.com/docker/docker/pull/17329), [#120078](https://github.com/docker/docker/pull/20078))
|
||||
|
||||
### Distribution
|
||||
|
||||
- Fix a panic that occurred when pulling an images with 0 layers ([#21222](https://github.com/docker/docker/pull/21222))
|
||||
- Fix a panic that could occur on error while pushing to a registry with a misconfigured token service ([#21212](https://github.com/docker/docker/pull/21212))
|
||||
+ All first-level delegation roles are now signed when doing a trusted push ([#21046](https://github.com/docker/docker/pull/21046))
|
||||
+ OAuth support for registries was added ([#20970](https://github.com/docker/docker/pull/20970))
|
||||
* `docker login` now handles token using the implementation found in [docker/distribution](https://github.com/docker/distribution) ([#20832](https://github.com/docker/docker/pull/20832))
|
||||
* `docker login` will no longer prompt for an email ([#20565](https://github.com/docker/docker/pull/20565))
|
||||
* Docker will now fallback to registry V1 if no basic auth credentials are available ([#20241](https://github.com/docker/docker/pull/20241))
|
||||
* Docker will now try to resume layer download where it left off after a network error/timeout ([#19840](https://github.com/docker/docker/pull/19840))
|
||||
- Fix generated manifest mediaType when pushing cross-repository ([#19509](https://github.com/docker/docker/pull/19509))
|
||||
- Fix docker requesting additional push credentials when pulling an image if Content Trust is enabled ([#20382](https://github.com/docker/docker/pull/20382))
|
||||
|
||||
### Logging
|
||||
|
||||
- Fix a race in the journald log driver ([#21311](https://github.com/docker/docker/pull/21311))
|
||||
* Docker syslog driver now uses the RFC-5424 format when emitting logs ([#20121](https://github.com/docker/docker/pull/20121))
|
||||
* Docker GELF log driver now allows to specify the compression algorithm and level via the `gelf-compression-type` and `gelf-compression-level` options ([#19831](https://github.com/docker/docker/pull/19831))
|
||||
* Docker daemon learned to output uncolorized logs via the `--raw-logs` options ([#19794](https://github.com/docker/docker/pull/19794))
|
||||
+ Docker, on Windows platform, now includes an ETW (Event Tracing in Windows) logging driver named `etwlogs` ([#19689](https://github.com/docker/docker/pull/19689))
|
||||
* Journald log driver learned how to handle tags ([#19564](https://github.com/docker/docker/pull/19564))
|
||||
+ The fluentd log driver learned the following options: `fluentd-address`, `fluentd-buffer-limit`, `fluentd-retry-wait`, `fluentd-max-retries` and `fluentd-async-connect` ([#19439](https://github.com/docker/docker/pull/19439))
|
||||
+ Docker learned to send log to Google Cloud via the new `gcplogs` logging driver. ([#18766](https://github.com/docker/docker/pull/18766))
|
||||
|
||||
|
||||
### Misc
|
||||
|
||||
+ When saving linked images together with `docker save` a subsequent `docker load` will correctly restore their parent/child relationship ([#21385](https://github.com/docker/docker/pull/c))
|
||||
+ Support for building the Docker cli for OpenBSD was added ([#21325](https://github.com/docker/docker/pull/21325))
|
||||
+ Labels can now be applied at network, volume and image creation ([#21270](https://github.com/docker/docker/pull/21270))
|
||||
* The `dockremap` is now created as a system user ([#21266](https://github.com/docker/docker/pull/21266))
|
||||
- Fix a few response body leaks ([#21258](https://github.com/docker/docker/pull/21258))
|
||||
- Docker, when run as a service with systemd, will now properly manage its processes cgroups ([#20633](https://github.com/docker/docker/pull/20633))
|
||||
* Docker info now reports the value of cgroup KernelMemory or emits a warning if it is not supported ([#20863](https://github.com/docker/docker/pull/20863))
|
||||
* Docker info now also reports the cgroup driver in use ([#20388](https://github.com/docker/docker/pull/20388))
|
||||
* Docker completion is now available on PowerShell ([#19894](https://github.com/docker/docker/pull/19894))
|
||||
* `dockerinit` is no more ([#19490](https://github.com/docker/docker/pull/19490),[#19851](https://github.com/docker/docker/pull/19851))
|
||||
+ Support for building Docker on arm64 was added ([#19013](https://github.com/docker/docker/pull/19013))
|
||||
+ Experimental support for building docker.exe in a native Windows Docker installation ([#18348](https://github.com/docker/docker/pull/18348))
|
||||
|
||||
### Networking
|
||||
|
||||
- Fix panic if a node is forcibly removed from the cluster ([#21671](https://github.com/docker/docker/pull/21671))
|
||||
- Fix "error creating vxlan interface" when starting a container in a Swarm cluster ([#21671](https://github.com/docker/docker/pull/21671))
|
||||
* `docker network inspect` will now report all endpoints whether they have an active container or not ([#21160](https://github.com/docker/docker/pull/21160))
|
||||
+ Experimental support for the MacVlan and IPVlan network drivers have been added ([#21122](https://github.com/docker/docker/pull/21122))
|
||||
* Output of `docker network ls` is now sorted by network name ([#20383](https://github.com/docker/docker/pull/20383))
|
||||
- Fix a bug where Docker would allow a network to be created with the reserved `default` name ([#19431](https://github.com/docker/docker/pull/19431))
|
||||
* `docker network inspect` returns whether a network is internal or not ([#19357](https://github.com/docker/docker/pull/19357))
|
||||
+ Control IPv6 via explicit option when creating a network (`docker network create --ipv6`). This shows up as a new `EnableIPv6` field in `docker network inspect` ([#17513](https://github.com/docker/docker/pull/17513))
|
||||
* Support for AAAA Records (aka IPv6 Service Discovery) in embedded DNS Server ([#21396](https://github.com/docker/docker/pull/21396))
|
||||
- Fix to not forward docker domain IPv6 queries to external servers ([#21396](https://github.com/docker/docker/pull/21396))
|
||||
* Multiple A/AAAA records from embedded DNS Server for DNS Round robin ([#21019](https://github.com/docker/docker/pull/21019))
|
||||
- Fix endpoint count inconsistency after an ungraceful dameon restart ([#21261](https://github.com/docker/docker/pull/21261))
|
||||
- Move the ownership of exposed ports and port-mapping options from Endpoint to Sandbox ([#21019](https://github.com/docker/docker/pull/21019))
|
||||
- Fixed a bug which prevents docker reload when host is configured with ipv6.disable=1 ([#21019](https://github.com/docker/docker/pull/21019))
|
||||
- Added inbuilt nil IPAM driver ([#21019](https://github.com/docker/docker/pull/21019))
|
||||
- Fixed bug in iptables.Exists() logic [#21019](https://github.com/docker/docker/pull/21019)
|
||||
- Fixed a Veth interface leak when using overlay network ([#21019](https://github.com/docker/docker/pull/21019))
|
||||
- Fixed a bug which prevents docker reload after a network delete during shutdown ([#20214](https://github.com/docker/docker/pull/20214))
|
||||
- Make sure iptables chains are recreated on firewalld reload ([#20419](https://github.com/docker/docker/pull/20419))
|
||||
- Allow to pass global datastore during config reload ([#20419](https://github.com/docker/docker/pull/20419))
|
||||
- For anonymous containers use the alias name for IP to name mapping, ie:DNS PTR record ([#21019](https://github.com/docker/docker/pull/21019))
|
||||
- Fix a panic when deleting an entry from /etc/hosts file ([#21019](https://github.com/docker/docker/pull/21019))
|
||||
- Source the forwarded DNS queries from the container net namespace ([#21019](https://github.com/docker/docker/pull/21019))
|
||||
- Fix to retain the network internal mode config for bridge networks on daemon reload ([#21780] (https://github.com/docker/docker/pull/21780))
|
||||
- Fix to retain IPAM driver option configs on daemon reload ([#21914] (https://github.com/docker/docker/pull/21914))
|
||||
|
||||
### Plugins
|
||||
|
||||
- Fix a file descriptor leak that would occur every time plugins were enumerated ([#20686](https://github.com/docker/docker/pull/20686))
|
||||
- Fix an issue where Authz plugin would corrupt the payload body when faced with a large amount of data ([#20602](https://github.com/docker/docker/pull/20602))
|
||||
|
||||
### Runtime
|
||||
|
||||
- Fix a panic that could occur when cleanup after a container started with invalid parameters ([#21716](https://github.com/docker/docker/pull/21716))
|
||||
- Fix a race with event timers stopping early ([#21692](https://github.com/docker/docker/pull/21692))
|
||||
- Fix race conditions in the layer store, potentially corrupting the map and crashing the process ([#21677](https://github.com/docker/docker/pull/21677))
|
||||
- Un-deprecate auto-creation of host directories for mounts. This feature was marked deprecated in ([#21666](https://github.com/docker/docker/pull/21666))
|
||||
Docker 1.9, but was decided to be too much of an backward-incompatible change, so it was decided to keep the feature.
|
||||
+ It is now possible for containers to share the NET and IPC namespaces when `userns` is enabled ([#21383](https://github.com/docker/docker/pull/21383))
|
||||
+ `docker inspect <image-id>` will now expose the rootfs layers ([#21370](https://github.com/docker/docker/pull/21370))
|
||||
+ Docker Windows gained a minimal `top` implementation ([#21354](https://github.com/docker/docker/pull/21354))
|
||||
* Docker learned to report the faulty exe when a container cannot be started due to its condition ([#21345](https://github.com/docker/docker/pull/21345))
|
||||
* Docker with device mapper will now refuse to run if `udev sync` is not available ([#21097](https://github.com/docker/docker/pull/21097))
|
||||
- Fix a bug where Docker would not validate the config file upon configuration reload ([#21089](https://github.com/docker/docker/pull/21089))
|
||||
- Fix a hang that would happen on attach if initial start was to fail ([#21048](https://github.com/docker/docker/pull/21048))
|
||||
- Fix an issue where registry service options in the daemon configuration file were not properly taken into account ([#21045](https://github.com/docker/docker/pull/21045))
|
||||
- Fix a race between the exec and resize operations ([#21022](https://github.com/docker/docker/pull/21022))
|
||||
- Fix an issue where nanoseconds were not correctly taken in account when filtering Docker events ([#21013](https://github.com/docker/docker/pull/21013))
|
||||
- Fix the handling of Docker command when passed a 64 bytes id ([#21002](https://github.com/docker/docker/pull/21002))
|
||||
* Docker will now return a `204` (i.e http.StatusNoContent) code when it successfully deleted a network ([#20977](https://github.com/docker/docker/pull/20977))
|
||||
- Fix a bug where the daemon would wait indefinitely in case the process it was about to killed had already exited on its own ([#20967](https://github.com/docker/docker/pull/20967)
|
||||
* The devmapper driver learned the `dm.min_free_space` option. If the mapped device free space reaches the passed value, new device creation will be prohibited. ([#20786](https://github.com/docker/docker/pull/20786))
|
||||
+ Docker can now prevent processes in container to gain new privileges via the `--security-opt=no-new-privileges` flag ([#20727](https://github.com/docker/docker/pull/20727))
|
||||
- Starting a container with the `--device` option will now correctly resolves symlinks ([#20684](https://github.com/docker/docker/pull/20684))
|
||||
+ Docker now relies on [`containerd`](https://github.com/docker/containerd) and [`runc`](https://github.com/opencontainers/runc) to spawn containers. ([#20662](https://github.com/docker/docker/pull/20662))
|
||||
- Fix docker configuration reloading to only alter value present in the given config file ([#20604](https://github.com/docker/docker/pull/20604))
|
||||
+ Docker now allows setting a container hostname via the `--hostname` flag when `--net=host` ([#20177](https://github.com/docker/docker/pull/20177))
|
||||
+ Docker now allows executing privileged container while running with `--userns-remap` if both `--privileged` and the new `--userns=host` flag are specified ([#20111](https://github.com/docker/docker/pull/20111))
|
||||
- Fix Docker not cleaning up correctly old containers upon restarting after a crash ([#19679](https://github.com/docker/docker/pull/19679))
|
||||
* Docker will now error out if it doesn't recognize a configuration key within the config file ([#19517](https://github.com/docker/docker/pull/19517))
|
||||
- Fix container loading, on daemon startup, when they depends on a plugin running within a container ([#19500](https://github.com/docker/docker/pull/19500))
|
||||
* `docker update` learned how to change a container restart policy ([#19116](https://github.com/docker/docker/pull/19116))
|
||||
* `docker inspect` now also returns a new `State` field containing the container state in a human readable way (i.e. one of `created`, `restarting`, `running`, `paused`, `exited` or `dead`)([#18966](https://github.com/docker/docker/pull/18966))
|
||||
+ Docker learned to limit the number of active pids (i.e. processes) within the container via the `pids-limit` flags. NOTE: This requires `CGROUP_PIDS=y` to be in the kernel configuration. ([#18697](https://github.com/docker/docker/pull/18697))
|
||||
- `docker load` now has a `--quiet` option to suppress the load output ([#20078](https://github.com/docker/docker/pull/20078))
|
||||
- Fix a bug in neighbor discovery for IPv6 peers ([#20842](https://github.com/docker/docker/pull/20842))
|
||||
- Fix a panic during cleanup if a container was started with invalid options ([#21802](https://github.com/docker/docker/pull/21802))
|
||||
- Fix a situation where a container cannot be stopped if the terminal is closed ([#21840](https://github.com/docker/docker/pull/21840))
|
||||
|
||||
### Security
|
||||
|
||||
* Object with the `pcp_pmcd_t` selinux type were given management access to `/var/lib/docker(/.*)?` ([#21370](https://github.com/docker/docker/pull/21370))
|
||||
* `restart_syscall`, `copy_file_range`, `mlock2` joined the list of allowed calls in the default seccomp profile ([#21117](https://github.com/docker/docker/pull/21117), [#21262](https://github.com/docker/docker/pull/21262))
|
||||
* `send`, `recv` and `x32` were added to the list of allowed syscalls and arch in the default seccomp profile ([#19432](https://github.com/docker/docker/pull/19432))
|
||||
* Docker Content Trust now requests the server to perform snapshot signing ([#21046](https://github.com/docker/docker/pull/21046))
|
||||
* Support for using YubiKeys for Content Trust signing has been moved out of experimental ([#21591](https://github.com/docker/docker/pull/21591))
|
||||
|
||||
### Volumes
|
||||
|
||||
* Output of `docker volume ls` is now sorted by volume name ([#20389](https://github.com/docker/docker/pull/20389))
|
||||
* Local volumes can now accepts options similar to the unix `mount` tool ([#20262](https://github.com/docker/docker/pull/20262))
|
||||
- Fix an issue where one letter directory name could not be used as source for volumes ([#21106](https://github.com/docker/docker/pull/21106))
|
||||
+ `docker run -v` now accepts a new flag `nocopy`. This tell the runtime not to copy the container path content into the volume (which is the default behavior) ([#21223](https://github.com/docker/docker/pull/21223))
|
||||
|
||||
## 1.10.3 (2016-03-10)
|
||||
|
||||
### Runtime
|
||||
@@ -25,9 +235,9 @@ be found.
|
||||
|
||||
### Security
|
||||
|
||||
- Fix linux32 emulation to fail during docker build [#20672](https://github.com/docker/docker/pull/20672)
|
||||
- Fix linux32 emulation to fail during docker build [#20672](https://github.com/docker/docker/pull/20672)
|
||||
It was due to the `personality` syscall being blocked by the default seccomp profile.
|
||||
- Fix Oracle XE 10g failing to start in a container [#20981](https://github.com/docker/docker/pull/20981)
|
||||
- Fix Oracle XE 10g failing to start in a container [#20981](https://github.com/docker/docker/pull/20981)
|
||||
It was due to the `ipc` syscall being blocked by the default seccomp profile.
|
||||
- Fix user namespaces not working on Linux From Scratch [#20685](https://github.com/docker/docker/pull/20685)
|
||||
- Fix issue preventing daemon to start if userns is enabled and the `subuid` or `subgid` files contain comments [#20725](https://github.com/docker/docker/pull/20725)
|
||||
@@ -113,7 +323,7 @@ Engine 1.10 migrator can be found on Docker Hub: https://hub.docker.com/r/docker
|
||||
+ Add `--tmpfs` flag to `docker run` to create a tmpfs mount in a container [#13587](https://github.com/docker/docker/pull/13587)
|
||||
+ Add `--format` flag to `docker images` command [#17692](https://github.com/docker/docker/pull/17692)
|
||||
+ Allow to set daemon configuration in a file and hot-reload it with the `SIGHUP` signal [#18587](https://github.com/docker/docker/pull/18587)
|
||||
+ Updated docker events to include more meta-data and event types [#18888](https://github.com/docker/docker/pull/18888)
|
||||
+ Updated docker events to include more meta-data and event types [#18888](https://github.com/docker/docker/pull/18888)
|
||||
This change is backward compatible in the API, but not on the CLI.
|
||||
+ Add `--blkio-weight-device` flag to `docker run` [#13959](https://github.com/docker/docker/pull/13959)
|
||||
+ Add `--device-read-bps` and `--device-write-bps` flags to `docker run` [#14466](https://github.com/docker/docker/pull/14466)
|
||||
@@ -148,18 +358,18 @@ Engine 1.10 migrator can be found on Docker Hub: https://hub.docker.com/r/docker
|
||||
+ Add support for custom seccomp profiles in `--security-opt` [#17989](https://github.com/docker/docker/pull/17989)
|
||||
+ Add default seccomp profile [#18780](https://github.com/docker/docker/pull/18780)
|
||||
+ Add `--authorization-plugin` flag to `daemon` to customize ACLs [#15365](https://github.com/docker/docker/pull/15365)
|
||||
+ Docker Content Trust now supports the ability to read and write user delegations [#18887](https://github.com/docker/docker/pull/18887)
|
||||
This is an optional, opt-in feature that requires the explicit use of the Notary command-line utility in order to be enabled.
|
||||
+ Docker Content Trust now supports the ability to read and write user delegations [#18887](https://github.com/docker/docker/pull/18887)
|
||||
This is an optional, opt-in feature that requires the explicit use of the Notary command-line utility in order to be enabled.
|
||||
Enabling delegation support in a specific repository will break the ability of Docker 1.9 and 1.8 to pull from that repository, if content trust is enabled.
|
||||
* Allow SELinux to run in a container when using the BTRFS storage driver [#16452](https://github.com/docker/docker/pull/16452)
|
||||
|
||||
### Distribution
|
||||
|
||||
* Use content-addressable storage for images and layers [#17924](https://github.com/docker/docker/pull/17924)
|
||||
Note that a migration is performed the first time docker is run; it can take a significant amount of time depending on the number of images and containers present.
|
||||
Images no longer depend on the parent chain but contain a list of layer references.
|
||||
* Use content-addressable storage for images and layers [#17924](https://github.com/docker/docker/pull/17924)
|
||||
Note that a migration is performed the first time docker is run; it can take a significant amount of time depending on the number of images and containers present.
|
||||
Images no longer depend on the parent chain but contain a list of layer references.
|
||||
`docker load`/`docker save` tarballs now also contain content-addressable image configurations.
|
||||
For more information: https://github.com/docker/docker/wiki/Engine-v1.10.0-content-addressability-migration
|
||||
For more information: https://github.com/docker/docker/wiki/Engine-v1.10.0-content-addressability-migration
|
||||
* Add support for the new [manifest format ("schema2")](https://github.com/docker/distribution/blob/master/docs/spec/manifest-v2-2.md) [#18785](https://github.com/docker/docker/pull/18785)
|
||||
* Lots of improvements for push and pull: performance++, retries on failed downloads, cancelling on client disconnect [#18353](https://github.com/docker/docker/pull/18353), [#18418](https://github.com/docker/docker/pull/18418), [#19109](https://github.com/docker/docker/pull/19109), [#18353](https://github.com/docker/docker/pull/18353)
|
||||
* Limit v1 protocol fallbacks [#18590](https://github.com/docker/docker/pull/18590)
|
||||
@@ -201,8 +411,8 @@ Engine 1.10 migrator can be found on Docker Hub: https://hub.docker.com/r/docker
|
||||
### Volumes
|
||||
|
||||
+ Add support to set the mount propagation mode for a volume [#17034](https://github.com/docker/docker/pull/17034)
|
||||
* Add `ls` and `inspect` endpoints to volume plugin API [#16534](https://github.com/docker/docker/pull/16534)
|
||||
Existing plugins need to make use of these new APIs to satisfy users' expectation
|
||||
* Add `ls` and `inspect` endpoints to volume plugin API [#16534](https://github.com/docker/docker/pull/16534)
|
||||
Existing plugins need to make use of these new APIs to satisfy users' expectation
|
||||
For that, please use the new MIME type `application/vnd.docker.plugins.v1.2+json` [#19549](https://github.com/docker/docker/pull/19549)
|
||||
- Fix data not being copied to named volumes [#19175](https://github.com/docker/docker/pull/19175)
|
||||
- Fix issues preventing volume drivers from being containerized [#19500](https://github.com/docker/docker/pull/19500)
|
||||
|
||||
38
Dockerfile
38
Dockerfile
@@ -30,20 +30,22 @@ RUN apt-key adv --keyserver hkp://p80.pool.sks-keyservers.net:80 --recv-keys E87
|
||||
|| apt-key adv --keyserver hkp://pgp.mit.edu:80 --recv-keys E871F18B51E0147C77796AC81196BA81F6B0FC61
|
||||
RUN echo deb http://ppa.launchpad.net/zfs-native/stable/ubuntu trusty main > /etc/apt/sources.list.d/zfs.list
|
||||
|
||||
# add llvm repo
|
||||
RUN apt-key adv --keyserver hkp://p80.pool.sks-keyservers.net:80 --recv-keys 6084F3CF814B57C1CF12EFD515CF4D18AF4F7421 \
|
||||
|| apt-key adv --keyserver hkp://pgp.mit.edu:80 --recv-keys 6084F3CF814B57C1CF12EFD515CF4D18AF4F7421
|
||||
RUN echo deb http://llvm.org/apt/trusty/ llvm-toolchain-trusty main > /etc/apt/sources.list.d/llvm.list
|
||||
|
||||
# allow replacing httpredir mirror
|
||||
ARG APT_MIRROR=httpredir.debian.org
|
||||
RUN sed -i s/httpredir.debian.org/$APT_MIRROR/g /etc/apt/sources.list
|
||||
|
||||
# Packaged dependencies
|
||||
RUN apt-get update && apt-get install -y \
|
||||
apparmor \
|
||||
apt-utils \
|
||||
aufs-tools \
|
||||
automake \
|
||||
bash-completion \
|
||||
bsdmainutils \
|
||||
btrfs-tools \
|
||||
build-essential \
|
||||
clang-3.8 \
|
||||
clang \
|
||||
createrepo \
|
||||
curl \
|
||||
dpkg-sig \
|
||||
@@ -64,15 +66,13 @@ RUN apt-get update && apt-get install -y \
|
||||
python-mock \
|
||||
python-pip \
|
||||
python-websocket \
|
||||
s3cmd=1.5.0* \
|
||||
ubuntu-zfs \
|
||||
xfsprogs \
|
||||
libzfs-dev \
|
||||
tar \
|
||||
zip \
|
||||
--no-install-recommends \
|
||||
&& ln -snf /usr/bin/clang-3.8 /usr/local/bin/clang \
|
||||
&& ln -snf /usr/bin/clang++-3.8 /usr/local/bin/clang++
|
||||
|
||||
&& pip install awscli==1.10.15
|
||||
# Get lvm2 source for compiling statically
|
||||
ENV LVM2_VERSION 2.02.103
|
||||
RUN mkdir -p /usr/local/lvm2 \
|
||||
@@ -96,7 +96,7 @@ RUN set -x \
|
||||
&& export OSXCROSS_PATH="/osxcross" \
|
||||
&& git clone https://github.com/tpoechtrager/osxcross.git $OSXCROSS_PATH \
|
||||
&& ( cd $OSXCROSS_PATH && git checkout -q $OSX_CROSS_COMMIT) \
|
||||
&& curl -sSL https://s3.dockerproject.org/darwin/${OSX_SDK}.tar.xz -o "${OSXCROSS_PATH}/tarballs/${OSX_SDK}.tar.xz" \
|
||||
&& curl -sSL https://s3.dockerproject.org/darwin/v2/${OSX_SDK}.tar.xz -o "${OSXCROSS_PATH}/tarballs/${OSX_SDK}.tar.xz" \
|
||||
&& UNATTENDED=yes OSX_VERSION_MIN=10.6 ${OSXCROSS_PATH}/build.sh
|
||||
ENV PATH /osxcross/target/bin:$PATH
|
||||
|
||||
@@ -119,7 +119,7 @@ RUN set -x \
|
||||
# IMPORTANT: If the version of Go is updated, the Windows to Linux CI machines
|
||||
# will need updating, to avoid errors. Ping #docker-maintainers on IRC
|
||||
# with a heads-up.
|
||||
ENV GO_VERSION 1.6
|
||||
ENV GO_VERSION 1.5.4
|
||||
RUN curl -fsSL "https://storage.googleapis.com/golang/go${GO_VERSION}.linux-amd64.tar.gz" \
|
||||
| tar -xzC /usr/local
|
||||
ENV PATH /go/bin:/usr/local/go/bin:$PATH
|
||||
@@ -170,12 +170,13 @@ RUN set -x \
|
||||
# Install notary server
|
||||
ENV NOTARY_VERSION docker-v1.11-3
|
||||
RUN set -x \
|
||||
&& export GO15VENDOREXPERIMENT=1 \
|
||||
&& export GOPATH="$(mktemp -d)" \
|
||||
&& git clone https://github.com/docker/notary.git "$GOPATH/src/github.com/docker/notary" \
|
||||
&& (cd "$GOPATH/src/github.com/docker/notary" && git checkout -q "$NOTARY_VERSION") \
|
||||
&& GOPATH="$GOPATH/src/github.com/docker/notary/Godeps/_workspace:$GOPATH" \
|
||||
&& GOPATH="$GOPATH/src/github.com/docker/notary/vendor:$GOPATH" \
|
||||
go build -o /usr/local/bin/notary-server github.com/docker/notary/cmd/notary-server \
|
||||
&& GOPATH="$GOPATH/src/github.com/docker/notary/Godeps/_workspace:$GOPATH" \
|
||||
&& GOPATH="$GOPATH/src/github.com/docker/notary/vendor:$GOPATH" \
|
||||
go build -o /usr/local/bin/notary github.com/docker/notary/cmd/notary \
|
||||
&& rm -rf "$GOPATH"
|
||||
|
||||
@@ -186,13 +187,6 @@ RUN git clone https://github.com/docker/docker-py.git /docker-py \
|
||||
&& git checkout -q $DOCKER_PY_COMMIT \
|
||||
&& pip install -r test-requirements.txt
|
||||
|
||||
# Setup s3cmd config
|
||||
RUN { \
|
||||
echo '[default]'; \
|
||||
echo 'access_key=$AWS_ACCESS_KEY'; \
|
||||
echo 'secret_key=$AWS_SECRET_KEY'; \
|
||||
} > ~/.s3cfg
|
||||
|
||||
# Set user.email so crosbymichael's in-container merge commits go smoothly
|
||||
RUN git config --global user.email 'docker-dummy@example.com'
|
||||
|
||||
@@ -247,7 +241,7 @@ RUN set -x \
|
||||
&& rm -rf "$GOPATH"
|
||||
|
||||
# Install runc
|
||||
ENV RUNC_COMMIT bbde9c426ff363d813b8722f0744115c13b408b6
|
||||
ENV RUNC_COMMIT baf6536d6259209c3edfa2b22237af82942d3dfa
|
||||
RUN set -x \
|
||||
&& export GOPATH="$(mktemp -d)" \
|
||||
&& git clone git://github.com/opencontainers/runc.git "$GOPATH/src/github.com/opencontainers/runc" \
|
||||
@@ -257,7 +251,7 @@ RUN set -x \
|
||||
&& cp runc /usr/local/bin/docker-runc
|
||||
|
||||
# Install containerd
|
||||
ENV CONTAINERD_COMMIT 142e22a4dce86f3b8ce068a0b043489d21976bb8
|
||||
ENV CONTAINERD_COMMIT 9dc2b3273db42c75368988a3885a3afd770069d9
|
||||
RUN set -x \
|
||||
&& export GOPATH="$(mktemp -d)" \
|
||||
&& git clone git://github.com/docker/containerd.git "$GOPATH/src/github.com/docker/containerd" \
|
||||
|
||||
@@ -96,7 +96,7 @@ RUN set -x \
|
||||
# We don't have official binary tarballs for ARM64, eigher for Go or bootstrap,
|
||||
# so we use the official armv6 released binaries as a GOROOT_BOOTSTRAP, and
|
||||
# build Go from source code.
|
||||
ENV GO_VERSION 1.5.3
|
||||
ENV GO_VERSION 1.5.4
|
||||
RUN mkdir /usr/src/go && curl -fsSL https://storage.googleapis.com/golang/go${GO_VERSION}.src.tar.gz | tar -v -C /usr/src/go -xz --strip-components=1 \
|
||||
&& cd /usr/src/go/src \
|
||||
&& GOOS=linux GOARCH=arm64 GOROOT_BOOTSTRAP="$(go env GOROOT)" ./make.bash
|
||||
@@ -119,12 +119,13 @@ RUN set -x \
|
||||
# Install notary server
|
||||
ENV NOTARY_VERSION docker-v1.11-3
|
||||
RUN set -x \
|
||||
&& export GO15VENDOREXPERIMENT=1 \
|
||||
&& export GOPATH="$(mktemp -d)" \
|
||||
&& git clone https://github.com/docker/notary.git "$GOPATH/src/github.com/docker/notary" \
|
||||
&& (cd "$GOPATH/src/github.com/docker/notary" && git checkout -q "$NOTARY_VERSION") \
|
||||
&& GOPATH="$GOPATH/src/github.com/docker/notary/Godeps/_workspace:$GOPATH" \
|
||||
&& GOPATH="$GOPATH/src/github.com/docker/notary/vendor:$GOPATH" \
|
||||
go build -o /usr/local/bin/notary-server github.com/docker/notary/cmd/notary-server \
|
||||
&& GOPATH="$GOPATH/src/github.com/docker/notary/Godeps/_workspace:$GOPATH" \
|
||||
&& GOPATH="$GOPATH/src/github.com/docker/notary/vendor:$GOPATH" \
|
||||
go build -o /usr/local/bin/notary github.com/docker/notary/cmd/notary \
|
||||
&& rm -rf "$GOPATH"
|
||||
|
||||
@@ -135,13 +136,6 @@ RUN git clone https://github.com/docker/docker-py.git /docker-py \
|
||||
&& git checkout -q $DOCKER_PY_COMMIT \
|
||||
&& pip install -r test-requirements.txt
|
||||
|
||||
# Setup s3cmd config
|
||||
RUN { \
|
||||
echo '[default]'; \
|
||||
echo 'access_key=$AWS_ACCESS_KEY'; \
|
||||
echo 'secret_key=$AWS_SECRET_KEY'; \
|
||||
} > ~/.s3cfg
|
||||
|
||||
# Set user.email so crosbymichael's in-container merge commits go smoothly
|
||||
RUN git config --global user.email 'docker-dummy@example.com'
|
||||
|
||||
@@ -187,7 +181,7 @@ RUN set -x \
|
||||
&& rm -rf "$GOPATH"
|
||||
|
||||
# Install runc
|
||||
ENV RUNC_COMMIT bbde9c426ff363d813b8722f0744115c13b408b6
|
||||
ENV RUNC_COMMIT baf6536d6259209c3edfa2b22237af82942d3dfa
|
||||
RUN set -x \
|
||||
&& export GOPATH="$(mktemp -d)" \
|
||||
&& git clone git://github.com/opencontainers/runc.git "$GOPATH/src/github.com/opencontainers/runc" \
|
||||
@@ -197,7 +191,7 @@ RUN set -x \
|
||||
&& cp runc /usr/local/bin/docker-runc
|
||||
|
||||
# Install containerd
|
||||
ENV CONTAINERD_COMMIT 142e22a4dce86f3b8ce068a0b043489d21976bb8
|
||||
ENV CONTAINERD_COMMIT 9dc2b3273db42c75368988a3885a3afd770069d9
|
||||
RUN set -x \
|
||||
&& export GOPATH="$(mktemp -d)" \
|
||||
&& git clone git://github.com/docker/containerd.git "$GOPATH/src/github.com/docker/containerd" \
|
||||
|
||||
@@ -65,8 +65,10 @@ RUN cd /usr/local/lvm2 \
|
||||
# see https://git.fedorahosted.org/cgit/lvm2.git/tree/INSTALL
|
||||
|
||||
# Install Go
|
||||
ENV GO_VERSION 1.6
|
||||
RUN curl -fsSL "https://storage.googleapis.com/golang/go${GO_VERSION}.linux-armv6l.tar.gz" \
|
||||
# TODO Update to 1.5.4 once available, or build from source, as these builds
|
||||
# are marked "end of life", see http://dave.cheney.net/unofficial-arm-tarballs
|
||||
ENV GO_VERSION 1.5.3
|
||||
RUN curl -fsSL "http://dave.cheney.net/paste/go${GO_VERSION}.linux-arm.tar.gz" \
|
||||
| tar -xzC /usr/local
|
||||
ENV PATH /go/bin:/usr/local/go/bin:$PATH
|
||||
ENV GOPATH /go:/go/src/github.com/docker/docker/vendor
|
||||
@@ -128,12 +130,13 @@ RUN set -x \
|
||||
# Install notary server
|
||||
ENV NOTARY_VERSION docker-v1.11-3
|
||||
RUN set -x \
|
||||
&& export GO15VENDOREXPERIMENT=1 \
|
||||
&& export GOPATH="$(mktemp -d)" \
|
||||
&& git clone https://github.com/docker/notary.git "$GOPATH/src/github.com/docker/notary" \
|
||||
&& (cd "$GOPATH/src/github.com/docker/notary" && git checkout -q "$NOTARY_VERSION") \
|
||||
&& GOPATH="$GOPATH/src/github.com/docker/notary/Godeps/_workspace:$GOPATH" \
|
||||
&& GOPATH="$GOPATH/src/github.com/docker/notary/vendor:$GOPATH" \
|
||||
go build -o /usr/local/bin/notary-server github.com/docker/notary/cmd/notary-server \
|
||||
&& GOPATH="$GOPATH/src/github.com/docker/notary/Godeps/_workspace:$GOPATH" \
|
||||
&& GOPATH="$GOPATH/src/github.com/docker/notary/vendor:$GOPATH" \
|
||||
go build -o /usr/local/bin/notary github.com/docker/notary/cmd/notary \
|
||||
&& rm -rf "$GOPATH"
|
||||
|
||||
@@ -197,7 +200,7 @@ RUN set -x \
|
||||
&& rm -rf "$GOPATH"
|
||||
|
||||
# Install runc
|
||||
ENV RUNC_COMMIT bbde9c426ff363d813b8722f0744115c13b408b6
|
||||
ENV RUNC_COMMIT baf6536d6259209c3edfa2b22237af82942d3dfa
|
||||
RUN set -x \
|
||||
&& export GOPATH="$(mktemp -d)" \
|
||||
&& git clone git://github.com/opencontainers/runc.git "$GOPATH/src/github.com/opencontainers/runc" \
|
||||
@@ -207,7 +210,7 @@ RUN set -x \
|
||||
&& cp runc /usr/local/bin/docker-runc
|
||||
|
||||
# Install containerd
|
||||
ENV CONTAINERD_COMMIT 142e22a4dce86f3b8ce068a0b043489d21976bb8
|
||||
ENV CONTAINERD_COMMIT 9dc2b3273db42c75368988a3885a3afd770069d9
|
||||
RUN set -x \
|
||||
&& export GOPATH="$(mktemp -d)" \
|
||||
&& git clone git://github.com/docker/containerd.git "$GOPATH/src/github.com/docker/containerd" \
|
||||
|
||||
@@ -74,7 +74,7 @@ WORKDIR /go/src/github.com/docker/docker
|
||||
ENV DOCKER_BUILDTAGS apparmor seccomp selinux
|
||||
|
||||
# Install runc
|
||||
ENV RUNC_COMMIT bbde9c426ff363d813b8722f0744115c13b408b6
|
||||
ENV RUNC_COMMIT baf6536d6259209c3edfa2b22237af82942d3dfa
|
||||
RUN set -x \
|
||||
&& export GOPATH="$(mktemp -d)" \
|
||||
&& git clone git://github.com/opencontainers/runc.git "$GOPATH/src/github.com/opencontainers/runc" \
|
||||
@@ -84,7 +84,7 @@ RUN set -x \
|
||||
&& cp runc /usr/local/bin/docker-runc
|
||||
|
||||
# Install containerd
|
||||
ENV CONTAINERD_COMMIT 142e22a4dce86f3b8ce068a0b043489d21976bb8
|
||||
ENV CONTAINERD_COMMIT 9dc2b3273db42c75368988a3885a3afd770069d9
|
||||
RUN set -x \
|
||||
&& export GOPATH="$(mktemp -d)" \
|
||||
&& git clone git://github.com/docker/containerd.git "$GOPATH/src/github.com/docker/containerd" \
|
||||
|
||||
@@ -71,13 +71,11 @@ RUN cd /usr/local/lvm2 \
|
||||
&& make install_device-mapper
|
||||
# see https://git.fedorahosted.org/cgit/lvm2.git/tree/INSTALL
|
||||
|
||||
# TODO install Go, using gccgo as GOROOT_BOOTSTRAP (Go 1.5+ supports ppc64le properly)
|
||||
# possibly a ppc64le/golang image?
|
||||
|
||||
## BUILD GOLANG 1.6
|
||||
ENV GO_VERSION 1.6
|
||||
# NOTE: ppc64le has compatibility issues with older versions of go, so make sure the version >= 1.6
|
||||
ENV GO_VERSION 1.6.2
|
||||
ENV GO_DOWNLOAD_URL https://golang.org/dl/go${GO_VERSION}.src.tar.gz
|
||||
ENV GO_DOWNLOAD_SHA256 a96cce8ce43a9bf9b2a4c7d470bc7ee0cb00410da815980681c8353218dcf146
|
||||
ENV GO_DOWNLOAD_SHA256 787b0b750d037016a30c6ed05a8a70a91b2e9db4bd9b1a2453aa502a63f1bccc
|
||||
ENV GOROOT_BOOTSTRAP /usr/local
|
||||
|
||||
RUN curl -fsSL "$GO_DOWNLOAD_URL" -o golang.tar.gz \
|
||||
@@ -129,12 +127,13 @@ RUN set -x \
|
||||
# Install notary and notary-server
|
||||
ENV NOTARY_VERSION docker-v1.11-3
|
||||
RUN set -x \
|
||||
&& export GO15VENDOREXPERIMENT=1 \
|
||||
&& export GOPATH="$(mktemp -d)" \
|
||||
&& git clone https://github.com/docker/notary.git "$GOPATH/src/github.com/docker/notary" \
|
||||
&& (cd "$GOPATH/src/github.com/docker/notary" && git checkout -q "$NOTARY_VERSION") \
|
||||
&& GOPATH="$GOPATH/src/github.com/docker/notary/Godeps/_workspace:$GOPATH" \
|
||||
&& GOPATH="$GOPATH/src/github.com/docker/notary/vendor:$GOPATH" \
|
||||
go build -o /usr/local/bin/notary-server github.com/docker/notary/cmd/notary-server \
|
||||
&& GOPATH="$GOPATH/src/github.com/docker/notary/Godeps/_workspace:$GOPATH" \
|
||||
&& GOPATH="$GOPATH/src/github.com/docker/notary/vendor:$GOPATH" \
|
||||
go build -o /usr/local/bin/notary github.com/docker/notary/cmd/notary \
|
||||
&& rm -rf "$GOPATH"
|
||||
|
||||
@@ -198,17 +197,17 @@ RUN set -x \
|
||||
&& rm -rf "$GOPATH"
|
||||
|
||||
# Install runc
|
||||
ENV RUNC_COMMIT bbde9c426ff363d813b8722f0744115c13b408b6
|
||||
ENV RUNC_COMMIT baf6536d6259209c3edfa2b22237af82942d3dfa
|
||||
RUN set -x \
|
||||
&& export GOPATH="$(mktemp -d)" \
|
||||
&& git clone git://github.com/opencontainers/runc.git "$GOPATH/src/github.com/opencontainers/runc" \
|
||||
&& cd "$GOPATH/src/github.com/opencontainers/runc" \
|
||||
&& git checkout -q "$RUNC_COMMIT" \
|
||||
&& make static BUILDTAGS="seccomp apparmor selinux" \
|
||||
&& make static BUILDTAGS="apparmor selinux" \
|
||||
&& cp runc /usr/local/bin/docker-runc
|
||||
|
||||
# Install containerd
|
||||
ENV CONTAINERD_COMMIT 142e22a4dce86f3b8ce068a0b043489d21976bb8
|
||||
ENV CONTAINERD_COMMIT 9dc2b3273db42c75368988a3885a3afd770069d9
|
||||
RUN set -x \
|
||||
&& export GOPATH="$(mktemp -d)" \
|
||||
&& git clone git://github.com/docker/containerd.git "$GOPATH/src/github.com/docker/containerd" \
|
||||
|
||||
@@ -110,11 +110,12 @@ RUN set -x \
|
||||
# Install notary server
|
||||
ENV NOTARY_VERSION docker-v1.11-3
|
||||
RUN set -x \
|
||||
&& export GO15VENDOREXPERIMENT=1 \
|
||||
&& export GOPATH="$(mktemp -d)" \
|
||||
&& git clone https://github.com/docker/notary.git "$GOPATH/src/github.com/docker/notary" \
|
||||
&& (cd "$GOPATH/src/github.com/docker/notary" && git checkout -q "$NOTARY_VERSION") \
|
||||
&& GOPATH="$GOPATH/src/github.com/docker/notary/Godeps/_workspace:$GOPATH" \
|
||||
go build -gccgoflags=-lpthread -o /usr/local/bin/notary-server github.com/docker/notary/cmd/notary-server \
|
||||
&& GOPATH="$GOPATH/src/github.com/docker/notary/vendor:$GOPATH" \
|
||||
go build -o /usr/local/bin/notary-server github.com/docker/notary/cmd/notary-server \
|
||||
&& rm -rf "$GOPATH"
|
||||
|
||||
# Get the "docker-py" source so we can run their integration tests
|
||||
@@ -177,7 +178,7 @@ RUN set -x \
|
||||
&& rm -rf "$GOPATH"
|
||||
|
||||
# Install runc
|
||||
ENV RUNC_COMMIT bbde9c426ff363d813b8722f0744115c13b408b6
|
||||
ENV RUNC_COMMIT baf6536d6259209c3edfa2b22237af82942d3dfa
|
||||
RUN set -x \
|
||||
&& export GOPATH="$(mktemp -d)" \
|
||||
&& git clone git://github.com/opencontainers/runc.git "$GOPATH/src/github.com/opencontainers/runc" \
|
||||
@@ -187,7 +188,7 @@ RUN set -x \
|
||||
&& cp runc /usr/local/bin/docker-runc
|
||||
|
||||
# Install containerd
|
||||
ENV CONTAINERD_COMMIT 142e22a4dce86f3b8ce068a0b043489d21976bb8
|
||||
ENV CONTAINERD_COMMIT 9dc2b3273db42c75368988a3885a3afd770069d9
|
||||
RUN set -x \
|
||||
&& export GOPATH="$(mktemp -d)" \
|
||||
&& git clone git://github.com/docker/containerd.git "$GOPATH/src/github.com/docker/containerd" \
|
||||
|
||||
@@ -30,7 +30,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Install runc
|
||||
ENV RUNC_COMMIT bbde9c426ff363d813b8722f0744115c13b408b6
|
||||
ENV RUNC_COMMIT baf6536d6259209c3edfa2b22237af82942d3dfa
|
||||
RUN set -x \
|
||||
&& export GOPATH="$(mktemp -d)" \
|
||||
&& git clone git://github.com/opencontainers/runc.git "$GOPATH/src/github.com/opencontainers/runc" \
|
||||
@@ -40,7 +40,7 @@ RUN set -x \
|
||||
&& cp runc /usr/local/bin/docker-runc
|
||||
|
||||
# Install containerd
|
||||
ENV CONTAINERD_COMMIT 142e22a4dce86f3b8ce068a0b043489d21976bb8
|
||||
ENV CONTAINERD_COMMIT 9dc2b3273db42c75368988a3885a3afd770069d9
|
||||
RUN set -x \
|
||||
&& export GOPATH="$(mktemp -d)" \
|
||||
&& git clone git://github.com/docker/containerd.git "$GOPATH/src/github.com/docker/containerd" \
|
||||
|
||||
@@ -38,9 +38,9 @@
|
||||
FROM windowsservercore
|
||||
|
||||
# Environment variable notes:
|
||||
# - GOLANG_VERSION must consistent with 'Dockerfile' used by Linux'.
|
||||
# - GO_VERSION must consistent with 'Dockerfile' used by Linux'.
|
||||
# - FROM_DOCKERFILE is used for detection of building within a container.
|
||||
ENV GOLANG_VERSION=1.6 \
|
||||
ENV GO_VERSION=1.5.4 \
|
||||
GIT_LOCATION=https://github.com/git-for-windows/git/releases/download/v2.7.2.windows.1/Git-2.7.2-64-bit.exe \
|
||||
RSRC_COMMIT=ba14da1f827188454a4591717fff29999010887f \
|
||||
GOPATH=C:/go;C:/go/src/github.com/docker/docker/vendor \
|
||||
@@ -63,7 +63,7 @@ RUN \
|
||||
Download-File %GIT_LOCATION% gitsetup.exe; \
|
||||
\
|
||||
Write-Host INFO: Downloading go...; \
|
||||
Download-File https://storage.googleapis.com/golang/go%GOLANG_VERSION%.windows-amd64.msi go.msi; \
|
||||
Download-File https://storage.googleapis.com/golang/go%GO_VERSION%.windows-amd64.msi go.msi; \
|
||||
\
|
||||
Write-Host INFO: Downloading compiler 1 of 3...; \
|
||||
Download-File https://raw.githubusercontent.com/jhowardmsft/docker-tdmgcc/master/gcc.zip gcc.zip; \
|
||||
|
||||
3
Makefile
3
Makefile
@@ -69,10 +69,11 @@ bundles:
|
||||
cross: build
|
||||
$(DOCKER_RUN_DOCKER) hack/make.sh dynbinary binary cross
|
||||
|
||||
|
||||
win: build
|
||||
$(DOCKER_RUN_DOCKER) hack/make.sh win
|
||||
|
||||
tgz: build
|
||||
$(DOCKER_RUN_DOCKER) hack/make.sh dynbinary binary cross tgz
|
||||
|
||||
deb: build
|
||||
$(DOCKER_RUN_DOCKER) hack/make.sh dynbinary build-deb
|
||||
|
||||
@@ -41,7 +41,7 @@ func (cli *DockerCli) CmdLoad(args ...string) error {
|
||||
}
|
||||
defer response.Body.Close()
|
||||
|
||||
if response.JSON {
|
||||
if response.Body != nil && response.JSON {
|
||||
return jsonmessage.DisplayJSONMessagesStream(response.Body, cli.out, cli.outFd, cli.isTerminalOut, nil)
|
||||
}
|
||||
|
||||
|
||||
@@ -252,7 +252,7 @@ func (cli *DockerCli) trustedReference(ref reference.NamedTagged) (reference.Can
|
||||
// Resolve the Auth config relevant for this server
|
||||
authConfig := cli.resolveAuthConfig(repoInfo.Index)
|
||||
|
||||
notaryRepo, err := cli.getNotaryRepository(repoInfo, authConfig)
|
||||
notaryRepo, err := cli.getNotaryRepository(repoInfo, authConfig, "pull")
|
||||
if err != nil {
|
||||
fmt.Fprintf(cli.out, "Error establishing connection to trust repository: %s\n", err)
|
||||
return nil, err
|
||||
|
||||
@@ -52,6 +52,7 @@ func WriteError(w http.ResponseWriter, err error) {
|
||||
"conflict": http.StatusConflict,
|
||||
"impossible": http.StatusNotAcceptable,
|
||||
"wrong login/password": http.StatusUnauthorized,
|
||||
"unauthorized": http.StatusUnauthorized,
|
||||
"hasn't been activated": http.StatusForbidden,
|
||||
} {
|
||||
if strings.Contains(errStr, keyword) {
|
||||
|
||||
@@ -7,11 +7,9 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"github.com/docker/distribution/digest"
|
||||
"github.com/docker/distribution/registry/api/errcode"
|
||||
"github.com/docker/docker/api/server/httputils"
|
||||
"github.com/docker/docker/builder/dockerfile"
|
||||
"github.com/docker/docker/pkg/ioutils"
|
||||
@@ -132,12 +130,6 @@ func (s *imageRouter) postImagesCreate(ctx context.Context, w http.ResponseWrite
|
||||
err = s.backend.PullImage(ctx, ref, metaHeaders, authConfig, output)
|
||||
}
|
||||
}
|
||||
// Check the error from pulling an image to make sure the request
|
||||
// was authorized. Modify the status if the request was
|
||||
// unauthorized to respond with 401 rather than 500.
|
||||
if err != nil && isAuthorizedError(err) {
|
||||
err = errcode.ErrorCodeUnauthorized.WithMessage(fmt.Sprintf("Authentication is required: %s", err))
|
||||
}
|
||||
} else { //import
|
||||
var newRef reference.Named
|
||||
if repo != "" {
|
||||
@@ -269,7 +261,17 @@ func (s *imageRouter) postImagesLoad(ctx context.Context, w http.ResponseWriter,
|
||||
return err
|
||||
}
|
||||
quiet := httputils.BoolValueOrDefault(r, "quiet", true)
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
|
||||
if !quiet {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
|
||||
output := ioutils.NewWriteFlusher(w)
|
||||
defer output.Close()
|
||||
if err := s.backend.LoadImage(r.Body, output, quiet); err != nil {
|
||||
output.Write(streamformatter.NewJSONStreamFormatter().FormatError(err))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
return s.backend.LoadImage(r.Body, w, quiet)
|
||||
}
|
||||
|
||||
@@ -379,16 +381,3 @@ func (s *imageRouter) getImagesSearch(ctx context.Context, w http.ResponseWriter
|
||||
}
|
||||
return httputils.WriteJSON(w, http.StatusOK, query.Results)
|
||||
}
|
||||
|
||||
func isAuthorizedError(err error) bool {
|
||||
if urlError, ok := err.(*url.Error); ok {
|
||||
err = urlError.Err
|
||||
}
|
||||
|
||||
if dError, ok := err.(errcode.Error); ok {
|
||||
if dError.ErrorCode() == errcode.ErrorCodeUnauthorized {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -55,11 +55,10 @@ func (s *systemRouter) getEvents(ctx context.Context, w http.ResponseWriter, r *
|
||||
return err
|
||||
}
|
||||
|
||||
timer := time.NewTimer(0)
|
||||
timer.Stop()
|
||||
var timeout <-chan time.Time
|
||||
if until > 0 || untilNano > 0 {
|
||||
dur := time.Unix(until, untilNano).Sub(time.Now())
|
||||
timer = time.NewTimer(dur)
|
||||
timeout = time.NewTimer(dur).C
|
||||
}
|
||||
|
||||
ef, err := filters.FromParam(r.Form.Get("filters"))
|
||||
@@ -99,7 +98,7 @@ func (s *systemRouter) getEvents(ctx context.Context, w http.ResponseWriter, r *
|
||||
if err := enc.Encode(jev); err != nil {
|
||||
return err
|
||||
}
|
||||
case <-timer.C:
|
||||
case <-timeout:
|
||||
return nil
|
||||
case <-closeNotify:
|
||||
logrus.Debug("Client disconnected, stop sending events")
|
||||
|
||||
@@ -29,6 +29,16 @@ func ValidateContextDirectory(srcPath string, excludes []string) error {
|
||||
return err
|
||||
}
|
||||
return filepath.Walk(contextRoot, func(filePath string, f os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
if os.IsPermission(err) {
|
||||
return fmt.Errorf("can't stat '%s'", filePath)
|
||||
}
|
||||
if os.IsNotExist(err) {
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// skip this directory/file if it's not in the path, it won't get added to the context
|
||||
if relFilePath, err := filepath.Rel(contextRoot, filePath); err != nil {
|
||||
return err
|
||||
@@ -41,16 +51,6 @@ func ValidateContextDirectory(srcPath string, excludes []string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
if os.IsPermission(err) {
|
||||
return fmt.Errorf("can't stat '%s'", filePath)
|
||||
}
|
||||
if os.IsNotExist(err) {
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// skip checking if symlinks point to non-existing files, such symlinks can be useful
|
||||
// also skip named pipes, because they hanging on open
|
||||
if f.Mode()&(os.ModeSymlink|os.ModeNamedPipe) != 0 {
|
||||
|
||||
@@ -216,12 +216,20 @@ func (b *Builder) build(config *types.ImageBuildOptions, context builder.Context
|
||||
return "", err
|
||||
}
|
||||
|
||||
if len(b.options.Labels) > 0 {
|
||||
line := "LABEL "
|
||||
for k, v := range b.options.Labels {
|
||||
line += fmt.Sprintf("%q=%q ", k, v)
|
||||
}
|
||||
_, node, err := parser.ParseLine(line)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
b.dockerfile.Children = append(b.dockerfile.Children, node)
|
||||
}
|
||||
|
||||
var shortImgID string
|
||||
for i, n := range b.dockerfile.Children {
|
||||
// we only want to add labels to the last layer
|
||||
if i == len(b.dockerfile.Children)-1 {
|
||||
b.addLabels()
|
||||
}
|
||||
select {
|
||||
case <-b.cancelled:
|
||||
logrus.Debug("Builder: build cancelled!")
|
||||
@@ -236,6 +244,7 @@ func (b *Builder) build(config *types.ImageBuildOptions, context builder.Context
|
||||
}
|
||||
return "", err
|
||||
}
|
||||
|
||||
shortImgID = stringid.TruncateID(b.image)
|
||||
fmt.Fprintf(b.Stdout, " ---> %s\n", shortImgID)
|
||||
if b.options.Remove {
|
||||
|
||||
@@ -37,19 +37,6 @@ import (
|
||||
"github.com/docker/engine-api/types/strslice"
|
||||
)
|
||||
|
||||
func (b *Builder) addLabels() {
|
||||
// merge labels
|
||||
if len(b.options.Labels) > 0 {
|
||||
logrus.Debugf("[BUILDER] setting labels %v", b.options.Labels)
|
||||
if b.runConfig.Labels == nil {
|
||||
b.runConfig.Labels = make(map[string]string)
|
||||
}
|
||||
for kL, vL := range b.options.Labels {
|
||||
b.runConfig.Labels[kL] = vL
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (b *Builder) commit(id string, autoCmd strslice.StrSlice, comment string) error {
|
||||
if b.disableCommit {
|
||||
return nil
|
||||
|
||||
@@ -34,7 +34,7 @@ func parseSubCommand(rest string) (*Node, map[string]bool, error) {
|
||||
return nil, nil, nil
|
||||
}
|
||||
|
||||
_, child, err := parseLine(rest)
|
||||
_, child, err := ParseLine(rest)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
@@ -68,8 +68,8 @@ func init() {
|
||||
}
|
||||
}
|
||||
|
||||
// parse a line and return the remainder.
|
||||
func parseLine(line string) (string, *Node, error) {
|
||||
// ParseLine parse a line and return the remainder.
|
||||
func ParseLine(line string) (string, *Node, error) {
|
||||
if line = stripComments(line); line == "" {
|
||||
return "", nil, nil
|
||||
}
|
||||
@@ -111,7 +111,7 @@ func Parse(rwc io.Reader) (*Node, error) {
|
||||
for scanner.Scan() {
|
||||
scannedLine := strings.TrimLeftFunc(scanner.Text(), unicode.IsSpace)
|
||||
currentLine++
|
||||
line, child, err := parseLine(scannedLine)
|
||||
line, child, err := ParseLine(scannedLine)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -126,7 +126,7 @@ func Parse(rwc io.Reader) (*Node, error) {
|
||||
continue
|
||||
}
|
||||
|
||||
line, child, err = parseLine(line + newline)
|
||||
line, child, err = ParseLine(line + newline)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -136,7 +136,7 @@ func Parse(rwc io.Reader) (*Node, error) {
|
||||
}
|
||||
}
|
||||
if child == nil && line != "" {
|
||||
_, child, err = parseLine(line)
|
||||
_, child, err = ParseLine(line)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -516,9 +516,9 @@ func copyEscapable(dst io.Writer, src io.ReadCloser, keys []byte) (written int64
|
||||
return written, err
|
||||
}
|
||||
|
||||
// ShouldRestart decides whether the daemon should restart the container or not.
|
||||
// ShouldRestartOnBoot decides whether the daemon should restart the container or not.
|
||||
// This is based on the container's restart policy.
|
||||
func (container *Container) ShouldRestart() bool {
|
||||
func (container *Container) ShouldRestartOnBoot() bool {
|
||||
return container.HostConfig.RestartPolicy.Name == "always" ||
|
||||
(container.HostConfig.RestartPolicy.Name == "unless-stopped" && !container.HasBeenManuallyStopped) ||
|
||||
(container.HostConfig.RestartPolicy.Name == "on-failure" && container.ExitCode != 0)
|
||||
@@ -667,7 +667,8 @@ func getEndpointPortMapInfo(ep libnetwork.Endpoint) (nat.PortMap, error) {
|
||||
return pm, nil
|
||||
}
|
||||
|
||||
func getSandboxPortMapInfo(sb libnetwork.Sandbox) nat.PortMap {
|
||||
// GetSandboxPortMapInfo retrieves the current port-mapping programmed for the given sandbox
|
||||
func GetSandboxPortMapInfo(sb libnetwork.Sandbox) nat.PortMap {
|
||||
pm := nat.PortMap{}
|
||||
if sb == nil {
|
||||
return pm
|
||||
@@ -824,7 +825,7 @@ func (container *Container) BuildCreateEndpointOptions(n libnetwork.Network, epC
|
||||
}
|
||||
|
||||
// Port-mapping rules belong to the container & applicable only to non-internal networks
|
||||
portmaps := getSandboxPortMapInfo(sb)
|
||||
portmaps := GetSandboxPortMapInfo(sb)
|
||||
if n.Info().Internal() || len(portmaps) > 0 {
|
||||
return createOptions, nil
|
||||
}
|
||||
@@ -909,6 +910,7 @@ func (container *Container) FullHostname() string {
|
||||
func (container *Container) RestartManager(reset bool) restartmanager.RestartManager {
|
||||
if reset {
|
||||
container.RestartCount = 0
|
||||
container.restartManager = nil
|
||||
}
|
||||
if container.restartManager == nil {
|
||||
container.restartManager = restartmanager.New(container.HostConfig.RestartPolicy)
|
||||
|
||||
@@ -24,11 +24,6 @@ func (history *History) Swap(i, j int) {
|
||||
containers[i], containers[j] = containers[j], containers[i]
|
||||
}
|
||||
|
||||
// Add the given container to history.
|
||||
func (history *History) Add(container *Container) {
|
||||
*history = append(*history, container)
|
||||
}
|
||||
|
||||
// sort orders the history by creation date in descendant order.
|
||||
func (history *History) sort() {
|
||||
sort.Sort(history)
|
||||
|
||||
@@ -41,14 +41,9 @@ func (c *memoryStore) Delete(id string) {
|
||||
// List returns a sorted list of containers from the store.
|
||||
// The containers are ordered by creation date.
|
||||
func (c *memoryStore) List() []*Container {
|
||||
containers := new(History)
|
||||
c.RLock()
|
||||
for _, cont := range c.s {
|
||||
containers.Add(cont)
|
||||
}
|
||||
c.RUnlock()
|
||||
containers := History(c.all())
|
||||
containers.sort()
|
||||
return *containers
|
||||
return containers
|
||||
}
|
||||
|
||||
// Size returns the number of containers in the store.
|
||||
@@ -60,9 +55,7 @@ func (c *memoryStore) Size() int {
|
||||
|
||||
// First returns the first container found in the store by a given filter.
|
||||
func (c *memoryStore) First(filter StoreFilter) *Container {
|
||||
c.RLock()
|
||||
defer c.RUnlock()
|
||||
for _, cont := range c.s {
|
||||
for _, cont := range c.all() {
|
||||
if filter(cont) {
|
||||
return cont
|
||||
}
|
||||
@@ -74,11 +67,8 @@ func (c *memoryStore) First(filter StoreFilter) *Container {
|
||||
// This operation is asyncronous in the memory store.
|
||||
// NOTE: Modifications to the store MUST NOT be done by the StoreReducer.
|
||||
func (c *memoryStore) ApplyAll(apply StoreReducer) {
|
||||
c.RLock()
|
||||
defer c.RUnlock()
|
||||
|
||||
wg := new(sync.WaitGroup)
|
||||
for _, cont := range c.s {
|
||||
for _, cont := range c.all() {
|
||||
wg.Add(1)
|
||||
go func(container *Container) {
|
||||
apply(container)
|
||||
@@ -89,4 +79,14 @@ func (c *memoryStore) ApplyAll(apply StoreReducer) {
|
||||
wg.Wait()
|
||||
}
|
||||
|
||||
func (c *memoryStore) all() []*Container {
|
||||
c.RLock()
|
||||
containers := make([]*Container, 0, len(c.s))
|
||||
for _, cont := range c.s {
|
||||
containers = append(containers, cont)
|
||||
}
|
||||
c.RUnlock()
|
||||
return containers
|
||||
}
|
||||
|
||||
var _ Store = &memoryStore{}
|
||||
|
||||
@@ -6,10 +6,11 @@ FROM debian:jessie
|
||||
|
||||
RUN apt-get update && apt-get install -y apparmor bash-completion btrfs-tools build-essential curl ca-certificates debhelper dh-apparmor dh-systemd git libapparmor-dev libdevmapper-dev libltdl-dev libsqlite3-dev pkg-config libsystemd-journal-dev --no-install-recommends && rm -rf /var/lib/apt/lists/*
|
||||
|
||||
ENV GO_VERSION 1.5.3
|
||||
ENV GO_VERSION 1.5.4
|
||||
RUN curl -fSL "https://storage.googleapis.com/golang/go${GO_VERSION}.linux-amd64.tar.gz" | tar xzC /usr/local
|
||||
ENV PATH $PATH:/usr/local/go/bin
|
||||
|
||||
ENV AUTO_GOPATH 1
|
||||
|
||||
ENV DOCKER_BUILDTAGS apparmor selinux
|
||||
ENV DOCKER_BUILDTAGS apparmor pkcs11 selinux
|
||||
ENV RUNC_BUILDTAGS apparmor selinux
|
||||
|
||||
@@ -6,10 +6,11 @@ FROM debian:stretch
|
||||
|
||||
RUN apt-get update && apt-get install -y apparmor bash-completion btrfs-tools build-essential curl ca-certificates debhelper dh-apparmor dh-systemd git libapparmor-dev libdevmapper-dev libltdl-dev libseccomp-dev libsqlite3-dev pkg-config libsystemd-dev --no-install-recommends && rm -rf /var/lib/apt/lists/*
|
||||
|
||||
ENV GO_VERSION 1.5.3
|
||||
ENV GO_VERSION 1.5.4
|
||||
RUN curl -fSL "https://storage.googleapis.com/golang/go${GO_VERSION}.linux-amd64.tar.gz" | tar xzC /usr/local
|
||||
ENV PATH $PATH:/usr/local/go/bin
|
||||
|
||||
ENV AUTO_GOPATH 1
|
||||
|
||||
ENV DOCKER_BUILDTAGS apparmor seccomp selinux
|
||||
ENV DOCKER_BUILDTAGS apparmor pkcs11 seccomp selinux
|
||||
ENV RUNC_BUILDTAGS apparmor seccomp selinux
|
||||
|
||||
@@ -7,10 +7,11 @@ FROM debian:wheezy-backports
|
||||
RUN apt-get update && apt-get install -y -t wheezy-backports btrfs-tools --no-install-recommends && rm -rf /var/lib/apt/lists/*
|
||||
RUN apt-get update && apt-get install -y apparmor bash-completion build-essential curl ca-certificates debhelper dh-apparmor dh-systemd git libapparmor-dev libdevmapper-dev libltdl-dev libsqlite3-dev pkg-config --no-install-recommends && rm -rf /var/lib/apt/lists/*
|
||||
|
||||
ENV GO_VERSION 1.5.3
|
||||
ENV GO_VERSION 1.5.4
|
||||
RUN curl -fSL "https://storage.googleapis.com/golang/go${GO_VERSION}.linux-amd64.tar.gz" | tar xzC /usr/local
|
||||
ENV PATH $PATH:/usr/local/go/bin
|
||||
|
||||
ENV AUTO_GOPATH 1
|
||||
|
||||
ENV DOCKER_BUILDTAGS apparmor selinux
|
||||
ENV DOCKER_BUILDTAGS apparmor pkcs11 selinux
|
||||
ENV RUNC_BUILDTAGS apparmor selinux
|
||||
|
||||
@@ -41,7 +41,8 @@ for version in "${versions[@]}"; do
|
||||
|
||||
echo >> "$version/Dockerfile"
|
||||
|
||||
extraBuildTags=
|
||||
extraBuildTags='pkcs11'
|
||||
runcBuildTags=
|
||||
|
||||
# this list is sorted alphabetically; please keep it that way
|
||||
packages=(
|
||||
@@ -64,7 +65,7 @@ for version in "${versions[@]}"; do
|
||||
# packaging for "sd-journal.h" and libraries varies
|
||||
case "$suite" in
|
||||
precise|wheezy) ;;
|
||||
sid|stretch|wily) packages+=( libsystemd-dev );;
|
||||
sid|stretch|wily|xenial) packages+=( libsystemd-dev );;
|
||||
*) packages+=( libsystemd-journal-dev );;
|
||||
esac
|
||||
|
||||
@@ -73,9 +74,11 @@ for version in "${versions[@]}"; do
|
||||
case "$suite" in
|
||||
precise|wheezy|jessie|trusty)
|
||||
packages=( "${packages[@]/libseccomp-dev}" )
|
||||
runcBuildTags="apparmor selinux"
|
||||
;;
|
||||
*)
|
||||
extraBuildTags+=' seccomp'
|
||||
runcBuildTags="apparmor seccomp selinux"
|
||||
;;
|
||||
esac
|
||||
|
||||
@@ -124,4 +127,5 @@ for version in "${versions[@]}"; do
|
||||
buildTags=$( echo "apparmor selinux $extraBuildTags" | xargs -n1 | sort -n | tr '\n' ' ' | sed -e 's/[[:space:]]*$//' )
|
||||
|
||||
echo "ENV DOCKER_BUILDTAGS $buildTags" >> "$version/Dockerfile"
|
||||
echo "ENV RUNC_BUILDTAGS $runcBuildTags" >> "$version/Dockerfile"
|
||||
done
|
||||
|
||||
@@ -6,10 +6,11 @@ FROM ubuntu:precise
|
||||
|
||||
RUN apt-get update && apt-get install -y apparmor bash-completion build-essential curl ca-certificates debhelper dh-apparmor git libapparmor-dev libltdl-dev libsqlite3-dev pkg-config --no-install-recommends && rm -rf /var/lib/apt/lists/*
|
||||
|
||||
ENV GO_VERSION 1.5.3
|
||||
ENV GO_VERSION 1.5.4
|
||||
RUN curl -fSL "https://storage.googleapis.com/golang/go${GO_VERSION}.linux-amd64.tar.gz" | tar xzC /usr/local
|
||||
ENV PATH $PATH:/usr/local/go/bin
|
||||
|
||||
ENV AUTO_GOPATH 1
|
||||
|
||||
ENV DOCKER_BUILDTAGS apparmor exclude_graphdriver_btrfs exclude_graphdriver_devicemapper selinux
|
||||
ENV DOCKER_BUILDTAGS apparmor exclude_graphdriver_btrfs exclude_graphdriver_devicemapper pkcs11 selinux
|
||||
ENV RUNC_BUILDTAGS apparmor selinux
|
||||
|
||||
@@ -6,10 +6,11 @@ FROM ubuntu:trusty
|
||||
|
||||
RUN apt-get update && apt-get install -y apparmor bash-completion btrfs-tools build-essential curl ca-certificates debhelper dh-apparmor dh-systemd git libapparmor-dev libdevmapper-dev libltdl-dev libsqlite3-dev pkg-config libsystemd-journal-dev --no-install-recommends && rm -rf /var/lib/apt/lists/*
|
||||
|
||||
ENV GO_VERSION 1.5.3
|
||||
ENV GO_VERSION 1.5.4
|
||||
RUN curl -fSL "https://storage.googleapis.com/golang/go${GO_VERSION}.linux-amd64.tar.gz" | tar xzC /usr/local
|
||||
ENV PATH $PATH:/usr/local/go/bin
|
||||
|
||||
ENV AUTO_GOPATH 1
|
||||
|
||||
ENV DOCKER_BUILDTAGS apparmor selinux
|
||||
ENV DOCKER_BUILDTAGS apparmor pkcs11 selinux
|
||||
ENV RUNC_BUILDTAGS apparmor selinux
|
||||
|
||||
@@ -6,10 +6,11 @@ FROM ubuntu:wily
|
||||
|
||||
RUN apt-get update && apt-get install -y apparmor bash-completion btrfs-tools build-essential curl ca-certificates debhelper dh-apparmor dh-systemd git libapparmor-dev libdevmapper-dev libltdl-dev libseccomp-dev libsqlite3-dev pkg-config libsystemd-dev --no-install-recommends && rm -rf /var/lib/apt/lists/*
|
||||
|
||||
ENV GO_VERSION 1.5.3
|
||||
ENV GO_VERSION 1.5.4
|
||||
RUN curl -fSL "https://storage.googleapis.com/golang/go${GO_VERSION}.linux-amd64.tar.gz" | tar xzC /usr/local
|
||||
ENV PATH $PATH:/usr/local/go/bin
|
||||
|
||||
ENV AUTO_GOPATH 1
|
||||
|
||||
ENV DOCKER_BUILDTAGS apparmor seccomp selinux
|
||||
ENV DOCKER_BUILDTAGS apparmor pkcs11 seccomp selinux
|
||||
ENV RUNC_BUILDTAGS apparmor seccomp selinux
|
||||
|
||||
16
contrib/builder/deb/amd64/ubuntu-xenial/Dockerfile
Normal file
16
contrib/builder/deb/amd64/ubuntu-xenial/Dockerfile
Normal file
@@ -0,0 +1,16 @@
|
||||
#
|
||||
# THIS FILE IS AUTOGENERATED; SEE "contrib/builder/deb/amd64/generate.sh"!
|
||||
#
|
||||
|
||||
FROM ubuntu:xenial
|
||||
|
||||
RUN apt-get update && apt-get install -y apparmor bash-completion btrfs-tools build-essential curl ca-certificates debhelper dh-apparmor dh-systemd git libapparmor-dev libdevmapper-dev libltdl-dev libseccomp-dev libsqlite3-dev pkg-config libsystemd-dev --no-install-recommends && rm -rf /var/lib/apt/lists/*
|
||||
|
||||
ENV GO_VERSION 1.5.4
|
||||
RUN curl -fSL "https://storage.googleapis.com/golang/go${GO_VERSION}.linux-amd64.tar.gz" | tar xzC /usr/local
|
||||
ENV PATH $PATH:/usr/local/go/bin
|
||||
|
||||
ENV AUTO_GOPATH 1
|
||||
|
||||
ENV DOCKER_BUILDTAGS apparmor pkcs11 seccomp selinux
|
||||
ENV RUNC_BUILDTAGS apparmor seccomp selinux
|
||||
@@ -6,13 +6,14 @@ FROM centos:7
|
||||
|
||||
RUN yum groupinstall -y "Development Tools"
|
||||
RUN yum -y swap -- remove systemd-container systemd-container-libs -- install systemd systemd-libs
|
||||
RUN yum install -y btrfs-progs-devel device-mapper-devel glibc-static libselinux-devel libtool-ltdl-devel pkgconfig selinux-policy selinux-policy-devel sqlite-devel systemd-devel tar
|
||||
RUN yum install -y btrfs-progs-devel device-mapper-devel glibc-static libselinux-devel libtool-ltdl-devel pkgconfig selinux-policy selinux-policy-devel sqlite-devel systemd-devel tar git
|
||||
|
||||
ENV GO_VERSION 1.5.3
|
||||
ENV GO_VERSION 1.5.4
|
||||
RUN curl -fSL "https://storage.googleapis.com/golang/go${GO_VERSION}.linux-amd64.tar.gz" | tar xzC /usr/local
|
||||
ENV PATH $PATH:/usr/local/go/bin
|
||||
|
||||
ENV AUTO_GOPATH 1
|
||||
|
||||
ENV DOCKER_BUILDTAGS selinux
|
||||
ENV DOCKER_BUILDTAGS pkcs11 selinux
|
||||
ENV RUNC_BUILDTAGS selinux
|
||||
|
||||
|
||||
@@ -5,13 +5,14 @@
|
||||
FROM fedora:22
|
||||
|
||||
RUN dnf install -y @development-tools fedora-packager
|
||||
RUN dnf install -y btrfs-progs-devel device-mapper-devel glibc-static libseccomp-devel libselinux-devel libtool-ltdl-devel pkgconfig selinux-policy selinux-policy-devel sqlite-devel systemd-devel tar
|
||||
RUN dnf install -y btrfs-progs-devel device-mapper-devel glibc-static libseccomp-devel libselinux-devel libtool-ltdl-devel pkgconfig selinux-policy selinux-policy-devel sqlite-devel systemd-devel tar git
|
||||
|
||||
ENV GO_VERSION 1.5.3
|
||||
ENV GO_VERSION 1.5.4
|
||||
RUN curl -fSL "https://storage.googleapis.com/golang/go${GO_VERSION}.linux-amd64.tar.gz" | tar xzC /usr/local
|
||||
ENV PATH $PATH:/usr/local/go/bin
|
||||
|
||||
ENV AUTO_GOPATH 1
|
||||
|
||||
ENV DOCKER_BUILDTAGS seccomp selinux
|
||||
ENV DOCKER_BUILDTAGS pkcs11 seccomp selinux
|
||||
ENV RUNC_BUILDTAGS seccomp selinux
|
||||
|
||||
|
||||
@@ -5,13 +5,14 @@
|
||||
FROM fedora:23
|
||||
|
||||
RUN dnf install -y @development-tools fedora-packager
|
||||
RUN dnf install -y btrfs-progs-devel device-mapper-devel glibc-static libseccomp-devel libselinux-devel libtool-ltdl-devel pkgconfig selinux-policy selinux-policy-devel sqlite-devel systemd-devel tar
|
||||
RUN dnf install -y btrfs-progs-devel device-mapper-devel glibc-static libseccomp-devel libselinux-devel libtool-ltdl-devel pkgconfig selinux-policy selinux-policy-devel sqlite-devel systemd-devel tar git
|
||||
|
||||
ENV GO_VERSION 1.5.3
|
||||
ENV GO_VERSION 1.5.4
|
||||
RUN curl -fSL "https://storage.googleapis.com/golang/go${GO_VERSION}.linux-amd64.tar.gz" | tar xzC /usr/local
|
||||
ENV PATH $PATH:/usr/local/go/bin
|
||||
|
||||
ENV AUTO_GOPATH 1
|
||||
|
||||
ENV DOCKER_BUILDTAGS seccomp selinux
|
||||
ENV DOCKER_BUILDTAGS pkcs11 seccomp selinux
|
||||
ENV RUNC_BUILDTAGS seccomp selinux
|
||||
|
||||
|
||||
@@ -38,7 +38,8 @@ for version in "${versions[@]}"; do
|
||||
|
||||
echo >> "$version/Dockerfile"
|
||||
|
||||
extraBuildTags=
|
||||
extraBuildTags='pkcs11'
|
||||
runcBuildTags=
|
||||
|
||||
case "$from" in
|
||||
centos:*)
|
||||
@@ -77,6 +78,7 @@ for version in "${versions[@]}"; do
|
||||
sqlite-devel # for "sqlite3.h"
|
||||
systemd-devel # for "sd-journal.h" and libraries
|
||||
tar # older versions of dev-tools do not have tar
|
||||
git # required for containerd and runc clone
|
||||
)
|
||||
|
||||
case "$from" in
|
||||
@@ -98,9 +100,11 @@ for version in "${versions[@]}"; do
|
||||
case "$from" in
|
||||
opensuse:*|oraclelinux:*|centos:7)
|
||||
packages=( "${packages[@]/libseccomp-devel}" )
|
||||
runcBuildTags="selinux"
|
||||
;;
|
||||
*)
|
||||
extraBuildTags+=' seccomp'
|
||||
runcBuildTags="seccomp selinux"
|
||||
;;
|
||||
esac
|
||||
|
||||
@@ -148,6 +152,7 @@ for version in "${versions[@]}"; do
|
||||
buildTags=$( echo "selinux $extraBuildTags" | xargs -n1 | sort -n | tr '\n' ' ' | sed -e 's/[[:space:]]*$//' )
|
||||
|
||||
echo "ENV DOCKER_BUILDTAGS $buildTags" >> "$version/Dockerfile"
|
||||
echo "ENV RUNC_BUILDTAGS $runcBuildTags" >> "$version/Dockerfile"
|
||||
echo >> "$version/Dockerfile"
|
||||
|
||||
case "$from" in
|
||||
|
||||
@@ -5,13 +5,14 @@
|
||||
FROM opensuse:13.2
|
||||
|
||||
RUN zypper --non-interactive install ca-certificates* curl gzip rpm-build
|
||||
RUN zypper --non-interactive install libbtrfs-devel device-mapper-devel glibc-static libselinux-devel libtool-ltdl-devel pkg-config selinux-policy selinux-policy-devel sqlite-devel systemd-devel tar systemd-rpm-macros
|
||||
RUN zypper --non-interactive install libbtrfs-devel device-mapper-devel glibc-static libselinux-devel libtool-ltdl-devel pkg-config selinux-policy selinux-policy-devel sqlite-devel systemd-devel tar git systemd-rpm-macros
|
||||
|
||||
ENV GO_VERSION 1.5.3
|
||||
ENV GO_VERSION 1.5.4
|
||||
RUN curl -fSL "https://storage.googleapis.com/golang/go${GO_VERSION}.linux-amd64.tar.gz" | tar xzC /usr/local
|
||||
ENV PATH $PATH:/usr/local/go/bin
|
||||
|
||||
ENV AUTO_GOPATH 1
|
||||
|
||||
ENV DOCKER_BUILDTAGS selinux
|
||||
ENV DOCKER_BUILDTAGS pkcs11 selinux
|
||||
ENV RUNC_BUILDTAGS selinux
|
||||
|
||||
|
||||
@@ -5,18 +5,19 @@
|
||||
FROM oraclelinux:6
|
||||
|
||||
RUN yum groupinstall -y "Development Tools"
|
||||
RUN yum install -y btrfs-progs-devel device-mapper-devel glibc-static libselinux-devel libtool-ltdl-devel pkgconfig selinux-policy selinux-policy-devel sqlite-devel tar
|
||||
RUN yum install -y btrfs-progs-devel device-mapper-devel glibc-static libselinux-devel libtool-ltdl-devel pkgconfig selinux-policy selinux-policy-devel sqlite-devel tar git
|
||||
|
||||
RUN yum install -y yum-utils && curl -o /etc/yum.repos.d/public-yum-ol6.repo http://yum.oracle.com/public-yum-ol6.repo && yum-config-manager -q --enable ol6_UEKR4
|
||||
RUN yum install -y kernel-uek-devel-4.1.12-32.el6uek
|
||||
|
||||
ENV GO_VERSION 1.5.3
|
||||
ENV GO_VERSION 1.5.4
|
||||
RUN curl -fSL "https://storage.googleapis.com/golang/go${GO_VERSION}.linux-amd64.tar.gz" | tar xzC /usr/local
|
||||
ENV PATH $PATH:/usr/local/go/bin
|
||||
|
||||
ENV AUTO_GOPATH 1
|
||||
|
||||
ENV DOCKER_BUILDTAGS selinux
|
||||
ENV DOCKER_BUILDTAGS pkcs11 selinux
|
||||
ENV RUNC_BUILDTAGS selinux
|
||||
|
||||
ENV CGO_CPPFLAGS -D__EXPORTED_HEADERS__ \
|
||||
-I/usr/src/kernels/4.1.12-32.el6uek.x86_64/arch/x86/include/generated/uapi \
|
||||
|
||||
@@ -5,13 +5,14 @@
|
||||
FROM oraclelinux:7
|
||||
|
||||
RUN yum groupinstall -y "Development Tools"
|
||||
RUN yum install -y --enablerepo=ol7_optional_latest btrfs-progs-devel device-mapper-devel glibc-static libselinux-devel libtool-ltdl-devel pkgconfig selinux-policy selinux-policy-devel sqlite-devel systemd-devel tar
|
||||
RUN yum install -y --enablerepo=ol7_optional_latest btrfs-progs-devel device-mapper-devel glibc-static libselinux-devel libtool-ltdl-devel pkgconfig selinux-policy selinux-policy-devel sqlite-devel systemd-devel tar git
|
||||
|
||||
ENV GO_VERSION 1.5.3
|
||||
ENV GO_VERSION 1.5.4
|
||||
RUN curl -fSL "https://storage.googleapis.com/golang/go${GO_VERSION}.linux-amd64.tar.gz" | tar xzC /usr/local
|
||||
ENV PATH $PATH:/usr/local/go/bin
|
||||
|
||||
ENV AUTO_GOPATH 1
|
||||
|
||||
ENV DOCKER_BUILDTAGS selinux
|
||||
ENV DOCKER_BUILDTAGS pkcs11 selinux
|
||||
ENV RUNC_BUILDTAGS selinux
|
||||
|
||||
|
||||
@@ -410,12 +410,12 @@ __docker_complete_log_drivers() {
|
||||
__docker_complete_log_options() {
|
||||
# see docs/reference/logging/index.md
|
||||
local awslogs_options="awslogs-region awslogs-group awslogs-stream"
|
||||
local fluentd_options="env fluentd-address labels tag"
|
||||
local fluentd_options="env fluentd-address fluentd-async-connect fluentd-buffer-limit fluentd-retry-wait fluentd-max-retries labels tag"
|
||||
local gcplogs_options="env gcp-log-cmd gcp-project labels"
|
||||
local gelf_options="env gelf-address gelf-compression-level gelf-compression-type labels tag"
|
||||
local journald_options="env labels tag"
|
||||
local json_file_options="env labels max-file max-size"
|
||||
local syslog_options="syslog-address syslog-tls-ca-cert syslog-tls-cert syslog-tls-key syslog-tls-skip-verify syslog-facility tag"
|
||||
local syslog_options="syslog-address syslog-format syslog-tls-ca-cert syslog-tls-cert syslog-tls-key syslog-tls-skip-verify syslog-facility tag"
|
||||
local splunk_options="env labels splunk-caname splunk-capath splunk-index splunk-insecureskipverify splunk-source splunk-sourcetype splunk-token splunk-url tag"
|
||||
|
||||
local all_options="$fluentd_options $gcplogs_options $gelf_options $journald_options $json_file_options $syslog_options $splunk_options"
|
||||
@@ -459,6 +459,10 @@ __docker_complete_log_options() {
|
||||
__docker_complete_log_driver_options() {
|
||||
local key=$(__docker_map_key_of_current_option '--log-opt')
|
||||
case "$key" in
|
||||
fluentd-async-connect)
|
||||
COMPREPLY=( $( compgen -W "false true" -- "${cur##*=}" ) )
|
||||
return
|
||||
;;
|
||||
gelf-address)
|
||||
COMPREPLY=( $( compgen -W "udp" -S "://" -- "${cur##*=}" ) )
|
||||
__docker_nospace
|
||||
@@ -503,6 +507,10 @@ __docker_complete_log_driver_options() {
|
||||
" -- "${cur##*=}" ) )
|
||||
return
|
||||
;;
|
||||
syslog-format)
|
||||
COMPREPLY=( $( compgen -W "rfc3164 rfc5424" -- "${cur##*=}" ) )
|
||||
return
|
||||
;;
|
||||
syslog-tls-@(ca-cert|cert|key))
|
||||
_filedir
|
||||
return
|
||||
@@ -611,7 +619,7 @@ _docker_attach() {
|
||||
|
||||
case "$cur" in
|
||||
-*)
|
||||
COMPREPLY=( $( compgen -W "--detach-keys --help --no-stdin --sig-proxy" -- "$cur" ) )
|
||||
COMPREPLY=( $( compgen -W "--detach-keys --help --no-stdin --sig-proxy=false" -- "$cur" ) )
|
||||
;;
|
||||
*)
|
||||
local counter=$(__docker_pos_first_nonflag '--detach-keys')
|
||||
@@ -633,6 +641,7 @@ _docker_build() {
|
||||
--cpu-quota
|
||||
--file -f
|
||||
--isolation
|
||||
--label
|
||||
--memory -m
|
||||
--memory-swap
|
||||
--shm-size
|
||||
@@ -697,7 +706,7 @@ _docker_commit() {
|
||||
|
||||
case "$cur" in
|
||||
-*)
|
||||
COMPREPLY=( $( compgen -W "--author -a --change -c --help --message -m --pause -p" -- "$cur" ) )
|
||||
COMPREPLY=( $( compgen -W "--author -a --change -c --help --message -m --pause=false -p=false" -- "$cur" ) )
|
||||
;;
|
||||
*)
|
||||
local counter=$(__docker_pos_first_nonflag '--author|-a|--change|-c|--message|-m')
|
||||
@@ -789,6 +798,7 @@ _docker_daemon() {
|
||||
--cluster-advertise
|
||||
--cluster-store
|
||||
--cluster-store-opt
|
||||
--containerd
|
||||
--default-gateway
|
||||
--default-gateway-v6
|
||||
--default-ulimit
|
||||
@@ -865,7 +875,7 @@ _docker_daemon() {
|
||||
__docker_complete_log_drivers
|
||||
return
|
||||
;;
|
||||
--pidfile|-p|--tlscacert|--tlscert|--tlskey)
|
||||
--containerd|--pidfile|-p|--tlscacert|--tlscert|--tlskey)
|
||||
_filedir
|
||||
return
|
||||
;;
|
||||
@@ -881,6 +891,7 @@ _docker_daemon() {
|
||||
dm.fs
|
||||
dm.loopdatasize
|
||||
dm.loopmetadatasize
|
||||
dm.min_free_space
|
||||
dm.mkfsarg
|
||||
dm.mountopt
|
||||
dm.override_udev_sync_check
|
||||
@@ -1071,7 +1082,7 @@ _docker_help() {
|
||||
_docker_history() {
|
||||
case "$cur" in
|
||||
-*)
|
||||
COMPREPLY=( $( compgen -W "--help --no-trunc --quiet -q" -- "$cur" ) )
|
||||
COMPREPLY=( $( compgen -W "--help --human=false -H=false --no-trunc --quiet -q" -- "$cur" ) )
|
||||
;;
|
||||
*)
|
||||
local counter=$(__docker_pos_first_nonflag)
|
||||
@@ -1211,7 +1222,7 @@ _docker_load() {
|
||||
|
||||
case "$cur" in
|
||||
-*)
|
||||
COMPREPLY=( $( compgen -W "--help --input -i" -- "$cur" ) )
|
||||
COMPREPLY=( $( compgen -W "--help --input -i --quiet -q" -- "$cur" ) )
|
||||
;;
|
||||
esac
|
||||
}
|
||||
@@ -1320,11 +1331,14 @@ _docker_network_create() {
|
||||
COMPREPLY=( $(compgen -W "$plugins" -- "$cur") )
|
||||
return
|
||||
;;
|
||||
--label)
|
||||
return
|
||||
;;
|
||||
esac
|
||||
|
||||
case "$cur" in
|
||||
-*)
|
||||
COMPREPLY=( $( compgen -W "--aux-address --driver -d --gateway --help --internal --ip-range --ipam-driver --ipam-opt --ipv6 --opt -o --subnet" -- "$cur" ) )
|
||||
COMPREPLY=( $( compgen -W "--aux-address --driver -d --gateway --help --internal --ip-range --ipam-driver --ipam-opt --ipv6 --label --opt -o --subnet" -- "$cur" ) )
|
||||
;;
|
||||
esac
|
||||
}
|
||||
@@ -1476,6 +1490,11 @@ _docker_ps() {
|
||||
COMPREPLY=( $( compgen -W "created dead exited paused restarting running" -- "${cur##*=}" ) )
|
||||
return
|
||||
;;
|
||||
volume)
|
||||
cur="${cur##*=}"
|
||||
__docker_complete_volumes
|
||||
return
|
||||
;;
|
||||
esac
|
||||
|
||||
case "$prev" in
|
||||
@@ -1483,7 +1502,7 @@ _docker_ps() {
|
||||
__docker_complete_containers_all
|
||||
;;
|
||||
--filter|-f)
|
||||
COMPREPLY=( $( compgen -S = -W "ancestor exited id label name status" -- "$cur" ) )
|
||||
COMPREPLY=( $( compgen -S = -W "ancestor exited id label name status volume" -- "$cur" ) )
|
||||
__docker_nospace
|
||||
return
|
||||
;;
|
||||
@@ -1654,6 +1673,7 @@ _docker_run() {
|
||||
--tmpfs
|
||||
--ulimit
|
||||
--user -u
|
||||
--userns
|
||||
--uts
|
||||
--volume-driver
|
||||
--volumes-from
|
||||
@@ -1690,6 +1710,24 @@ _docker_run() {
|
||||
__docker_complete_log_driver_options && return
|
||||
__docker_complete_restart && return
|
||||
|
||||
local key=$(__docker_map_key_of_current_option '--security-opt')
|
||||
case "$key" in
|
||||
label)
|
||||
[[ $cur == *: ]] && return
|
||||
COMPREPLY=( $( compgen -W "user: role: type: level: disable" -- "${cur##*=}") )
|
||||
if [ "${COMPREPLY[*]}" != "disable" ] ; then
|
||||
__docker_nospace
|
||||
fi
|
||||
return
|
||||
;;
|
||||
seccomp)
|
||||
local cur=${cur##*=}
|
||||
_filedir
|
||||
COMPREPLY+=( $( compgen -W "unconfined" -- "$cur" ) )
|
||||
return
|
||||
;;
|
||||
esac
|
||||
|
||||
case "$prev" in
|
||||
--add-host)
|
||||
case "$cur" in
|
||||
@@ -1787,32 +1825,20 @@ _docker_run() {
|
||||
return
|
||||
;;
|
||||
--security-opt)
|
||||
case "$cur" in
|
||||
label=*:*)
|
||||
;;
|
||||
label=*)
|
||||
local cur=${cur##*=}
|
||||
COMPREPLY=( $( compgen -W "user: role: type: level: disable" -- "$cur") )
|
||||
if [ "${COMPREPLY[*]}" != "disable" ] ; then
|
||||
__docker_nospace
|
||||
fi
|
||||
;;
|
||||
seccomp=*)
|
||||
local cur=${cur##*=}
|
||||
_filedir
|
||||
COMPREPLY+=( $( compgen -W "unconfined" -- "$cur" ) )
|
||||
;;
|
||||
*)
|
||||
COMPREPLY=( $( compgen -W "label apparmor seccomp" -S ":" -- "$cur") )
|
||||
__docker_nospace
|
||||
;;
|
||||
esac
|
||||
COMPREPLY=( $( compgen -W "apparmor= label= no-new-privileges seccomp=" -- "$cur") )
|
||||
if [ "${COMPREPLY[*]}" != "no-new-privileges" ] ; then
|
||||
__docker_nospace
|
||||
fi
|
||||
return
|
||||
;;
|
||||
--user|-u)
|
||||
__docker_complete_user_group
|
||||
return
|
||||
;;
|
||||
--userns)
|
||||
COMPREPLY=( $( compgen -W "host" -- "$cur" ) )
|
||||
return
|
||||
;;
|
||||
--volume-driver)
|
||||
__docker_complete_plugins Volume
|
||||
return
|
||||
@@ -2015,14 +2041,14 @@ _docker_volume_create() {
|
||||
__docker_complete_plugins Volume
|
||||
return
|
||||
;;
|
||||
--name|--opt|-o)
|
||||
--label|--name|--opt|-o)
|
||||
return
|
||||
;;
|
||||
esac
|
||||
|
||||
case "$cur" in
|
||||
-*)
|
||||
COMPREPLY=( $( compgen -W "--driver -d --help --name --opt -o" -- "$cur" ) )
|
||||
COMPREPLY=( $( compgen -W "--driver -d --help --label --name --opt -o" -- "$cur" ) )
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
@@ -50,11 +50,11 @@ __docker_arguments() {
|
||||
__docker_get_containers() {
|
||||
[[ $PREFIX = -* ]] && return 1
|
||||
integer ret=1
|
||||
local kind
|
||||
declare -a running stopped lines args
|
||||
local kind type line s
|
||||
declare -a running stopped lines args names
|
||||
|
||||
kind=$1
|
||||
shift
|
||||
kind=$1; shift
|
||||
type=$1; shift
|
||||
[[ $kind = (stopped|all) ]] && args=($args -a)
|
||||
|
||||
lines=(${(f)"$(_call_program commands docker $docker_options ps --no-trunc $args)"})
|
||||
@@ -73,39 +73,40 @@ __docker_get_containers() {
|
||||
lines=(${lines[2,-1]})
|
||||
|
||||
# Container ID
|
||||
local line
|
||||
local s
|
||||
for line in $lines; do
|
||||
s="${${line[${begin[CONTAINER ID]},${end[CONTAINER ID]}]%% ##}[0,12]}"
|
||||
s="$s:${(l:15:: :::)${${line[${begin[CREATED]},${end[CREATED]}]/ ago/}%% ##}}"
|
||||
s="$s, ${${${line[${begin[IMAGE]},${end[IMAGE]}]}/:/\\:}%% ##}"
|
||||
if [[ ${line[${begin[STATUS]},${end[STATUS]}]} = Exit* ]]; then
|
||||
stopped=($stopped $s)
|
||||
else
|
||||
running=($running $s)
|
||||
fi
|
||||
done
|
||||
if [[ $type = (ids|all) ]]; then
|
||||
for line in $lines; do
|
||||
s="${${line[${begin[CONTAINER ID]},${end[CONTAINER ID]}]%% ##}[0,12]}"
|
||||
s="$s:${(l:15:: :::)${${line[${begin[CREATED]},${end[CREATED]}]/ ago/}%% ##}}"
|
||||
s="$s, ${${${line[${begin[IMAGE]},${end[IMAGE]}]}/:/\\:}%% ##}"
|
||||
if [[ ${line[${begin[STATUS]},${end[STATUS]}]} = Exit* ]]; then
|
||||
stopped=($stopped $s)
|
||||
else
|
||||
running=($running $s)
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
# Names: we only display the one without slash. All other names
|
||||
# are generated and may clutter the completion. However, with
|
||||
# Swarm, all names may be prefixed by the swarm node name.
|
||||
local -a names
|
||||
for line in $lines; do
|
||||
names=(${(ps:,:)${${line[${begin[NAMES]},${end[NAMES]}]}%% *}})
|
||||
# First step: find a common prefix and strip it (swarm node case)
|
||||
(( ${#${(u)names%%/*}} == 1 )) && names=${names#${names[1]%%/*}/}
|
||||
# Second step: only keep the first name without a /
|
||||
s=${${names:#*/*}[1]}
|
||||
# If no name, well give up.
|
||||
(( $#s != 0 )) || continue
|
||||
s="$s:${(l:15:: :::)${${line[${begin[CREATED]},${end[CREATED]}]/ ago/}%% ##}}"
|
||||
s="$s, ${${${line[${begin[IMAGE]},${end[IMAGE]}]}/:/\\:}%% ##}"
|
||||
if [[ ${line[${begin[STATUS]},${end[STATUS]}]} = Exit* ]]; then
|
||||
stopped=($stopped $s)
|
||||
else
|
||||
running=($running $s)
|
||||
fi
|
||||
done
|
||||
if [[ $type = (names|all) ]]; then
|
||||
for line in $lines; do
|
||||
names=(${(ps:,:)${${line[${begin[NAMES]},${end[NAMES]}]}%% *}})
|
||||
# First step: find a common prefix and strip it (swarm node case)
|
||||
(( ${#${(u)names%%/*}} == 1 )) && names=${names#${names[1]%%/*}/}
|
||||
# Second step: only keep the first name without a /
|
||||
s=${${names:#*/*}[1]}
|
||||
# If no name, well give up.
|
||||
(( $#s != 0 )) || continue
|
||||
s="$s:${(l:15:: :::)${${line[${begin[CREATED]},${end[CREATED]}]/ ago/}%% ##}}"
|
||||
s="$s, ${${${line[${begin[IMAGE]},${end[IMAGE]}]}/:/\\:}%% ##}"
|
||||
if [[ ${line[${begin[STATUS]},${end[STATUS]}]} = Exit* ]]; then
|
||||
stopped=($stopped $s)
|
||||
else
|
||||
running=($running $s)
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
[[ $kind = (running|all) ]] && _describe -t containers-running "running containers" running "$@" && ret=0
|
||||
[[ $kind = (stopped|all) ]] && _describe -t containers-stopped "stopped containers" stopped "$@" && ret=0
|
||||
@@ -114,17 +115,27 @@ __docker_get_containers() {
|
||||
|
||||
__docker_stoppedcontainers() {
|
||||
[[ $PREFIX = -* ]] && return 1
|
||||
__docker_get_containers stopped "$@"
|
||||
__docker_get_containers stopped all "$@"
|
||||
}
|
||||
|
||||
__docker_runningcontainers() {
|
||||
[[ $PREFIX = -* ]] && return 1
|
||||
__docker_get_containers running "$@"
|
||||
__docker_get_containers running all "$@"
|
||||
}
|
||||
|
||||
__docker_containers() {
|
||||
[[ $PREFIX = -* ]] && return 1
|
||||
__docker_get_containers all "$@"
|
||||
__docker_get_containers all all "$@"
|
||||
}
|
||||
|
||||
__docker_containers_ids() {
|
||||
[[ $PREFIX = -* ]] && return 1
|
||||
__docker_get_containers all ids "$@"
|
||||
}
|
||||
|
||||
__docker_containers_names() {
|
||||
[[ $PREFIX = -* ]] && return 1
|
||||
__docker_get_containers all names "$@"
|
||||
}
|
||||
|
||||
__docker_images() {
|
||||
@@ -200,12 +211,12 @@ __docker_get_log_options() {
|
||||
local -a awslogs_options fluentd_options gelf_options journald_options json_file_options syslog_options splunk_options
|
||||
|
||||
awslogs_options=("awslogs-region" "awslogs-group" "awslogs-stream")
|
||||
fluentd_options=("env" "fluentd-address" "labels" "tag")
|
||||
fluentd_options=("env" "fluentd-address" "fluentd-async-connect" "fluentd-buffer-limit" "fluentd-retry-wait" "fluentd-max-retries" "labels" "tag")
|
||||
gcplogs_options=("env" "gcp-log-cmd" "gcp-project" "labels")
|
||||
gelf_options=("env" "gelf-address" "labels" "tag")
|
||||
journald_options=("env" "labels")
|
||||
gelf_options=("env" "gelf-address" "gelf-compression-level" "gelf-compression-type" "labels" "tag")
|
||||
journald_options=("env" "labels" "tag")
|
||||
json_file_options=("env" "labels" "max-file" "max-size")
|
||||
syslog_options=("syslog-address" "syslog-tls-ca-cert" "syslog-tls-cert" "syslog-tls-key" "syslog-tls-skip-verify" "syslog-facility" "tag")
|
||||
syslog_options=("syslog-address" "syslog-format" "syslog-tls-ca-cert" "syslog-tls-cert" "syslog-tls-key" "syslog-tls-skip-verify" "syslog-facility" "tag")
|
||||
splunk_options=("env" "labels" "splunk-caname" "splunk-capath" "splunk-index" "splunk-insecureskipverify" "splunk-source" "splunk-sourcetype" "splunk-token" "splunk-url" "tag")
|
||||
|
||||
[[ $log_driver = (awslogs|all) ]] && _describe -t awslogs-options "awslogs options" awslogs_options "$@" && ret=0
|
||||
@@ -225,7 +236,15 @@ __docker_log_options() {
|
||||
integer ret=1
|
||||
|
||||
if compset -P '*='; then
|
||||
_message 'value' && ret=0
|
||||
case "${${words[-1]%=*}#*=}" in
|
||||
(syslog-format)
|
||||
syslog_format_opts=('rfc3164' 'rfc5424')
|
||||
_describe -t syslog-format-opts "Syslog format Options" syslog_format_opts && ret=0
|
||||
;;
|
||||
*)
|
||||
_message 'value' && ret=0
|
||||
;;
|
||||
esac
|
||||
else
|
||||
__docker_get_log_options -qS "=" && ret=0
|
||||
fi
|
||||
@@ -244,6 +263,43 @@ __docker_complete_detach_keys() {
|
||||
_describe -t detach_keys-ctrl "'ctrl-' + 'a-z @ [ \\\\ ] ^ _'" ctrl_keys -qS "," && ret=0
|
||||
}
|
||||
|
||||
__docker_complete_ps_filters() {
|
||||
[[ $PREFIX = -* ]] && return 1
|
||||
integer ret=1
|
||||
|
||||
if compset -P '*='; then
|
||||
case "${${words[-1]%=*}#*=}" in
|
||||
(ancestor)
|
||||
__docker_images && ret=0
|
||||
;;
|
||||
(before|since)
|
||||
__docker_containers && ret=0
|
||||
;;
|
||||
(id)
|
||||
__docker_containers_ids && ret=0
|
||||
;;
|
||||
(name)
|
||||
__docker_containers_names && ret=0
|
||||
;;
|
||||
(status)
|
||||
status_opts=('created' 'dead' 'exited' 'paused' 'restarting' 'running')
|
||||
_describe -t status-filter-opts "Status Filter Options" status_opts && ret=0
|
||||
;;
|
||||
(volume)
|
||||
__docker_volumes && ret=0
|
||||
;;
|
||||
*)
|
||||
_message 'value' && ret=0
|
||||
;;
|
||||
esac
|
||||
else
|
||||
opts=('ancestor' 'before' 'exited' 'id' 'label' 'name' 'since' 'status' 'volume')
|
||||
_describe -t filter-opts "Filter Options" opts -qS "=" && ret=0
|
||||
fi
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
__docker_networks() {
|
||||
[[ $PREFIX = -* ]] && return 1
|
||||
integer ret=1
|
||||
@@ -335,6 +391,7 @@ __docker_network_subcommand() {
|
||||
"($help)--ipam-driver=[IP Address Management Driver]:driver:(default)" \
|
||||
"($help)*--ipam-opt=[Custom IPAM plugin options]:opt=value: " \
|
||||
"($help)--ipv6[Enable IPv6 networking]" \
|
||||
"($help)*--label=[Set metadata on a network]:label=value: " \
|
||||
"($help)*"{-o=,--opt=}"[Driver specific options]:opt=value: " \
|
||||
"($help)*--subnet=[Subnet in CIDR format that represents a network segment]:IP/mask: " \
|
||||
"($help -)1:Network Name: " && ret=0
|
||||
@@ -425,6 +482,7 @@ __docker_volume_subcommand() {
|
||||
_arguments $(__docker_arguments) \
|
||||
$opts_help \
|
||||
"($help -d --driver)"{-d=,--driver=}"[Volume driver name]:Driver name:(local)" \
|
||||
"($help)*--label=[Set metadata for a volume]:label=value: " \
|
||||
"($help)--name=[Volume name]" \
|
||||
"($help)*"{-o=,--opt=}"[Driver specific options]:Driver option: " && ret=0
|
||||
;;
|
||||
@@ -489,6 +547,7 @@ __docker_subcommand() {
|
||||
"($help)--isolation=[Container isolation technology]:isolation:(default hyperv process)"
|
||||
"($help)*--shm-size=[Size of '/dev/shm' (format is '<number><unit>')]:shm size: "
|
||||
"($help)*--ulimit=[ulimit options]:ulimit: "
|
||||
"($help)--userns=[Container user namespace]:user namespace:(host)"
|
||||
)
|
||||
opts_build_create_run_update=(
|
||||
"($help)--cpu-shares=[CPU shares (relative weight)]:CPU shares:(0 10 100 200 500 800 1000)"
|
||||
@@ -526,7 +585,7 @@ __docker_subcommand() {
|
||||
"($help)--ipc=[IPC namespace to use]:IPC namespace: "
|
||||
"($help)*--link=[Add link to another container]:link:->link"
|
||||
"($help)*"{-l=,--label=}"[Container metadata]:label: "
|
||||
"($help)--log-driver=[Default driver for container logs]:Logging driver:(json-file syslog journald gelf fluentd awslogs splunk none)"
|
||||
"($help)--log-driver=[Default driver for container logs]:Logging driver:(awslogs etwlogs fluentd gcplogs gelf journald json-file none splunk syslog)"
|
||||
"($help)*--log-opt=[Log driver specific options]:log driver options:__docker_log_options"
|
||||
"($help)--mac-address=[Container MAC address]:MAC address: "
|
||||
"($help)--name=[Container name]:name: "
|
||||
@@ -540,7 +599,6 @@ __docker_subcommand() {
|
||||
"($help)--pid=[PID namespace to use]:PID: "
|
||||
"($help)--privileged[Give extended privileges to this container]"
|
||||
"($help)--read-only[Mount the container's root filesystem as read only]"
|
||||
"($help)--restart=[Restart policy]:restart policy:(no on-failure always unless-stopped)"
|
||||
"($help)*--security-opt=[Security options]:security option: "
|
||||
"($help -t --tty)"{-t,--tty}"[Allocate a pseudo-tty]"
|
||||
"($help -u --user)"{-u=,--user=}"[Username or UID]:user:_users"
|
||||
@@ -554,6 +612,7 @@ __docker_subcommand() {
|
||||
"($help)--blkio-weight=[Block IO (relative weight), between 10 and 1000]:Block IO weight:(10 100 500 1000)"
|
||||
"($help)--kernel-memory=[Kernel memory limit in bytes]:Memory limit: "
|
||||
"($help)--memory-reservation=[Memory soft limit]:Memory limit: "
|
||||
"($help)--restart=[Restart policy]:restart policy:(no on-failure always unless-stopped)"
|
||||
)
|
||||
opts_attach_exec_run_start=(
|
||||
"($help)--detach-keys=[Escape key sequence used to detach a container]:sequence:__docker_complete_detach_keys"
|
||||
@@ -576,6 +635,7 @@ __docker_subcommand() {
|
||||
"($help)*--build-arg[Build-time variables]:<varname>=<value>: " \
|
||||
"($help -f --file)"{-f=,--file=}"[Name of the Dockerfile]:Dockerfile:_files" \
|
||||
"($help)--force-rm[Always remove intermediate containers]" \
|
||||
"($help)*--label=[Set metadata for an image]:label=value: " \
|
||||
"($help)--no-cache[Do not use cache when building the image]" \
|
||||
"($help)--pull[Attempt to pull a newer version of the image]" \
|
||||
"($help -q --quiet)"{-q,--quiet}"[Suppress verbose build output]" \
|
||||
@@ -639,6 +699,7 @@ __docker_subcommand() {
|
||||
"($help -b --bridge)"{-b=,--bridge=}"[Attach containers to a network bridge]:bridge:_net_interfaces" \
|
||||
"($help)--bip=[Network bridge IP]:IP address: " \
|
||||
"($help)--cgroup-parent=[Parent cgroup for all containers]:cgroup: " \
|
||||
"($help)--containerd=[Path to containerd socket]:socket:_files -g \"*.sock\"" \
|
||||
"($help -D --debug)"{-D,--debug}"[Enable debug mode]" \
|
||||
"($help)--default-gateway[Container default gateway IPv4 address]:IPv4 address: " \
|
||||
"($help)--default-gateway-v6[Container default gateway IPv6 address]:IPv6 address: " \
|
||||
@@ -666,7 +727,7 @@ __docker_subcommand() {
|
||||
"($help)--ipv6[Enable IPv6 networking]" \
|
||||
"($help -l --log-level)"{-l=,--log-level=}"[Logging level]:level:(debug info warn error fatal)" \
|
||||
"($help)*--label=[Key=value labels]:label: " \
|
||||
"($help)--log-driver=[Default driver for container logs]:Logging driver:(json-file syslog journald gelf fluentd awslogs splunk none)" \
|
||||
"($help)--log-driver=[Default driver for container logs]:Logging driver:(awslogs etwlogs fluentd gcplogs gelf journald json-file none splunk syslog)" \
|
||||
"($help)*--log-opt=[Log driver specific options]:log driver options:__docker_log_options" \
|
||||
"($help)--mtu=[Network MTU]:mtu:(0 576 1420 1500 9000)" \
|
||||
"($help -p --pidfile)"{-p=,--pidfile=}"[Path to use for daemon PID file]:PID file:_files" \
|
||||
@@ -676,9 +737,9 @@ __docker_subcommand() {
|
||||
"($help)--selinux-enabled[Enable selinux support]" \
|
||||
"($help)*--storage-opt=[Storage driver options]:storage driver options: " \
|
||||
"($help)--tls[Use TLS]" \
|
||||
"($help)--tlscacert=[Trust certs signed only by this CA]:PEM file:_files -g "*.(pem|crt)"" \
|
||||
"($help)--tlscert=[Path to TLS certificate file]:PEM file:_files -g "*.(pem|crt)"" \
|
||||
"($help)--tlskey=[Path to TLS key file]:Key file:_files -g "*.(pem|key)"" \
|
||||
"($help)--tlscacert=[Trust certs signed only by this CA]:PEM file:_files -g \"*.(pem|crt)\"" \
|
||||
"($help)--tlscert=[Path to TLS certificate file]:PEM file:_files -g \"*.(pem|crt)\"" \
|
||||
"($help)--tlskey=[Path to TLS key file]:Key file:_files -g \"*.(pem|key)\"" \
|
||||
"($help)--tlsverify[Use TLS and verify the remote]" \
|
||||
"($help)--userns-remap=[User/Group setting for user namespaces]:user\:group:->users-groups" \
|
||||
"($help)--userland-proxy[Use userland proxy for loopback traffic]" && ret=0
|
||||
@@ -810,7 +871,8 @@ __docker_subcommand() {
|
||||
(load)
|
||||
_arguments $(__docker_arguments) \
|
||||
$opts_help \
|
||||
"($help -i --input)"{-i=,--input=}"[Read from tar archive file]:archive file:_files -g "*.((tar|TAR)(.gz|.GZ|.Z|.bz2|.lzma|.xz|)|(tbz|tgz|txz))(-.)"" && ret=0
|
||||
"($help -i --input)"{-i=,--input=}"[Read from tar archive file]:archive file:_files -g \"*.((tar|TAR)(.gz|.GZ|.Z|.bz2|.lzma|.xz|)|(tbz|tgz|txz))(-.)\"" \
|
||||
"($help -q --quiet)"{-q,--quiet}"[Suppress the load output]" && ret=0
|
||||
;;
|
||||
(login)
|
||||
_arguments $(__docker_arguments) \
|
||||
@@ -866,7 +928,7 @@ __docker_subcommand() {
|
||||
$opts_help \
|
||||
"($help -a --all)"{-a,--all}"[Show all containers]" \
|
||||
"($help)--before=[Show only container created before...]:containers:__docker_containers" \
|
||||
"($help)*"{-f=,--filter=}"[Filter values]:filter: " \
|
||||
"($help)*"{-f=,--filter=}"[Filter values]:filter:->filter-options" \
|
||||
"($help)--format[Pretty-print containers using a Go template]:format: " \
|
||||
"($help -l --latest)"{-l,--latest}"[Show only the latest created container]" \
|
||||
"($help)-n[Show n last created containers, include non-running one]:n:(1 5 10 25 50)" \
|
||||
@@ -874,16 +936,24 @@ __docker_subcommand() {
|
||||
"($help -q --quiet)"{-q,--quiet}"[Only show numeric IDs]" \
|
||||
"($help -s --size)"{-s,--size}"[Display total file sizes]" \
|
||||
"($help)--since=[Show only containers created since...]:containers:__docker_containers" && ret=0
|
||||
|
||||
case $state in
|
||||
(filter-options)
|
||||
__docker_complete_ps_filters && ret=0
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
(pull)
|
||||
_arguments $(__docker_arguments) \
|
||||
$opts_help \
|
||||
"($help -a --all-tags)"{-a,--all-tags}"[Download all tagged images]" \
|
||||
"($help)--disable-content-trust[Skip image verification]" \
|
||||
"($help -):name:__docker_search" && ret=0
|
||||
;;
|
||||
(push)
|
||||
_arguments $(__docker_arguments) \
|
||||
$opts_help \
|
||||
"($help)--disable-content-trust[Skip image signing]" \
|
||||
"($help -): :__docker_images" && ret=0
|
||||
;;
|
||||
(rename)
|
||||
|
||||
@@ -222,6 +222,7 @@ func (daemon *Daemon) exportContainerRw(container *container.Container) (archive
|
||||
|
||||
archive, err := container.RWLayer.TarStream()
|
||||
if err != nil {
|
||||
daemon.Unmount(container) // logging is already handled in the `Unmount` function
|
||||
return nil, err
|
||||
}
|
||||
return ioutils.NewReadCloserWrapper(archive, func() error {
|
||||
|
||||
@@ -82,7 +82,7 @@ func (config *Config) InstallFlags(cmd *flag.FlagSet, usageFn func(string) strin
|
||||
cmd.StringVar(&config.CorsHeaders, []string{"-api-cors-header"}, "", usageFn("Set CORS headers in the remote API"))
|
||||
cmd.StringVar(&config.CgroupParent, []string{"-cgroup-parent"}, "", usageFn("Set parent cgroup for all containers"))
|
||||
cmd.StringVar(&config.RemappedRoot, []string{"-userns-remap"}, "", usageFn("User/Group setting for user namespaces"))
|
||||
cmd.StringVar(&config.ContainerdAddr, []string{"-containerd"}, "", usageFn("Path to containerD socket"))
|
||||
cmd.StringVar(&config.ContainerdAddr, []string{"-containerd"}, "", usageFn("Path to containerd socket"))
|
||||
|
||||
config.attachExperimentalFlags(cmd, usageFn)
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ var (
|
||||
// ErrRootFSReadOnly is returned when a container
|
||||
// rootfs is marked readonly.
|
||||
ErrRootFSReadOnly = errors.New("container rootfs is marked read-only")
|
||||
getPortMapInfo = container.GetSandboxPortMapInfo
|
||||
)
|
||||
|
||||
func (daemon *Daemon) buildSandboxOptions(container *container.Container, n libnetwork.Network) ([]libnetwork.SandboxOption, error) {
|
||||
@@ -581,6 +582,8 @@ func (daemon *Daemon) connectToNetwork(container *container.Container, idOrName
|
||||
return fmt.Errorf("Updating join info failed: %v", err)
|
||||
}
|
||||
|
||||
container.NetworkSettings.Ports = getPortMapInfo(sb)
|
||||
|
||||
daemon.LogNetworkEventWithAttributes(n, "connect", map[string]string{"container": container.ID})
|
||||
return nil
|
||||
}
|
||||
@@ -633,6 +636,8 @@ func disconnectFromNetwork(container *container.Container, n libnetwork.Network,
|
||||
return fmt.Errorf("container %s failed to leave network %s: %v", container.ID, n.Name(), err)
|
||||
}
|
||||
|
||||
container.NetworkSettings.Ports = getPortMapInfo(sbox)
|
||||
|
||||
if err := ep.Delete(false); err != nil {
|
||||
return fmt.Errorf("endpoint delete failed for container %s on network %s: %v", container.ID, n.Name(), err)
|
||||
}
|
||||
@@ -720,7 +725,7 @@ func (daemon *Daemon) releaseNetwork(container *container.Container) {
|
||||
|
||||
sb, err := daemon.netController.SandboxByID(sid)
|
||||
if err != nil {
|
||||
logrus.Errorf("error locating sandbox id %s: %v", sid, err)
|
||||
logrus.Warnf("error locating sandbox id %s: %v", sid, err)
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -295,7 +295,18 @@ func specDevice(d *configs.Device) specs.Device {
|
||||
}
|
||||
}
|
||||
|
||||
func getDevicesFromPath(deviceMapping containertypes.DeviceMapping) (devs []specs.Device, err error) {
|
||||
func specDeviceCgroup(d *configs.Device) specs.DeviceCgroup {
|
||||
t := string(d.Type)
|
||||
return specs.DeviceCgroup{
|
||||
Allow: true,
|
||||
Type: &t,
|
||||
Major: &d.Major,
|
||||
Minor: &d.Minor,
|
||||
Access: &d.Permissions,
|
||||
}
|
||||
}
|
||||
|
||||
func getDevicesFromPath(deviceMapping containertypes.DeviceMapping) (devs []specs.Device, devPermissions []specs.DeviceCgroup, err error) {
|
||||
resolvedPathOnHost := deviceMapping.PathOnHost
|
||||
|
||||
// check if it is a symbolic link
|
||||
@@ -309,7 +320,7 @@ func getDevicesFromPath(deviceMapping containertypes.DeviceMapping) (devs []spec
|
||||
// if there was no error, return the device
|
||||
if err == nil {
|
||||
device.Path = deviceMapping.PathInContainer
|
||||
return append(devs, specDevice(device)), nil
|
||||
return append(devs, specDevice(device)), append(devPermissions, specDeviceCgroup(device)), nil
|
||||
}
|
||||
|
||||
// if the device is not a device node
|
||||
@@ -330,6 +341,7 @@ func getDevicesFromPath(deviceMapping containertypes.DeviceMapping) (devs []spec
|
||||
// add the device to userSpecified devices
|
||||
childDevice.Path = strings.Replace(dpath, resolvedPathOnHost, deviceMapping.PathInContainer, 1)
|
||||
devs = append(devs, specDevice(childDevice))
|
||||
devPermissions = append(devPermissions, specDeviceCgroup(childDevice))
|
||||
|
||||
return nil
|
||||
})
|
||||
@@ -337,10 +349,10 @@ func getDevicesFromPath(deviceMapping containertypes.DeviceMapping) (devs []spec
|
||||
}
|
||||
|
||||
if len(devs) > 0 {
|
||||
return devs, nil
|
||||
return devs, devPermissions, nil
|
||||
}
|
||||
|
||||
return devs, fmt.Errorf("error gathering device information while adding custom device %q: %s", deviceMapping.PathOnHost, err)
|
||||
return devs, devPermissions, fmt.Errorf("error gathering device information while adding custom device %q: %s", deviceMapping.PathOnHost, err)
|
||||
}
|
||||
|
||||
func mergeDevices(defaultDevices, userDevices []*configs.Device) []*configs.Device {
|
||||
|
||||
@@ -140,6 +140,10 @@ type Daemon struct {
|
||||
// unique enough to only return a single container object
|
||||
// If none of these searches succeed, an error is returned
|
||||
func (daemon *Daemon) GetContainer(prefixOrName string) (*container.Container, error) {
|
||||
if len(prefixOrName) == 0 {
|
||||
return nil, errors.NewBadRequestError(fmt.Errorf("No container name or ID supplied"))
|
||||
}
|
||||
|
||||
if containerByID := daemon.containers.Get(prefixOrName); containerByID != nil {
|
||||
// prefix is an exact match to a full container ID
|
||||
return containerByID, nil
|
||||
@@ -293,6 +297,11 @@ func (daemon *Daemon) restore() error {
|
||||
go func(c *container.Container) {
|
||||
defer wg.Done()
|
||||
if c.IsRunning() || c.IsPaused() {
|
||||
// Fix activityCount such that graph mounts can be unmounted later
|
||||
if err := daemon.layerStore.ReinitRWLayer(c.RWLayer); err != nil {
|
||||
logrus.Errorf("Failed to ReinitRWLayer for %s due to %s", c.ID, err)
|
||||
return
|
||||
}
|
||||
if err := daemon.containerd.Restore(c.ID, libcontainerd.WithRestartManager(c.RestartManager(true))); err != nil {
|
||||
logrus.Errorf("Failed to restore with containerd: %q", err)
|
||||
return
|
||||
@@ -300,14 +309,10 @@ func (daemon *Daemon) restore() error {
|
||||
}
|
||||
// fixme: only if not running
|
||||
// get list of containers we need to restart
|
||||
if daemon.configStore.AutoRestart && !c.IsRunning() && !c.IsPaused() && c.ShouldRestart() {
|
||||
if daemon.configStore.AutoRestart && !c.IsRunning() && !c.IsPaused() && c.ShouldRestartOnBoot() {
|
||||
mapLock.Lock()
|
||||
restartContainers[c] = make(chan struct{})
|
||||
mapLock.Unlock()
|
||||
} else if !c.IsRunning() && !c.IsPaused() {
|
||||
if mountid, err := daemon.layerStore.GetMountID(c.ID); err == nil {
|
||||
daemon.cleanupMountsByID(mountid)
|
||||
}
|
||||
}
|
||||
|
||||
// if c.hostConfig.Links is nil (not just empty), then it is using the old sqlite links and needs to be migrated
|
||||
@@ -362,6 +367,9 @@ func (daemon *Daemon) restore() error {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure networks are available before starting
|
||||
daemon.waitForNetworks(c)
|
||||
if err := daemon.containerStart(c); err != nil {
|
||||
logrus.Errorf("Failed to start container %s: %s", c.ID, err)
|
||||
}
|
||||
@@ -405,6 +413,33 @@ func (daemon *Daemon) restore() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// waitForNetworks is used during daemon initialization when starting up containers
|
||||
// It ensures that all of a container's networks are available before the daemon tries to start the container.
|
||||
// In practice it just makes sure the discovery service is available for containers which use a network that require discovery.
|
||||
func (daemon *Daemon) waitForNetworks(c *container.Container) {
|
||||
if daemon.discoveryWatcher == nil {
|
||||
return
|
||||
}
|
||||
// Make sure if the container has a network that requires discovery that the discovery service is available before starting
|
||||
for netName := range c.NetworkSettings.Networks {
|
||||
// If we get `ErrNoSuchNetwork` here, it can assumed that it is due to discovery not being ready
|
||||
// Most likely this is because the K/V store used for discovery is in a container and needs to be started
|
||||
if _, err := daemon.netController.NetworkByName(netName); err != nil {
|
||||
if _, ok := err.(libnetwork.ErrNoSuchNetwork); !ok {
|
||||
continue
|
||||
}
|
||||
// use a longish timeout here due to some slowdowns in libnetwork if the k/v store is on anything other than --net=host
|
||||
// FIXME: why is this slow???
|
||||
logrus.Debugf("Container %s waiting for network to be ready", c.Name)
|
||||
select {
|
||||
case <-daemon.discoveryWatcher.ReadyCh():
|
||||
case <-time.After(60 * time.Second):
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (daemon *Daemon) mergeAndVerifyConfig(config *containertypes.Config, img *image.Image) error {
|
||||
if img != nil && img.Config != nil {
|
||||
if err := merge(config, img.Config); err != nil {
|
||||
@@ -531,6 +566,9 @@ func (daemon *Daemon) newContainer(name string, config *containertypes.Config, i
|
||||
|
||||
// GetByName returns a container given a name.
|
||||
func (daemon *Daemon) GetByName(name string) (*container.Container, error) {
|
||||
if len(name) == 0 {
|
||||
return nil, fmt.Errorf("No container name supplied")
|
||||
}
|
||||
fullName := name
|
||||
if name[0] != '/' {
|
||||
fullName = "/" + name
|
||||
@@ -1597,7 +1635,7 @@ func (daemon *Daemon) initDiscovery(config *Config) error {
|
||||
func (daemon *Daemon) Reload(config *Config) error {
|
||||
daemon.configStore.reloadLock.Lock()
|
||||
defer daemon.configStore.reloadLock.Unlock()
|
||||
if config.IsValueSet("label") {
|
||||
if config.IsValueSet("labels") {
|
||||
daemon.configStore.Labels = config.Labels
|
||||
}
|
||||
if config.IsValueSet("debug") {
|
||||
|
||||
@@ -5,7 +5,7 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
@@ -28,91 +28,53 @@ func (daemon *Daemon) cleanupMountsFromReaderByID(reader io.Reader, id string, u
|
||||
return nil
|
||||
}
|
||||
var errors []string
|
||||
mountRoot := ""
|
||||
shmSuffix := "/" + id + "/shm"
|
||||
mergedSuffix := "/" + id + "/merged"
|
||||
|
||||
regexps := getCleanPatterns(id)
|
||||
sc := bufio.NewScanner(reader)
|
||||
for sc.Scan() {
|
||||
line := sc.Text()
|
||||
fields := strings.Fields(line)
|
||||
if strings.HasPrefix(fields[4], daemon.root) {
|
||||
logrus.Debugf("Mount base: %v", fields[4])
|
||||
mnt := fields[4]
|
||||
if strings.HasSuffix(mnt, shmSuffix) || strings.HasSuffix(mnt, mergedSuffix) {
|
||||
logrus.Debugf("Unmounting %v", mnt)
|
||||
if err := unmount(mnt); err != nil {
|
||||
logrus.Error(err)
|
||||
errors = append(errors, err.Error())
|
||||
if fields := strings.Fields(sc.Text()); len(fields) >= 4 {
|
||||
if mnt := fields[4]; strings.HasPrefix(mnt, daemon.root) {
|
||||
for _, p := range regexps {
|
||||
if p.MatchString(mnt) {
|
||||
if err := unmount(mnt); err != nil {
|
||||
logrus.Error(err)
|
||||
errors = append(errors, err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if mountBase := filepath.Base(mnt); mountBase == id {
|
||||
mountRoot = mnt
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if mountRoot != "" {
|
||||
logrus.Debugf("Unmounting %v", mountRoot)
|
||||
if err := unmount(mountRoot); err != nil {
|
||||
logrus.Error(err)
|
||||
errors = append(errors, err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
if err := sc.Err(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(errors) > 0 {
|
||||
return fmt.Errorf("Error cleaningup mounts:\n%v", strings.Join(errors, "\n"))
|
||||
return fmt.Errorf("Error cleaning up mounts:\n%v", strings.Join(errors, "\n"))
|
||||
}
|
||||
|
||||
logrus.Debugf("Cleaning up old container shm/mqueue/rootfs mounts: done.")
|
||||
logrus.Debugf("Cleaning up old mountid %v: done.", id)
|
||||
return nil
|
||||
}
|
||||
|
||||
// cleanupMounts umounts shm/mqueue mounts for old containers
|
||||
func (daemon *Daemon) cleanupMounts() error {
|
||||
logrus.Debugf("Cleaning up old container shm/mqueue/rootfs mounts: start.")
|
||||
f, err := os.Open("/proc/self/mountinfo")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
return daemon.cleanupMountsFromReader(f, mount.Unmount)
|
||||
return daemon.cleanupMountsByID("")
|
||||
}
|
||||
|
||||
func (daemon *Daemon) cleanupMountsFromReader(reader io.Reader, unmount func(target string) error) error {
|
||||
if daemon.root == "" {
|
||||
return nil
|
||||
func getCleanPatterns(id string) (regexps []*regexp.Regexp) {
|
||||
var patterns []string
|
||||
if id == "" {
|
||||
id = "[0-9a-f]{64}"
|
||||
patterns = append(patterns, "containers/"+id+"/shm")
|
||||
}
|
||||
sc := bufio.NewScanner(reader)
|
||||
var errors []string
|
||||
for sc.Scan() {
|
||||
line := sc.Text()
|
||||
fields := strings.Fields(line)
|
||||
if strings.HasPrefix(fields[4], daemon.root) {
|
||||
logrus.Debugf("Mount base: %v", fields[4])
|
||||
mnt := fields[4]
|
||||
mountBase := filepath.Base(mnt)
|
||||
if mountBase == "shm" || mountBase == "merged" {
|
||||
logrus.Debugf("Unmounting %v", mnt)
|
||||
if err := unmount(mnt); err != nil {
|
||||
logrus.Error(err)
|
||||
errors = append(errors, err.Error())
|
||||
}
|
||||
}
|
||||
patterns = append(patterns, "aufs/mnt/"+id+"$", "overlay/"+id+"/merged$", "zfs/graph/"+id+"$")
|
||||
for _, p := range patterns {
|
||||
r, err := regexp.Compile(p)
|
||||
if err == nil {
|
||||
regexps = append(regexps, r)
|
||||
}
|
||||
}
|
||||
|
||||
if err := sc.Err(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(errors) > 0 {
|
||||
return fmt.Errorf("Error cleaningup mounts:\n%v", strings.Join(errors, "\n"))
|
||||
}
|
||||
|
||||
logrus.Debugf("Cleaning up old container shm/mqueue/rootfs mounts: done.")
|
||||
return nil
|
||||
return
|
||||
}
|
||||
|
||||
@@ -59,7 +59,7 @@ func TestCleanupMounts(t *testing.T) {
|
||||
return nil
|
||||
}
|
||||
|
||||
d.cleanupMountsFromReader(strings.NewReader(mountsFixture), unmount)
|
||||
d.cleanupMountsFromReaderByID(strings.NewReader(mountsFixture), "", unmount)
|
||||
|
||||
if unmounted != 1 {
|
||||
t.Fatalf("Expected to unmount the shm (and the shm only)")
|
||||
@@ -97,7 +97,7 @@ func TestNotCleanupMounts(t *testing.T) {
|
||||
return nil
|
||||
}
|
||||
mountInfo := `234 232 0:59 / /dev/shm rw,nosuid,nodev,noexec,relatime - tmpfs shm rw,size=65536k`
|
||||
d.cleanupMountsFromReader(strings.NewReader(mountInfo), unmount)
|
||||
d.cleanupMountsFromReaderByID(strings.NewReader(mountInfo), "", unmount)
|
||||
if unmounted {
|
||||
t.Fatalf("Expected not to clean up /dev/shm")
|
||||
}
|
||||
|
||||
@@ -320,7 +320,7 @@ func TestDaemonReloadLabels(t *testing.T) {
|
||||
}
|
||||
|
||||
valuesSets := make(map[string]interface{})
|
||||
valuesSets["label"] = "foo:baz"
|
||||
valuesSets["labels"] = "foo:baz"
|
||||
newConfig := &Config{
|
||||
CommonConfig: CommonConfig{
|
||||
Labels: []string{"foo:baz"},
|
||||
@@ -345,7 +345,7 @@ func TestDaemonReloadNotAffectOthers(t *testing.T) {
|
||||
}
|
||||
|
||||
valuesSets := make(map[string]interface{})
|
||||
valuesSets["label"] = "foo:baz"
|
||||
valuesSets["labels"] = "foo:baz"
|
||||
newConfig := &Config{
|
||||
CommonConfig: CommonConfig{
|
||||
Labels: []string{"foo:baz"},
|
||||
@@ -381,6 +381,12 @@ func TestDaemonDiscoveryReload(t *testing.T) {
|
||||
&discovery.Entry{Host: "127.0.0.1", Port: "3333"},
|
||||
}
|
||||
|
||||
select {
|
||||
case <-time.After(10 * time.Second):
|
||||
t.Fatal("timeout waiting for discovery")
|
||||
case <-daemon.discoveryWatcher.ReadyCh():
|
||||
}
|
||||
|
||||
stopCh := make(chan struct{})
|
||||
defer close(stopCh)
|
||||
ch, errCh := daemon.discoveryWatcher.Watch(stopCh)
|
||||
@@ -414,6 +420,13 @@ func TestDaemonDiscoveryReload(t *testing.T) {
|
||||
if err := daemon.Reload(newConfig); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
select {
|
||||
case <-time.After(10 * time.Second):
|
||||
t.Fatal("timeout waiting for discovery")
|
||||
case <-daemon.discoveryWatcher.ReadyCh():
|
||||
}
|
||||
|
||||
ch, errCh = daemon.discoveryWatcher.Watch(stopCh)
|
||||
|
||||
select {
|
||||
@@ -450,6 +463,13 @@ func TestDaemonDiscoveryReloadFromEmptyDiscovery(t *testing.T) {
|
||||
if err := daemon.Reload(newConfig); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
select {
|
||||
case <-time.After(10 * time.Second):
|
||||
t.Fatal("timeout waiting for discovery")
|
||||
case <-daemon.discoveryWatcher.ReadyCh():
|
||||
}
|
||||
|
||||
stopCh := make(chan struct{})
|
||||
defer close(stopCh)
|
||||
ch, errCh := daemon.discoveryWatcher.Watch(stopCh)
|
||||
@@ -488,6 +508,12 @@ func TestDaemonDiscoveryReloadOnlyClusterAdvertise(t *testing.T) {
|
||||
if err := daemon.Reload(newConfig); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
select {
|
||||
case <-daemon.discoveryWatcher.ReadyCh():
|
||||
case <-time.After(10 * time.Second):
|
||||
t.Fatal("Timeout waiting for discovery")
|
||||
}
|
||||
stopCh := make(chan struct{})
|
||||
defer close(stopCh)
|
||||
ch, errCh := daemon.discoveryWatcher.Watch(stopCh)
|
||||
|
||||
@@ -130,7 +130,7 @@ func getBlkioWeightDevices(config containertypes.Resources) ([]specs.WeightDevic
|
||||
weight := weightDevice.Weight
|
||||
d := specs.WeightDevice{Weight: &weight}
|
||||
d.Major = int64(stat.Rdev / 256)
|
||||
d.Major = int64(stat.Rdev % 256)
|
||||
d.Minor = int64(stat.Rdev % 256)
|
||||
blkioWeightDevices = append(blkioWeightDevices, d)
|
||||
}
|
||||
|
||||
@@ -187,7 +187,7 @@ func getBlkioReadIOpsDevices(config containertypes.Resources) ([]specs.ThrottleD
|
||||
rate := iopsDevice.Rate
|
||||
d := specs.ThrottleDevice{Rate: &rate}
|
||||
d.Major = int64(stat.Rdev / 256)
|
||||
d.Major = int64(stat.Rdev % 256)
|
||||
d.Minor = int64(stat.Rdev % 256)
|
||||
blkioReadIOpsDevice = append(blkioReadIOpsDevice, d)
|
||||
}
|
||||
|
||||
@@ -205,7 +205,7 @@ func getBlkioWriteIOpsDevices(config containertypes.Resources) ([]specs.Throttle
|
||||
rate := iopsDevice.Rate
|
||||
d := specs.ThrottleDevice{Rate: &rate}
|
||||
d.Major = int64(stat.Rdev / 256)
|
||||
d.Major = int64(stat.Rdev % 256)
|
||||
d.Minor = int64(stat.Rdev % 256)
|
||||
blkioWriteIOpsDevice = append(blkioWriteIOpsDevice, d)
|
||||
}
|
||||
|
||||
@@ -223,7 +223,7 @@ func getBlkioReadBpsDevices(config containertypes.Resources) ([]specs.ThrottleDe
|
||||
rate := bpsDevice.Rate
|
||||
d := specs.ThrottleDevice{Rate: &rate}
|
||||
d.Major = int64(stat.Rdev / 256)
|
||||
d.Major = int64(stat.Rdev % 256)
|
||||
d.Minor = int64(stat.Rdev % 256)
|
||||
blkioReadBpsDevice = append(blkioReadBpsDevice, d)
|
||||
}
|
||||
|
||||
@@ -241,7 +241,7 @@ func getBlkioWriteBpsDevices(config containertypes.Resources) ([]specs.ThrottleD
|
||||
rate := bpsDevice.Rate
|
||||
d := specs.ThrottleDevice{Rate: &rate}
|
||||
d.Major = int64(stat.Rdev / 256)
|
||||
d.Major = int64(stat.Rdev % 256)
|
||||
d.Minor = int64(stat.Rdev % 256)
|
||||
blkioWriteBpsDevice = append(blkioWriteBpsDevice, d)
|
||||
}
|
||||
|
||||
@@ -466,28 +466,36 @@ func verifyContainerResources(resources *containertypes.Resources, sysInfo *sysi
|
||||
func (daemon *Daemon) getCgroupDriver() string {
|
||||
cgroupDriver := cgroupFsDriver
|
||||
|
||||
// No other cgroup drivers are supported at the moment. Warn the
|
||||
// user if they tried to set one other than cgroupfs
|
||||
for _, option := range daemon.configStore.ExecOptions {
|
||||
if UsingSystemd(daemon.configStore) {
|
||||
cgroupDriver = cgroupSystemdDriver
|
||||
}
|
||||
return cgroupDriver
|
||||
}
|
||||
|
||||
// getCD gets the raw value of the native.cgroupdriver option, if set.
|
||||
func getCD(config *Config) string {
|
||||
for _, option := range config.ExecOptions {
|
||||
key, val, err := parsers.ParseKeyValueOpt(option)
|
||||
if err != nil || !strings.EqualFold(key, "native.cgroupdriver") {
|
||||
continue
|
||||
}
|
||||
if val != cgroupFsDriver {
|
||||
logrus.Warnf("cgroupdriver '%s' is not supported", val)
|
||||
}
|
||||
return val
|
||||
}
|
||||
|
||||
return cgroupDriver
|
||||
return ""
|
||||
}
|
||||
|
||||
func usingSystemd(config *Config) bool {
|
||||
// No support for systemd cgroup atm
|
||||
return false
|
||||
// VerifyCgroupDriver validates native.cgroupdriver
|
||||
func VerifyCgroupDriver(config *Config) error {
|
||||
cd := getCD(config)
|
||||
if cd == "" || cd == cgroupFsDriver || cd == cgroupSystemdDriver {
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("native.cgroupdriver option %s not supported", cd)
|
||||
}
|
||||
|
||||
func (daemon *Daemon) usingSystemd() bool {
|
||||
return daemon.getCgroupDriver() == cgroupSystemdDriver
|
||||
// UsingSystemd returns true if cli option includes native.cgroupdriver=systemd
|
||||
func UsingSystemd(config *Config) bool {
|
||||
return getCD(config) == cgroupSystemdDriver
|
||||
}
|
||||
|
||||
// verifyPlatformContainerSettings performs platform-specific validation of the
|
||||
@@ -533,7 +541,7 @@ func verifyPlatformContainerSettings(daemon *Daemon, hostConfig *containertypes.
|
||||
return warnings, fmt.Errorf("Cannot use the --read-only option when user namespaces are enabled")
|
||||
}
|
||||
}
|
||||
if hostConfig.CgroupParent != "" && daemon.usingSystemd() {
|
||||
if hostConfig.CgroupParent != "" && UsingSystemd(daemon.configStore) {
|
||||
// CgroupParent for systemd cgroup should be named as "xxx.slice"
|
||||
if len(hostConfig.CgroupParent) <= 6 || !strings.HasSuffix(hostConfig.CgroupParent, ".slice") {
|
||||
return warnings, fmt.Errorf("cgroup-parent for systemd cgroup should be a valid slice named as \"xxx.slice\"")
|
||||
@@ -554,7 +562,10 @@ func verifyDaemonSettings(config *Config) error {
|
||||
if !config.bridgeConfig.EnableIPTables && config.bridgeConfig.EnableIPMasq {
|
||||
config.bridgeConfig.EnableIPMasq = false
|
||||
}
|
||||
if config.CgroupParent != "" && usingSystemd(config) {
|
||||
if err := VerifyCgroupDriver(config); err != nil {
|
||||
return err
|
||||
}
|
||||
if config.CgroupParent != "" && UsingSystemd(config) {
|
||||
if len(config.CgroupParent) <= 6 || !strings.HasSuffix(config.CgroupParent, ".slice") {
|
||||
return fmt.Errorf("cgroup-parent for systemd cgroup should be a valid slice named as \"xxx.slice\"")
|
||||
}
|
||||
@@ -1081,6 +1092,11 @@ func (daemon *Daemon) stats(c *container.Container) (*types.StatsJSON, error) {
|
||||
MaxUsage: mem.MaxUsage,
|
||||
Stats: cgs.MemoryStats.Stats,
|
||||
Failcnt: mem.Failcnt,
|
||||
Limit: mem.Limit,
|
||||
}
|
||||
// if the container does not set memory limit, use the machineMemory
|
||||
if mem.Limit > daemon.statsCollector.machineMemory && daemon.statsCollector.machineMemory > 0 {
|
||||
s.MemoryStats.Limit = daemon.statsCollector.machineMemory
|
||||
}
|
||||
if cgs.PidsStats != nil {
|
||||
s.PidsStats = types.PidsStats{
|
||||
|
||||
@@ -102,7 +102,7 @@ func (daemon *Daemon) cleanupContainer(container *container.Container, forceRemo
|
||||
// Save container state to disk. So that if error happens before
|
||||
// container meta file got removed from disk, then a restart of
|
||||
// docker should not make a dead container alive.
|
||||
if err := container.ToDiskLocking(); err != nil {
|
||||
if err := container.ToDiskLocking(); err != nil && !os.IsNotExist(err) {
|
||||
logrus.Errorf("Error saving dying container to disk: %v", err)
|
||||
}
|
||||
|
||||
@@ -123,10 +123,14 @@ func (daemon *Daemon) cleanupContainer(container *container.Container, forceRemo
|
||||
return fmt.Errorf("Unable to remove filesystem for %v: %v", container.ID, err)
|
||||
}
|
||||
|
||||
metadata, err := daemon.layerStore.ReleaseRWLayer(container.RWLayer)
|
||||
layer.LogReleaseMetadata(metadata)
|
||||
if err != nil && err != layer.ErrMountDoesNotExist {
|
||||
return fmt.Errorf("Driver %s failed to remove root filesystem %s: %s", daemon.GraphDriverName(), container.ID, err)
|
||||
// When container creation fails and `RWLayer` has not been created yet, we
|
||||
// do not call `ReleaseRWLayer`
|
||||
if container.RWLayer != nil {
|
||||
metadata, err := daemon.layerStore.ReleaseRWLayer(container.RWLayer)
|
||||
layer.LogReleaseMetadata(metadata)
|
||||
if err != nil && err != layer.ErrMountDoesNotExist {
|
||||
return fmt.Errorf("Driver %s failed to remove root filesystem %s: %s", daemon.GraphDriverName(), container.ID, err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
@@ -27,18 +27,24 @@ type discoveryReloader interface {
|
||||
discovery.Watcher
|
||||
Stop()
|
||||
Reload(backend, address string, clusterOpts map[string]string) error
|
||||
ReadyCh() <-chan struct{}
|
||||
}
|
||||
|
||||
type daemonDiscoveryReloader struct {
|
||||
backend discovery.Backend
|
||||
ticker *time.Ticker
|
||||
term chan bool
|
||||
readyCh chan struct{}
|
||||
}
|
||||
|
||||
func (d *daemonDiscoveryReloader) Watch(stopCh <-chan struct{}) (<-chan discovery.Entries, <-chan error) {
|
||||
return d.backend.Watch(stopCh)
|
||||
}
|
||||
|
||||
func (d *daemonDiscoveryReloader) ReadyCh() <-chan struct{} {
|
||||
return d.readyCh
|
||||
}
|
||||
|
||||
func discoveryOpts(clusterOpts map[string]string) (time.Duration, time.Duration, error) {
|
||||
var (
|
||||
heartbeat = defaultDiscoveryHeartbeat
|
||||
@@ -87,38 +93,64 @@ func initDiscovery(backendAddress, advertiseAddress string, clusterOpts map[stri
|
||||
backend: backend,
|
||||
ticker: time.NewTicker(heartbeat),
|
||||
term: make(chan bool),
|
||||
readyCh: make(chan struct{}),
|
||||
}
|
||||
// We call Register() on the discovery backend in a loop for the whole lifetime of the daemon,
|
||||
// but we never actually Watch() for nodes appearing and disappearing for the moment.
|
||||
reloader.advertise(advertiseAddress)
|
||||
go reloader.advertiseHeartbeat(advertiseAddress)
|
||||
return reloader, nil
|
||||
}
|
||||
|
||||
func (d *daemonDiscoveryReloader) advertise(address string) {
|
||||
d.registerAddr(address)
|
||||
go d.advertiseHeartbeat(address)
|
||||
}
|
||||
|
||||
func (d *daemonDiscoveryReloader) registerAddr(addr string) {
|
||||
if err := d.backend.Register(addr); err != nil {
|
||||
log.Warnf("Registering as %q in discovery failed: %v", addr, err)
|
||||
}
|
||||
}
|
||||
|
||||
// advertiseHeartbeat registers the current node against the discovery backend using the specified
|
||||
// address. The function never returns, as registration against the backend comes with a TTL and
|
||||
// requires regular heartbeats.
|
||||
func (d *daemonDiscoveryReloader) advertiseHeartbeat(address string) {
|
||||
var ready bool
|
||||
if err := d.initHeartbeat(address); err == nil {
|
||||
ready = true
|
||||
close(d.readyCh)
|
||||
}
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-d.ticker.C:
|
||||
d.registerAddr(address)
|
||||
if err := d.backend.Register(address); err != nil {
|
||||
log.Warnf("Registering as %q in discovery failed: %v", address, err)
|
||||
} else {
|
||||
if !ready {
|
||||
close(d.readyCh)
|
||||
ready = true
|
||||
}
|
||||
}
|
||||
case <-d.term:
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// initHeartbeat is used to do the first heartbeat. It uses a tight loop until
|
||||
// either the timeout period is reached or the heartbeat is successful and returns.
|
||||
func (d *daemonDiscoveryReloader) initHeartbeat(address string) error {
|
||||
// Setup a short ticker until the first heartbeat has succeeded
|
||||
t := time.NewTicker(500 * time.Millisecond)
|
||||
defer t.Stop()
|
||||
// timeout makes sure that after a period of time we stop being so aggressive trying to reach the discovery service
|
||||
timeout := time.After(60 * time.Second)
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-timeout:
|
||||
return errors.New("timeout waiting for initial discovery")
|
||||
case <-d.term:
|
||||
return errors.New("terminated")
|
||||
case <-t.C:
|
||||
if err := d.backend.Register(address); err == nil {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Reload makes the watcher to stop advertising and reconfigures it to advertise in a new address.
|
||||
func (d *daemonDiscoveryReloader) Reload(backendAddress, advertiseAddress string, clusterOpts map[string]string) error {
|
||||
d.Stop()
|
||||
@@ -130,8 +162,9 @@ func (d *daemonDiscoveryReloader) Reload(backendAddress, advertiseAddress string
|
||||
|
||||
d.backend = backend
|
||||
d.ticker = time.NewTicker(heartbeat)
|
||||
d.readyCh = make(chan struct{})
|
||||
|
||||
d.advertise(advertiseAddress)
|
||||
go d.advertiseHeartbeat(advertiseAddress)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@ import (
|
||||
"os"
|
||||
"os/exec"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"sync"
|
||||
"syscall"
|
||||
@@ -64,21 +65,14 @@ func init() {
|
||||
graphdriver.Register("aufs", Init)
|
||||
}
|
||||
|
||||
type data struct {
|
||||
referenceCount int
|
||||
path string
|
||||
}
|
||||
|
||||
// Driver contains information about the filesystem mounted.
|
||||
// root of the filesystem
|
||||
// sync.Mutex to protect against concurrent modifications
|
||||
// active maps mount id to the count
|
||||
type Driver struct {
|
||||
root string
|
||||
uidMaps []idtools.IDMap
|
||||
gidMaps []idtools.IDMap
|
||||
sync.Mutex // Protects concurrent modification to active
|
||||
active map[string]*data
|
||||
sync.Mutex
|
||||
root string
|
||||
uidMaps []idtools.IDMap
|
||||
gidMaps []idtools.IDMap
|
||||
pathCacheLock sync.Mutex
|
||||
pathCache map[string]string
|
||||
}
|
||||
|
||||
// Init returns a new AUFS driver.
|
||||
@@ -111,10 +105,10 @@ func Init(root string, options []string, uidMaps, gidMaps []idtools.IDMap) (grap
|
||||
}
|
||||
|
||||
a := &Driver{
|
||||
root: root,
|
||||
active: make(map[string]*data),
|
||||
uidMaps: uidMaps,
|
||||
gidMaps: gidMaps,
|
||||
root: root,
|
||||
uidMaps: uidMaps,
|
||||
gidMaps: gidMaps,
|
||||
pathCache: make(map[string]string),
|
||||
}
|
||||
|
||||
rootUID, rootGID, err := idtools.GetRootUIDGID(uidMaps, gidMaps)
|
||||
@@ -228,9 +222,7 @@ func (a *Driver) Create(id, parent, mountLabel string) error {
|
||||
}
|
||||
}
|
||||
}
|
||||
a.Lock()
|
||||
a.active[id] = &data{}
|
||||
a.Unlock()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -259,108 +251,91 @@ func (a *Driver) createDirsFor(id string) error {
|
||||
|
||||
// Remove will unmount and remove the given id.
|
||||
func (a *Driver) Remove(id string) error {
|
||||
// Protect the a.active from concurrent access
|
||||
a.Lock()
|
||||
defer a.Unlock()
|
||||
|
||||
m := a.active[id]
|
||||
if m != nil {
|
||||
if m.referenceCount > 0 {
|
||||
return nil
|
||||
}
|
||||
// Make sure the dir is umounted first
|
||||
if err := a.unmount(m); err != nil {
|
||||
return err
|
||||
}
|
||||
a.pathCacheLock.Lock()
|
||||
mountpoint, exists := a.pathCache[id]
|
||||
a.pathCacheLock.Unlock()
|
||||
if !exists {
|
||||
mountpoint = a.getMountpoint(id)
|
||||
}
|
||||
tmpDirs := []string{
|
||||
"mnt",
|
||||
"diff",
|
||||
if err := a.unmount(mountpoint); err != nil {
|
||||
// no need to return here, we can still try to remove since the `Rename` will fail below if still mounted
|
||||
logrus.Debugf("aufs: error while unmounting %s: %v", mountpoint, err)
|
||||
}
|
||||
|
||||
// Atomically remove each directory in turn by first moving it out of the
|
||||
// way (so that docker doesn't find it anymore) before doing removal of
|
||||
// the whole tree.
|
||||
for _, p := range tmpDirs {
|
||||
realPath := path.Join(a.rootPath(), p, id)
|
||||
tmpPath := path.Join(a.rootPath(), p, fmt.Sprintf("%s-removing", id))
|
||||
if err := os.Rename(realPath, tmpPath); err != nil && !os.IsNotExist(err) {
|
||||
return err
|
||||
}
|
||||
defer os.RemoveAll(tmpPath)
|
||||
tmpMntPath := path.Join(a.mntPath(), fmt.Sprintf("%s-removing", id))
|
||||
if err := os.Rename(mountpoint, tmpMntPath); err != nil && !os.IsNotExist(err) {
|
||||
return err
|
||||
}
|
||||
defer os.RemoveAll(tmpMntPath)
|
||||
|
||||
tmpDiffpath := path.Join(a.diffPath(), fmt.Sprintf("%s-removing", id))
|
||||
if err := os.Rename(a.getDiffPath(id), tmpDiffpath); err != nil && !os.IsNotExist(err) {
|
||||
return err
|
||||
}
|
||||
defer os.RemoveAll(tmpDiffpath)
|
||||
|
||||
// Remove the layers file for the id
|
||||
if err := os.Remove(path.Join(a.rootPath(), "layers", id)); err != nil && !os.IsNotExist(err) {
|
||||
return err
|
||||
}
|
||||
if m != nil {
|
||||
delete(a.active, id)
|
||||
}
|
||||
|
||||
a.pathCacheLock.Lock()
|
||||
delete(a.pathCache, id)
|
||||
a.pathCacheLock.Unlock()
|
||||
return nil
|
||||
}
|
||||
|
||||
// Get returns the rootfs path for the id.
|
||||
// This will mount the dir at it's given path
|
||||
func (a *Driver) Get(id, mountLabel string) (string, error) {
|
||||
// Protect the a.active from concurrent access
|
||||
a.Lock()
|
||||
defer a.Unlock()
|
||||
|
||||
m := a.active[id]
|
||||
if m == nil {
|
||||
m = &data{}
|
||||
a.active[id] = m
|
||||
}
|
||||
|
||||
parents, err := a.getParentLayerPaths(id)
|
||||
if err != nil && !os.IsNotExist(err) {
|
||||
return "", err
|
||||
}
|
||||
|
||||
// If a dir does not have a parent ( no layers )do not try to mount
|
||||
// just return the diff path to the data
|
||||
m.path = path.Join(a.rootPath(), "diff", id)
|
||||
if len(parents) > 0 {
|
||||
m.path = path.Join(a.rootPath(), "mnt", id)
|
||||
if m.referenceCount == 0 {
|
||||
if err := a.mount(id, m, mountLabel, parents); err != nil {
|
||||
return "", err
|
||||
}
|
||||
a.pathCacheLock.Lock()
|
||||
m, exists := a.pathCache[id]
|
||||
a.pathCacheLock.Unlock()
|
||||
|
||||
if !exists {
|
||||
m = a.getDiffPath(id)
|
||||
if len(parents) > 0 {
|
||||
m = a.getMountpoint(id)
|
||||
}
|
||||
}
|
||||
m.referenceCount++
|
||||
return m.path, nil
|
||||
|
||||
// If a dir does not have a parent ( no layers )do not try to mount
|
||||
// just return the diff path to the data
|
||||
if len(parents) > 0 {
|
||||
if err := a.mount(id, m, mountLabel, parents); err != nil {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
|
||||
a.pathCacheLock.Lock()
|
||||
a.pathCache[id] = m
|
||||
a.pathCacheLock.Unlock()
|
||||
return m, nil
|
||||
}
|
||||
|
||||
// Put unmounts and updates list of active mounts.
|
||||
func (a *Driver) Put(id string) error {
|
||||
// Protect the a.active from concurrent access
|
||||
a.Lock()
|
||||
defer a.Unlock()
|
||||
a.pathCacheLock.Lock()
|
||||
m, exists := a.pathCache[id]
|
||||
if !exists {
|
||||
m = a.getMountpoint(id)
|
||||
a.pathCache[id] = m
|
||||
}
|
||||
a.pathCacheLock.Unlock()
|
||||
|
||||
m := a.active[id]
|
||||
if m == nil {
|
||||
// but it might be still here
|
||||
if a.Exists(id) {
|
||||
path := path.Join(a.rootPath(), "mnt", id)
|
||||
err := Unmount(path)
|
||||
if err != nil {
|
||||
logrus.Debugf("Failed to unmount %s aufs: %v", id, err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
err := a.unmount(m)
|
||||
if err != nil {
|
||||
logrus.Debugf("Failed to unmount %s aufs: %v", id, err)
|
||||
}
|
||||
if count := m.referenceCount; count > 1 {
|
||||
m.referenceCount = count - 1
|
||||
} else {
|
||||
ids, _ := getParentIds(a.rootPath(), id)
|
||||
// We only mounted if there are any parents
|
||||
if ids != nil && len(ids) > 0 {
|
||||
a.unmount(m)
|
||||
}
|
||||
delete(a.active, id)
|
||||
}
|
||||
return nil
|
||||
return err
|
||||
}
|
||||
|
||||
// Diff produces an archive of the changes between the specified
|
||||
@@ -443,16 +418,16 @@ func (a *Driver) getParentLayerPaths(id string) ([]string, error) {
|
||||
return layers, nil
|
||||
}
|
||||
|
||||
func (a *Driver) mount(id string, m *data, mountLabel string, layers []string) error {
|
||||
func (a *Driver) mount(id string, target string, mountLabel string, layers []string) error {
|
||||
a.Lock()
|
||||
defer a.Unlock()
|
||||
|
||||
// If the id is mounted or we get an error return
|
||||
if mounted, err := a.mounted(m); err != nil || mounted {
|
||||
if mounted, err := a.mounted(target); err != nil || mounted {
|
||||
return err
|
||||
}
|
||||
|
||||
var (
|
||||
target = m.path
|
||||
rw = path.Join(a.rootPath(), "diff", id)
|
||||
)
|
||||
rw := a.getDiffPath(id)
|
||||
|
||||
if err := a.aufsMount(layers, rw, target, mountLabel); err != nil {
|
||||
return fmt.Errorf("error creating aufs mount to %s: %v", target, err)
|
||||
@@ -460,26 +435,42 @@ func (a *Driver) mount(id string, m *data, mountLabel string, layers []string) e
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *Driver) unmount(m *data) error {
|
||||
if mounted, err := a.mounted(m); err != nil || !mounted {
|
||||
func (a *Driver) unmount(mountPath string) error {
|
||||
a.Lock()
|
||||
defer a.Unlock()
|
||||
|
||||
if mounted, err := a.mounted(mountPath); err != nil || !mounted {
|
||||
return err
|
||||
}
|
||||
return Unmount(m.path)
|
||||
if err := Unmount(mountPath); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *Driver) mounted(m *data) (bool, error) {
|
||||
var buf syscall.Statfs_t
|
||||
if err := syscall.Statfs(m.path, &buf); err != nil {
|
||||
return false, nil
|
||||
}
|
||||
return graphdriver.FsMagic(buf.Type) == graphdriver.FsMagicAufs, nil
|
||||
func (a *Driver) mounted(mountpoint string) (bool, error) {
|
||||
return graphdriver.Mounted(graphdriver.FsMagicAufs, mountpoint)
|
||||
}
|
||||
|
||||
// Cleanup aufs and unmount all mountpoints
|
||||
func (a *Driver) Cleanup() error {
|
||||
for id, m := range a.active {
|
||||
var dirs []string
|
||||
if err := filepath.Walk(a.mntPath(), func(path string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !info.IsDir() {
|
||||
return nil
|
||||
}
|
||||
dirs = append(dirs, path)
|
||||
return nil
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, m := range dirs {
|
||||
if err := a.unmount(m); err != nil {
|
||||
logrus.Errorf("Unmounting %s: %s", stringid.TruncateID(id), err)
|
||||
logrus.Debugf("aufs error unmounting %s: %s", stringid.TruncateID(m), err)
|
||||
}
|
||||
}
|
||||
return mountpk.Unmount(a.root)
|
||||
|
||||
@@ -200,7 +200,7 @@ func TestMountedFalseResponse(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
response, err := d.mounted(d.active["1"])
|
||||
response, err := d.mounted(d.getDiffPath("1"))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -227,7 +227,7 @@ func TestMountedTrueReponse(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
response, err := d.mounted(d.active["2"])
|
||||
response, err := d.mounted(d.pathCache["2"])
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -293,7 +293,7 @@ func TestRemoveMountedDir(t *testing.T) {
|
||||
t.Fatal("mntPath should not be empty string")
|
||||
}
|
||||
|
||||
mounted, err := d.mounted(d.active["2"])
|
||||
mounted, err := d.mounted(d.pathCache["2"])
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@@ -46,3 +46,19 @@ func getParentIds(root, id string) ([]string, error) {
|
||||
}
|
||||
return out, s.Err()
|
||||
}
|
||||
|
||||
func (a *Driver) getMountpoint(id string) string {
|
||||
return path.Join(a.mntPath(), id)
|
||||
}
|
||||
|
||||
func (a *Driver) mntPath() string {
|
||||
return path.Join(a.rootPath(), "mnt")
|
||||
}
|
||||
|
||||
func (a *Driver) getDiffPath(id string) string {
|
||||
return path.Join(a.diffPath(), id)
|
||||
}
|
||||
|
||||
func (a *Driver) diffPath() string {
|
||||
return path.Join(a.rootPath(), "diff")
|
||||
}
|
||||
|
||||
@@ -7,6 +7,10 @@ package btrfs
|
||||
#include <dirent.h>
|
||||
#include <btrfs/ioctl.h>
|
||||
#include <btrfs/ctree.h>
|
||||
|
||||
static void set_name_btrfs_ioctl_vol_args_v2(struct btrfs_ioctl_vol_args_v2* btrfs_struct, const char* value) {
|
||||
snprintf(btrfs_struct->name, BTRFS_SUBVOL_NAME_MAX, "%s", value);
|
||||
}
|
||||
*/
|
||||
import "C"
|
||||
|
||||
@@ -159,9 +163,10 @@ func subvolSnapshot(src, dest, name string) error {
|
||||
|
||||
var args C.struct_btrfs_ioctl_vol_args_v2
|
||||
args.fd = C.__s64(getDirFd(srcDir))
|
||||
for i, c := range []byte(name) {
|
||||
args.name[i] = C.char(c)
|
||||
}
|
||||
|
||||
var cs = C.CString(name)
|
||||
C.set_name_btrfs_ioctl_vol_args_v2(&args, cs)
|
||||
C.free(unsafe.Pointer(cs))
|
||||
|
||||
_, _, errno := syscall.Syscall(syscall.SYS_IOCTL, getDirFd(destDir), C.BTRFS_IOC_SNAP_CREATE_V2,
|
||||
uintptr(unsafe.Pointer(&args)))
|
||||
|
||||
32
daemon/graphdriver/counter.go
Normal file
32
daemon/graphdriver/counter.go
Normal file
@@ -0,0 +1,32 @@
|
||||
package graphdriver
|
||||
|
||||
import "sync"
|
||||
|
||||
// RefCounter is a generic counter for use by graphdriver Get/Put calls
|
||||
type RefCounter struct {
|
||||
counts map[string]int
|
||||
mu sync.Mutex
|
||||
}
|
||||
|
||||
// NewRefCounter returns a new RefCounter
|
||||
func NewRefCounter() *RefCounter {
|
||||
return &RefCounter{counts: make(map[string]int)}
|
||||
}
|
||||
|
||||
// Increment increaes the ref count for the given id and returns the current count
|
||||
func (c *RefCounter) Increment(id string) int {
|
||||
c.mu.Lock()
|
||||
c.counts[id]++
|
||||
count := c.counts[id]
|
||||
c.mu.Unlock()
|
||||
return count
|
||||
}
|
||||
|
||||
// Decrement decreases the ref count for the given id and returns the current count
|
||||
func (c *RefCounter) Decrement(id string) int {
|
||||
c.mu.Lock()
|
||||
c.counts[id]--
|
||||
count := c.counts[id]
|
||||
c.mu.Unlock()
|
||||
return count
|
||||
}
|
||||
@@ -22,6 +22,7 @@ import (
|
||||
"github.com/Sirupsen/logrus"
|
||||
|
||||
"github.com/docker/docker/daemon/graphdriver"
|
||||
"github.com/docker/docker/dockerversion"
|
||||
"github.com/docker/docker/pkg/devicemapper"
|
||||
"github.com/docker/docker/pkg/idtools"
|
||||
"github.com/docker/docker/pkg/loopback"
|
||||
@@ -69,9 +70,6 @@ type devInfo struct {
|
||||
Deleted bool `json:"deleted"`
|
||||
devices *DeviceSet
|
||||
|
||||
mountCount int
|
||||
mountPath string
|
||||
|
||||
// The global DeviceSet lock guarantees that we serialize all
|
||||
// the calls to libdevmapper (which is not threadsafe), but we
|
||||
// sometimes release that lock while sleeping. In that case
|
||||
@@ -1659,7 +1657,12 @@ func (devices *DeviceSet) initDevmapper(doInit bool) error {
|
||||
|
||||
// https://github.com/docker/docker/issues/4036
|
||||
if supported := devicemapper.UdevSetSyncSupport(true); !supported {
|
||||
logrus.Errorf("devmapper: Udev sync is not supported. This will lead to data loss and unexpected behavior. Install a dynamic binary to use devicemapper or select a different storage driver. For more information, see https://docs.docker.com/engine/reference/commandline/daemon/#daemon-storage-driver-option")
|
||||
if dockerversion.IAmStatic == "true" {
|
||||
logrus.Errorf("devmapper: Udev sync is not supported. This will lead to data loss and unexpected behavior. Install a dynamic binary to use devicemapper or select a different storage driver. For more information, see https://docs.docker.com/engine/reference/commandline/daemon/#daemon-storage-driver-option")
|
||||
} else {
|
||||
logrus.Errorf("devmapper: Udev sync is not supported. This will lead to data loss and unexpected behavior. Install a more recent version of libdevmapper or select a different storage driver. For more information, see https://docs.docker.com/engine/reference/commandline/daemon/#daemon-storage-driver-option")
|
||||
}
|
||||
|
||||
if !devices.overrideUdevSyncCheck {
|
||||
return graphdriver.ErrNotSupported
|
||||
}
|
||||
@@ -1991,13 +1994,6 @@ func (devices *DeviceSet) DeleteDevice(hash string, syncDelete bool) error {
|
||||
devices.Lock()
|
||||
defer devices.Unlock()
|
||||
|
||||
// If mountcount is not zero, that means devices is still in use
|
||||
// or has not been Put() properly. Fail device deletion.
|
||||
|
||||
if info.mountCount != 0 {
|
||||
return fmt.Errorf("devmapper: Can't delete device %v as it is still mounted. mntCount=%v", info.Hash, info.mountCount)
|
||||
}
|
||||
|
||||
return devices.deleteDevice(info, syncDelete)
|
||||
}
|
||||
|
||||
@@ -2116,13 +2112,11 @@ func (devices *DeviceSet) cancelDeferredRemoval(info *devInfo) error {
|
||||
}
|
||||
|
||||
// Shutdown shuts down the device by unmounting the root.
|
||||
func (devices *DeviceSet) Shutdown() error {
|
||||
func (devices *DeviceSet) Shutdown(home string) error {
|
||||
logrus.Debugf("devmapper: [deviceset %s] Shutdown()", devices.devicePrefix)
|
||||
logrus.Debugf("devmapper: Shutting down DeviceSet: %s", devices.root)
|
||||
defer logrus.Debugf("devmapper: [deviceset %s] Shutdown() END", devices.devicePrefix)
|
||||
|
||||
var devs []*devInfo
|
||||
|
||||
// Stop deletion worker. This should start delivering new events to
|
||||
// ticker channel. That means no new instance of cleanupDeletedDevice()
|
||||
// will run after this call. If one instance is already running at
|
||||
@@ -2139,30 +2133,46 @@ func (devices *DeviceSet) Shutdown() error {
|
||||
// metadata. Hence save this early before trying to deactivate devices.
|
||||
devices.saveDeviceSetMetaData()
|
||||
|
||||
for _, info := range devices.Devices {
|
||||
devs = append(devs, info)
|
||||
// ignore the error since it's just a best effort to not try to unmount something that's mounted
|
||||
mounts, _ := mount.GetMounts()
|
||||
mounted := make(map[string]bool, len(mounts))
|
||||
for _, mnt := range mounts {
|
||||
mounted[mnt.Mountpoint] = true
|
||||
}
|
||||
devices.Unlock()
|
||||
|
||||
for _, info := range devs {
|
||||
info.lock.Lock()
|
||||
if info.mountCount > 0 {
|
||||
if err := filepath.Walk(path.Join(home, "mnt"), func(p string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !info.IsDir() {
|
||||
return nil
|
||||
}
|
||||
|
||||
if mounted[p] {
|
||||
// We use MNT_DETACH here in case it is still busy in some running
|
||||
// container. This means it'll go away from the global scope directly,
|
||||
// and the device will be released when that container dies.
|
||||
if err := syscall.Unmount(info.mountPath, syscall.MNT_DETACH); err != nil {
|
||||
logrus.Debugf("devmapper: Shutdown unmounting %s, error: %s", info.mountPath, err)
|
||||
if err := syscall.Unmount(p, syscall.MNT_DETACH); err != nil {
|
||||
logrus.Debugf("devmapper: Shutdown unmounting %s, error: %s", p, err)
|
||||
}
|
||||
|
||||
devices.Lock()
|
||||
if err := devices.deactivateDevice(info); err != nil {
|
||||
logrus.Debugf("devmapper: Shutdown deactivate %s , error: %s", info.Hash, err)
|
||||
}
|
||||
devices.Unlock()
|
||||
}
|
||||
info.lock.Unlock()
|
||||
|
||||
if devInfo, err := devices.lookupDevice(path.Base(p)); err != nil {
|
||||
logrus.Debugf("devmapper: Shutdown lookup device %s, error: %s", path.Base(p), err)
|
||||
} else {
|
||||
if err := devices.deactivateDevice(devInfo); err != nil {
|
||||
logrus.Debugf("devmapper: Shutdown deactivate %s , error: %s", devInfo.Hash, err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}); err != nil && !os.IsNotExist(err) {
|
||||
devices.Unlock()
|
||||
return err
|
||||
}
|
||||
|
||||
devices.Unlock()
|
||||
|
||||
info, _ := devices.lookupDeviceWithLock("")
|
||||
if info != nil {
|
||||
info.lock.Lock()
|
||||
@@ -2202,15 +2212,6 @@ func (devices *DeviceSet) MountDevice(hash, path, mountLabel string) error {
|
||||
devices.Lock()
|
||||
defer devices.Unlock()
|
||||
|
||||
if info.mountCount > 0 {
|
||||
if path != info.mountPath {
|
||||
return fmt.Errorf("devmapper: Trying to mount devmapper device in multiple places (%s, %s)", info.mountPath, path)
|
||||
}
|
||||
|
||||
info.mountCount++
|
||||
return nil
|
||||
}
|
||||
|
||||
if err := devices.activateDeviceIfNeeded(info, false); err != nil {
|
||||
return fmt.Errorf("devmapper: Error activating devmapper device for '%s': %s", hash, err)
|
||||
}
|
||||
@@ -2234,9 +2235,6 @@ func (devices *DeviceSet) MountDevice(hash, path, mountLabel string) error {
|
||||
return fmt.Errorf("devmapper: Error mounting '%s' on '%s': %s", info.DevName(), path, err)
|
||||
}
|
||||
|
||||
info.mountCount = 1
|
||||
info.mountPath = path
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -2256,20 +2254,6 @@ func (devices *DeviceSet) UnmountDevice(hash, mountPath string) error {
|
||||
devices.Lock()
|
||||
defer devices.Unlock()
|
||||
|
||||
// If there are running containers when daemon crashes, during daemon
|
||||
// restarting, it will kill running containers and will finally call
|
||||
// Put() without calling Get(). So info.MountCount may become negative.
|
||||
// if info.mountCount goes negative, we do the unmount and assign
|
||||
// it to 0.
|
||||
|
||||
info.mountCount--
|
||||
if info.mountCount > 0 {
|
||||
return nil
|
||||
} else if info.mountCount < 0 {
|
||||
logrus.Warnf("devmapper: Mount count of device went negative. Put() called without matching Get(). Resetting count to 0")
|
||||
info.mountCount = 0
|
||||
}
|
||||
|
||||
logrus.Debugf("devmapper: Unmount(%s)", mountPath)
|
||||
if err := syscall.Unmount(mountPath, syscall.MNT_DETACH); err != nil {
|
||||
return err
|
||||
@@ -2280,8 +2264,6 @@ func (devices *DeviceSet) UnmountDevice(hash, mountPath string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
info.mountPath = ""
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@ type Driver struct {
|
||||
home string
|
||||
uidMaps []idtools.IDMap
|
||||
gidMaps []idtools.IDMap
|
||||
ctr *graphdriver.RefCounter
|
||||
}
|
||||
|
||||
// Init creates a driver with the given home and the set of options.
|
||||
@@ -46,6 +47,7 @@ func Init(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (grap
|
||||
home: home,
|
||||
uidMaps: uidMaps,
|
||||
gidMaps: gidMaps,
|
||||
ctr: graphdriver.NewRefCounter(),
|
||||
}
|
||||
|
||||
return graphdriver.NewNaiveDiffDriver(d, uidMaps, gidMaps), nil
|
||||
@@ -108,7 +110,7 @@ func (d *Driver) GetMetadata(id string) (map[string]string, error) {
|
||||
|
||||
// Cleanup unmounts a device.
|
||||
func (d *Driver) Cleanup() error {
|
||||
err := d.DeviceSet.Shutdown()
|
||||
err := d.DeviceSet.Shutdown(d.home)
|
||||
|
||||
if err2 := mount.Unmount(d.home); err == nil {
|
||||
err = err2
|
||||
@@ -151,26 +153,35 @@ func (d *Driver) Remove(id string) error {
|
||||
// Get mounts a device with given id into the root filesystem
|
||||
func (d *Driver) Get(id, mountLabel string) (string, error) {
|
||||
mp := path.Join(d.home, "mnt", id)
|
||||
rootFs := path.Join(mp, "rootfs")
|
||||
if count := d.ctr.Increment(id); count > 1 {
|
||||
return rootFs, nil
|
||||
}
|
||||
|
||||
uid, gid, err := idtools.GetRootUIDGID(d.uidMaps, d.gidMaps)
|
||||
if err != nil {
|
||||
d.ctr.Decrement(id)
|
||||
return "", err
|
||||
}
|
||||
|
||||
// Create the target directories if they don't exist
|
||||
if err := idtools.MkdirAllAs(path.Join(d.home, "mnt"), 0755, uid, gid); err != nil && !os.IsExist(err) {
|
||||
d.ctr.Decrement(id)
|
||||
return "", err
|
||||
}
|
||||
if err := idtools.MkdirAs(mp, 0755, uid, gid); err != nil && !os.IsExist(err) {
|
||||
d.ctr.Decrement(id)
|
||||
return "", err
|
||||
}
|
||||
|
||||
// Mount the device
|
||||
if err := d.DeviceSet.MountDevice(id, mp, mountLabel); err != nil {
|
||||
d.ctr.Decrement(id)
|
||||
return "", err
|
||||
}
|
||||
|
||||
rootFs := path.Join(mp, "rootfs")
|
||||
if err := idtools.MkdirAllAs(rootFs, 0755, uid, gid); err != nil && !os.IsExist(err) {
|
||||
d.ctr.Decrement(id)
|
||||
d.DeviceSet.UnmountDevice(id, mp)
|
||||
return "", err
|
||||
}
|
||||
@@ -180,6 +191,7 @@ func (d *Driver) Get(id, mountLabel string) (string, error) {
|
||||
// Create an "id" file with the container/image id in it to help reconstruct this in case
|
||||
// of later problems
|
||||
if err := ioutil.WriteFile(idFile, []byte(id), 0600); err != nil {
|
||||
d.ctr.Decrement(id)
|
||||
d.DeviceSet.UnmountDevice(id, mp)
|
||||
return "", err
|
||||
}
|
||||
@@ -190,6 +202,9 @@ func (d *Driver) Get(id, mountLabel string) (string, error) {
|
||||
|
||||
// Put unmounts a device and removes it.
|
||||
func (d *Driver) Put(id string) error {
|
||||
if count := d.ctr.Decrement(id); count > 0 {
|
||||
return nil
|
||||
}
|
||||
mp := path.Join(d.home, "mnt", id)
|
||||
err := d.DeviceSet.UnmountDevice(id, mp)
|
||||
if err != nil {
|
||||
|
||||
@@ -1,8 +1,19 @@
|
||||
package graphdriver
|
||||
|
||||
import "syscall"
|
||||
|
||||
var (
|
||||
// Slice of drivers that should be used in an order
|
||||
priority = []string{
|
||||
"zfs",
|
||||
}
|
||||
)
|
||||
|
||||
// Mounted checks if the given path is mounted as the fs type
|
||||
func Mounted(fsType FsMagic, mountPath string) (bool, error) {
|
||||
var buf syscall.Statfs_t
|
||||
if err := syscall.Statfs(mountPath, &buf); err != nil {
|
||||
return false, err
|
||||
}
|
||||
return FsMagic(buf.Type) == fsType, nil
|
||||
}
|
||||
|
||||
@@ -42,6 +42,8 @@ const (
|
||||
FsMagicXfs = FsMagic(0x58465342)
|
||||
// FsMagicZfs filesystem id for Zfs
|
||||
FsMagicZfs = FsMagic(0x2fc12fc1)
|
||||
// FsMagicOverlay filesystem id for overlay
|
||||
FsMagicOverlay = FsMagic(0x794C7630)
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -86,3 +88,12 @@ func GetFSMagic(rootpath string) (FsMagic, error) {
|
||||
}
|
||||
return FsMagic(buf.Type), nil
|
||||
}
|
||||
|
||||
// Mounted checks if the given path is mounted as the fs type
|
||||
func Mounted(fsType FsMagic, mountPath string) (bool, error) {
|
||||
var buf syscall.Statfs_t
|
||||
if err := syscall.Statfs(mountPath, &buf); err != nil {
|
||||
return false, err
|
||||
}
|
||||
return FsMagic(buf.Type) == fsType, nil
|
||||
}
|
||||
|
||||
@@ -88,21 +88,14 @@ func (d *naiveDiffDriverWithApply) ApplyDiff(id, parent string, diff archive.Rea
|
||||
// of that. This means all child images share file (but not directory)
|
||||
// data with the parent.
|
||||
|
||||
// ActiveMount contains information about the count, path and whether is mounted or not.
|
||||
// This information is part of the Driver, that contains list of active mounts that are part of this overlay.
|
||||
type ActiveMount struct {
|
||||
count int
|
||||
path string
|
||||
mounted bool
|
||||
}
|
||||
|
||||
// Driver contains information about the home directory and the list of active mounts that are created using this driver.
|
||||
type Driver struct {
|
||||
home string
|
||||
sync.Mutex // Protects concurrent modification to active
|
||||
active map[string]*ActiveMount
|
||||
uidMaps []idtools.IDMap
|
||||
gidMaps []idtools.IDMap
|
||||
home string
|
||||
pathCacheLock sync.Mutex
|
||||
pathCache map[string]string
|
||||
uidMaps []idtools.IDMap
|
||||
gidMaps []idtools.IDMap
|
||||
ctr *graphdriver.RefCounter
|
||||
}
|
||||
|
||||
var backingFs = "<unknown>"
|
||||
@@ -151,10 +144,11 @@ func Init(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (grap
|
||||
}
|
||||
|
||||
d := &Driver{
|
||||
home: home,
|
||||
active: make(map[string]*ActiveMount),
|
||||
uidMaps: uidMaps,
|
||||
gidMaps: gidMaps,
|
||||
home: home,
|
||||
pathCache: make(map[string]string),
|
||||
uidMaps: uidMaps,
|
||||
gidMaps: gidMaps,
|
||||
ctr: graphdriver.NewRefCounter(),
|
||||
}
|
||||
|
||||
return NaiveDiffDriverWithApply(d, uidMaps, gidMaps), nil
|
||||
@@ -325,23 +319,14 @@ func (d *Driver) Remove(id string) error {
|
||||
if err := os.RemoveAll(d.dir(id)); err != nil && !os.IsNotExist(err) {
|
||||
return err
|
||||
}
|
||||
d.pathCacheLock.Lock()
|
||||
delete(d.pathCache, id)
|
||||
d.pathCacheLock.Unlock()
|
||||
return nil
|
||||
}
|
||||
|
||||
// Get creates and mounts the required file system for the given id and returns the mount path.
|
||||
func (d *Driver) Get(id string, mountLabel string) (string, error) {
|
||||
// Protect the d.active from concurrent access
|
||||
d.Lock()
|
||||
defer d.Unlock()
|
||||
|
||||
mount := d.active[id]
|
||||
if mount != nil {
|
||||
mount.count++
|
||||
return mount.path, nil
|
||||
}
|
||||
|
||||
mount = &ActiveMount{count: 1}
|
||||
|
||||
dir := d.dir(id)
|
||||
if _, err := os.Stat(dir); err != nil {
|
||||
return "", err
|
||||
@@ -350,9 +335,10 @@ func (d *Driver) Get(id string, mountLabel string) (string, error) {
|
||||
// If id has a root, just return it
|
||||
rootDir := path.Join(dir, "root")
|
||||
if _, err := os.Stat(rootDir); err == nil {
|
||||
mount.path = rootDir
|
||||
d.active[id] = mount
|
||||
return mount.path, nil
|
||||
d.pathCacheLock.Lock()
|
||||
d.pathCache[id] = rootDir
|
||||
d.pathCacheLock.Unlock()
|
||||
return rootDir, nil
|
||||
}
|
||||
|
||||
lowerID, err := ioutil.ReadFile(path.Join(dir, "lower-id"))
|
||||
@@ -364,56 +350,76 @@ func (d *Driver) Get(id string, mountLabel string) (string, error) {
|
||||
workDir := path.Join(dir, "work")
|
||||
mergedDir := path.Join(dir, "merged")
|
||||
|
||||
if count := d.ctr.Increment(id); count > 1 {
|
||||
return mergedDir, nil
|
||||
}
|
||||
|
||||
opts := fmt.Sprintf("lowerdir=%s,upperdir=%s,workdir=%s", lowerDir, upperDir, workDir)
|
||||
|
||||
// if it's mounted already, just return
|
||||
mounted, err := d.mounted(mergedDir)
|
||||
if err != nil {
|
||||
d.ctr.Decrement(id)
|
||||
return "", err
|
||||
}
|
||||
if mounted {
|
||||
d.ctr.Decrement(id)
|
||||
return mergedDir, nil
|
||||
}
|
||||
|
||||
if err := syscall.Mount("overlay", mergedDir, "overlay", 0, label.FormatMountLabel(opts, mountLabel)); err != nil {
|
||||
d.ctr.Decrement(id)
|
||||
return "", fmt.Errorf("error creating overlay mount to %s: %v", mergedDir, err)
|
||||
}
|
||||
// chown "workdir/work" to the remapped root UID/GID. Overlay fs inside a
|
||||
// user namespace requires this to move a directory from lower to upper.
|
||||
rootUID, rootGID, err := idtools.GetRootUIDGID(d.uidMaps, d.gidMaps)
|
||||
if err != nil {
|
||||
d.ctr.Decrement(id)
|
||||
syscall.Unmount(mergedDir, 0)
|
||||
return "", err
|
||||
}
|
||||
|
||||
if err := os.Chown(path.Join(workDir, "work"), rootUID, rootGID); err != nil {
|
||||
d.ctr.Decrement(id)
|
||||
syscall.Unmount(mergedDir, 0)
|
||||
return "", err
|
||||
}
|
||||
mount.path = mergedDir
|
||||
mount.mounted = true
|
||||
d.active[id] = mount
|
||||
|
||||
return mount.path, nil
|
||||
d.pathCacheLock.Lock()
|
||||
d.pathCache[id] = mergedDir
|
||||
d.pathCacheLock.Unlock()
|
||||
|
||||
return mergedDir, nil
|
||||
}
|
||||
|
||||
func (d *Driver) mounted(dir string) (bool, error) {
|
||||
return graphdriver.Mounted(graphdriver.FsMagicOverlay, dir)
|
||||
}
|
||||
|
||||
// Put unmounts the mount path created for the give id.
|
||||
func (d *Driver) Put(id string) error {
|
||||
// Protect the d.active from concurrent access
|
||||
d.Lock()
|
||||
defer d.Unlock()
|
||||
if count := d.ctr.Decrement(id); count > 0 {
|
||||
return nil
|
||||
}
|
||||
d.pathCacheLock.Lock()
|
||||
mountpoint, exists := d.pathCache[id]
|
||||
d.pathCacheLock.Unlock()
|
||||
|
||||
mount := d.active[id]
|
||||
if mount == nil {
|
||||
if !exists {
|
||||
logrus.Debugf("Put on a non-mounted device %s", id)
|
||||
// but it might be still here
|
||||
if d.Exists(id) {
|
||||
mergedDir := path.Join(d.dir(id), "merged")
|
||||
err := syscall.Unmount(mergedDir, 0)
|
||||
if err != nil {
|
||||
logrus.Debugf("Failed to unmount %s overlay: %v", id, err)
|
||||
}
|
||||
mountpoint = path.Join(d.dir(id), "merged")
|
||||
}
|
||||
return nil
|
||||
|
||||
d.pathCacheLock.Lock()
|
||||
d.pathCache[id] = mountpoint
|
||||
d.pathCacheLock.Unlock()
|
||||
}
|
||||
|
||||
mount.count--
|
||||
if mount.count > 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
defer delete(d.active, id)
|
||||
if mount.mounted {
|
||||
err := syscall.Unmount(mount.path, 0)
|
||||
if err != nil {
|
||||
if mounted, err := d.mounted(mountpoint); mounted || err != nil {
|
||||
if err = syscall.Unmount(mountpoint, 0); err != nil {
|
||||
logrus.Debugf("Failed to unmount %s overlay: %v", id, err)
|
||||
}
|
||||
return err
|
||||
|
||||
@@ -13,7 +13,6 @@ import (
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"sync"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
@@ -47,10 +46,6 @@ const (
|
||||
type Driver struct {
|
||||
// info stores the shim driver information
|
||||
info hcsshim.DriverInfo
|
||||
// Mutex protects concurrent modification to active
|
||||
sync.Mutex
|
||||
// active stores references to the activated layers
|
||||
active map[string]int
|
||||
}
|
||||
|
||||
var _ graphdriver.DiffGetterDriver = &Driver{}
|
||||
@@ -63,7 +58,6 @@ func InitFilter(home string, options []string, uidMaps, gidMaps []idtools.IDMap)
|
||||
HomeDir: home,
|
||||
Flavour: filterDriver,
|
||||
},
|
||||
active: make(map[string]int),
|
||||
}
|
||||
return d, nil
|
||||
}
|
||||
@@ -76,7 +70,6 @@ func InitDiff(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (
|
||||
HomeDir: home,
|
||||
Flavour: diffDriver,
|
||||
},
|
||||
active: make(map[string]int),
|
||||
}
|
||||
return d, nil
|
||||
}
|
||||
@@ -189,9 +182,6 @@ func (d *Driver) Get(id, mountLabel string) (string, error) {
|
||||
logrus.Debugf("WindowsGraphDriver Get() id %s mountLabel %s", id, mountLabel)
|
||||
var dir string
|
||||
|
||||
d.Lock()
|
||||
defer d.Unlock()
|
||||
|
||||
rID, err := d.resolveID(id)
|
||||
if err != nil {
|
||||
return "", err
|
||||
@@ -203,16 +193,14 @@ func (d *Driver) Get(id, mountLabel string) (string, error) {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if d.active[rID] == 0 {
|
||||
if err := hcsshim.ActivateLayer(d.info, rID); err != nil {
|
||||
return "", err
|
||||
}
|
||||
if err := hcsshim.PrepareLayer(d.info, rID, layerChain); err != nil {
|
||||
if err2 := hcsshim.DeactivateLayer(d.info, rID); err2 != nil {
|
||||
logrus.Warnf("Failed to Deactivate %s: %s", id, err)
|
||||
}
|
||||
return "", err
|
||||
if err := hcsshim.ActivateLayer(d.info, rID); err != nil {
|
||||
return "", err
|
||||
}
|
||||
if err := hcsshim.PrepareLayer(d.info, rID, layerChain); err != nil {
|
||||
if err2 := hcsshim.DeactivateLayer(d.info, rID); err2 != nil {
|
||||
logrus.Warnf("Failed to Deactivate %s: %s", id, err)
|
||||
}
|
||||
return "", err
|
||||
}
|
||||
|
||||
mountPath, err := hcsshim.GetLayerMountPath(d.info, rID)
|
||||
@@ -223,8 +211,6 @@ func (d *Driver) Get(id, mountLabel string) (string, error) {
|
||||
return "", err
|
||||
}
|
||||
|
||||
d.active[rID]++
|
||||
|
||||
// If the layer has a mount path, use that. Otherwise, use the
|
||||
// folder path.
|
||||
if mountPath != "" {
|
||||
@@ -245,22 +231,10 @@ func (d *Driver) Put(id string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
d.Lock()
|
||||
defer d.Unlock()
|
||||
|
||||
if d.active[rID] > 1 {
|
||||
d.active[rID]--
|
||||
} else if d.active[rID] == 1 {
|
||||
if err := hcsshim.UnprepareLayer(d.info, rID); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := hcsshim.DeactivateLayer(d.info, rID); err != nil {
|
||||
return err
|
||||
}
|
||||
delete(d.active, rID)
|
||||
if err := hcsshim.UnprepareLayer(d.info, rID); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
return hcsshim.DeactivateLayer(d.info, rID)
|
||||
}
|
||||
|
||||
// Cleanup ensures the information the driver stores is properly removed.
|
||||
@@ -270,62 +244,40 @@ func (d *Driver) Cleanup() error {
|
||||
|
||||
// Diff produces an archive of the changes between the specified
|
||||
// layer and its parent layer which may be "".
|
||||
// The layer should be mounted when calling this function
|
||||
func (d *Driver) Diff(id, parent string) (_ archive.Archive, err error) {
|
||||
rID, err := d.resolveID(id)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Getting the layer paths must be done outside of the lock.
|
||||
layerChain, err := d.getLayerChain(rID)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
var undo func()
|
||||
|
||||
d.Lock()
|
||||
|
||||
// To support export, a layer must be activated but not prepared.
|
||||
if d.info.Flavour == filterDriver {
|
||||
if d.active[rID] == 0 {
|
||||
if err = hcsshim.ActivateLayer(d.info, rID); err != nil {
|
||||
d.Unlock()
|
||||
return
|
||||
}
|
||||
undo = func() {
|
||||
if err := hcsshim.DeactivateLayer(d.info, rID); err != nil {
|
||||
logrus.Warnf("Failed to Deactivate %s: %s", rID, err)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if err = hcsshim.UnprepareLayer(d.info, rID); err != nil {
|
||||
d.Unlock()
|
||||
return
|
||||
}
|
||||
undo = func() {
|
||||
if err := hcsshim.PrepareLayer(d.info, rID, layerChain); err != nil {
|
||||
logrus.Warnf("Failed to re-PrepareLayer %s: %s", rID, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
// this is assuming that the layer is unmounted
|
||||
if err := hcsshim.UnprepareLayer(d.info, rID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
d.Unlock()
|
||||
defer func() {
|
||||
if err := hcsshim.PrepareLayer(d.info, rID, layerChain); err != nil {
|
||||
logrus.Warnf("Failed to Deactivate %s: %s", rID, err)
|
||||
}
|
||||
}()
|
||||
|
||||
arch, err := d.exportLayer(rID, layerChain)
|
||||
if err != nil {
|
||||
undo()
|
||||
return
|
||||
}
|
||||
return ioutils.NewReadCloserWrapper(arch, func() error {
|
||||
defer undo()
|
||||
return arch.Close()
|
||||
}), nil
|
||||
}
|
||||
|
||||
// Changes produces a list of changes between the specified layer
|
||||
// and its parent layer. If parent is "", then all changes will be ADD changes.
|
||||
// The layer should be mounted when calling this function
|
||||
func (d *Driver) Changes(id, parent string) ([]archive.Change, error) {
|
||||
rID, err := d.resolveID(id)
|
||||
if err != nil {
|
||||
@@ -336,31 +288,15 @@ func (d *Driver) Changes(id, parent string) ([]archive.Change, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
d.Lock()
|
||||
if d.info.Flavour == filterDriver {
|
||||
if d.active[rID] == 0 {
|
||||
if err = hcsshim.ActivateLayer(d.info, rID); err != nil {
|
||||
d.Unlock()
|
||||
return nil, err
|
||||
}
|
||||
defer func() {
|
||||
if err := hcsshim.DeactivateLayer(d.info, rID); err != nil {
|
||||
logrus.Warnf("Failed to Deactivate %s: %s", rID, err)
|
||||
}
|
||||
}()
|
||||
} else {
|
||||
if err = hcsshim.UnprepareLayer(d.info, rID); err != nil {
|
||||
d.Unlock()
|
||||
return nil, err
|
||||
}
|
||||
defer func() {
|
||||
if err := hcsshim.PrepareLayer(d.info, rID, parentChain); err != nil {
|
||||
logrus.Warnf("Failed to re-PrepareLayer %s: %s", rID, err)
|
||||
}
|
||||
}()
|
||||
}
|
||||
// this is assuming that the layer is unmounted
|
||||
if err := hcsshim.UnprepareLayer(d.info, rID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
d.Unlock()
|
||||
defer func() {
|
||||
if err := hcsshim.PrepareLayer(d.info, rID, parentChain); err != nil {
|
||||
logrus.Warnf("Failed to Deactivate %s: %s", rID, err)
|
||||
}
|
||||
}()
|
||||
|
||||
r, err := hcsshim.NewLayerReader(d.info, id, parentChain)
|
||||
if err != nil {
|
||||
@@ -391,6 +327,7 @@ func (d *Driver) Changes(id, parent string) ([]archive.Change, error) {
|
||||
// ApplyDiff extracts the changeset from the given diff into the
|
||||
// layer with the specified id and parent, returning the size of the
|
||||
// new layer in bytes.
|
||||
// The layer should not be mounted when calling this function
|
||||
func (d *Driver) ApplyDiff(id, parent string, diff archive.Reader) (size int64, err error) {
|
||||
rPId, err := d.resolveID(parent)
|
||||
if err != nil {
|
||||
|
||||
@@ -22,12 +22,6 @@ import (
|
||||
"github.com/opencontainers/runc/libcontainer/label"
|
||||
)
|
||||
|
||||
type activeMount struct {
|
||||
count int
|
||||
path string
|
||||
mounted bool
|
||||
}
|
||||
|
||||
type zfsOptions struct {
|
||||
fsName string
|
||||
mountPath string
|
||||
@@ -109,9 +103,9 @@ func Init(base string, opt []string, uidMaps, gidMaps []idtools.IDMap) (graphdri
|
||||
dataset: rootDataset,
|
||||
options: options,
|
||||
filesystemsCache: filesystemsCache,
|
||||
active: make(map[string]*activeMount),
|
||||
uidMaps: uidMaps,
|
||||
gidMaps: gidMaps,
|
||||
ctr: graphdriver.NewRefCounter(),
|
||||
}
|
||||
return graphdriver.NewNaiveDiffDriver(d, uidMaps, gidMaps), nil
|
||||
}
|
||||
@@ -166,9 +160,9 @@ type Driver struct {
|
||||
options zfsOptions
|
||||
sync.Mutex // protects filesystem cache against concurrent access
|
||||
filesystemsCache map[string]bool
|
||||
active map[string]*activeMount
|
||||
uidMaps []idtools.IDMap
|
||||
gidMaps []idtools.IDMap
|
||||
ctr *graphdriver.RefCounter
|
||||
}
|
||||
|
||||
func (d *Driver) String() string {
|
||||
@@ -302,81 +296,64 @@ func (d *Driver) Remove(id string) error {
|
||||
|
||||
// Get returns the mountpoint for the given id after creating the target directories if necessary.
|
||||
func (d *Driver) Get(id, mountLabel string) (string, error) {
|
||||
d.Lock()
|
||||
defer d.Unlock()
|
||||
|
||||
mnt := d.active[id]
|
||||
if mnt != nil {
|
||||
mnt.count++
|
||||
return mnt.path, nil
|
||||
mountpoint := d.mountPath(id)
|
||||
if count := d.ctr.Increment(id); count > 1 {
|
||||
return mountpoint, nil
|
||||
}
|
||||
|
||||
mnt = &activeMount{count: 1}
|
||||
|
||||
mountpoint := d.mountPath(id)
|
||||
filesystem := d.zfsPath(id)
|
||||
options := label.FormatMountLabel("", mountLabel)
|
||||
logrus.Debugf(`[zfs] mount("%s", "%s", "%s")`, filesystem, mountpoint, options)
|
||||
|
||||
rootUID, rootGID, err := idtools.GetRootUIDGID(d.uidMaps, d.gidMaps)
|
||||
if err != nil {
|
||||
d.ctr.Decrement(id)
|
||||
return "", err
|
||||
}
|
||||
// Create the target directories if they don't exist
|
||||
if err := idtools.MkdirAllAs(mountpoint, 0755, rootUID, rootGID); err != nil {
|
||||
d.ctr.Decrement(id)
|
||||
return "", err
|
||||
}
|
||||
|
||||
if err := mount.Mount(filesystem, mountpoint, "zfs", options); err != nil {
|
||||
d.ctr.Decrement(id)
|
||||
return "", fmt.Errorf("error creating zfs mount of %s to %s: %v", filesystem, mountpoint, err)
|
||||
}
|
||||
|
||||
// this could be our first mount after creation of the filesystem, and the root dir may still have root
|
||||
// permissions instead of the remapped root uid:gid (if user namespaces are enabled):
|
||||
if err := os.Chown(mountpoint, rootUID, rootGID); err != nil {
|
||||
mount.Unmount(mountpoint)
|
||||
d.ctr.Decrement(id)
|
||||
return "", fmt.Errorf("error modifying zfs mountpoint (%s) directory ownership: %v", mountpoint, err)
|
||||
}
|
||||
mnt.path = mountpoint
|
||||
mnt.mounted = true
|
||||
d.active[id] = mnt
|
||||
|
||||
return mountpoint, nil
|
||||
}
|
||||
|
||||
// Put removes the existing mountpoint for the given id if it exists.
|
||||
func (d *Driver) Put(id string) error {
|
||||
d.Lock()
|
||||
defer d.Unlock()
|
||||
|
||||
mnt := d.active[id]
|
||||
if mnt == nil {
|
||||
logrus.Debugf("[zfs] Put on a non-mounted device %s", id)
|
||||
// but it might be still here
|
||||
if d.Exists(id) {
|
||||
err := mount.Unmount(d.mountPath(id))
|
||||
if err != nil {
|
||||
logrus.Debugf("[zfs] Failed to unmount %s zfs fs: %v", id, err)
|
||||
}
|
||||
}
|
||||
if count := d.ctr.Decrement(id); count > 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
mnt.count--
|
||||
if mnt.count > 0 {
|
||||
return nil
|
||||
mountpoint := d.mountPath(id)
|
||||
mounted, err := graphdriver.Mounted(graphdriver.FsMagicZfs, mountpoint)
|
||||
if err != nil || !mounted {
|
||||
return err
|
||||
}
|
||||
|
||||
defer delete(d.active, id)
|
||||
if mnt.mounted {
|
||||
logrus.Debugf(`[zfs] unmount("%s")`, mnt.path)
|
||||
logrus.Debugf(`[zfs] unmount("%s")`, mountpoint)
|
||||
|
||||
if err := mount.Unmount(mnt.path); err != nil {
|
||||
return fmt.Errorf("error unmounting to %s: %v", mnt.path, err)
|
||||
}
|
||||
if err := mount.Unmount(mountpoint); err != nil {
|
||||
return fmt.Errorf("error unmounting to %s: %v", mountpoint, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Exists checks to see if the cache entry exists for the given id.
|
||||
func (d *Driver) Exists(id string) bool {
|
||||
d.Lock()
|
||||
defer d.Unlock()
|
||||
return d.filesystemsCache[d.zfsPath(id)] == true
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package daemon
|
||||
import (
|
||||
"fmt"
|
||||
"runtime"
|
||||
"strings"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
@@ -81,7 +82,14 @@ func (daemon *Daemon) killWithSignal(container *container.Container, sig int) er
|
||||
}
|
||||
|
||||
if err := daemon.kill(container, sig); err != nil {
|
||||
return fmt.Errorf("Cannot kill container %s: %s", container.ID, err)
|
||||
err = fmt.Errorf("Cannot kill container %s: %s", container.ID, err)
|
||||
// if container or process not exists, ignore the error
|
||||
if strings.Contains(err.Error(), "container not found") ||
|
||||
strings.Contains(err.Error(), "no such process") {
|
||||
logrus.Warnf("%s", err.Error())
|
||||
} else {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
attributes := map[string]string{
|
||||
|
||||
@@ -63,11 +63,11 @@ package journald
|
||||
// fds[0].events = POLLHUP;
|
||||
// fds[1].fd = sd_journal_get_fd(j);
|
||||
// if (fds[1].fd < 0) {
|
||||
// return -1;
|
||||
// return fds[1].fd;
|
||||
// }
|
||||
// jevents = sd_journal_get_events(j);
|
||||
// if (jevents < 0) {
|
||||
// return -1;
|
||||
// return jevents;
|
||||
// }
|
||||
// fds[1].events = jevents;
|
||||
// sd_journal_get_timeout(j, &when);
|
||||
@@ -81,7 +81,7 @@ package journald
|
||||
// i = poll(fds, 2, timeout);
|
||||
// if ((i == -1) && (errno != EINTR)) {
|
||||
// /* An unexpected error. */
|
||||
// return -1;
|
||||
// return (errno != 0) ? -errno : -EINTR;
|
||||
// }
|
||||
// if (fds[0].revents & POLLHUP) {
|
||||
// /* The close notification pipe was closed. */
|
||||
@@ -101,6 +101,7 @@ import (
|
||||
"time"
|
||||
"unsafe"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
"github.com/coreos/go-systemd/journal"
|
||||
"github.com/docker/docker/daemon/logger"
|
||||
)
|
||||
@@ -177,9 +178,18 @@ func (s *journald) followJournal(logWatcher *logger.LogWatcher, config logger.Re
|
||||
s.readers.readers[logWatcher] = logWatcher
|
||||
s.readers.mu.Unlock()
|
||||
go func() {
|
||||
// Keep copying journal data out until we're notified to stop.
|
||||
for C.wait_for_data_or_close(j, pfd[0]) == 1 {
|
||||
// Keep copying journal data out until we're notified to stop
|
||||
// or we hit an error.
|
||||
status := C.wait_for_data_or_close(j, pfd[0])
|
||||
for status == 1 {
|
||||
cursor = s.drainJournal(logWatcher, config, j, cursor)
|
||||
status = C.wait_for_data_or_close(j, pfd[0])
|
||||
}
|
||||
if status < 0 {
|
||||
cerrstr := C.strerror(C.int(-status))
|
||||
errstr := C.GoString(cerrstr)
|
||||
fmtstr := "error %q while attempting to follow journal for container %q"
|
||||
logrus.Errorf(fmtstr, errstr, s.vars["CONTAINER_ID_FULL"])
|
||||
}
|
||||
// Clean up.
|
||||
C.close(pfd[0])
|
||||
@@ -293,14 +303,21 @@ func (s *journald) readLogs(logWatcher *logger.LogWatcher, config logger.ReadCon
|
||||
}
|
||||
cursor = s.drainJournal(logWatcher, config, j, "")
|
||||
if config.Follow {
|
||||
// Create a pipe that we can poll at the same time as the journald descriptor.
|
||||
if C.pipe(&pipes[0]) == C.int(-1) {
|
||||
logWatcher.Err <- fmt.Errorf("error opening journald close notification pipe")
|
||||
// Allocate a descriptor for following the journal, if we'll
|
||||
// need one. Do it here so that we can report if it fails.
|
||||
if fd := C.sd_journal_get_fd(j); fd < C.int(0) {
|
||||
logWatcher.Err <- fmt.Errorf("error opening journald follow descriptor: %q", C.GoString(C.strerror(-fd)))
|
||||
} else {
|
||||
s.followJournal(logWatcher, config, j, pipes, cursor)
|
||||
// Let followJournal handle freeing the journal context
|
||||
// object and closing the channel.
|
||||
following = true
|
||||
// Create a pipe that we can poll at the same time as
|
||||
// the journald descriptor.
|
||||
if C.pipe(&pipes[0]) == C.int(-1) {
|
||||
logWatcher.Err <- fmt.Errorf("error opening journald close notification pipe")
|
||||
} else {
|
||||
s.followJournal(logWatcher, config, j, pipes, cursor)
|
||||
// Let followJournal handle freeing the journal context
|
||||
// object and closing the channel.
|
||||
following = true
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
|
||||
@@ -77,6 +77,7 @@ func (daemon *Daemon) StateChanged(id string, e libcontainerd.StateInfo) error {
|
||||
c.Reset(false)
|
||||
return err
|
||||
}
|
||||
daemon.LogContainerEvent(c, "start")
|
||||
case libcontainerd.StatePause:
|
||||
c.Paused = true
|
||||
daemon.LogContainerEvent(c, "pause")
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
"github.com/docker/docker/container"
|
||||
"github.com/docker/docker/daemon/caps"
|
||||
"github.com/docker/docker/libcontainerd"
|
||||
@@ -78,6 +79,7 @@ func setResources(s *specs.Spec, r containertypes.Resources) error {
|
||||
func setDevices(s *specs.Spec, c *container.Container) error {
|
||||
// Build lists of devices allowed and created within the container.
|
||||
var devs []specs.Device
|
||||
devPermissions := s.Linux.Resources.Devices
|
||||
if c.HostConfig.Privileged {
|
||||
hostDevices, err := devices.HostDevices()
|
||||
if err != nil {
|
||||
@@ -86,18 +88,26 @@ func setDevices(s *specs.Spec, c *container.Container) error {
|
||||
for _, d := range hostDevices {
|
||||
devs = append(devs, specDevice(d))
|
||||
}
|
||||
rwm := "rwm"
|
||||
devPermissions = []specs.DeviceCgroup{
|
||||
{
|
||||
Allow: true,
|
||||
Access: &rwm,
|
||||
},
|
||||
}
|
||||
} else {
|
||||
for _, deviceMapping := range c.HostConfig.Devices {
|
||||
d, err := getDevicesFromPath(deviceMapping)
|
||||
d, dPermissions, err := getDevicesFromPath(deviceMapping)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
devs = append(devs, d...)
|
||||
devPermissions = append(devPermissions, dPermissions...)
|
||||
}
|
||||
}
|
||||
|
||||
s.Linux.Devices = append(s.Linux.Devices, devs...)
|
||||
s.Linux.Resources.Devices = devPermissions
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -526,6 +536,8 @@ func setMounts(daemon *Daemon, s *specs.Spec, c *container.Container, mounts []c
|
||||
}
|
||||
}
|
||||
}
|
||||
s.Linux.ReadonlyPaths = nil
|
||||
s.Linux.MaskedPaths = nil
|
||||
}
|
||||
|
||||
// TODO: until a kernel/mount solution exists for handling remount in a user namespace,
|
||||
@@ -574,16 +586,24 @@ func (daemon *Daemon) createSpec(c *container.Container) (*libcontainerd.Spec, e
|
||||
}
|
||||
|
||||
var cgroupsPath string
|
||||
scopePrefix := "docker"
|
||||
parent := "/docker"
|
||||
useSystemd := UsingSystemd(daemon.configStore)
|
||||
if useSystemd {
|
||||
parent = "system.slice"
|
||||
}
|
||||
|
||||
if c.HostConfig.CgroupParent != "" {
|
||||
cgroupsPath = filepath.Join(c.HostConfig.CgroupParent, c.ID)
|
||||
parent = c.HostConfig.CgroupParent
|
||||
} else if daemon.configStore.CgroupParent != "" {
|
||||
parent = daemon.configStore.CgroupParent
|
||||
}
|
||||
|
||||
if useSystemd {
|
||||
cgroupsPath = parent + ":" + scopePrefix + ":" + c.ID
|
||||
logrus.Debugf("createSpec: cgroupsPath: %s", cgroupsPath)
|
||||
} else {
|
||||
defaultCgroupParent := "/docker"
|
||||
if daemon.configStore.CgroupParent != "" {
|
||||
defaultCgroupParent = daemon.configStore.CgroupParent
|
||||
} else if daemon.usingSystemd() {
|
||||
defaultCgroupParent = "system.slice"
|
||||
}
|
||||
cgroupsPath = filepath.Join(defaultCgroupParent, c.ID)
|
||||
cgroupsPath = filepath.Join(parent, c.ID)
|
||||
}
|
||||
s.Linux.CgroupsPath = &cgroupsPath
|
||||
|
||||
@@ -642,15 +662,16 @@ func (daemon *Daemon) createSpec(c *container.Container) (*libcontainerd.Spec, e
|
||||
|
||||
if apparmor.IsEnabled() {
|
||||
appArmorProfile := "docker-default"
|
||||
if c.HostConfig.Privileged {
|
||||
appArmorProfile = "unconfined"
|
||||
} else if len(c.AppArmorProfile) > 0 {
|
||||
if len(c.AppArmorProfile) > 0 {
|
||||
appArmorProfile = c.AppArmorProfile
|
||||
} else if c.HostConfig.Privileged {
|
||||
appArmorProfile = "unconfined"
|
||||
}
|
||||
s.Process.ApparmorProfile = appArmorProfile
|
||||
}
|
||||
s.Process.SelinuxLabel = c.GetProcessLabel()
|
||||
s.Process.NoNewPrivileges = c.NoNewPrivileges
|
||||
s.Linux.MountLabel = c.MountLabel
|
||||
|
||||
return (*libcontainerd.Spec)(&s), nil
|
||||
}
|
||||
|
||||
@@ -131,7 +131,6 @@ func (daemon *Daemon) containerStart(container *container.Container) (err error)
|
||||
return err
|
||||
}
|
||||
|
||||
defer daemon.LogContainerEvent(container, "start") // this is logged even on error
|
||||
if err := daemon.containerd.Create(container.ID, *spec, libcontainerd.WithRestartManager(container.RestartManager(true))); err != nil {
|
||||
// if we receive an internal error from the initial start of a container then lets
|
||||
// return it instead of entering the restart loop
|
||||
@@ -149,6 +148,9 @@ func (daemon *Daemon) containerStart(container *container.Container) (err error)
|
||||
}
|
||||
|
||||
container.Reset(false)
|
||||
|
||||
// start event is logged even on error
|
||||
daemon.LogContainerEvent(container, "start")
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -174,8 +176,10 @@ func (daemon *Daemon) Cleanup(container *container.Container) {
|
||||
daemon.unregisterExecCommand(container, eConfig)
|
||||
}
|
||||
|
||||
if err := container.UnmountVolumes(false, daemon.LogVolumeEvent); err != nil {
|
||||
logrus.Warnf("%s cleanup: Failed to umount volumes: %v", container.ID, err)
|
||||
if container.BaseFS != "" {
|
||||
if err := container.UnmountVolumes(false, daemon.LogVolumeEvent); err != nil {
|
||||
logrus.Warnf("%s cleanup: Failed to umount volumes: %v", container.ID, err)
|
||||
}
|
||||
}
|
||||
container.CancelAttachContext()
|
||||
}
|
||||
|
||||
@@ -41,11 +41,11 @@ func (daemon *Daemon) ContainerStats(prefixOrName string, config *backend.Contai
|
||||
|
||||
var preCPUStats types.CPUStats
|
||||
getStatJSON := func(v interface{}) *types.StatsJSON {
|
||||
ss := v.(*types.StatsJSON)
|
||||
ss := v.(types.StatsJSON)
|
||||
ss.PreCPUStats = preCPUStats
|
||||
// ss.MemoryStats.Limit = uint64(update.MemoryLimit)
|
||||
preCPUStats = ss.CPUStats
|
||||
return ss
|
||||
return &ss
|
||||
}
|
||||
|
||||
enc := json.NewEncoder(outStream)
|
||||
|
||||
@@ -14,6 +14,7 @@ import (
|
||||
"github.com/Sirupsen/logrus"
|
||||
"github.com/docker/docker/container"
|
||||
"github.com/docker/docker/pkg/pubsub"
|
||||
sysinfo "github.com/docker/docker/pkg/system"
|
||||
"github.com/docker/engine-api/types"
|
||||
"github.com/opencontainers/runc/libcontainer/system"
|
||||
)
|
||||
@@ -35,6 +36,11 @@ func (daemon *Daemon) newStatsCollector(interval time.Duration) *statsCollector
|
||||
clockTicksPerSecond: uint64(system.GetClockTicks()),
|
||||
bufReader: bufio.NewReaderSize(nil, 128),
|
||||
}
|
||||
meminfo, err := sysinfo.ReadMemInfo()
|
||||
if err == nil && meminfo.MemTotal > 0 {
|
||||
s.machineMemory = uint64(meminfo.MemTotal)
|
||||
}
|
||||
|
||||
go s.run()
|
||||
return s
|
||||
}
|
||||
@@ -47,6 +53,7 @@ type statsCollector struct {
|
||||
clockTicksPerSecond uint64
|
||||
publishers map[*container.Container]*pubsub.Publisher
|
||||
bufReader *bufio.Reader
|
||||
machineMemory uint64
|
||||
}
|
||||
|
||||
// collect registers the container with the collector and adds it to
|
||||
@@ -128,7 +135,7 @@ func (s *statsCollector) run() {
|
||||
// FIXME: move to containerd
|
||||
stats.CPUStats.SystemUsage = systemUsage
|
||||
|
||||
pair.publisher.Publish(stats)
|
||||
pair.publisher.Publish(*stats)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -330,7 +330,20 @@ func (ld *v1LayerDescriptor) Download(ctx context.Context, progressOutput progre
|
||||
logrus.Debugf("Downloaded %s to tempfile %s", ld.ID(), ld.tmpFile.Name())
|
||||
|
||||
ld.tmpFile.Seek(0, 0)
|
||||
return ld.tmpFile, ld.layerSize, nil
|
||||
|
||||
// hand off the temporary file to the download manager, so it will only
|
||||
// be closed once
|
||||
tmpFile := ld.tmpFile
|
||||
ld.tmpFile = nil
|
||||
|
||||
return ioutils.NewReadCloserWrapper(tmpFile, func() error {
|
||||
tmpFile.Close()
|
||||
err := os.RemoveAll(tmpFile.Name())
|
||||
if err != nil {
|
||||
logrus.Errorf("Failed to remove temp file: %s", tmpFile.Name())
|
||||
}
|
||||
return err
|
||||
}), ld.layerSize, nil
|
||||
}
|
||||
|
||||
func (ld *v1LayerDescriptor) Close() {
|
||||
|
||||
@@ -17,7 +17,6 @@ import (
|
||||
"github.com/docker/distribution/manifest/schema1"
|
||||
"github.com/docker/distribution/manifest/schema2"
|
||||
"github.com/docker/distribution/registry/api/errcode"
|
||||
"github.com/docker/distribution/registry/client"
|
||||
"github.com/docker/distribution/registry/client/auth"
|
||||
"github.com/docker/distribution/registry/client/transport"
|
||||
"github.com/docker/docker/distribution/metadata"
|
||||
@@ -278,7 +277,19 @@ func (ld *v2LayerDescriptor) Download(ctx context.Context, progressOutput progre
|
||||
ld.verifier = nil
|
||||
return nil, 0, xfer.DoNotRetry{Err: err}
|
||||
}
|
||||
return tmpFile, size, nil
|
||||
|
||||
// hand off the temporary file to the download manager, so it will only
|
||||
// be closed once
|
||||
ld.tmpFile = nil
|
||||
|
||||
return ioutils.NewReadCloserWrapper(tmpFile, func() error {
|
||||
tmpFile.Close()
|
||||
err := os.RemoveAll(tmpFile.Name())
|
||||
if err != nil {
|
||||
logrus.Errorf("Failed to remove temp file: %s", tmpFile.Name())
|
||||
}
|
||||
return err
|
||||
}), size, nil
|
||||
}
|
||||
|
||||
func (ld *v2LayerDescriptor) Close() {
|
||||
@@ -326,7 +337,7 @@ func (p *v2Puller) pullV2Tag(ctx context.Context, ref reference.Named) (tagUpdat
|
||||
// NOTE: not using TagService.Get, since it uses HEAD requests
|
||||
// against the manifests endpoint, which are not supported by
|
||||
// all registry versions.
|
||||
manifest, err = manSvc.Get(ctx, "", client.WithTag(tagged.Tag()))
|
||||
manifest, err = manSvc.Get(ctx, "", distribution.WithTag(tagged.Tag()))
|
||||
if err != nil {
|
||||
return false, allowV1Fallback(err)
|
||||
}
|
||||
|
||||
@@ -166,7 +166,7 @@ func (p *v2Pusher) pushV2Tag(ctx context.Context, ref reference.NamedTagged, ima
|
||||
return err
|
||||
}
|
||||
|
||||
putOptions := []distribution.ManifestServiceOption{client.WithTag(ref.Tag())}
|
||||
putOptions := []distribution.ManifestServiceOption{distribution.WithTag(ref.Tag())}
|
||||
if _, err = manSvc.Put(ctx, manifest, putOptions...); err != nil {
|
||||
logrus.Warnf("failed to upload schema2 manifest: %v - falling back to schema1", err)
|
||||
|
||||
|
||||
@@ -121,6 +121,10 @@ func (ls *mockLayerStore) GetMountID(string) (string, error) {
|
||||
return "", errors.New("not implemented")
|
||||
}
|
||||
|
||||
func (ls *mockLayerStore) ReinitRWLayer(layer.RWLayer) error {
|
||||
return errors.New("not implemented")
|
||||
}
|
||||
|
||||
func (ls *mockLayerStore) Cleanup() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -74,5 +74,9 @@ func (cli *DaemonCli) getPlatformRemoteOptions() []libcontainerd.RemoteOption {
|
||||
} else {
|
||||
opts = append(opts, libcontainerd.WithStartDaemon(true))
|
||||
}
|
||||
if daemon.UsingSystemd(cli.Config) {
|
||||
args := []string{"--systemd-cgroup=true"}
|
||||
opts = append(opts, libcontainerd.WithRuntimeArgs(args))
|
||||
}
|
||||
return opts
|
||||
}
|
||||
|
||||
@@ -56,14 +56,14 @@ directory including the following:
|
||||
|
||||
To check if the `docker.service` uses an `EnvironmentFile`:
|
||||
|
||||
$ sudo systemctl show docker | grep EnvironmentFile
|
||||
$ systemctl show docker | grep EnvironmentFile
|
||||
EnvironmentFile=-/etc/sysconfig/docker (ignore_errors=yes)
|
||||
|
||||
Alternatively, find out where the service file is located:
|
||||
|
||||
$ sudo systemctl status docker | grep Loaded
|
||||
Loaded: loaded (/usr/lib/systemd/system/docker.service; enabled)
|
||||
$ sudo grep EnvironmentFile /usr/lib/systemd/system/docker.service
|
||||
$ systemctl show --property=FragmentPath docker
|
||||
FragmentPath=/usr/lib/systemd/system/docker.service
|
||||
$ grep EnvironmentFile /usr/lib/systemd/system/docker.service
|
||||
EnvironmentFile=-/etc/sysconfig/docker
|
||||
|
||||
You can customize the Docker daemon options using override files as explained in the
|
||||
@@ -143,7 +143,7 @@ Flush changes:
|
||||
|
||||
Verify that the configuration has been loaded:
|
||||
|
||||
$ sudo systemctl show docker --property Environment
|
||||
$ systemctl show --property=Environment docker
|
||||
Environment=HTTP_PROXY=http://proxy.example.com:80/
|
||||
|
||||
Restart Docker:
|
||||
|
||||
@@ -133,17 +133,6 @@ The following double-dash options are deprecated and have no replacement:
|
||||
docker ps --before-id
|
||||
docker search --trusted
|
||||
|
||||
### Auto-creating missing host paths for bind mounts
|
||||
**Deprecated in Release: v1.9**
|
||||
|
||||
**Target for Removal in Release: 1.11**
|
||||
|
||||
When creating a container with a bind-mounted volume-- `docker run -v /host/path:/container/path` --
|
||||
docker was automatically creating the `/host/path` if it didn't already exist.
|
||||
|
||||
This auto-creation of the host path is deprecated and docker will error out if
|
||||
the path does not exist.
|
||||
|
||||
### Interacting with V1 registries
|
||||
|
||||
Version 1.9 adds a flag (`--disable-legacy-registry=false`) which prevents the docker daemon from `pull`, `push`, and `login` operations against v1 registries. Though disabled by default, this signals the intent to deprecate the v1 protocol.
|
||||
|
||||
@@ -169,9 +169,10 @@ Responds with a list of Docker subsystems which this plugin implements.
|
||||
After activation, the plugin will then be sent events from this subsystem.
|
||||
|
||||
Possible values are:
|
||||
- [`authz`](plugins_authorization.md)
|
||||
- [`NetworkDriver`](plugins_network.md)
|
||||
- [`VolumeDriver`](plugins_volume.md)
|
||||
|
||||
* [`authz`](plugins_authorization.md)
|
||||
* [`NetworkDriver`](plugins_network.md)
|
||||
* [`VolumeDriver`](plugins_volume.md)
|
||||
|
||||
|
||||
## Plugin retries
|
||||
|
||||
@@ -149,7 +149,7 @@ should implement the following two methods:
|
||||
"User": "The user identification",
|
||||
"UserAuthNMethod": "The authentication method used",
|
||||
"RequestMethod": "The HTTP method",
|
||||
"RequestUri": "The HTTP request URI",
|
||||
"RequestURI": "The HTTP request URI",
|
||||
"RequestBody": "Byte array containing the raw HTTP request body",
|
||||
"RequestHeader": "Byte array containing the raw HTTP request header as a map[string][]string ",
|
||||
"RequestStatusCode": "Request status code"
|
||||
@@ -174,7 +174,7 @@ should implement the following two methods:
|
||||
"User": "The user identification",
|
||||
"UserAuthNMethod": "The authentication method used",
|
||||
"RequestMethod": "The HTTP method",
|
||||
"RequestUri": "The HTTP request URI",
|
||||
"RequestURI": "The HTTP request URI",
|
||||
"RequestBody": "Byte array containing the raw HTTP request body",
|
||||
"RequestHeader": "Byte array containing the raw HTTP request header as a map[string][]string",
|
||||
"RequestStatusCode": "Request status code",
|
||||
|
||||
@@ -9,7 +9,7 @@ weight = 110
|
||||
+++
|
||||
<![end-metadata]-->
|
||||
|
||||
# Binaries
|
||||
# Installation from binaries
|
||||
|
||||
**This instruction set is meant for hackers who want to try out Docker
|
||||
on a variety of environments.**
|
||||
@@ -85,90 +85,137 @@ exhibit unexpected behaviour.
|
||||
> vendor for the system, and might break regulations and security
|
||||
> policies in heavily regulated environments.
|
||||
|
||||
## Get the Docker binary
|
||||
## Get the Docker Engine binaries
|
||||
|
||||
You can download either the latest release binary or a specific version.
|
||||
After downloading a binary file, you must set the file's execute bit to run it.
|
||||
You can download either the latest release binaries or a specific version. To get
|
||||
the list of stable release version numbers from GitHub, view the `docker/docker`
|
||||
[releases page](https://github.com/docker/docker/releases). You can get the MD5
|
||||
and SHA256 hashes by appending .md5 and .sha256 to the URLs respectively
|
||||
|
||||
To set the file's execute bit on Linux and OS X:
|
||||
|
||||
$ chmod +x docker
|
||||
|
||||
To get the list of stable release version numbers from GitHub, view the
|
||||
`docker/docker` [releases page](https://github.com/docker/docker/releases).
|
||||
|
||||
> **Note**
|
||||
>
|
||||
> 1) You can get the MD5 and SHA256 hashes by appending .md5 and .sha256 to the URLs respectively
|
||||
>
|
||||
> 2) You can get the compressed binaries by appending .tgz to the URLs
|
||||
|
||||
### Get the Linux binary
|
||||
### Get the Linux binaries
|
||||
|
||||
To download the latest version for Linux, use the
|
||||
following URLs:
|
||||
|
||||
https://get.docker.com/builds/Linux/i386/docker-latest
|
||||
https://get.docker.com/builds/Linux/i386/docker-latest.tgz
|
||||
|
||||
https://get.docker.com/builds/Linux/x86_64/docker-latest
|
||||
https://get.docker.com/builds/Linux/x86_64/docker-latest.tgz
|
||||
|
||||
To download a specific version for Linux, use the
|
||||
following URL patterns:
|
||||
|
||||
https://get.docker.com/builds/Linux/i386/docker-<version>
|
||||
https://get.docker.com/builds/Linux/i386/docker-<version>.tgz
|
||||
|
||||
https://get.docker.com/builds/Linux/x86_64/docker-<version>
|
||||
https://get.docker.com/builds/Linux/x86_64/docker-<version>.tgz
|
||||
|
||||
For example:
|
||||
|
||||
https://get.docker.com/builds/Linux/i386/docker-1.9.1
|
||||
https://get.docker.com/builds/Linux/i386/docker-1.11.0.tgz
|
||||
|
||||
https://get.docker.com/builds/Linux/x86_64/docker-1.9.1
|
||||
https://get.docker.com/builds/Linux/x86_64/docker-1.11.0.tgz
|
||||
|
||||
> **Note** These instructions are for Docker Engine 1.11 and up. Engine 1.10 and
|
||||
> under consists of a single binary, and instructions for those versions are
|
||||
> different. To install version 1.10 or below, follow the instructions in the
|
||||
> <a href="/v1.10/engine/installation/binaries/" target="_blank">1.10 documentation</a>.
|
||||
|
||||
|
||||
#### Install the Linux binaries
|
||||
|
||||
After downloading, you extract the archive, which puts the binaries in a
|
||||
directory named `docker` in your current location.
|
||||
|
||||
```bash
|
||||
$ tar -xvzf docker-latest.tgz
|
||||
|
||||
docker/
|
||||
docker/docker-containerd-ctr
|
||||
docker/docker
|
||||
docker/docker-containerd
|
||||
docker/docker-runc
|
||||
docker/docker-containerd-shim
|
||||
```
|
||||
|
||||
Engine requires these binaries to be installed in your host's `$PATH`.
|
||||
For example, to install the binaries in `/usr/bin`:
|
||||
|
||||
```bash
|
||||
$ mv docker/* /usr/bin/
|
||||
```
|
||||
|
||||
> **Note**: If you already have Engine installed on your host, make sure you
|
||||
> stop Engine before installing (`killall docker`), and install the binaries
|
||||
> in the same location. You can find the location of the current installation
|
||||
> with `dirname $(which docker)`.
|
||||
|
||||
#### Run the Engine daemon on Linux
|
||||
|
||||
You can manually start the Engine in daemon mode using:
|
||||
|
||||
```bash
|
||||
$ sudo docker daemon &
|
||||
```
|
||||
|
||||
The GitHub repository provides samples of init-scripts you can use to control
|
||||
the daemon through a process manager, such as upstart or systemd. You can find
|
||||
these scripts in the <a href="https://github.com/docker/docker/tree/master/contrib/init">
|
||||
contrib directory</a>.
|
||||
|
||||
For additional information about running the Engine in daemon mode, refer to
|
||||
the [daemon command](../reference/commandline/daemon.md) in the Engine command
|
||||
line reference.
|
||||
|
||||
### Get the Mac OS X binary
|
||||
|
||||
The Mac OS X binary is only a client. You cannot use it to run the `docker`
|
||||
daemon. To download the latest version for Mac OS X, use the following URLs:
|
||||
|
||||
https://get.docker.com/builds/Darwin/x86_64/docker-latest
|
||||
https://get.docker.com/builds/Darwin/x86_64/docker-latest.tgz
|
||||
|
||||
To download a specific version for Mac OS X, use the
|
||||
following URL patterns:
|
||||
following URL pattern:
|
||||
|
||||
https://get.docker.com/builds/Darwin/x86_64/docker-<version>
|
||||
https://get.docker.com/builds/Darwin/x86_64/docker-<version>.tgz
|
||||
|
||||
For example:
|
||||
|
||||
https://get.docker.com/builds/Darwin/x86_64/docker-1.9.1
|
||||
https://get.docker.com/builds/Darwin/x86_64/docker-1.11.0.tgz
|
||||
|
||||
You can extract the downloaded archive either by double-clicking the downloaded
|
||||
`.tgz` or on the command line, using `tar -xvzf docker-1.11.0.tgz`. The client
|
||||
binary can be executed from any location on your filesystem.
|
||||
|
||||
|
||||
### Get the Windows binary
|
||||
|
||||
You can only download the Windows client binary for version `1.9.1` onwards.
|
||||
Moreover, the binary is only a client, you cannot use it to run the `docker` daemon.
|
||||
You can only download the Windows binary for version `1.9.1` onwards.
|
||||
Moreover, the 32-bit (`i386`) binary is only a client, you cannot use it to
|
||||
run the `docker` daemon. The 64-bit binary (`x86_64`) is both a client and
|
||||
daemon.
|
||||
|
||||
To download the latest version for Windows, use the following URLs:
|
||||
|
||||
https://get.docker.com/builds/Windows/i386/docker-latest.exe
|
||||
https://get.docker.com/builds/Windows/i386/docker-latest.zip
|
||||
|
||||
https://get.docker.com/builds/Windows/x86_64/docker-latest.exe
|
||||
https://get.docker.com/builds/Windows/x86_64/docker-latest.zip
|
||||
|
||||
To download a specific version for Windows, use the following URL pattern:
|
||||
|
||||
https://get.docker.com/builds/Windows/i386/docker-<version>.exe
|
||||
https://get.docker.com/builds/Windows/i386/docker-<version>.zip
|
||||
|
||||
https://get.docker.com/builds/Windows/x86_64/docker-<version>.exe
|
||||
https://get.docker.com/builds/Windows/x86_64/docker-<version>.zip
|
||||
|
||||
For example:
|
||||
|
||||
https://get.docker.com/builds/Windows/i386/docker-1.9.1.exe
|
||||
https://get.docker.com/builds/Windows/i386/docker-1.11.0.zip
|
||||
|
||||
https://get.docker.com/builds/Windows/x86_64/docker-1.9.1.exe
|
||||
https://get.docker.com/builds/Windows/x86_64/docker-1.11.0.zip
|
||||
|
||||
|
||||
## Run the Docker daemon
|
||||
|
||||
# start the docker in daemon mode from the directory you unpacked
|
||||
$ sudo ./docker daemon &
|
||||
> **Note** These instructions are for Engine 1.11 and up. Instructions for older
|
||||
> versions are slightly different. To install version 1.10 or below, follow the
|
||||
> instructions in the <a href="/v1.10/engine/installation/binaries/" target="_blank">1.10 documentation</a>.
|
||||
|
||||
## Giving non-root access
|
||||
|
||||
@@ -188,21 +235,15 @@ need to add `sudo` to all the client commands.
|
||||
> The *docker* group (or the group specified with `-G`) is root-equivalent;
|
||||
> see [*Docker Daemon Attack Surface*](../security/security.md#docker-daemon-attack-surface) details.
|
||||
|
||||
## Upgrades
|
||||
## Upgrade Docker Engine
|
||||
|
||||
To upgrade your manual installation of Docker, first kill the docker
|
||||
To upgrade your manual installation of Docker Engine on Linux, first kill the docker
|
||||
daemon:
|
||||
|
||||
$ killall docker
|
||||
|
||||
Then follow the regular installation steps.
|
||||
Then follow the [regular installation steps](#get-the-linux-binaries).
|
||||
|
||||
## Run your first container!
|
||||
|
||||
# check your docker version
|
||||
$ sudo ./docker version
|
||||
|
||||
# run a container and open an interactive shell in the container
|
||||
$ sudo ./docker run -i -t ubuntu /bin/bash
|
||||
## Next steps
|
||||
|
||||
Continue with the [User Guide](../userguide/index.md).
|
||||
|
||||
@@ -14,6 +14,7 @@ weight = -6
|
||||
|
||||
Docker is supported on these Ubuntu operating systems:
|
||||
|
||||
- Ubuntu Xenial 16.04 (LTS)
|
||||
- Ubuntu Wily 15.10
|
||||
- Ubuntu Trusty 14.04 (LTS)
|
||||
- Ubuntu Precise 12.04 (LTS)
|
||||
@@ -85,6 +86,10 @@ packages from the new repository:
|
||||
|
||||
deb https://apt.dockerproject.org/repo ubuntu-wily main
|
||||
|
||||
- Ubuntu Xenial 16.04 (LTS)
|
||||
|
||||
deb https://apt.dockerproject.org/repo ubuntu-xenial main
|
||||
|
||||
> **Note**: Docker does not provide packages for all architectures. You can find
|
||||
> nightly built binaries in https://master.dockerproject.org. To install docker on
|
||||
> a multi-architecture system, add an `[arch=...]` clause to the entry. Refer to the
|
||||
@@ -109,10 +114,11 @@ packages from the new repository:
|
||||
|
||||
### Prerequisites by Ubuntu Version
|
||||
|
||||
- Ubuntu Xenial 16.04 (LTS)
|
||||
- Ubuntu Wily 15.10
|
||||
- Ubuntu Trusty 14.04 (LTS)
|
||||
|
||||
For Ubuntu Trusty and Wily, it's recommended to install the
|
||||
For Ubuntu Trusty, Wily, and Xenial, it's recommended to install the
|
||||
`linux-image-extra` kernel package. The `linux-image-extra` package
|
||||
allows you use the `aufs` storage driver.
|
||||
|
||||
|
||||
@@ -996,7 +996,7 @@ Tag the image `name` into a repository
|
||||
|
||||
**Example response**:
|
||||
|
||||
HTTP/1.1 201 OK
|
||||
HTTP/1.1 201 Created
|
||||
|
||||
Query Parameters:
|
||||
|
||||
|
||||
@@ -151,7 +151,7 @@ Create a container
|
||||
"ExposedPorts": {
|
||||
"22/tcp": {}
|
||||
},
|
||||
"SecurityOpts": [""],
|
||||
"SecurityOpts": [],
|
||||
"HostConfig": {
|
||||
"Binds": ["/tmp:/tmp"],
|
||||
"Links": ["redis3:redis"],
|
||||
@@ -1147,7 +1147,7 @@ Tag the image `name` into a repository
|
||||
|
||||
**Example response**:
|
||||
|
||||
HTTP/1.1 201 OK
|
||||
HTTP/1.1 201 Created
|
||||
|
||||
Query Parameters:
|
||||
|
||||
@@ -1644,7 +1644,7 @@ Sets up an exec instance in a running container `id`
|
||||
|
||||
**Example response**:
|
||||
|
||||
HTTP/1.1 201 OK
|
||||
HTTP/1.1 201 Created
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
@@ -1685,8 +1685,8 @@ interactive session with the `exec` command.
|
||||
|
||||
**Example response**:
|
||||
|
||||
HTTP/1.1 201 OK
|
||||
Content-Type: application/json
|
||||
HTTP/1.1 200 OK
|
||||
Content-Type: application/vnd.docker.raw-stream
|
||||
|
||||
{{ STREAM }}
|
||||
|
||||
@@ -1717,7 +1717,7 @@ This API is valid only if `tty` was specified as part of creating and starting t
|
||||
|
||||
**Example response**:
|
||||
|
||||
HTTP/1.1 201 OK
|
||||
HTTP/1.1 201 Created
|
||||
Content-Type: plain/text
|
||||
|
||||
Query Parameters:
|
||||
|
||||
@@ -151,7 +151,7 @@ Create a container
|
||||
"ExposedPorts": {
|
||||
"22/tcp": {}
|
||||
},
|
||||
"SecurityOpts": [""],
|
||||
"SecurityOpts": [],
|
||||
"HostConfig": {
|
||||
"Binds": ["/tmp:/tmp"],
|
||||
"Links": ["redis3:redis"],
|
||||
@@ -1095,7 +1095,7 @@ Tag the image `name` into a repository
|
||||
|
||||
**Example response**:
|
||||
|
||||
HTTP/1.1 201 OK
|
||||
HTTP/1.1 201 Created
|
||||
|
||||
Query Parameters:
|
||||
|
||||
@@ -1606,7 +1606,7 @@ Sets up an exec instance in a running container `id`
|
||||
|
||||
**Example response**:
|
||||
|
||||
HTTP/1.1 201 OK
|
||||
HTTP/1.1 201 Created
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
@@ -1647,8 +1647,8 @@ interactive session with the `exec` command.
|
||||
|
||||
**Example response**:
|
||||
|
||||
HTTP/1.1 201 OK
|
||||
Content-Type: application/json
|
||||
HTTP/1.1 200 OK
|
||||
Content-Type: application/vnd.docker.raw-stream
|
||||
|
||||
{{ STREAM }}
|
||||
|
||||
@@ -1679,7 +1679,7 @@ This API is valid only if `tty` was specified as part of creating and starting t
|
||||
|
||||
**Example response**:
|
||||
|
||||
HTTP/1.1 201 OK
|
||||
HTTP/1.1 201 Created
|
||||
Content-Type: plain/text
|
||||
|
||||
Query Parameters:
|
||||
|
||||
@@ -168,7 +168,7 @@ Create a container
|
||||
"RestartPolicy": { "Name": "", "MaximumRetryCount": 0 },
|
||||
"NetworkMode": "bridge",
|
||||
"Devices": [],
|
||||
"SecurityOpt": [""]
|
||||
"SecurityOpt": []
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1308,7 +1308,7 @@ Tag the image `name` into a repository
|
||||
|
||||
**Example response**:
|
||||
|
||||
HTTP/1.1 201 OK
|
||||
HTTP/1.1 201 Created
|
||||
|
||||
Query Parameters:
|
||||
|
||||
@@ -1769,7 +1769,7 @@ Sets up an exec instance in a running container `id`
|
||||
|
||||
**Example response**:
|
||||
|
||||
HTTP/1.1 201 OK
|
||||
HTTP/1.1 201 Created
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
@@ -1810,8 +1810,8 @@ interactive session with the `exec` command.
|
||||
|
||||
**Example response**:
|
||||
|
||||
HTTP/1.1 201 OK
|
||||
Content-Type: application/json
|
||||
HTTP/1.1 200 OK
|
||||
Content-Type: application/vnd.docker.raw-stream
|
||||
|
||||
{{ STREAM }}
|
||||
|
||||
@@ -1842,7 +1842,7 @@ This API is valid only if `tty` was specified as part of creating and starting t
|
||||
|
||||
**Example response**:
|
||||
|
||||
HTTP/1.1 201 OK
|
||||
HTTP/1.1 201 Created
|
||||
Content-Type: text/plain
|
||||
|
||||
Query Parameters:
|
||||
|
||||
@@ -184,7 +184,7 @@ Create a container
|
||||
"Devices": [],
|
||||
"Ulimits": [{}],
|
||||
"LogConfig": { "Type": "json-file", Config: {} },
|
||||
"SecurityOpt": [""],
|
||||
"SecurityOpt": [],
|
||||
"CgroupParent": ""
|
||||
}
|
||||
}
|
||||
@@ -1408,7 +1408,7 @@ Tag the image `name` into a repository
|
||||
|
||||
**Example response**:
|
||||
|
||||
HTTP/1.1 201 OK
|
||||
HTTP/1.1 201 Created
|
||||
|
||||
Query Parameters:
|
||||
|
||||
@@ -1887,7 +1887,7 @@ Sets up an exec instance in a running container `id`
|
||||
|
||||
**Example response**:
|
||||
|
||||
HTTP/1.1 201 OK
|
||||
HTTP/1.1 201 Created
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
@@ -1929,8 +1929,8 @@ interactive session with the `exec` command.
|
||||
|
||||
**Example response**:
|
||||
|
||||
HTTP/1.1 201 OK
|
||||
Content-Type: application/json
|
||||
HTTP/1.1 200 OK
|
||||
Content-Type: application/vnd.docker.raw-stream
|
||||
|
||||
{{ STREAM }}
|
||||
|
||||
@@ -1961,7 +1961,7 @@ This API is valid only if `tty` was specified as part of creating and starting t
|
||||
|
||||
**Example response**:
|
||||
|
||||
HTTP/1.1 201 OK
|
||||
HTTP/1.1 201 Created
|
||||
Content-Type: text/plain
|
||||
|
||||
Query Parameters:
|
||||
|
||||
@@ -191,7 +191,7 @@ Create a container
|
||||
"Devices": [],
|
||||
"Ulimits": [{}],
|
||||
"LogConfig": { "Type": "json-file", "Config": {} },
|
||||
"SecurityOpt": [""],
|
||||
"SecurityOpt": [],
|
||||
"CgroupParent": ""
|
||||
}
|
||||
}
|
||||
@@ -1477,7 +1477,7 @@ Tag the image `name` into a repository
|
||||
|
||||
**Example response**:
|
||||
|
||||
HTTP/1.1 201 OK
|
||||
HTTP/1.1 201 Created
|
||||
|
||||
Query Parameters:
|
||||
|
||||
@@ -1970,7 +1970,7 @@ Sets up an exec instance in a running container `id`
|
||||
|
||||
**Example response**:
|
||||
|
||||
HTTP/1.1 201 OK
|
||||
HTTP/1.1 201 Created
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
@@ -2012,8 +2012,8 @@ interactive session with the `exec` command.
|
||||
|
||||
**Example response**:
|
||||
|
||||
HTTP/1.1 201 OK
|
||||
Content-Type: application/json
|
||||
HTTP/1.1 200 OK
|
||||
Content-Type: application/vnd.docker.raw-stream
|
||||
|
||||
{{ STREAM }}
|
||||
|
||||
@@ -2044,7 +2044,7 @@ This API is valid only if `tty` was specified as part of creating and starting t
|
||||
|
||||
**Example response**:
|
||||
|
||||
HTTP/1.1 201 OK
|
||||
HTTP/1.1 201 Created
|
||||
Content-Type: text/plain
|
||||
|
||||
Query Parameters:
|
||||
|
||||
@@ -154,14 +154,9 @@ Create a container
|
||||
"com.example.license": "GPL",
|
||||
"com.example.version": "1.0"
|
||||
},
|
||||
"Mounts": [
|
||||
{
|
||||
"Source": "/data",
|
||||
"Destination": "/data",
|
||||
"Mode": "ro,Z",
|
||||
"RW": false
|
||||
}
|
||||
],
|
||||
"Volumes": {
|
||||
"/volumes/data": {}
|
||||
},
|
||||
"WorkingDir": "",
|
||||
"NetworkDisabled": false,
|
||||
"MacAddress": "12:34:56:78:9a:bc",
|
||||
@@ -198,7 +193,7 @@ Create a container
|
||||
"Devices": [],
|
||||
"Ulimits": [{}],
|
||||
"LogConfig": { "Type": "json-file", "Config": {} },
|
||||
"SecurityOpt": [""],
|
||||
"SecurityOpt": [],
|
||||
"CgroupParent": ""
|
||||
}
|
||||
}
|
||||
@@ -245,7 +240,8 @@ Json Parameters:
|
||||
- **Entrypoint** - Set the entry point for the container as a string or an array
|
||||
of strings.
|
||||
- **Image** - A string specifying the image name to use for the container.
|
||||
- **Mounts** - An array of mount points in the container.
|
||||
- **Volumes** - An object mapping mount point paths (strings) inside the
|
||||
container to empty objects.
|
||||
- **WorkingDir** - A string specifying the working directory for commands to
|
||||
run in.
|
||||
- **NetworkDisabled** - Boolean value, when true disables networking for the
|
||||
@@ -1622,7 +1618,7 @@ Tag the image `name` into a repository
|
||||
|
||||
**Example response**:
|
||||
|
||||
HTTP/1.1 201 OK
|
||||
HTTP/1.1 201 Created
|
||||
|
||||
Query Parameters:
|
||||
|
||||
@@ -2116,7 +2112,7 @@ Sets up an exec instance in a running container `id`
|
||||
|
||||
**Example response**:
|
||||
|
||||
HTTP/1.1 201 OK
|
||||
HTTP/1.1 201 Created
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
@@ -2158,8 +2154,8 @@ interactive session with the `exec` command.
|
||||
|
||||
**Example response**:
|
||||
|
||||
HTTP/1.1 201 OK
|
||||
Content-Type: application/json
|
||||
HTTP/1.1 200 OK
|
||||
Content-Type: application/vnd.docker.raw-stream
|
||||
|
||||
{{ STREAM }}
|
||||
|
||||
@@ -2190,7 +2186,7 @@ This API is valid only if `tty` was specified as part of creating and starting t
|
||||
|
||||
**Example response**:
|
||||
|
||||
HTTP/1.1 201 OK
|
||||
HTTP/1.1 201 Created
|
||||
Content-Type: text/plain
|
||||
|
||||
Query Parameters:
|
||||
|
||||
@@ -158,14 +158,9 @@ Create a container
|
||||
"com.example.license": "GPL",
|
||||
"com.example.version": "1.0"
|
||||
},
|
||||
"Mounts": [
|
||||
{
|
||||
"Source": "/data",
|
||||
"Destination": "/data",
|
||||
"Mode": "ro,Z",
|
||||
"RW": false
|
||||
}
|
||||
],
|
||||
"Volumes": {
|
||||
"/volumes/data": {}
|
||||
},
|
||||
"WorkingDir": "",
|
||||
"NetworkDisabled": false,
|
||||
"MacAddress": "12:34:56:78:9a:bc",
|
||||
@@ -206,7 +201,7 @@ Create a container
|
||||
"Devices": [],
|
||||
"Ulimits": [{}],
|
||||
"LogConfig": { "Type": "json-file", "Config": {} },
|
||||
"SecurityOpt": [""],
|
||||
"SecurityOpt": [],
|
||||
"CgroupParent": "",
|
||||
"VolumeDriver": ""
|
||||
}
|
||||
@@ -256,7 +251,8 @@ Json Parameters:
|
||||
- **Entrypoint** - Set the entry point for the container as a string or an array
|
||||
of strings.
|
||||
- **Image** - A string specifying the image name to use for the container.
|
||||
- **Mounts** - An array of mount points in the container.
|
||||
- **Volumes** - An object mapping mount point paths (strings) inside the
|
||||
container to empty objects.
|
||||
- **WorkingDir** - A string specifying the working directory for commands to
|
||||
run in.
|
||||
- **NetworkDisabled** - Boolean value, when true disables networking for the
|
||||
@@ -1773,7 +1769,7 @@ Tag the image `name` into a repository
|
||||
|
||||
**Example response**:
|
||||
|
||||
HTTP/1.1 201 OK
|
||||
HTTP/1.1 201 Created
|
||||
|
||||
Query Parameters:
|
||||
|
||||
@@ -2270,7 +2266,7 @@ Sets up an exec instance in a running container `id`
|
||||
|
||||
**Example response**:
|
||||
|
||||
HTTP/1.1 201 OK
|
||||
HTTP/1.1 201 Created
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
@@ -2314,8 +2310,8 @@ interactive session with the `exec` command.
|
||||
|
||||
**Example response**:
|
||||
|
||||
HTTP/1.1 201 OK
|
||||
Content-Type: application/json
|
||||
HTTP/1.1 200 OK
|
||||
Content-Type: application/vnd.docker.raw-stream
|
||||
|
||||
{{ STREAM }}
|
||||
|
||||
@@ -2347,7 +2343,7 @@ This API is valid only if `tty` was specified as part of creating and starting t
|
||||
|
||||
**Example response**:
|
||||
|
||||
HTTP/1.1 201 OK
|
||||
HTTP/1.1 201 Created
|
||||
Content-Type: text/plain
|
||||
|
||||
Query Parameters:
|
||||
|
||||
@@ -246,20 +246,9 @@ Create a container
|
||||
"com.example.license": "GPL",
|
||||
"com.example.version": "1.0"
|
||||
},
|
||||
"Mounts": [
|
||||
{
|
||||
"Name": "fac362...80535",
|
||||
"Source": "/data",
|
||||
"Destination": "/data",
|
||||
"Driver": "local",
|
||||
"Mode": "ro,Z",
|
||||
"RW": false,
|
||||
"Propagation": ""
|
||||
}
|
||||
],
|
||||
"Volumes": {
|
||||
"/volumes/data": {}
|
||||
}
|
||||
},
|
||||
"WorkingDir": "",
|
||||
"NetworkDisabled": false,
|
||||
"MacAddress": "12:34:56:78:9a:bc",
|
||||
@@ -305,10 +294,21 @@ Create a container
|
||||
"Devices": [],
|
||||
"Ulimits": [{}],
|
||||
"LogConfig": { "Type": "json-file", "Config": {} },
|
||||
"SecurityOpt": [""],
|
||||
"SecurityOpt": [],
|
||||
"CgroupParent": "",
|
||||
"VolumeDriver": "",
|
||||
"ShmSize": 67108864
|
||||
},
|
||||
"NetworkingConfig": {
|
||||
"EndpointsConfig": {
|
||||
"isolated_nw" : {
|
||||
"IPAMConfig": {
|
||||
"IPv4Address":"172.20.30.33",
|
||||
"IPv6Address":"2001:db8:abcd::3033"
|
||||
},
|
||||
"Links":["container_1", "container_2"],
|
||||
"Aliases":["server_x", "server_y"]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -366,7 +366,8 @@ Json Parameters:
|
||||
- **Entrypoint** - Set the entry point for the container as a string or an array
|
||||
of strings.
|
||||
- **Image** - A string specifying the image name to use for the container.
|
||||
- **Mounts** - An array of mount points in the container.
|
||||
- **Volumes** - An object mapping mount point paths (strings) inside the
|
||||
container to empty objects.
|
||||
- **WorkingDir** - A string specifying the working directory for commands to
|
||||
run in.
|
||||
- **NetworkDisabled** - Boolean value, when true disables networking for the
|
||||
@@ -1984,7 +1985,7 @@ Tag the image `name` into a repository
|
||||
|
||||
**Example response**:
|
||||
|
||||
HTTP/1.1 201 OK
|
||||
HTTP/1.1 201 Created
|
||||
|
||||
Query Parameters:
|
||||
|
||||
@@ -2547,7 +2548,7 @@ Sets up an exec instance in a running container `id`
|
||||
|
||||
**Example response**:
|
||||
|
||||
HTTP/1.1 201 OK
|
||||
HTTP/1.1 201 Created
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
@@ -2594,8 +2595,8 @@ interactive session with the `exec` command.
|
||||
|
||||
**Example response**:
|
||||
|
||||
HTTP/1.1 201 OK
|
||||
Content-Type: application/json
|
||||
HTTP/1.1 200 OK
|
||||
Content-Type: application/vnd.docker.raw-stream
|
||||
|
||||
{{ STREAM }}
|
||||
|
||||
@@ -2627,7 +2628,7 @@ This API is valid only if `tty` was specified as part of creating and starting t
|
||||
|
||||
**Example response**:
|
||||
|
||||
HTTP/1.1 201 OK
|
||||
HTTP/1.1 201 Created
|
||||
Content-Type: text/plain
|
||||
|
||||
Query Parameters:
|
||||
@@ -2653,112 +2654,28 @@ Return low-level information about the `exec` command `id`.
|
||||
**Example response**:
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Content-Type: plain/text
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"ID" : "11fb006128e8ceb3942e7c58d77750f24210e35f879dd204ac975c184b820b39",
|
||||
"Running" : false,
|
||||
"ExitCode" : 2,
|
||||
"ProcessConfig" : {
|
||||
"privileged" : false,
|
||||
"user" : "",
|
||||
"tty" : false,
|
||||
"entrypoint" : "sh",
|
||||
"arguments" : [
|
||||
"-c",
|
||||
"exit 2"
|
||||
]
|
||||
},
|
||||
"OpenStdin" : false,
|
||||
"OpenStderr" : false,
|
||||
"OpenStdout" : false,
|
||||
"Container" : {
|
||||
"State" : {
|
||||
"Status" : "running",
|
||||
"Running" : true,
|
||||
"Paused" : false,
|
||||
"Restarting" : false,
|
||||
"OOMKilled" : false,
|
||||
"Pid" : 3650,
|
||||
"ExitCode" : 0,
|
||||
"Error" : "",
|
||||
"StartedAt" : "2014-11-17T22:26:03.717657531Z",
|
||||
"FinishedAt" : "0001-01-01T00:00:00Z"
|
||||
"CanRemove": false,
|
||||
"ContainerID": "b53ee82b53a40c7dca428523e34f741f3abc51d9f297a14ff874bf761b995126",
|
||||
"DetachKeys": "",
|
||||
"ExitCode": 2,
|
||||
"ID": "f33bbfb39f5b142420f4759b2348913bd4a8d1a6d7fd56499cb41a1bb91d7b3b",
|
||||
"OpenStderr": true,
|
||||
"OpenStdin": true,
|
||||
"OpenStdout": true,
|
||||
"ProcessConfig": {
|
||||
"arguments": [
|
||||
"-c",
|
||||
"exit 2"
|
||||
],
|
||||
"entrypoint": "sh",
|
||||
"privileged": false,
|
||||
"tty": true,
|
||||
"user": "1000"
|
||||
},
|
||||
"ID" : "8f177a186b977fb451136e0fdf182abff5599a08b3c7f6ef0d36a55aaf89634c",
|
||||
"Created" : "2014-11-17T22:26:03.626304998Z",
|
||||
"Path" : "date",
|
||||
"Args" : [],
|
||||
"Config" : {
|
||||
"Hostname" : "8f177a186b97",
|
||||
"Domainname" : "",
|
||||
"User" : "",
|
||||
"AttachStdin" : false,
|
||||
"AttachStdout" : false,
|
||||
"AttachStderr" : false,
|
||||
"ExposedPorts" : null,
|
||||
"Tty" : false,
|
||||
"OpenStdin" : false,
|
||||
"StdinOnce" : false,
|
||||
"Env" : [ "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" ],
|
||||
"Cmd" : [
|
||||
"date"
|
||||
],
|
||||
"Image" : "ubuntu",
|
||||
"Volumes" : null,
|
||||
"WorkingDir" : "",
|
||||
"Entrypoint" : null,
|
||||
"NetworkDisabled" : false,
|
||||
"MacAddress" : "",
|
||||
"OnBuild" : null,
|
||||
"SecurityOpt" : null
|
||||
},
|
||||
"Image" : "5506de2b643be1e6febbf3b8a240760c6843244c41e12aa2f60ccbb7153d17f5",
|
||||
"NetworkSettings": {
|
||||
"Bridge": "",
|
||||
"SandboxID": "",
|
||||
"HairpinMode": false,
|
||||
"LinkLocalIPv6Address": "",
|
||||
"LinkLocalIPv6PrefixLen": 0,
|
||||
"Ports": null,
|
||||
"SandboxKey": "",
|
||||
"SecondaryIPAddresses": null,
|
||||
"SecondaryIPv6Addresses": null,
|
||||
"EndpointID": "",
|
||||
"Gateway": "",
|
||||
"GlobalIPv6Address": "",
|
||||
"GlobalIPv6PrefixLen": 0,
|
||||
"IPAddress": "",
|
||||
"IPPrefixLen": 0,
|
||||
"IPv6Gateway": "",
|
||||
"MacAddress": "",
|
||||
"Networks": {
|
||||
"bridge": {
|
||||
"NetworkID": "7ea29fc1412292a2d7bba362f9253545fecdfa8ce9a6e37dd10ba8bee7129812",
|
||||
"EndpointID": "7587b82f0dada3656fda26588aee72630c6fab1536d36e394b2bfbcf898c971d",
|
||||
"Gateway": "172.17.0.1",
|
||||
"IPAddress": "172.17.0.2",
|
||||
"IPPrefixLen": 16,
|
||||
"IPv6Gateway": "",
|
||||
"GlobalIPv6Address": "",
|
||||
"GlobalIPv6PrefixLen": 0,
|
||||
"MacAddress": "02:42:ac:12:00:02"
|
||||
}
|
||||
}
|
||||
},
|
||||
"ResolvConfPath" : "/var/lib/docker/containers/8f177a186b977fb451136e0fdf182abff5599a08b3c7f6ef0d36a55aaf89634c/resolv.conf",
|
||||
"HostnamePath" : "/var/lib/docker/containers/8f177a186b977fb451136e0fdf182abff5599a08b3c7f6ef0d36a55aaf89634c/hostname",
|
||||
"HostsPath" : "/var/lib/docker/containers/8f177a186b977fb451136e0fdf182abff5599a08b3c7f6ef0d36a55aaf89634c/hosts",
|
||||
"LogPath": "/var/lib/docker/containers/1eb5fabf5a03807136561b3c00adcd2992b535d624d5e18b6cdc6a6844d9767b/1eb5fabf5a03807136561b3c00adcd2992b535d624d5e18b6cdc6a6844d9767b-json.log",
|
||||
"Name" : "/test",
|
||||
"Driver" : "aufs",
|
||||
"ExecDriver" : "native-0.2",
|
||||
"MountLabel" : "",
|
||||
"ProcessLabel" : "",
|
||||
"AppArmorProfile" : "",
|
||||
"RestartCount" : 0,
|
||||
"Mounts" : []
|
||||
}
|
||||
"Running": false
|
||||
}
|
||||
|
||||
Status Codes:
|
||||
@@ -2789,7 +2706,8 @@ Status Codes:
|
||||
"Driver": "local",
|
||||
"Mountpoint": "/var/lib/docker/volumes/tardis"
|
||||
}
|
||||
]
|
||||
],
|
||||
"Warnings": []
|
||||
}
|
||||
|
||||
Query Parameters:
|
||||
@@ -3045,11 +2963,17 @@ Content-Type: application/json
|
||||
"Name":"isolated_nw",
|
||||
"Driver":"bridge",
|
||||
"IPAM":{
|
||||
"Config":[{
|
||||
"Subnet":"172.20.0.0/16",
|
||||
"IPRange":"172.20.10.0/24",
|
||||
"Gateway":"172.20.10.11"
|
||||
}],
|
||||
"Config":[
|
||||
{
|
||||
"Subnet":"172.20.0.0/16",
|
||||
"IPRange":"172.20.10.0/24",
|
||||
"Gateway":"172.20.10.11"
|
||||
},
|
||||
{
|
||||
"Subnet":"2001:db8:abcd::/64",
|
||||
"Gateway":"2001:db8:abcd::1011"
|
||||
}
|
||||
],
|
||||
"Options": {
|
||||
"foo": "bar"
|
||||
}
|
||||
|
||||
@@ -265,20 +265,9 @@ Create a container
|
||||
"com.example.license": "GPL",
|
||||
"com.example.version": "1.0"
|
||||
},
|
||||
"Mounts": [
|
||||
{
|
||||
"Name": "fac362...80535",
|
||||
"Source": "/data",
|
||||
"Destination": "/data",
|
||||
"Driver": "local",
|
||||
"Mode": "ro,Z",
|
||||
"RW": false,
|
||||
"Propagation": ""
|
||||
}
|
||||
],
|
||||
"Volumes": {
|
||||
"/volumes/data": {}
|
||||
}
|
||||
},
|
||||
"WorkingDir": "",
|
||||
"NetworkDisabled": false,
|
||||
"MacAddress": "12:34:56:78:9a:bc",
|
||||
@@ -324,10 +313,21 @@ Create a container
|
||||
"Devices": [],
|
||||
"Ulimits": [{}],
|
||||
"LogConfig": { "Type": "json-file", "Config": {} },
|
||||
"SecurityOpt": [""],
|
||||
"SecurityOpt": [],
|
||||
"CgroupParent": "",
|
||||
"VolumeDriver": "",
|
||||
"ShmSize": 67108864
|
||||
},
|
||||
"NetworkingConfig": {
|
||||
"EndpointsConfig": {
|
||||
"isolated_nw" : {
|
||||
"IPAMConfig": {
|
||||
"IPv4Address":"172.20.30.33",
|
||||
"IPv6Address":"2001:db8:abcd::3033"
|
||||
},
|
||||
"Links":["container_1", "container_2"],
|
||||
"Aliases":["server_x", "server_y"]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -386,7 +386,8 @@ Json Parameters:
|
||||
- **Entrypoint** - Set the entry point for the container as a string or an array
|
||||
of strings.
|
||||
- **Image** - A string specifying the image name to use for the container.
|
||||
- **Mounts** - An array of mount points in the container.
|
||||
- **Volumes** - An object mapping mount point paths (strings) inside the
|
||||
container to empty objects.
|
||||
- **WorkingDir** - A string specifying the working directory for commands to
|
||||
run in.
|
||||
- **NetworkDisabled** - Boolean value, when true disables networking for the
|
||||
@@ -516,8 +517,8 @@ Return low-level information on the container `id`
|
||||
"Tty": false,
|
||||
"User": "",
|
||||
"Volumes": {
|
||||
"/volumes/data": {}
|
||||
},
|
||||
"/volumes/data": {}
|
||||
},
|
||||
"WorkingDir": "",
|
||||
"StopSignal": "SIGTERM"
|
||||
},
|
||||
@@ -1659,7 +1660,7 @@ Query Parameters:
|
||||
You can provide one or more `t` parameters.
|
||||
- **remote** – A Git repository URI or HTTP/HTTPS URI build source. If the
|
||||
URI specifies a filename, the file's contents are placed into a file
|
||||
called `Dockerfile`.
|
||||
called `Dockerfile`.
|
||||
- **q** – Suppress verbose build output.
|
||||
- **nocache** – Do not use the cache when building the image.
|
||||
- **pull** - Attempt to pull the image even if an older image exists locally.
|
||||
@@ -1677,6 +1678,7 @@ Query Parameters:
|
||||
variable expansion in other Dockerfile instructions. This is not meant for
|
||||
passing secret values. [Read more about the buildargs instruction](../../reference/builder.md#arg)
|
||||
- **shmsize** - Size of `/dev/shm` in bytes. The size must be greater than 0. If omitted the system uses 64MB.
|
||||
- **labels** – JSON map of string pairs for labels to set on the image.
|
||||
|
||||
Request Headers:
|
||||
|
||||
@@ -2020,7 +2022,7 @@ Tag the image `name` into a repository
|
||||
|
||||
**Example response**:
|
||||
|
||||
HTTP/1.1 201 OK
|
||||
HTTP/1.1 201 Created
|
||||
|
||||
Query Parameters:
|
||||
|
||||
@@ -2590,7 +2592,7 @@ Sets up an exec instance in a running container `id`
|
||||
|
||||
**Example response**:
|
||||
|
||||
HTTP/1.1 201 OK
|
||||
HTTP/1.1 201 Created
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
@@ -2637,8 +2639,8 @@ interactive session with the `exec` command.
|
||||
|
||||
**Example response**:
|
||||
|
||||
HTTP/1.1 201 OK
|
||||
Content-Type: application/json
|
||||
HTTP/1.1 200 OK
|
||||
Content-Type: application/vnd.docker.raw-stream
|
||||
|
||||
{{ STREAM }}
|
||||
|
||||
@@ -2670,7 +2672,7 @@ This API is valid only if `tty` was specified as part of creating and starting t
|
||||
|
||||
**Example response**:
|
||||
|
||||
HTTP/1.1 201 OK
|
||||
HTTP/1.1 201 Created
|
||||
Content-Type: text/plain
|
||||
|
||||
Query Parameters:
|
||||
@@ -2696,112 +2698,28 @@ Return low-level information about the `exec` command `id`.
|
||||
**Example response**:
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Content-Type: plain/text
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"ID" : "11fb006128e8ceb3942e7c58d77750f24210e35f879dd204ac975c184b820b39",
|
||||
"Running" : false,
|
||||
"ExitCode" : 2,
|
||||
"ProcessConfig" : {
|
||||
"privileged" : false,
|
||||
"user" : "",
|
||||
"tty" : false,
|
||||
"entrypoint" : "sh",
|
||||
"arguments" : [
|
||||
"-c",
|
||||
"exit 2"
|
||||
]
|
||||
},
|
||||
"OpenStdin" : false,
|
||||
"OpenStderr" : false,
|
||||
"OpenStdout" : false,
|
||||
"Container" : {
|
||||
"State" : {
|
||||
"Status" : "running",
|
||||
"Running" : true,
|
||||
"Paused" : false,
|
||||
"Restarting" : false,
|
||||
"OOMKilled" : false,
|
||||
"Pid" : 3650,
|
||||
"ExitCode" : 0,
|
||||
"Error" : "",
|
||||
"StartedAt" : "2014-11-17T22:26:03.717657531Z",
|
||||
"FinishedAt" : "0001-01-01T00:00:00Z"
|
||||
"CanRemove": false,
|
||||
"ContainerID": "b53ee82b53a40c7dca428523e34f741f3abc51d9f297a14ff874bf761b995126",
|
||||
"DetachKeys": "",
|
||||
"ExitCode": 2,
|
||||
"ID": "f33bbfb39f5b142420f4759b2348913bd4a8d1a6d7fd56499cb41a1bb91d7b3b",
|
||||
"OpenStderr": true,
|
||||
"OpenStdin": true,
|
||||
"OpenStdout": true,
|
||||
"ProcessConfig": {
|
||||
"arguments": [
|
||||
"-c",
|
||||
"exit 2"
|
||||
],
|
||||
"entrypoint": "sh",
|
||||
"privileged": false,
|
||||
"tty": true,
|
||||
"user": "1000"
|
||||
},
|
||||
"ID" : "8f177a186b977fb451136e0fdf182abff5599a08b3c7f6ef0d36a55aaf89634c",
|
||||
"Created" : "2014-11-17T22:26:03.626304998Z",
|
||||
"Path" : "date",
|
||||
"Args" : [],
|
||||
"Config" : {
|
||||
"Hostname" : "8f177a186b97",
|
||||
"Domainname" : "",
|
||||
"User" : "",
|
||||
"AttachStdin" : false,
|
||||
"AttachStdout" : false,
|
||||
"AttachStderr" : false,
|
||||
"ExposedPorts" : null,
|
||||
"Tty" : false,
|
||||
"OpenStdin" : false,
|
||||
"StdinOnce" : false,
|
||||
"Env" : [ "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" ],
|
||||
"Cmd" : [
|
||||
"date"
|
||||
],
|
||||
"Image" : "ubuntu",
|
||||
"Volumes" : null,
|
||||
"WorkingDir" : "",
|
||||
"Entrypoint" : null,
|
||||
"NetworkDisabled" : false,
|
||||
"MacAddress" : "",
|
||||
"OnBuild" : null,
|
||||
"SecurityOpt" : null
|
||||
},
|
||||
"Image" : "5506de2b643be1e6febbf3b8a240760c6843244c41e12aa2f60ccbb7153d17f5",
|
||||
"NetworkSettings": {
|
||||
"Bridge": "",
|
||||
"SandboxID": "",
|
||||
"HairpinMode": false,
|
||||
"LinkLocalIPv6Address": "",
|
||||
"LinkLocalIPv6PrefixLen": 0,
|
||||
"Ports": null,
|
||||
"SandboxKey": "",
|
||||
"SecondaryIPAddresses": null,
|
||||
"SecondaryIPv6Addresses": null,
|
||||
"EndpointID": "",
|
||||
"Gateway": "",
|
||||
"GlobalIPv6Address": "",
|
||||
"GlobalIPv6PrefixLen": 0,
|
||||
"IPAddress": "",
|
||||
"IPPrefixLen": 0,
|
||||
"IPv6Gateway": "",
|
||||
"MacAddress": "",
|
||||
"Networks": {
|
||||
"bridge": {
|
||||
"NetworkID": "7ea29fc1412292a2d7bba362f9253545fecdfa8ce9a6e37dd10ba8bee7129812",
|
||||
"EndpointID": "7587b82f0dada3656fda26588aee72630c6fab1536d36e394b2bfbcf898c971d",
|
||||
"Gateway": "172.17.0.1",
|
||||
"IPAddress": "172.17.0.2",
|
||||
"IPPrefixLen": 16,
|
||||
"IPv6Gateway": "",
|
||||
"GlobalIPv6Address": "",
|
||||
"GlobalIPv6PrefixLen": 0,
|
||||
"MacAddress": "02:42:ac:12:00:02"
|
||||
}
|
||||
}
|
||||
},
|
||||
"ResolvConfPath" : "/var/lib/docker/containers/8f177a186b977fb451136e0fdf182abff5599a08b3c7f6ef0d36a55aaf89634c/resolv.conf",
|
||||
"HostnamePath" : "/var/lib/docker/containers/8f177a186b977fb451136e0fdf182abff5599a08b3c7f6ef0d36a55aaf89634c/hostname",
|
||||
"HostsPath" : "/var/lib/docker/containers/8f177a186b977fb451136e0fdf182abff5599a08b3c7f6ef0d36a55aaf89634c/hosts",
|
||||
"LogPath": "/var/lib/docker/containers/1eb5fabf5a03807136561b3c00adcd2992b535d624d5e18b6cdc6a6844d9767b/1eb5fabf5a03807136561b3c00adcd2992b535d624d5e18b6cdc6a6844d9767b-json.log",
|
||||
"Name" : "/test",
|
||||
"Driver" : "aufs",
|
||||
"ExecDriver" : "native-0.2",
|
||||
"MountLabel" : "",
|
||||
"ProcessLabel" : "",
|
||||
"AppArmorProfile" : "",
|
||||
"RestartCount" : 0,
|
||||
"Mounts" : []
|
||||
}
|
||||
"Running": false
|
||||
}
|
||||
|
||||
Status Codes:
|
||||
@@ -2832,7 +2750,8 @@ Status Codes:
|
||||
"Driver": "local",
|
||||
"Mountpoint": "/var/lib/docker/volumes/tardis"
|
||||
}
|
||||
]
|
||||
],
|
||||
"Warnings": []
|
||||
}
|
||||
|
||||
Query Parameters:
|
||||
@@ -2856,7 +2775,11 @@ Create a volume
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"Name": "tardis"
|
||||
"Name": "tardis",
|
||||
"Labels": {
|
||||
"com.example.some-label": "some-value",
|
||||
"com.example.some-other-label": "some-other-value"
|
||||
},
|
||||
}
|
||||
|
||||
**Example response**:
|
||||
@@ -2867,7 +2790,11 @@ Create a volume
|
||||
{
|
||||
"Name": "tardis",
|
||||
"Driver": "local",
|
||||
"Mountpoint": "/var/lib/docker/volumes/tardis"
|
||||
"Mountpoint": "/var/lib/docker/volumes/tardis",
|
||||
"Labels": {
|
||||
"com.example.some-label": "some-value",
|
||||
"com.example.some-other-label": "some-other-value"
|
||||
},
|
||||
}
|
||||
|
||||
Status Codes:
|
||||
@@ -2881,6 +2808,7 @@ JSON Parameters:
|
||||
- **Driver** - Name of the volume driver to use. Defaults to `local` for the name.
|
||||
- **DriverOpts** - A mapping of driver options and values. These options are
|
||||
passed directly to the driver and are driver specific.
|
||||
- **Labels** - Labels to set on the volume, specified as a map: `{"key":"value" [,"key2":"value2"]}`
|
||||
|
||||
### Inspect a volume
|
||||
|
||||
@@ -2898,9 +2826,13 @@ Return low-level information on the volume `name`
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"Name": "tardis",
|
||||
"Driver": "local",
|
||||
"Mountpoint": "/var/lib/docker/volumes/tardis"
|
||||
"Name": "tardis",
|
||||
"Driver": "local",
|
||||
"Mountpoint": "/var/lib/docker/volumes/tardis/_data",
|
||||
"Labels": {
|
||||
"com.example.some-label": "some-value",
|
||||
"com.example.some-other-label": "some-other-value"
|
||||
}
|
||||
}
|
||||
|
||||
Status Codes:
|
||||
@@ -3071,6 +3003,10 @@ Content-Type: application/json
|
||||
"com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
|
||||
"com.docker.network.bridge.name": "docker0",
|
||||
"com.docker.network.driver.mtu": "1500"
|
||||
},
|
||||
"Labels": {
|
||||
"com.example.some-label": "some-value",
|
||||
"com.example.some-other-label": "some-other-value"
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -3094,19 +3030,38 @@ Content-Type: application/json
|
||||
|
||||
{
|
||||
"Name":"isolated_nw",
|
||||
"CheckDuplicate":false,
|
||||
"Driver":"bridge",
|
||||
"EnableIPv6": false,
|
||||
"EnableIPv6": true,
|
||||
"IPAM":{
|
||||
"Config":[{
|
||||
"Subnet":"172.20.0.0/16",
|
||||
"IPRange":"172.20.10.0/24",
|
||||
"Gateway":"172.20.10.11"
|
||||
}],
|
||||
"Config":[
|
||||
{
|
||||
"Subnet":"172.20.0.0/16",
|
||||
"IPRange":"172.20.10.0/24",
|
||||
"Gateway":"172.20.10.11"
|
||||
},
|
||||
{
|
||||
"Subnet":"2001:db8:abcd::/64",
|
||||
"Gateway":"2001:db8:abcd::1011"
|
||||
}
|
||||
],
|
||||
"Options": {
|
||||
"foo": "bar"
|
||||
}
|
||||
},
|
||||
"Internal":true
|
||||
"Internal":true,
|
||||
"Options": {
|
||||
"com.docker.network.bridge.default_bridge": "true",
|
||||
"com.docker.network.bridge.enable_icc": "true",
|
||||
"com.docker.network.bridge.enable_ip_masquerade": "true",
|
||||
"com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
|
||||
"com.docker.network.bridge.name": "docker0",
|
||||
"com.docker.network.driver.mtu": "1500"
|
||||
},
|
||||
"Labels": {
|
||||
"com.example.some-label": "some-value",
|
||||
"com.example.some-other-label": "some-other-value"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
@@ -3131,12 +3086,13 @@ Status Codes:
|
||||
JSON Parameters:
|
||||
|
||||
- **Name** - The new network's name. this is a mandatory field
|
||||
- **CheckDuplicate** - Requests daemon to check for networks with same name
|
||||
- **Driver** - Name of the network driver plugin to use. Defaults to `bridge` driver
|
||||
- **Internal** - Restrict external access to the network
|
||||
- **IPAM** - Optional custom IP scheme for the network
|
||||
- **EnableIPv6** - Enable IPv6 on the network
|
||||
- **Options** - Network specific options to be used by the drivers
|
||||
- **CheckDuplicate** - Requests daemon to check for networks with same name
|
||||
- **Labels** - Labels to set on the network, specified as a map: `{"key":"value" [,"key2":"value2"]}`
|
||||
|
||||
### Connect a container to a network
|
||||
|
||||
|
||||
@@ -1174,8 +1174,10 @@ To use these, simply pass them on the command line using the `--build-arg
|
||||
`ARG` variables are not persisted into the built image as `ENV` variables are.
|
||||
However, `ARG` variables do impact the build cache in similar ways. If a
|
||||
Dockerfile defines an `ARG` variable whose value is different from a previous
|
||||
build, then a "cache miss" occurs upon its first usage, not its declaration.
|
||||
For example, consider this Dockerfile:
|
||||
build, then a "cache miss" occurs upon first use of the `ARG` variable. The
|
||||
declaration of the `ARG` variable does not count as a use.
|
||||
|
||||
For example, consider these two Dockerfile:
|
||||
|
||||
```
|
||||
1 FROM ubuntu
|
||||
@@ -1183,12 +1185,17 @@ For example, consider this Dockerfile:
|
||||
3 RUN echo $CONT_IMG_VER
|
||||
```
|
||||
|
||||
If you specify `--build-arg CONT_IMG_VER=<value>` on the command line the
|
||||
specification on line 2 does not cause a cache miss; line 3 does cause a cache
|
||||
miss. The definition on line 2 has no impact on the resulting image. The `RUN`
|
||||
on line 3 executes a command and in doing so defines a set of environment
|
||||
variables, including `CONT_IMG_VER`. At that point, the `ARG` variable may
|
||||
impact the resulting image, so a cache miss occurs.
|
||||
```
|
||||
1 FROM ubuntu
|
||||
2 ARG CONT_IMG_VER
|
||||
3 RUN echo hello
|
||||
```
|
||||
|
||||
If you specify `--build-arg CONT_IMG_VER=<value>` on the command line, in both
|
||||
cases, the specification on line 2 does not cause a cache miss; line 3 does
|
||||
cause a cache miss.`ARG CONT_IMG_VER` causes the RUN line to be identified
|
||||
as the same as running `CONT_IMG_VER=<value>` echo hello, so if the `<value>`
|
||||
changes, we get a cache miss.
|
||||
|
||||
Consider another example under the same command line:
|
||||
|
||||
@@ -1203,6 +1210,20 @@ the variable's value in the `ENV` references the `ARG` variable and that
|
||||
variable is changed through the command line. In this example, the `ENV`
|
||||
command causes the image to include the value.
|
||||
|
||||
If an `ENV` instruction overrides an `ARG` instruction of the same name, like
|
||||
this Dockerfile:
|
||||
|
||||
```
|
||||
1 FROM ubuntu
|
||||
2 ARG CONT_IMG_VER
|
||||
3 ENV CONT_IMG_VER hello
|
||||
4 RUN echo $CONT_IMG_VER
|
||||
```
|
||||
|
||||
Line 3 does not cause a cache miss because the value of `CONT_IMG_VER` is a
|
||||
constant (`hello`). As a result, the environment variables and values used on
|
||||
the `RUN` (line 4) doesn't change between builds.
|
||||
|
||||
## ONBUILD
|
||||
|
||||
ONBUILD [INSTRUCTION]
|
||||
|
||||
@@ -26,6 +26,7 @@ parent = "smn_cli"
|
||||
--force-rm Always remove intermediate containers
|
||||
--help Print usage
|
||||
--isolation="" Container isolation technology
|
||||
--label=[] Set metadata for an image
|
||||
-m, --memory="" Memory limit for all build containers
|
||||
--memory-swap="" A positive integer equal to memory plus swap. Specify -1 to enable unlimited swap.
|
||||
--no-cache Do not use cache when building the image
|
||||
|
||||
@@ -21,13 +21,14 @@ weight = -1
|
||||
-b, --bridge="" Attach containers to a network bridge
|
||||
--bip="" Specify network bridge IP
|
||||
--cgroup-parent= Set parent cgroup for all containers
|
||||
-D, --debug Enable debug mode
|
||||
--default-gateway="" Container default gateway IPv4 address
|
||||
--default-gateway-v6="" Container default gateway IPv6 address
|
||||
--cluster-store="" URL of the distributed storage backend
|
||||
--cluster-advertise="" Address of the daemon instance on the cluster
|
||||
--cluster-store-opt=map[] Set cluster options
|
||||
--config-file=/etc/docker/daemon.json Daemon configuration file
|
||||
--containerd Path to containerd socket
|
||||
-D, --debug Enable debug mode
|
||||
--default-gateway="" Container default gateway IPv4 address
|
||||
--default-gateway-v6="" Container default gateway IPv6 address
|
||||
--dns=[] DNS server to use
|
||||
--dns-opt=[] DNS options to use
|
||||
--dns-search=[] DNS search domains to use
|
||||
@@ -194,17 +195,17 @@ options for `zfs` start with `zfs`.
|
||||
to create and manage the thin-pool volume. This volume is then handed to Docker
|
||||
to exclusively create snapshot volumes needed for images and containers.
|
||||
|
||||
Managing the thin-pool outside of Docker makes for the most feature-rich
|
||||
Managing the thin-pool outside of Engine makes for the most feature-rich
|
||||
method of having Docker utilize device mapper thin provisioning as the
|
||||
backing storage for Docker's containers. The highlights of the lvm-based
|
||||
backing storage for Docker containers. The highlights of the lvm-based
|
||||
thin-pool management feature include: automatic or interactive thin-pool
|
||||
resize support, dynamically changing thin-pool features, automatic thinp
|
||||
metadata checking when lvm activates the thin-pool, etc.
|
||||
|
||||
As a fallback if no thin pool is provided, loopback files will be
|
||||
As a fallback if no thin pool is provided, loopback files are
|
||||
created. Loopback is very slow, but can be used without any
|
||||
pre-configuration of storage. It is strongly recommended that you do
|
||||
not use loopback in production. Ensure your Docker daemon has a
|
||||
not use loopback in production. Ensure your Engine daemon has a
|
||||
`--storage-opt dm.thinpooldev` argument provided.
|
||||
|
||||
Example use:
|
||||
@@ -440,29 +441,33 @@ options for `zfs` start with `zfs`.
|
||||
|
||||
* `dm.min_free_space`
|
||||
|
||||
Specifies the min free space percent in thin pool require for new device
|
||||
Specifies the min free space percent in a thin pool require for new device
|
||||
creation to succeed. This check applies to both free data space as well
|
||||
as free metadata space. Valid values are from 0% - 99%. Value 0% disables
|
||||
free space checking logic. If user does not specify a value for this optoin,
|
||||
then default value for this option is 10%.
|
||||
free space checking logic. If user does not specify a value for this option,
|
||||
the Engine uses a default value of 10%.
|
||||
|
||||
Whenever a new thin pool device is created (during docker pull or
|
||||
during container creation), docker will check minimum free space is
|
||||
available as specified by this parameter. If that is not the case, then
|
||||
device creation will fail and docker operation will fail.
|
||||
Whenever a new a thin pool device is created (during `docker pull` or during
|
||||
container creation), the Engine checks if the minimum free space is
|
||||
available. If sufficient space is unavailable, then device creation fails
|
||||
and any relevant `docker` operation fails.
|
||||
|
||||
One will have to create more free space in thin pool to recover from the
|
||||
error. Either delete some of the images and containers from thin pool and
|
||||
create free space or add more storage to thin pool.
|
||||
To recover from this error, you must create more free space in the thin pool
|
||||
to recover from the error. You can create free space by deleting some images
|
||||
and containers from the thin pool. You can also add more storage to the thin
|
||||
pool.
|
||||
|
||||
For lvm thin pool, one can add more storage to volume group container thin
|
||||
pool and that should automatically resolve it. If loop devices are being
|
||||
used, then stop docker, grow the size of loop files and restart docker and
|
||||
that should resolve the issue.
|
||||
To add more space to a LVM (logical volume management) thin pool, just add
|
||||
more storage to the volume group container thin pool; this should automatically
|
||||
resolve any errors. If your configuration uses loop devices, then stop the
|
||||
Engine daemon, grow the size of loop files and restart the daemon to resolve
|
||||
the issue.
|
||||
|
||||
Example use:
|
||||
|
||||
$ docker daemon --storage-opt dm.min_free_space_percent=10%
|
||||
```bash
|
||||
$ docker daemon --storage-opt dm.min_free_space=10%
|
||||
```
|
||||
|
||||
Currently supported options of `zfs`:
|
||||
|
||||
@@ -490,12 +495,13 @@ with the `--exec-opt` flag. All the flag's options have the `native` prefix. A
|
||||
single `native.cgroupdriver` option is available.
|
||||
|
||||
The `native.cgroupdriver` option specifies the management of the container's
|
||||
cgroups. You can specify only specify `cgroupfs` at the moment. If you omit the
|
||||
cgroups. You can specify only specify `cgroupfs` or `systemd`. If you specify
|
||||
`systemd` and it is not available, the system errors out. If you omit the
|
||||
`native.cgroupdriver` option,` cgroupfs` is used.
|
||||
|
||||
This example explicitely sets the `cgroupdriver` to `cgroupfs`:
|
||||
This example sets the `cgroupdriver` to `systemd`:
|
||||
|
||||
$ sudo docker daemon --exec-opt native.cgroupdriver=cgroupfs
|
||||
$ sudo docker daemon --exec-opt native.cgroupdriver=systemd
|
||||
|
||||
Setting this option applies to all containers the daemon launches.
|
||||
|
||||
|
||||
@@ -85,16 +85,16 @@ If nothing matches `REPOSITORY[:TAG]`, the list is empty.
|
||||
## Listing the full length image IDs
|
||||
|
||||
$ docker images --no-trunc
|
||||
REPOSITORY TAG IMAGE ID CREATED SIZE
|
||||
<none> <none> 77af4d6b9913e693e8d0b4b294fa62ade6054e6b2f1ffb617ac955dd63fb0182 19 hours ago 1.089 GB
|
||||
committest latest b6fa739cedf5ea12a620a439402b6004d057da800f91c7524b5086a5e4749c9f 19 hours ago 1.089 GB
|
||||
<none> <none> 78a85c484f71509adeaace20e72e941f6bdd2b25b4c75da8693efd9f61a37921 19 hours ago 1.089 GB
|
||||
docker latest 30557a29d5abc51e5f1d5b472e79b7e296f595abcf19fe6b9199dbbc809c6ff4 20 hours ago 1.089 GB
|
||||
<none> <none> 0124422dd9f9cf7ef15c0617cda3931ee68346455441d66ab8bdc5b05e9fdce5 20 hours ago 1.089 GB
|
||||
<none> <none> 18ad6fad340262ac2a636efd98a6d1f0ea775ae3d45240d3418466495a19a81b 22 hours ago 1.082 GB
|
||||
<none> <none> f9f1e26352f0a3ba6a0ff68167559f64f3e21ff7ada60366e2d44a04befd1d3a 23 hours ago 1.089 GB
|
||||
tryout latest 2629d1fa0b81b222fca63371ca16cbf6a0772d07759ff80e8d1369b926940074 23 hours ago 131.5 MB
|
||||
<none> <none> 5ed6274db6ceb2397844896966ea239290555e74ef307030ebb01ff91b1914df 24 hours ago 1.089 GB
|
||||
REPOSITORY TAG IMAGE ID CREATED SIZE
|
||||
<none> <none> sha256:77af4d6b9913e693e8d0b4b294fa62ade6054e6b2f1ffb617ac955dd63fb0182 19 hours ago 1.089 GB
|
||||
committest latest sha256:b6fa739cedf5ea12a620a439402b6004d057da800f91c7524b5086a5e4749c9f 19 hours ago 1.089 GB
|
||||
<none> <none> sha256:78a85c484f71509adeaace20e72e941f6bdd2b25b4c75da8693efd9f61a37921 19 hours ago 1.089 GB
|
||||
docker latest sha256:30557a29d5abc51e5f1d5b472e79b7e296f595abcf19fe6b9199dbbc809c6ff4 20 hours ago 1.089 GB
|
||||
<none> <none> sha256:0124422dd9f9cf7ef15c0617cda3931ee68346455441d66ab8bdc5b05e9fdce5 20 hours ago 1.089 GB
|
||||
<none> <none> sha256:18ad6fad340262ac2a636efd98a6d1f0ea775ae3d45240d3418466495a19a81b 22 hours ago 1.082 GB
|
||||
<none> <none> sha256:f9f1e26352f0a3ba6a0ff68167559f64f3e21ff7ada60366e2d44a04befd1d3a 23 hours ago 1.089 GB
|
||||
tryout latest sha256:2629d1fa0b81b222fca63371ca16cbf6a0772d07759ff80e8d1369b926940074 23 hours ago 131.5 MB
|
||||
<none> <none> sha256:5ed6274db6ceb2397844896966ea239290555e74ef307030ebb01ff91b1914df 24 hours ago 1.089 GB
|
||||
|
||||
## Listing image digests
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@ parent = "smn_cli"
|
||||
|
||||
--help Print usage
|
||||
-i, --input="" Read from a tar archive file, instead of STDIN. The tarball may be compressed with gzip, bzip, or xz
|
||||
-q, --quiet Suppress the load output. Without this option, a progress bar is displayed.
|
||||
|
||||
Loads a tarred repository from a file or the standard input stream.
|
||||
Restores both images and tags.
|
||||
|
||||
@@ -23,6 +23,7 @@ parent = "smn_cli"
|
||||
--ipam-driver=default IP Address Management Driver
|
||||
--ipam-opt=map[] Set custom IPAM driver specific options
|
||||
--ipv6 Enable IPv6 networking
|
||||
--label=[] Set metadata on a network
|
||||
-o --opt=map[] Set custom driver specific options
|
||||
--subnet=[] Subnet in CIDR format that represents a network segment
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user