Compare commits

..

75 Commits

Author SHA1 Message Date
Michael Crosby 010d74ec2f Bump to v0.7.4
Docker-DCO-1.0-Signed-off-by: Michael Crosby <michael@crosbymichael.com> (github: crosbymichael)
2014-01-07 18:06:20 -08:00
Guillaume J. Charmes bb76985d39 Merge pull request #3474 from creack/fix_add_cache_issue
Fix ADD caching issue with . prefixed path
2014-01-07 17:24:18 -08:00
Guillaume J. Charmes 28ec47c441 Merge pull request #3492 from unclejack/3449-fix_docker_build_on_devicemapper
#3449 - fix `docker build` on devicemapper
2014-01-07 17:12:31 -08:00
unclejack d003cfea25 Revert "Add -S option to tar for efficient sparse file handling"
This reverts commit 733bf5d3dd.

This is needed to fix "no such file" errors `docker build` errors for
devicemapper.

This fixes issue #3449.

Docker-DCO-1.0-Signed-off-by: Cristian Staretu <cristian.staretu@gmail.com> (github: unclejack)
2014-01-08 02:58:39 +02:00
Guillaume J. Charmes f3103e5c91 Fix issue with file caching + prevent wrong cache hit
Docker-DCO-1.0-Signed-off-by: Guillaume J. Charmes <guillaume.charmes@docker.com> (github: creack)
2014-01-07 16:53:55 -08:00
Guillaume J. Charmes ef7e000a13 Make vfs error more explicit
Docker-DCO-1.0-Signed-off-by: Guillaume J. Charmes <guillaume.charmes@docker.com> (github: creack)
2014-01-07 16:02:41 -08:00
Guillaume J. Charmes 811341423b Fix ADD caching issue with . prefixed path
Docker-DCO-1.0-Signed-off-by: Guillaume J. Charmes <charmes.guillaume@gmail.com> (github: creack)
2014-01-07 16:02:20 -08:00
Andy Rothfusz b3addb5fb8 Merge pull request #3430 from lsm5/fedora-official-image
install instructions use unprefixed fedora image
2014-01-07 15:12:37 -08:00
Andy Rothfusz 00ee6d1925 Merge pull request #3483 from lukaspustina/patch-1
Missing redirect in line 85
2014-01-07 15:11:02 -08:00
Andy Rothfusz 6f8a79c23c Merge pull request #3462 from tsaavik/patch-2
Simplified and streamlined Amazon Quickstart
2014-01-07 15:09:35 -08:00
Andy Rothfusz cf8063d152 Merge pull request #3461 from jbeda/patch-1
Update instructions for mtu flag for Docker on GCE
2014-01-07 15:03:19 -08:00
Andy Rothfusz 3e10fe1a15 Merge pull request #3488 from jamtur01/1310
Fixed #3481 - Added Ubuntu Saucy to installation
2014-01-07 14:56:03 -08:00
Michael Crosby 45ecdf9c8e Merge pull request #3487 from crosbymichael/improve-images-speed
Only get rootfs when we need to calculate the image size
2014-01-07 14:47:31 -08:00
Tianon Gravi b942f24ba8 Merge pull request #3491 from tianon/travis-numeric-commit
Fix Travis handling of a fully-numeric commit hash being YAML-converted ...
2014-01-07 14:35:06 -08:00
Tianon Gravi 3779291e9b Fix Travis handling of a fully-numeric commit hash being YAML-converted to a number instead of a string
Docker-DCO-1.0-Signed-off-by: Andrew Page <admwiggin@gmail.com> (github: tianon)
2014-01-07 15:27:51 -07:00
Michael Crosby fa14a1b983 Only get rootfs when we need to calculate the image size
Docker-DCO-1.0-Signed-off-by: Michael Crosby <crosby.michael@gmail.com> (github: crosbymichael)
2014-01-07 13:56:26 -08:00
Tianon Gravi f9e14cc838 Merge pull request #3489 from tianon/travis-fixes
Fix Travis PR testing to not overwrite the "master" that Travis creates with our "upstream master"
2014-01-07 12:53:19 -08:00
Victor Vieux f2ea539467 Update REMOTE_TODO.md 2014-01-07 12:51:17 -08:00
Tianon Gravi 7c4e5fbd46 Fix Travis PR testing to not overwrite the "master" that Travis creates with our "upstream master", and to also ignore commits with no content (like a Merge commit - there's no need to sign off on literally nothing)
Docker-DCO-1.0-Signed-off-by: Andrew Page <admwiggin@gmail.com> (github: tianon)
2014-01-07 13:45:40 -07:00
James Turnbull 97ef8a067c Fixed #3481 - Added Ubuntu Saucy to installation
Docker-DCO-1.0-Signed-off-by: James Turnbull <james@lovedthanlost.net> jamtur01
2014-01-07 11:46:07 -08:00
Michael Crosby 4b9e475a3d Merge pull request #2091 from keeb/add-dco
Add Developer Certificate of Origin Text
2014-01-07 10:42:53 -08:00
Michael Crosby 1d0aeae339 Merge pull request #3431 from shin-/ping_standalone_check
Check standalone header when pinging a registry server.
2014-01-07 10:33:07 -08:00
Solomon Hykes 859856b3e4 Merge pull request #3475 from tianon/travis
Add Travis CI configuration to validate DCO and gofmt
2014-01-07 10:19:43 -08:00
Michael Crosby b8b18a2b42 Merge pull request #3435 from roylee17/3149-fix_port_mapping_of_tcp_plus_udp
Fix #3149: port mapping of TCP + UDP
2014-01-07 10:08:13 -08:00
Tianon Gravi 561d1db074 Add Travis CI configuration to validate DCO and gofmt
After each push, Travis CI will trigger, and check two things:

- make sure that each commit in the push has the Docker certificate of origin
- make sure that all .go files changed by this sequence of commits are correctly formatted in the most recent commit

Note: there is one edge case; if you do a git force push, we cannot figure out the actual commits in the force push, and we will just run the checks as if upstream master were the base. Pull requests will always be tested correctly, though.

Docker-DCO-1.0-Signed-off-by: Andrew Page <admwiggin@gmail.com> (github: tianon)
2014-01-07 08:25:54 -07:00
Michael Crosby 1f9abfe841 Merge pull request #3480 from tianon/gofmt
Run 'gofmt -s -w'
2014-01-07 06:41:23 -08:00
lukaspustina 2b93f18223 Missing pipe in line 85 2014-01-07 15:20:38 +01:00
Tianon Gravi 8f3b8f3835 Run 'gofmt -s -w' 2014-01-06 22:14:35 -07:00
Michael Crosby fca83b4cfb Merge pull request #3477 from creack/fix_tar_leaks
Make CopyFileWithTar use a pipe instead of a buffer. Save more than 1Gb of ram for a 500Mb file.
2014-01-06 18:04:44 -08:00
Guillaume J. Charmes 444a087ac2 Make CopyFileWithTar use a pipe instead of a buffer. Save more than 1Gb of ram for a 500Mb file. 2014-01-06 17:44:22 -08:00
Victor Vieux e1c861cf33 Update REMOTE_TODO.md 2014-01-06 17:37:30 -08:00
Nick Stinemates 6fe3da9924 Remove the @github handle as it generates emails. 2014-01-06 17:21:14 -08:00
Andy Rothfusz f43f3fa218 Merge pull request #3473 from dhrp/docs-version-warning-fix
[docs] Fix for wrong version warning on master instead of latest.
2014-01-06 16:26:04 -08:00
Thatcher Peskens 1e551c7cc5 [docs] Fix for wrong version warning on master instead of latest. 2014-01-06 16:18:00 -08:00
Michael Crosby 2c395ce8fb Merge pull request #3328 from shykes/pkg-iptables
Move utility package 'iptables' to pkg/iptables
2014-01-06 15:54:07 -08:00
Solomon Hykes 7799ae27ca Move utility package 'iptables' to pkg/iptables 2014-01-06 15:41:24 -08:00
Michael Crosby bb754fd34d Merge pull request #3388 from tianon/more-build-tests
Add more TestBuild Dockerfiles, especially for 'echo shebang' testing
2014-01-06 15:14:30 -08:00
Victor Vieux a0298c0bd0 Merge pull request #3420 from RoelVanNyen/getfullname
Cleanup: runtime.getFullName is deprecated by getFullName
2014-01-06 13:59:04 -08:00
Victor Vieux a86a82cb7e Merge pull request #3384 from tianon/fix-load-help
Fix "docker load" help by removing "SOURCE" prompt and mentioning STDIN
2014-01-06 13:30:16 -08:00
Nick Stinemates 36ab1836f9 Fix dotCloud to Docker, Inc 2014-01-06 12:26:53 -08:00
shin- 5e8912e0e8 Fixed registry unit tests 2014-01-06 21:04:44 +01:00
Victor Vieux 4e414f6205 Merge pull request #3377 from cpuguy83/3333-fix_-H_default
Make blank -H option default to the same as no -H was sent
2014-01-06 11:30:27 -08:00
Michael Crosby 4f31141e13 Merge pull request #3310 from pnasrat/cgroups-subpackage
Extract cgroups utilities to own submodule.
2014-01-06 11:27:29 -08:00
Michael Crosby ee6823d797 Merge pull request #3297 from jaseg/master
Return meaningful error for meaningless Dockerfiles
2014-01-06 10:58:24 -08:00
Michael Crosby 1363dfdd1d Merge pull request #3426 from bcbcarl/3425-upgrade_vbox_guest_additions
Upgrade VBox Guest Additions (Fix #3425)
2014-01-06 10:39:26 -08:00
Joe Beda b308e33106 Tweak formatting for GCE instructions 2014-01-06 10:35:51 -08:00
Victor Vieux e5b09523dc Merge pull request #3367 from cpuguy83/3362-unify_cmd_entrypoint_handling
Use same error handling while unmarshalling args for CMD and ENTRYPOINT
2014-01-06 10:29:37 -08:00
Victor Vieux d44abae873 Merge pull request #3441 from RoelVanNyen/container_start
Just pass the container in RegisterLinks(), no need to lookup by name
2014-01-06 10:19:01 -08:00
Brian Goff 323c4b5211 Use same error handling while unmarshalling args for CMD and ENTRYPOINT 2014-01-06 13:15:14 -05:00
Michael Crosby 5b4a0cac4e Merge pull request #3335 from vieux/remote_todo
add REMOTE_TODO
2014-01-06 10:12:08 -08:00
Victor Vieux 73294b6d56 Merge pull request #3455 from crigor/fix-pull-message
Fix login message to say pull instead of push.
2014-01-06 10:02:32 -08:00
David Mcanulty d6ca05f7cb Simplified and streamlined Amazon Quickstart
The amazon quickstart images are EBS backed and include cloudinit. I've personally tested these documentation changes as a new user to Docker.
2014-01-06 09:53:58 -08:00
Victor Vieux dfc2dc4d35 Merge pull request #3445 from dotcloud/merge_release_v0.7.3
Merge release v0.7.3
2014-01-06 09:51:41 -08:00
Joe Beda ea762c1a51 Update instructions for mtu flag for Docker on GCE 2014-01-06 09:29:33 -08:00
Christopher Rigor 599009191a Fix login message to say pull instead of push. 2014-01-05 17:07:16 +08:00
Tianon Gravi af50b2f17c Merge pull request #3454 from sudosurootdev/master
Fix spelling error in hack/make.sh comment
2014-01-04 20:24:48 -08:00
sudosurootdev 2a1181f404 Spelling error. 2014-01-04 23:15:15 -05:00
Tianon Gravi f7afbf34fe Merge pull request #3448 from tmahesh/patch-1
Changelog date typo fix: 2013-01-02 -> 2014-01-02
2014-01-04 08:21:48 -08:00
Mahesh Tiyyagura 3069bf9460 Changelog date typo fix: 2013-01-02 -> 2014-01-02 2014-01-04 11:24:48 +05:30
Tianon Gravi 32b9a429c5 Change version to 0.7.3-dev 2014-01-03 17:02:59 -07:00
Tianon Gravi 76910d16cc Merge pull request #3439 from dotcloud/bump_v0.7.3
Bump v0.7.3
2014-01-03 16:01:56 -08:00
Roel Van Nyen 42c7dc448f Just pass the container in RegisterLinks(), no need to lookup by name again 2014-01-03 15:49:39 +01:00
Tzu-Jung Lee f560b87a86 Fix #3149: port mapping of TCP + UDP
Signed-off-by: Tzu-Jung Lee <roylee17@gmail.com>
2014-01-02 16:01:04 -08:00
Paul Nasrat c561212b83 Extract cgroups utilities to own submodule.
Use mountinfo rather than for cgroups parsing.
Make helper method private and change name.
Makes method naming more explicit rather than GetThisCgroup.
Use upstream term subsystem rather than cgroupType.
2014-01-02 17:54:57 -05:00
shin- 589515c717 Check standalone header when pinging a registry server. Standalone has to be true to use basic auth (in addition to previous requirements) 2014-01-02 17:51:42 +01:00
Lokesh Mandvekar 523f726716 install instructions use unprefixed fedora image
Signed-off-by: Lokesh Mandvekar <lsm5@redhat.com>
2014-01-02 11:29:24 -05:00
Carl X. Su 848f290012 Upgrade VBox Guest Additions (Fix #3425) 2014-01-02 12:56:29 +08:00
Roel Van Nyen 9dd7ae4074 Cleanup: runtime.getFullName is deprecated by getFullName 2014-01-02 00:06:50 +01:00
Tianon Gravi c6dcee329d Add more TestBuild Dockerfiles, especially for making sure manual RUN echo '#!...' continues to work correctly 2013-12-30 00:10:48 -07:00
Tianon Gravi 83d631b6a4 Fix "docker load" help by removing "SOURCE" prompt and mentioning STDIN
Fixes #3383
2013-12-29 13:25:57 -07:00
Brian Goff 8b82b0dfe7 Make blank -H option default to the same as no -H was sent 2013-12-29 14:36:46 -05:00
Victor Vieux 3264c1c5eb add REMOTE_TODO 2013-12-23 19:01:10 -08:00
jaseg b8cd2bc94d Return meaningful error for meaningless Dockerfiles 2013-12-20 16:19:21 +01:00
Nick Stinemates 8f382aaecd Merged with master 2013-12-04 12:40:54 -08:00
Nick Stinemates 821a82ac6c Add Developer Certificate of Origin Text
We purposely chose to license Docker under the Apache 2.0 license. This is a well-known
license, which is popular for its permissive and flexible properties, while still
encouraging a collaborative community. It also makes certain representations with regard
to contributions, and the rights given to contributors, the project, people who use Docker,
people who modify Docker, etc.

This approach to contributions is inspired by the popular Linux Developer
"Certificate of Origin". This approach makes it simple for new contributors to get started,
and avoids bureaucracy in tracking contributions and contributors.

To indicate accordance, each individual contribution to the Project is signed off by the
developer, using his or her real name, email address, and github handle in the format below:

	Docker-DCO-1.0-Signed-off-by: Joe Smith <joe.smith@email.com>
2013-10-04 14:27:26 -07:00
47 changed files with 682 additions and 240 deletions
+23
View File
@@ -0,0 +1,23 @@
# Note: right now we don't use go-specific features of travis.
# Later we might automate "go test" etc. (or do it inside a docker container...?)
language: go
go: 1.2
# Disable the normal go build.
install: true
before_script:
- env | sort
- sudo apt-get update -qq
- sudo apt-get install -qq python-yaml
- git remote add upstream git://github.com/dotcloud/docker.git
- git fetch --append --no-tags upstream refs/heads/master:refs/remotes/upstream/master
# sometimes we have upstream master already as origin/master (PRs), but other times we don't, so let's just make sure we have a completely unambiguous way to specify "upstream master" from here out
script:
- hack/travis/dco.py
- hack/travis/gofmt.py
# vim:set sw=2 ts=2:
-1
View File
@@ -48,7 +48,6 @@ Daniel YC Lin <dlin.tw@gmail.com>
Darren Coxall <darren@darrencoxall.com>
David Calavera <david.calavera@gmail.com>
David Sissitka <me@dsissitka.com>
Dinesh Subhraveti <dineshs@altiscale.com>
Deni Bertovic <deni@kset.org>
Dominik Honnef <dominik@honnef.co>
Don Spaulding <donspauldingii@gmail.com>
+35 -1
View File
@@ -1,6 +1,40 @@
# Changelog
## 0.7.3 (2013-01-02)
## 0.7.4 (2014-01-07)
#### Builder
- Fix ADD caching issue with . prefixed path
- Fix docker build on devicemapper by reverting sparse file tar option
- Fix issue with file caching and prevent wrong cache hit
* Use same error handling while unmarshalling CMD and ENTRYPOINT
#### Documentation
* Simplify and streamline Amazon Quickstart
* Install instructions use unprefixed fedora image
* Update instructions for mtu flag for Docker on GCE
+ Add Ubuntu Saucy to installation
- Fix for wrong version warning on master instead of latest
#### Runtime
- Only get the image's rootfs when we need to calculate the image size
- Correctly handle unmapping UDP ports
* Make CopyFileWithTar use a pipe instead of a buffer to save memory on docker build
- Fix login message to say pull instead of push
- Fix "docker load" help by removing "SOURCE" prompt and mentioning STDIN
* Make blank -H option default to the same as no -H was sent
* Extract cgroups utilities to own submodule
#### Other
+ Add Travis CI configuration to validate DCO and gofmt requirements
+ Add Developer Certificate of Origin Text
* Upgrade VBox Guest Additions
* Check standalone header when pinging a registry server
## 0.7.3 (2014-01-02)
#### Builder
+30 -8
View File
@@ -105,17 +105,39 @@ name and email address match your git configuration. The AUTHORS file is
regenerated occasionally from the git commit history, so a mismatch may result
in your changes being overwritten.
### Approval
### Sign your work
Docker maintainers use LGTM (looks good to me) in comments on the code review
to indicate acceptance.
The sign-off is a simple line at the end of the explanation for the
patch, which certifies that you wrote it or otherwise have the right to
pass it on as an open-source patch. The rules are pretty simple: if you
can certify the below:
```
Docker Developer Grant and Certificate of Origin 1.0
By making a contribution to the Docker Project ("Project"), I represent and warrant that:
a. The contribution was created in whole or in part by me and I have the right to submit the contribution on my own behalf or on behalf of a third party who has authorized me to submit this contribution to the Project; or
b. The contribution is based upon previous work that, to the best of my knowledge, is covered under an appropriate open source license and I have the right and authorization to submit that work with modifications, whether created in whole or in part by me, under the same open source license (unless I am permitted to submit under a different license) that I have identified in the contribution; or
c. The contribution was provided directly to me by some other person who represented and warranted (a) or (b) and I have not modified it.
d. I understand and agree that this Project and the contribution are publicly known and that a record of the contribution (including all personal information I submit with it, including my sign-off record) is maintained indefinitely and may be redistributed consistent with this Project or the open source license(s) involved.
e. I hereby grant to the Project, Docker, Inc and its successors; and recipients of software distributed by the Project a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, modify, prepare derivative works of, publicly display, publicly perform, sublicense, and distribute this contribution and such modifications and derivative works consistent with this Project, the open source license indicated in the previous work or other appropriate open source license specified by the Project and approved by the Open Source Initiative(OSI) at http://www.opensource.org.
```
then you just add a line saying
Docker-DCO-1.0-Signed-off-by: Joe Smith <joe.smith@email.com> (github: github_handle)
using your real name (sorry, no pseudonyms or anonymous contributions.)
If you have any questions, please refer to the FAQ in the [docs](http://docs.docker.io)
A change requires LGTMs from an absolute majority of the maintainers of each
component affected. For example, if a change affects docs/ and registry/, it
needs an absolute majority from the maintainers of docs/ AND, separately, an
absolute majority of the maintainers of registry
For more details see [MAINTAINERS.md](hack/MAINTAINERS.md)
### How can I become a maintainer?
+1
View File
@@ -2,6 +2,7 @@ Solomon Hykes <solomon@dotcloud.com> (@shykes)
Guillaume Charmes <guillaume@dotcloud.com> (@creack)
Victor Vieux <victor@dotcloud.com> (@vieux)
Michael Crosby <michael@crosbymichael.com> (@crosbymichael)
.travis.yml: Tianon Gravi <admwiggin@gmail.com> (@tianon)
api.go: Victor Vieux <victor@dotcloud.com> (@vieux)
Dockerfile: Tianon Gravi <admwiggin@gmail.com> (@tianon)
Makefile: Tianon Gravi <admwiggin@gmail.com> (@tianon)
+46
View File
@@ -0,0 +1,46 @@
```
**GET**
send objects deprecate multi-stream
TODO "/events": getEvents, N
ok "/info": getInfo, 1
ok "/version": getVersion, 1
... "/images/json": getImagesJSON, N
TODO "/images/viz": getImagesViz, 0 yes
TODO "/images/search": getImagesSearch, N
#3490 "/images/{name:.*}/get": getImagesGet, 0
TODO "/images/{name:.*}/history": getImagesHistory, 1
TODO "/images/{name:.*}/json": getImagesByName, 1
TODO "/containers/ps": getContainersJSON, N
TODO "/containers/json": getContainersJSON, 1
ok "/containers/{name:.*}/export": getContainersExport, 0
TODO "/containers/{name:.*}/changes": getContainersChanges, 1
TODO "/containers/{name:.*}/json": getContainersByName, 1
TODO "/containers/{name:.*}/top": getContainersTop, N
TODO "/containers/{name:.*}/attach/ws": wsContainersAttach, 0 yes
**POST**
TODO "/auth": postAuth, 0 yes
ok "/commit": postCommit, 0
TODO "/build": postBuild, 0 yes
TODO "/images/create": postImagesCreate, N yes yes (pull)
TODO "/images/{name:.*}/insert": postImagesInsert, N yes yes
TODO "/images/load": postImagesLoad, 1 yes (stdin)
TODO "/images/{name:.*}/push": postImagesPush, N yes
ok "/images/{name:.*}/tag": postImagesTag, 0
ok "/containers/create": postContainersCreate, 0
ok "/containers/{name:.*}/kill": postContainersKill, 0
#3476 "/containers/{name:.*}/restart": postContainersRestart, 0
ok "/containers/{name:.*}/start": postContainersStart, 0
ok "/containers/{name:.*}/stop": postContainersStop, 0
ok "/containers/{name:.*}/wait": postContainersWait, 0
ok "/containers/{name:.*}/resize": postContainersResize, 0
TODO "/containers/{name:.*}/attach": postContainersAttach, 0 yes
TODO "/containers/{name:.*}/copy": postContainersCopy, 0 yes
**DELETE**
#3180 "/containers/{name:.*}": deleteContainers, 0
TODO "/images/{name:.*}": deleteImages, N
**OPTIONS**
ok "": optionsHandler, 0
```
+1 -1
View File
@@ -1 +1 @@
0.7.3
0.7.4
Vendored
+4 -4
View File
@@ -70,7 +70,7 @@ SCRIPT
# trigger dkms to build the virtualbox guest module install.
$vbox_script = <<VBOX_SCRIPT + $script
# Install the VirtualBox guest additions if they aren't already installed.
if [ ! -d /opt/VBoxGuestAdditions-4.3.4/ ]; then
if [ ! -d /opt/VBoxGuestAdditions-4.3.6/ ]; then
# Update remote package metadata. 'apt-get update' is idempotent.
apt-get update -q
@@ -79,10 +79,10 @@ if [ ! -d /opt/VBoxGuestAdditions-4.3.4/ ]; then
apt-get install -q -y linux-headers-generic-lts-raring dkms
echo 'Downloading VBox Guest Additions...'
wget -cq http://dlc.sun.com.edgesuite.net/virtualbox/4.3.4/VBoxGuestAdditions_4.3.4.iso
echo "f120793fa35050a8280eacf9c930cf8d9b88795161520f6515c0cc5edda2fe8a VBoxGuestAdditions_4.3.4.iso" | sha256sum --check || exit 1
wget -cq http://dlc.sun.com.edgesuite.net/virtualbox/4.3.6/VBoxGuestAdditions_4.3.6.iso
echo "95648fcdb5d028e64145a2fe2f2f28c946d219da366389295a61fed296ca79f0 VBoxGuestAdditions_4.3.6.iso" | sha256sum --check || exit 1
mount -o loop,ro /home/vagrant/VBoxGuestAdditions_4.3.4.iso /mnt
mount -o loop,ro /home/vagrant/VBoxGuestAdditions_4.3.6.iso /mnt
/mnt/VBoxLinuxAdditions.run --nox11
umount /mnt
fi
+36 -23
View File
@@ -3,8 +3,8 @@ package archive
import (
"archive/tar"
"bytes"
"compress/gzip"
"compress/bzip2"
"compress/gzip"
"fmt"
"github.com/dotcloud/docker/utils"
"io"
@@ -149,7 +149,7 @@ func escapeName(name string) string {
// Tar creates an archive from the directory at `path`, only including files whose relative
// paths are included in `filter`. If `filter` is nil, then all files are included.
func TarFilter(path string, options *TarOptions) (io.Reader, error) {
args := []string{"tar", "-S", "--numeric-owner", "-f", "-", "-C", path, "-T", "-"}
args := []string{"tar", "--numeric-owner", "-f", "-", "-C", path, "-T", "-"}
if options.Includes == nil {
options.Includes = []string{"."}
}
@@ -228,7 +228,7 @@ func Untar(archive io.Reader, path string, options *TarOptions) error {
compression := DetectCompression(buf)
utils.Debugf("Archive compression detected: %s", compression.Extension())
args := []string{"-S", "--numeric-owner", "-f", "-", "-C", path, "-x" + compression.Flag()}
args := []string{"--numeric-owner", "-f", "-", "-C", path, "-x" + compression.Flag()}
if options != nil {
for _, exclude := range options.Excludes {
@@ -299,7 +299,7 @@ func CopyWithTar(src, dst string) error {
//
// If `dst` ends with a trailing slash '/', the final destination path
// will be `dst/base(src)`.
func CopyFileWithTar(src, dst string) error {
func CopyFileWithTar(src, dst string) (err error) {
utils.Debugf("CopyFileWithTar(%s, %s)", src, dst)
srcSt, err := os.Stat(src)
if err != nil {
@@ -316,25 +316,38 @@ func CopyFileWithTar(src, dst string) error {
if err := os.MkdirAll(filepath.Dir(dst), 0700); err != nil && !os.IsExist(err) {
return err
}
buf := new(bytes.Buffer)
tw := tar.NewWriter(buf)
hdr, err := tar.FileInfoHeader(srcSt, "")
if err != nil {
return err
}
hdr.Name = filepath.Base(dst)
if err := tw.WriteHeader(hdr); err != nil {
return err
}
srcF, err := os.Open(src)
if err != nil {
return err
}
if _, err := io.Copy(tw, srcF); err != nil {
return err
}
tw.Close()
return Untar(buf, filepath.Dir(dst), nil)
r, w := io.Pipe()
errC := utils.Go(func() error {
defer w.Close()
srcF, err := os.Open(src)
if err != nil {
return err
}
defer srcF.Close()
tw := tar.NewWriter(w)
hdr, err := tar.FileInfoHeader(srcSt, "")
if err != nil {
return err
}
hdr.Name = filepath.Base(dst)
if err := tw.WriteHeader(hdr); err != nil {
return err
}
if _, err := io.Copy(tw, srcF); err != nil {
return err
}
tw.Close()
return nil
})
defer func() {
if er := <-errC; err != nil {
err = er
}
}()
return Untar(r, filepath.Dir(dst), nil)
}
// CmdStream executes a command, and returns its stdout as a stream.
+30 -23
View File
@@ -213,16 +213,30 @@ func (b *buildFile) CmdEnv(args string) error {
return b.commit("", b.config.Cmd, fmt.Sprintf("ENV %s", replacedVar))
}
func (b *buildFile) CmdCmd(args string) error {
func (b *buildFile) buildCmdFromJson(args string) []string {
var cmd []string
if err := json.Unmarshal([]byte(args), &cmd); err != nil {
utils.Debugf("Error unmarshalling: %s, setting cmd to /bin/sh -c", err)
utils.Debugf("Error unmarshalling: %s, setting to /bin/sh -c", err)
cmd = []string{"/bin/sh", "-c", args}
}
if err := b.commit("", cmd, fmt.Sprintf("CMD %v", cmd)); err != nil {
return cmd
}
func (b *buildFile) CmdCmd(args string) error {
cmd := b.buildCmdFromJson(args)
b.config.Cmd = cmd
if err := b.commit("", b.config.Cmd, fmt.Sprintf("CMD %v", cmd)); err != nil {
return err
}
return nil
}
func (b *buildFile) CmdEntrypoint(args string) error {
entrypoint := b.buildCmdFromJson(args)
b.config.Entrypoint = entrypoint
if err := b.commit("", b.config.Cmd, fmt.Sprintf("ENTRYPOINT %v", entrypoint)); err != nil {
return err
}
b.config.Cmd = cmd
return nil
}
@@ -245,23 +259,6 @@ func (b *buildFile) CmdCopy(args string) error {
return fmt.Errorf("COPY has been deprecated. Please use ADD instead")
}
func (b *buildFile) CmdEntrypoint(args string) error {
if args == "" {
return fmt.Errorf("Entrypoint cannot be empty")
}
var entrypoint []string
if err := json.Unmarshal([]byte(args), &entrypoint); err != nil {
b.config.Entrypoint = []string{"/bin/sh", "-c", args}
} else {
b.config.Entrypoint = entrypoint
}
if err := b.commit("", b.config.Cmd, fmt.Sprintf("ENTRYPOINT %s", args)); err != nil {
return err
}
return nil
}
func (b *buildFile) CmdWorkdir(workdir string) error {
b.config.WorkingDir = workdir
return b.commit("", b.config.Cmd, fmt.Sprintf("WORKDIR %v", workdir))
@@ -410,6 +407,15 @@ func (b *buildFile) CmdAdd(args string) error {
hash string
sums = b.context.GetSums()
)
// Has tarsum strips the '.' and './', we put it back for comparaison.
for file, sum := range sums {
if len(file) == 0 || file[0] != '.' && file[0] != '/' {
delete(sums, file)
sums["./"+file] = sum
}
}
if fi, err := os.Stat(path.Join(b.contextPath, origPath)); err != nil {
return err
} else if fi.IsDir() {
@@ -431,7 +437,8 @@ func (b *buildFile) CmdAdd(args string) error {
if err != nil {
return err
}
if hit {
// If we do not have a hash, never use the cache
if hit && hash != "" {
return nil
}
}
@@ -653,7 +660,7 @@ func (b *buildFile) Build(context io.Reader) (string, error) {
}
return b.image, nil
}
return "", fmt.Errorf("An error occurred during the build\n")
return "", fmt.Errorf("No image was generated. This may be because the Dockerfile does not, like, do anything.\n")
}
func NewBuildFile(srv *Server, outStream, errStream io.Writer, verbose, utilizeCache, rm bool, outOld io.Writer, sf *utils.StreamFormatter, auth *auth.AuthConfig) BuildFile {
+101
View File
@@ -0,0 +1,101 @@
package cgroups
import (
"bufio"
"fmt"
"github.com/dotcloud/docker/mount"
"io"
"io/ioutil"
"os"
"path/filepath"
"strconv"
"strings"
)
// https://www.kernel.org/doc/Documentation/cgroups/cgroups.txt
func FindCgroupMountpoint(subsystem string) (string, error) {
mounts, err := mount.GetMounts()
if err != nil {
return "", err
}
for _, mount := range mounts {
if mount.Fstype == "cgroup" {
for _, opt := range strings.Split(mount.VfsOpts, ",") {
if opt == subsystem {
return mount.Mountpoint, nil
}
}
}
}
return "", fmt.Errorf("cgroup mountpoint not found for %s", subsystem)
}
// Returns the relative path to the cgroup docker is running in.
func getThisCgroupDir(subsystem string) (string, error) {
f, err := os.Open("/proc/self/cgroup")
if err != nil {
return "", err
}
defer f.Close()
return parseCgroupFile(subsystem, f)
}
func parseCgroupFile(subsystem string, r io.Reader) (string, error) {
s := bufio.NewScanner(r)
for s.Scan() {
if err := s.Err(); err != nil {
return "", err
}
text := s.Text()
parts := strings.Split(text, ":")
if parts[1] == subsystem {
return parts[2], nil
}
}
return "", fmt.Errorf("cgroup '%s' not found in /proc/self/cgroup", subsystem)
}
// Returns a list of pids for the given container.
func GetPidsForContainer(id string) ([]int, error) {
pids := []int{}
// memory is chosen randomly, any cgroup used by docker works
subsystem := "memory"
cgroupRoot, err := FindCgroupMountpoint(subsystem)
if err != nil {
return pids, err
}
cgroupDir, err := getThisCgroupDir(subsystem)
if err != nil {
return pids, err
}
filename := filepath.Join(cgroupRoot, cgroupDir, id, "tasks")
if _, err := os.Stat(filename); os.IsNotExist(err) {
// With more recent lxc versions use, cgroup will be in lxc/
filename = filepath.Join(cgroupRoot, cgroupDir, "lxc", id, "tasks")
}
output, err := ioutil.ReadFile(filename)
if err != nil {
return pids, err
}
for _, p := range strings.Split(string(output), "\n") {
if len(p) == 0 {
continue
}
pid, err := strconv.Atoi(p)
if err != nil {
return pids, fmt.Errorf("Invalid pid '%s': %s", p, err)
}
pids = append(pids, pid)
}
return pids, nil
}
+27
View File
@@ -0,0 +1,27 @@
package cgroups
import (
"bytes"
"testing"
)
const (
cgroupsContents = `11:hugetlb:/
10:perf_event:/
9:blkio:/
8:net_cls:/
7:freezer:/
6:devices:/
5:memory:/
4:cpuacct,cpu:/
3:cpuset:/
2:name=systemd:/user.slice/user-1000.slice/session-16.scope`
)
func TestParseCgroups(t *testing.T) {
r := bytes.NewBuffer([]byte(cgroupsContents))
_, err := parseCgroupFile("blkio", r)
if err != nil {
t.Fatal(err)
}
}
+2 -2
View File
@@ -1100,7 +1100,7 @@ func (cli *DockerCli) CmdPull(args ...string) error {
if err := pull(authConfig); err != nil {
if err.Error() == registry.ErrLoginRequired.Error() {
fmt.Fprintln(cli.out, "\nPlease login prior to push:")
fmt.Fprintln(cli.out, "\nPlease login prior to pull:")
if err := cli.CmdLogin(endpoint); err != nil {
return err
}
@@ -2207,7 +2207,7 @@ func (cli *DockerCli) CmdSave(args ...string) error {
}
func (cli *DockerCli) CmdLoad(args ...string) error {
cmd := cli.Subcmd("load", "SOURCE", "Load an image from a tar archive")
cmd := cli.Subcmd("load", "", "Load an image from a tar archive on STDIN")
if err := cmd.Parse(args); err != nil {
return err
}
+4 -9
View File
@@ -26,18 +26,13 @@ Amazon QuickStart
<https://console.aws.amazon.com/ec2/v2/home?#LaunchInstanceWizard:>`_ menu
on your AWS Console.
* When picking the source AMI for your instance type, select "Community
AMIs".
* Click the ``Select`` button for a 64Bit Ubuntu image. For example: Ubuntu Server 12.04.3 LTS
* Search for ``amd64 precise``. Pick one of the amd64 Ubuntu images.
* If you choose a EBS enabled AMI, you'll also be able to launch a
* For testing you can use the default (possibly free)
``t1.micro`` instance (more info on `pricing
<http://aws.amazon.com/en/ec2/pricing/>`_). ``t1.micro`` instances are
eligible for Amazon's Free Usage Tier.
<http://aws.amazon.com/en/ec2/pricing/>`_).
* When you click select you'll be taken to the instance setup, and you're one
click away from having your Ubuntu VM up and running.
* Click the ``Next: Configure Instance Details`` button at the bottom right.
2. **Tell CloudInit to install Docker:**
+1 -1
View File
@@ -67,7 +67,7 @@ Now let's verify that Docker is working.
.. code-block:: bash
sudo docker run -i -t mattdm/fedora /bin/bash
sudo docker run -i -t fedora /bin/bash
**Done!**, now continue with the :ref:`hello_world` example.
+3 -2
View File
@@ -57,12 +57,13 @@
docker-playground:~$ curl get.docker.io | bash
docker-playground:~$ sudo update-rc.d docker defaults
7. If running in zones: us-central1-a, europe-west1-1, and europe-west1-b, the docker daemon must be started with the `-mtu` flag. Without the flag, you may experience intermittent network pauses.
7. If running in zones: ``us-central1-a``, ``europe-west1-1``, and ``europe-west1-b``, the docker daemon must be started with the ``-mtu`` flag. Without the flag, you may experience intermittent network pauses.
`See this issue <https://code.google.com/p/google-compute-engine/issues/detail?id=57>`_ for more details.
.. code-block:: bash
docker -d -mtu 1460
docker-playground:~$ echo "DOCKER_OPTS="$DOCKER_OPTS -mtu 1460" | sudo tee -a /etc/defaults/docker
docker-playground:~$ sudo service docker restart
8. Start a new container:
+1 -1
View File
@@ -65,7 +65,7 @@ Now let's verify that Docker is working.
.. code-block:: bash
sudo docker run -i -t mattdm/fedora /bin/bash
sudo docker run -i -t fedora /bin/bash
**Done!**, now continue with the :ref:`hello_world` example.
+6 -5
View File
@@ -17,7 +17,7 @@ Ubuntu
Docker is supported on the following versions of Ubuntu:
- :ref:`ubuntu_precise`
- :ref:`ubuntu_raring`
- :ref:`ubuntu_raring_saucy`
Please read :ref:`ufw`, if you plan to use `UFW (Uncomplicated
Firewall) <https://help.ubuntu.com/community/UFW>`_
@@ -108,10 +108,12 @@ Type ``exit`` to exit
**Done!**, now continue with the :ref:`hello_world` example.
.. _ubuntu_raring:
.. _ubuntu_raring_saucy:
Ubuntu Raring 13.04 (64 bit)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Ubuntu Raring 13.04 and Saucy 13.10 (64 bit)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
These instructions cover both Ubuntu Raring 13.04 and Saucy 13.10.
Dependencies
------------
@@ -169,7 +171,6 @@ Type ``exit`` to exit
**Done!**, now continue with the :ref:`hello_world` example.
.. _ufw:
Docker and UFW
+5
View File
@@ -117,6 +117,11 @@ For example:
* ``tcp://host:4243`` -> tcp connection on host:4243
* ``unix://path/to/socket`` -> unix socket located at ``path/to/socket``
``-H``, when empty, will default to the same value as when no ``-H`` was passed in.
``-H`` also accepts short form for TCP bindings:
``host[:port]`` or ``:port``
.. code-block:: bash
# Run docker in daemon mode
+1 -1
View File
@@ -82,7 +82,7 @@ In this scenario:
$ sudo ifconfig bridge0 192.168.227.1 netmask 255.255.255.0
# Edit your Docker startup file
$ echo "DOCKER_OPTS=\"-b=bridge0\"" /etc/default/docker
$ echo "DOCKER_OPTS=\"-b=bridge0\"" >> /etc/default/docker
# Start Docker
$ sudo service docker start
+1 -1
View File
@@ -92,7 +92,7 @@ $(function(){
$('.version-flyer ul').html('<li class="alternative active-slug"><a href="" title="Switch to local">Local</a></li>');
}
if (doc_version == "master") {
if (doc_version == "latest") {
$('.version-flyer .version-note').hide();
}
+2 -2
View File
@@ -1,8 +1,8 @@
package engine
import (
"path"
"net/http"
"path"
)
// ServeHTTP executes a job as specified by the http request `r`, and sends the
@@ -22,7 +22,7 @@ func (eng *Engine) ServeHTTP(w http.ResponseWriter, r *http.Request) {
jobArgs = []string{}
}
w.Header().Set("Job-Name", jobName)
for _, arg := range(jobArgs) {
for _, arg := range jobArgs {
w.Header().Add("Job-Args", arg)
}
job := eng.Job(jobName, jobArgs...)
+5 -5
View File
@@ -87,17 +87,17 @@ func (graph *Graph) Get(name string) (*Image, error) {
if err != nil {
return nil, err
}
// Check that the filesystem layer exists
rootfs, err := graph.driver.Get(img.ID)
if err != nil {
return nil, fmt.Errorf("Driver %s failed to get image rootfs %s: %s", graph.driver, img.ID, err)
}
if img.ID != id {
return nil, fmt.Errorf("Image stored at '%s' has wrong id '%s'", id, img.ID)
}
img.graph = graph
if img.Size < 0 {
rootfs, err := graph.driver.Get(img.ID)
if err != nil {
return nil, fmt.Errorf("Driver %s failed to get image rootfs %s: %s", graph.driver, img.ID, err)
}
var size int64
if img.Parent == "" {
if size, err = utils.TreeSize(rootfs); err != nil {
+2 -3
View File
@@ -36,9 +36,8 @@ func (d *Driver) Cleanup() error {
}
func copyDir(src, dst string) error {
cmd := exec.Command("cp", "-aT", "--reflink=auto", src, dst)
if err := cmd.Run(); err != nil {
return err
if output, err := exec.Command("cp", "-aT", "--reflink=auto", src, dst).CombinedOutput(); err != nil {
return fmt.Errorf("Error VFS copying directory: %s (%s)", err, output)
}
return nil
}
+1 -1
View File
@@ -17,7 +17,7 @@ set -e
# DO NOT CALL THIS SCRIPT DIRECTLY.
# - The right way to call this script is to invoke "make" from
# your checkout of the Docker repository.
# the Makefile will so a "docker build -t docker ." and then
# the Makefile will do a "docker build -t docker ." and then
# "docker run hack/make.sh" in the resulting container image.
#
+49
View File
@@ -0,0 +1,49 @@
#!/usr/bin/env python
import re
import subprocess
import yaml
from env import commit_range
commit_format = '-%n hash: "%h"%n author: %aN <%aE>%n message: |%n%w(0,2,2)%B'
gitlog = subprocess.check_output([
'git', 'log', '--reverse',
'--format=format:'+commit_format,
'..'.join(commit_range), '--',
])
commits = yaml.load(gitlog)
if not commits:
exit(0) # what? how can we have no commits?
DCO = 'Docker-DCO-1.0-Signed-off-by:'
p = re.compile(r'^{0} ([^<]+) <([^<>@]+@[^<>]+)> \(github: (\S+)\)$'.format(re.escape(DCO)), re.MULTILINE|re.UNICODE)
failed_commits = 0
for commit in commits:
commit['stat'] = subprocess.check_output([
'git', 'log', '--format=format:', '--max-count=1',
'--name-status', commit['hash'], '--',
])
if commit['stat'] == '':
print 'Commit {0} has no actual changed content, skipping.'.format(commit['hash'])
continue
m = p.search(commit['message'])
if not m:
print 'Commit {1} does not have a properly formatted "{0}" marker.'.format(DCO, commit['hash'])
failed_commits += 1
continue # print ALL the commits that don't have a proper DCO
(name, email, github) = m.groups()
# TODO verify that "github" is the person who actually made this commit via the GitHub API
if failed_commits > 0:
exit(failed_commits)
print 'All commits have a valid "{0}" marker.'.format(DCO)
exit(0)
+21
View File
@@ -0,0 +1,21 @@
import os
import subprocess
if 'TRAVIS' not in os.environ:
print 'TRAVIS is not defined; this should run in TRAVIS. Sorry.'
exit(127)
if os.environ['TRAVIS_PULL_REQUEST'] != 'false':
commit_range = [os.environ['TRAVIS_BRANCH'], 'FETCH_HEAD']
else:
try:
subprocess.check_call([
'git', 'log', '-1', '--format=format:',
os.environ['TRAVIS_COMMIT_RANGE'], '--',
])
commit_range = os.environ['TRAVIS_COMMIT_RANGE'].split('...')
if len(commit_range) == 1: # if it didn't split, it must have been separated by '..' instead
commit_range = commit_range[0].split('..')
except subprocess.CalledProcessError:
print 'TRAVIS_COMMIT_RANGE is invalid. This seems to be a force push. We will just assume it must be against upstream master and compare all commits in between.'
commit_range = ['upstream/master', 'HEAD']
+28
View File
@@ -0,0 +1,28 @@
#!/usr/bin/env python
import subprocess
from env import commit_range
files = subprocess.check_output([
'git', 'diff', '--diff-filter=ACMR',
'--name-only', '...'.join(commit_range), '--',
])
exit_status = 0
for filename in files.split('\n'):
if filename.endswith('.go'):
try:
out = subprocess.check_output(['gofmt', '-s', '-l', filename])
if out != '':
print out,
exit_status = 1
except subprocess.CalledProcessError:
exit_status = 1
if exit_status != 0:
print 'Reformat the files listed above with "gofmt -s -w" and try again.'
exit(exit_status)
print 'All files pass gofmt.'
exit(0)
+108 -10
View File
@@ -132,6 +132,23 @@ run [ "$(cat /e)" = "blah" ]
[][2]string{{"/x", "hello"}, {"/", "blah"}},
},
// Comments, shebangs, and executability, oh my!
{
`
FROM {IMAGE}
# This is an ordinary comment.
RUN { echo '#!/bin/sh'; echo 'echo hello world'; } > /hello.sh
RUN [ ! -x /hello.sh ]
RUN chmod +x /hello.sh
RUN [ -x /hello.sh ]
RUN [ "$(cat /hello.sh)" = $'#!/bin/sh\necho hello world' ]
RUN [ "$(/hello.sh)" = "hello world" ]
`,
nil,
nil,
},
// Environment variable
{
`
from {IMAGE}
@@ -142,6 +159,19 @@ run [ "$FOO" = "BAR" ]
nil,
},
// Environment overwriting
{
`
from {IMAGE}
env FOO BAR
run [ "$FOO" = "BAR" ]
env FOO BAZ
run [ "$FOO" = "BAZ" ]
`,
nil,
nil,
},
{
`
from {IMAGE}
@@ -391,6 +421,8 @@ func TestBuildEntrypoint(t *testing.T) {
}
if img.Config.Entrypoint[0] != "/bin/echo" {
t.Log(img.Config.Entrypoint[0])
t.Fail()
}
}
@@ -425,7 +457,7 @@ func TestBuildEntrypointRunCleanup(t *testing.T) {
}
}
func checkCacheBehavior(t *testing.T, template testContextTemplate, expectHit bool) {
func checkCacheBehavior(t *testing.T, template testContextTemplate, expectHit bool) (imageId string) {
eng := NewTestEngine(t)
defer nuke(mkRuntimeFromEngine(eng, t))
@@ -434,20 +466,36 @@ func checkCacheBehavior(t *testing.T, template testContextTemplate, expectHit bo
t.Fatal(err)
}
imageId := img.ID
imageId = img.ID
img = nil
img, err = buildImage(template, t, eng, expectHit)
if err != nil {
t.Fatal(err)
}
hit := imageId == img.ID
if hit != expectHit {
t.Logf("Cache misbehavior, got hit=%t, expected hit=%t: (first: %s, second %s)",
hit, expectHit, imageId, img.ID)
t.Fail()
if hit := imageId == img.ID; hit != expectHit {
t.Fatalf("Cache misbehavior, got hit=%t, expected hit=%t: (first: %s, second %s)", hit, expectHit, imageId, img.ID)
}
return
}
func checkCacheBehaviorFromEngime(t *testing.T, template testContextTemplate, expectHit bool, eng *engine.Engine) (imageId string) {
img, err := buildImage(template, t, eng, true)
if err != nil {
t.Fatal(err)
}
imageId = img.ID
img, err = buildImage(template, t, eng, expectHit)
if err != nil {
t.Fatal(err)
}
if hit := imageId == img.ID; hit != expectHit {
t.Fatalf("Cache misbehavior, got hit=%t, expected hit=%t: (first: %s, second %s)", hit, expectHit, imageId, img.ID)
}
return
}
func TestBuildImageWithCache(t *testing.T) {
@@ -474,11 +522,61 @@ func TestBuildADDLocalFileWithCache(t *testing.T) {
maintainer dockerio
run echo "first"
add foo /usr/lib/bla/bar
run [ "$(cat /usr/lib/bla/bar)" = "hello" ]
run echo "second"
add . /src/
run [ "$(cat /src/foo)" = "hello" ]
`,
[][2]string{{"foo", "hello"}},
[][2]string{
{"foo", "hello"},
},
nil}
checkCacheBehavior(t, template, true)
eng := NewTestEngine(t)
defer nuke(mkRuntimeFromEngine(eng, t))
id1 := checkCacheBehaviorFromEngime(t, template, true, eng)
template.files = append(template.files, [2]string{"bar", "hello2"})
id2 := checkCacheBehaviorFromEngime(t, template, true, eng)
if id1 == id2 {
t.Fatal("The cache should have been invalided but hasn't.")
}
id3 := checkCacheBehaviorFromEngime(t, template, true, eng)
if id2 != id3 {
t.Fatal("The cache should have been used but hasn't.")
}
template.files[1][1] = "hello3"
id4 := checkCacheBehaviorFromEngime(t, template, true, eng)
if id3 == id4 {
t.Fatal("The cache should have been invalided but hasn't.")
}
template.dockerfile += `
add ./bar /src2/
run ls /src2/bar
`
id5 := checkCacheBehaviorFromEngime(t, template, true, eng)
if id4 == id5 {
t.Fatal("The cache should have been invalided but hasn't.")
}
template.files[1][1] = "hello4"
id6 := checkCacheBehaviorFromEngime(t, template, true, eng)
if id5 == id6 {
t.Fatal("The cache should have been invalided but hasn't.")
}
template.dockerfile += `
add bar /src2/bar2
add /bar /src2/bar3
run ls /src2/bar2 /src2/bar3
`
id7 := checkCacheBehaviorFromEngime(t, template, true, eng)
if id6 == id7 {
t.Fatal("The cache should have been invalided but hasn't.")
}
template.files[1][1] = "hello5"
id8 := checkCacheBehaviorFromEngime(t, template, true, eng)
if id7 == id8 {
t.Fatal("The cache should have been invalided but hasn't.")
}
}
func TestBuildADDLocalFileWithoutCache(t *testing.T) {
+1 -1
View File
@@ -1,7 +1,7 @@
package docker
import (
"github.com/dotcloud/docker/iptables"
"github.com/dotcloud/docker/pkg/iptables"
"os"
"testing"
)
+1 -1
View File
@@ -2,7 +2,7 @@ package docker
import (
"fmt"
"github.com/dotcloud/docker/iptables"
"github.com/dotcloud/docker/pkg/iptables"
"path"
"strings"
)
+5 -1
View File
@@ -4,6 +4,10 @@ import (
"time"
)
func GetMounts() ([]*MountInfo, error) {
return parseMountTable()
}
// Looks at /proc/self/mountinfo to determine of the specified
// mountpoint has been mounted
func Mounted(mountpoint string) (bool, error) {
@@ -14,7 +18,7 @@ func Mounted(mountpoint string) (bool, error) {
// Search the table for the mountpoint
for _, e := range entries {
if e.mountpoint == mountpoint {
if e.Mountpoint == mountpoint {
return true, nil
}
}
+36 -13
View File
@@ -5,22 +5,35 @@ import (
"fmt"
"io"
"os"
"strings"
)
const (
// We only parse upto the mountinfo because that is all we
// care about right now
mountinfoFormat = "%d %d %d:%d %s %s %s"
/* 36 35 98:0 /mnt1 /mnt2 rw,noatime master:1 - ext3 /dev/root rw,errors=continue
(1)(2)(3) (4) (5) (6) (7) (8) (9) (10) (11)
(1) mount ID: unique identifier of the mount (may be reused after umount)
(2) parent ID: ID of parent (or of self for the top of the mount tree)
(3) major:minor: value of st_dev for files on filesystem
(4) root: root of the mount within the filesystem
(5) mount point: mount point relative to the process's root
(6) mount options: per mount options
(7) optional fields: zero or more fields of the form "tag[:value]"
(8) separator: marks the end of the optional fields
(9) filesystem type: name of filesystem of the form "type[.subtype]"
(10) mount source: filesystem specific information or "none"
(11) super options: per super block options*/
mountinfoFormat = "%d %d %d:%d %s %s %s "
)
// Represents one line from /proc/self/mountinfo
type procEntry struct {
id, parent, major, minor int
source, mountpoint, opts string
type MountInfo struct {
Id, Parent, Major, Minor int
Root, Mountpoint, Opts string
Fstype, Source, VfsOpts string
}
// Parse /proc/self/mountinfo because comparing Dev and ino does not work from bind mounts
func parseMountTable() ([]*procEntry, error) {
func parseMountTable() ([]*MountInfo, error) {
f, err := os.Open("/proc/self/mountinfo")
if err != nil {
return nil, err
@@ -30,10 +43,10 @@ func parseMountTable() ([]*procEntry, error) {
return parseInfoFile(f)
}
func parseInfoFile(r io.Reader) ([]*procEntry, error) {
func parseInfoFile(r io.Reader) ([]*MountInfo, error) {
var (
s = bufio.NewScanner(r)
out = []*procEntry{}
out = []*MountInfo{}
)
for s.Scan() {
@@ -42,14 +55,24 @@ func parseInfoFile(r io.Reader) ([]*procEntry, error) {
}
var (
p = &procEntry{}
p = &MountInfo{}
text = s.Text()
)
if _, err := fmt.Sscanf(text, mountinfoFormat,
&p.id, &p.parent, &p.major, &p.minor,
&p.source, &p.mountpoint, &p.opts); err != nil {
&p.Id, &p.Parent, &p.Major, &p.Minor,
&p.Root, &p.Mountpoint, &p.Opts); err != nil {
return nil, fmt.Errorf("Scanning '%s' failed: %s", text, err)
}
// Safe as mountinfo encodes mountpoints with spaces as \040.
index := strings.Index(text, " - ")
postSeparatorFields := strings.Fields(text[index+3:])
if len(postSeparatorFields) != 3 {
return nil, fmt.Errorf("Error did not find 3 fields post '-' in '%s'", text)
}
p.Fstype = postSeparatorFields[0]
p.Source = postSeparatorFields[1]
p.VfsOpts = postSeparatorFields[2]
out = append(out, p)
}
return out, nil
+11 -6
View File
@@ -4,7 +4,7 @@ import (
"encoding/binary"
"errors"
"fmt"
"github.com/dotcloud/docker/iptables"
"github.com/dotcloud/docker/pkg/iptables"
"github.com/dotcloud/docker/pkg/netlink"
"github.com/dotcloud/docker/proxy"
"github.com/dotcloud/docker/utils"
@@ -248,12 +248,12 @@ type PortMapper struct {
}
func (mapper *PortMapper) Map(ip net.IP, port int, backendAddr net.Addr) error {
mapKey := (&net.TCPAddr{Port: port, IP: ip}).String()
if _, exists := mapper.tcpProxies[mapKey]; exists {
return fmt.Errorf("Port %s is already in use", mapKey)
}
if _, isTCP := backendAddr.(*net.TCPAddr); isTCP {
mapKey := (&net.TCPAddr{Port: port, IP: ip}).String()
if _, exists := mapper.tcpProxies[mapKey]; exists {
return fmt.Errorf("TCP Port %s is already in use", mapKey)
}
backendPort := backendAddr.(*net.TCPAddr).Port
backendIP := backendAddr.(*net.TCPAddr).IP
if mapper.iptables != nil {
@@ -270,6 +270,10 @@ func (mapper *PortMapper) Map(ip net.IP, port int, backendAddr net.Addr) error {
mapper.tcpProxies[mapKey] = proxy
go proxy.Run()
} else {
mapKey := (&net.UDPAddr{Port: port, IP: ip}).String()
if _, exists := mapper.udpProxies[mapKey]; exists {
return fmt.Errorf("UDP: Port %s is already in use", mapKey)
}
backendPort := backendAddr.(*net.UDPAddr).Port
backendIP := backendAddr.(*net.UDPAddr).IP
if mapper.iptables != nil {
@@ -290,8 +294,8 @@ func (mapper *PortMapper) Map(ip net.IP, port int, backendAddr net.Addr) error {
}
func (mapper *PortMapper) Unmap(ip net.IP, port int, proto string) error {
mapKey := (&net.TCPAddr{Port: port, IP: ip}).String()
if proto == "tcp" {
mapKey := (&net.TCPAddr{Port: port, IP: ip}).String()
backendAddr, ok := mapper.tcpMapping[mapKey]
if !ok {
return fmt.Errorf("Port tcp/%s is not mapped", mapKey)
@@ -307,6 +311,7 @@ func (mapper *PortMapper) Unmap(ip net.IP, port int, proto string) error {
}
delete(mapper.tcpMapping, mapKey)
} else {
mapKey := (&net.UDPAddr{Port: port, IP: ip}).String()
backendAddr, ok := mapper.udpMapping[mapKey]
if !ok {
return fmt.Errorf("Port udp/%s is not mapped", mapKey)
+2 -1
View File
@@ -1,7 +1,7 @@
package docker
import (
"github.com/dotcloud/docker/iptables"
"github.com/dotcloud/docker/pkg/iptables"
"github.com/dotcloud/docker/proxy"
"net"
"testing"
@@ -340,6 +340,7 @@ func NewStubProxy(frontendAddr, backendAddr net.Addr) (proxy.Proxy, error) {
}
func TestPortMapper(t *testing.T) {
// FIXME: is this iptables chain still used anywhere?
var chain *iptables.Chain
mapper := &PortMapper{
tcpMapping: make(map[string]*net.TCPAddr),
+1
View File
@@ -0,0 +1 @@
Michael Crosby <michael@crosbymichael.com> (@crosbymichael)
+1 -1
View File
@@ -1,8 +1,8 @@
package docker
import (
"os"
"io"
"os"
)
func CopyFile(dstFile, srcFile *os.File) error {
+1 -1
View File
@@ -25,8 +25,8 @@ btrfs_reflink(int fd_out, int fd_in)
import "C"
import (
"os"
"io"
"os"
"syscall"
)
+30 -12
View File
@@ -25,11 +25,11 @@ var (
ErrLoginRequired = errors.New("Authentication is required.")
)
func pingRegistryEndpoint(endpoint string) error {
func pingRegistryEndpoint(endpoint string) (bool, error) {
if endpoint == auth.IndexServerAddress() {
// Skip the check, we now this one is valid
// (and we never want to fallback to http in case of error)
return nil
return false, nil
}
httpDial := func(proto string, addr string) (net.Conn, error) {
// Set the connect timeout to 5 seconds
@@ -45,14 +45,26 @@ func pingRegistryEndpoint(endpoint string) error {
client := &http.Client{Transport: httpTransport}
resp, err := client.Get(endpoint + "_ping")
if err != nil {
return err
return false, err
}
defer resp.Body.Close()
if resp.Header.Get("X-Docker-Registry-Version") == "" {
return errors.New("This does not look like a Registry server (\"X-Docker-Registry-Version\" header not found in the response)")
return false, errors.New("This does not look like a Registry server (\"X-Docker-Registry-Version\" header not found in the response)")
}
return nil
standalone := resp.Header.Get("X-Docker-Registry-Standalone")
utils.Debugf("Registry standalone header: '%s'", standalone)
// If the header is absent, we assume true for compatibility with earlier
// versions of the registry
if standalone == "" {
return true, nil
// Accepted values are "true" (case-insensitive) and "1".
} else if strings.EqualFold(standalone, "true") || standalone == "1" {
return true, nil
}
// Otherwise, not standalone
return false, nil
}
func validateRepositoryName(repositoryName string) error {
@@ -122,16 +134,16 @@ func ExpandAndVerifyRegistryUrl(hostname string) (string, error) {
// there is no path given. Expand with default path
hostname = hostname + "/v1/"
}
if err := pingRegistryEndpoint(hostname); err != nil {
if _, err := pingRegistryEndpoint(hostname); err != nil {
return "", errors.New("Invalid Registry endpoint: " + err.Error())
}
return hostname, nil
}
endpoint := fmt.Sprintf("https://%s/v1/", hostname)
if err := pingRegistryEndpoint(endpoint); err != nil {
if _, err := pingRegistryEndpoint(endpoint); err != nil {
utils.Debugf("Registry %s does not work (%s), falling back to http", endpoint, err)
endpoint = fmt.Sprintf("http://%s/v1/", hostname)
if err = pingRegistryEndpoint(endpoint); err != nil {
if _, err = pingRegistryEndpoint(endpoint); err != nil {
//TODO: triggering highland build can be done there without "failing"
return "", errors.New("Invalid Registry endpoint: " + err.Error())
}
@@ -682,12 +694,18 @@ func NewRegistry(authConfig *auth.AuthConfig, factory *utils.HTTPRequestFactory,
return nil, err
}
// If we're working with a private registry over HTTPS, send Basic Auth headers
// If we're working with a standalone private registry over HTTPS, send Basic Auth headers
// alongside our requests.
if indexEndpoint != auth.IndexServerAddress() && strings.HasPrefix(indexEndpoint, "https://") {
utils.Debugf("Endpoint %s is eligible for private registry auth. Enabling decorator.", indexEndpoint)
dec := utils.NewHTTPAuthDecorator(authConfig.Username, authConfig.Password)
factory.AddDecorator(dec)
standalone, err := pingRegistryEndpoint(indexEndpoint)
if err != nil {
return nil, err
}
if standalone {
utils.Debugf("Endpoint %s is eligible for private registry auth. Enabling decorator.", indexEndpoint)
dec := utils.NewHTTPAuthDecorator(authConfig.Username, authConfig.Password)
factory.AddDecorator(dec)
}
}
r.reqFactory = factory
+2 -1
View File
@@ -23,10 +23,11 @@ func spawnTestRegistry(t *testing.T) *Registry {
}
func TestPingRegistryEndpoint(t *testing.T) {
err := pingRegistryEndpoint(makeURL("/v1/"))
standalone, err := pingRegistryEndpoint(makeURL("/v1/"))
if err != nil {
t.Fatal(err)
}
assertEqual(t, standalone, true, "Expected standalone to be true (default)")
}
func TestGetRemoteHistory(t *testing.T) {
+5 -9
View File
@@ -4,11 +4,12 @@ import (
"container/list"
"fmt"
"github.com/dotcloud/docker/archive"
"github.com/dotcloud/docker/pkg/graphdb"
"github.com/dotcloud/docker/cgroups"
"github.com/dotcloud/docker/graphdriver"
"github.com/dotcloud/docker/graphdriver/aufs"
_ "github.com/dotcloud/docker/graphdriver/devmapper"
_ "github.com/dotcloud/docker/graphdriver/vfs"
"github.com/dotcloud/docker/pkg/graphdb"
"github.com/dotcloud/docker/utils"
"io"
"io/ioutil"
@@ -332,7 +333,7 @@ func (runtime *Runtime) restore() error {
// FIXME: comment please!
func (runtime *Runtime) UpdateCapabilities(quiet bool) {
if cgroupMemoryMountpoint, err := utils.FindCgroupMountpoint("memory"); err != nil {
if cgroupMemoryMountpoint, err := cgroups.FindCgroupMountpoint("memory"); err != nil {
if !quiet {
log.Printf("WARNING: %s\n", err)
}
@@ -582,11 +583,6 @@ func (runtime *Runtime) Commit(container *Container, repository, tag, comment, a
return img, nil
}
// FIXME: this is deprecated by the getFullName *function*
func (runtime *Runtime) getFullName(name string) (string, error) {
return getFullName(name)
}
func getFullName(name string) (string, error) {
if name == "" {
return "", fmt.Errorf("Container name cannot be empty")
@@ -598,7 +594,7 @@ func getFullName(name string) (string, error) {
}
func (runtime *Runtime) GetByName(name string) (*Container, error) {
fullName, err := runtime.getFullName(name)
fullName, err := getFullName(name)
if err != nil {
return nil, err
}
@@ -614,7 +610,7 @@ func (runtime *Runtime) GetByName(name string) (*Container, error) {
}
func (runtime *Runtime) Children(name string) (map[string]*Container, error) {
name, err := runtime.getFullName(name)
name, err := getFullName(name)
if err != nil {
return nil, err
}
+5 -9
View File
@@ -6,6 +6,7 @@ import (
"fmt"
"github.com/dotcloud/docker/archive"
"github.com/dotcloud/docker/auth"
"github.com/dotcloud/docker/cgroups"
"github.com/dotcloud/docker/engine"
"github.com/dotcloud/docker/pkg/graphdb"
"github.com/dotcloud/docker/registry"
@@ -702,7 +703,7 @@ func (srv *Server) ContainerTop(name, psArgs string) (*APITop, error) {
if !container.State.IsRunning() {
return nil, fmt.Errorf("Container %s is not running", name)
}
pids, err := utils.GetPidsForContainer(container.ID)
pids, err := cgroups.GetPidsForContainer(container.ID)
if err != nil {
return nil, err
}
@@ -1437,7 +1438,7 @@ func (srv *Server) ContainerDestroy(name string, removeVolume, removeLink bool)
if container == nil {
return fmt.Errorf("No such link: %s", name)
}
name, err := srv.runtime.getFullName(name)
name, err := getFullName(name)
if err != nil {
return err
}
@@ -1714,12 +1715,8 @@ func (srv *Server) ImageGetCached(imgID string, config *Config) (*Image, error)
return nil, nil
}
func (srv *Server) RegisterLinks(name string, hostConfig *HostConfig) error {
func (srv *Server) RegisterLinks(container *Container, hostConfig *HostConfig) error {
runtime := srv.runtime
container := runtime.Get(name)
if container == nil {
return fmt.Errorf("No such container: %s", name)
}
if hostConfig != nil && hostConfig.Links != nil {
for _, l := range hostConfig.Links {
@@ -1792,8 +1789,7 @@ func (srv *Server) ContainerStart(job *engine.Job) engine.Status {
}
}
// Register any links from the host config before starting the container
// FIXME: we could just pass the container here, no need to lookup by name again.
if err := srv.RegisterLinks(name, &hostConfig); err != nil {
if err := srv.RegisterLinks(container, &hostConfig); err != nil {
job.Error(err)
return engine.StatusErr
}
-1
View File
@@ -322,7 +322,6 @@ func migratePortMappings(config *Config, hostConfig *HostConfig) error {
return nil
}
// Links come in the format of
// name:alias
func parseLink(rawLink string) (map[string]string, error) {
+4 -79
View File
@@ -583,28 +583,6 @@ func CompareKernelVersion(a, b *KernelVersionInfo) int {
return 0
}
func FindCgroupMountpoint(cgroupType string) (string, error) {
output, err := ioutil.ReadFile("/proc/mounts")
if err != nil {
return "", err
}
// /proc/mounts has 6 fields per line, one mount per line, e.g.
// cgroup /sys/fs/cgroup/devices cgroup rw,relatime,devices 0 0
for _, line := range strings.Split(string(output), "\n") {
parts := strings.Split(line, " ")
if len(parts) == 6 && parts[2] == "cgroup" {
for _, opt := range strings.Split(parts[3], ",") {
if opt == cgroupType {
return parts[1], nil
}
}
}
}
return "", fmt.Errorf("cgroup mountpoint not found for %s", cgroupType)
}
func GetKernelVersion() (*KernelVersionInfo, error) {
var (
err error
@@ -803,7 +781,7 @@ func ParseHost(defaultHost string, defaultPort int, defaultUnix, addr string) (s
host string
port int
)
addr = strings.TrimSpace(addr)
switch {
case strings.HasPrefix(addr, "unix://"):
proto = "unix"
@@ -814,6 +792,9 @@ func ParseHost(defaultHost string, defaultPort int, defaultUnix, addr string) (s
case strings.HasPrefix(addr, "tcp://"):
proto = "tcp"
addr = strings.TrimPrefix(addr, "tcp://")
case addr == "":
proto = "unix"
addr = defaultUnix
default:
if strings.Contains(addr, "://") {
return "", fmt.Errorf("Invalid bind address protocol: %s", addr)
@@ -1157,59 +1138,3 @@ func CopyFile(src, dst string) (int64, error) {
defer df.Close()
return io.Copy(df, sf)
}
// Returns the relative path to the cgroup docker is running in.
func GetThisCgroup(cgroupType string) (string, error) {
output, err := ioutil.ReadFile("/proc/self/cgroup")
if err != nil {
return "", err
}
for _, line := range strings.Split(string(output), "\n") {
parts := strings.Split(line, ":")
// any type used by docker should work
if parts[1] == cgroupType {
return parts[2], nil
}
}
return "", fmt.Errorf("cgroup '%s' not found in /proc/self/cgroup", cgroupType)
}
// Returns a list of pids for the given container.
func GetPidsForContainer(id string) ([]int, error) {
pids := []int{}
// memory is chosen randomly, any cgroup used by docker works
cgroupType := "memory"
cgroupRoot, err := FindCgroupMountpoint(cgroupType)
if err != nil {
return pids, err
}
cgroupThis, err := GetThisCgroup(cgroupType)
if err != nil {
return pids, err
}
filename := filepath.Join(cgroupRoot, cgroupThis, id, "tasks")
if _, err := os.Stat(filename); os.IsNotExist(err) {
// With more recent lxc versions use, cgroup will be in lxc/
filename = filepath.Join(cgroupRoot, cgroupThis, "lxc", id, "tasks")
}
output, err := ioutil.ReadFile(filename)
if err != nil {
return pids, err
}
for _, p := range strings.Split(string(output), "\n") {
if len(p) == 0 {
continue
}
pid, err := strconv.Atoi(p)
if err != nil {
return pids, fmt.Errorf("Invalid pid '%s': %s", p, err)
}
pids = append(pids, pid)
}
return pids, nil
}
+3
View File
@@ -316,6 +316,9 @@ func TestParseHost(t *testing.T) {
if addr, err := ParseHost(defaultHttpHost, defaultHttpPort, defaultUnix, "tcp://:7777"); err != nil || addr != "tcp://127.0.0.1:7777" {
t.Errorf("tcp://:7777 -> expected tcp://127.0.0.1:7777, got %s", addr)
}
if addr, err := ParseHost(defaultHttpHost, defaultHttpPort, defaultUnix, ""); err != nil || addr != "unix:///var/run/docker.sock" {
t.Errorf("empty argument -> expected unix:///var/run/docker.sock, got %s", addr)
}
if addr, err := ParseHost(defaultHttpHost, defaultHttpPort, defaultUnix, "unix:///var/run/docker.sock"); err != nil || addr != "unix:///var/run/docker.sock" {
t.Errorf("unix:///var/run/docker.sock -> expected unix:///var/run/docker.sock, got %s", addr)
}