Merge remote-tracking branch 'upstream/master' into doc_remove

Docker-DCO-1.1-Signed-off-by: hollietealok <hollie@docker.com> (github: hollietealok)
Upstream-commit: 97283fa985623ca59183026a13951e7e9e6ce144
Component: engine
This commit is contained in:
hollietealok
2014-07-24 11:28:19 -07:00
11 changed files with 121 additions and 66 deletions
+17 -6
View File
@@ -131,7 +131,7 @@ func (compression *Compression) Extension() string {
return ""
}
func addTarFile(path, name string, tw *tar.Writer) error {
func addTarFile(path, name string, tw *tar.Writer, twBuf *bufio.Writer) error {
fi, err := os.Lstat(path)
if err != nil {
return err
@@ -181,11 +181,18 @@ func addTarFile(path, name string, tw *tar.Writer) error {
if err != nil {
return err
}
if _, err := io.Copy(tw, file); err != nil {
file.Close()
twBuf.Reset(tw)
_, err = io.Copy(twBuf, file)
file.Close()
if err != nil {
return err
}
file.Close()
err = twBuf.Flush()
if err != nil {
return err
}
twBuf.Reset(nil)
}
return nil
@@ -328,6 +335,8 @@ func TarWithOptions(srcPath string, options *TarOptions) (io.ReadCloser, error)
options.Includes = []string{"."}
}
twBuf := bufio.NewWriterSize(nil, twBufSize)
for _, include := range options.Includes {
filepath.Walk(filepath.Join(srcPath, include), func(filePath string, f os.FileInfo, err error) error {
if err != nil {
@@ -355,7 +364,7 @@ func TarWithOptions(srcPath string, options *TarOptions) (io.ReadCloser, error)
}
}
if err := addTarFile(filePath, relFilePath, tw); err != nil {
if err := addTarFile(filePath, relFilePath, tw, twBuf); err != nil {
utils.Debugf("Can't add file %s to tar: %s\n", srcPath, err)
}
return nil
@@ -394,6 +403,7 @@ func Untar(archive io.Reader, dest string, options *TarOptions) error {
defer decompressedArchive.Close()
tr := tar.NewReader(decompressedArchive)
trBuf := bufio.NewReaderSize(nil, trBufSize)
var dirs []*tar.Header
@@ -439,7 +449,8 @@ func Untar(archive io.Reader, dest string, options *TarOptions) error {
}
}
}
if err := createTarFile(path, dest, hdr, tr, options == nil || !options.NoLchown); err != nil {
trBuf.Reset(tr)
if err := createTarFile(path, dest, hdr, trBuf, options == nil || !options.NoLchown); err != nil {
return err
}
+39
View File
@@ -199,3 +199,42 @@ func TestUntarUstarGnuConflict(t *testing.T) {
t.Fatalf("%s not found in the archive", "root/.cpanm/work/1395823785.24209/Plack-1.0030/blib/man3/Plack::Middleware::LighttpdScriptNameFix.3pm")
}
}
func prepareUntarSourceDirectory(numberOfFiles int, targetPath string) (int, error) {
fileData := []byte("fooo")
for n := 0; n < numberOfFiles; n++ {
fileName := fmt.Sprintf("file-%d", n)
if err := ioutil.WriteFile(path.Join(targetPath, fileName), fileData, 0700); err != nil {
return 0, err
}
}
totalSize := numberOfFiles * len(fileData)
return totalSize, nil
}
func BenchmarkTarUntar(b *testing.B) {
origin, err := ioutil.TempDir("", "docker-test-untar-origin")
if err != nil {
b.Fatal(err)
}
tempDir, err := ioutil.TempDir("", "docker-test-untar-destination")
if err != nil {
b.Fatal(err)
}
target := path.Join(tempDir, "dest")
n, err := prepareUntarSourceDirectory(100, origin)
if err != nil {
b.Fatal(err)
}
b.ResetTimer()
b.SetBytes(int64(n))
defer os.RemoveAll(origin)
defer os.RemoveAll(tempDir)
for n := 0; n < b.N; n++ {
err := TarUntar(origin, target)
if err != nil {
b.Fatal(err)
}
os.RemoveAll(target)
}
}
+3 -1
View File
@@ -1,6 +1,7 @@
package archive
import (
"bufio"
"bytes"
"fmt"
"io"
@@ -343,6 +344,7 @@ func ExportChanges(dir string, changes []Change) (Archive, error) {
tw := tar.NewWriter(writer)
go func() {
twBuf := bufio.NewWriterSize(nil, twBufSize)
// In general we log errors here but ignore them because
// during e.g. a diff operation the container can continue
// mutating the filesystem and we can see transient errors
@@ -365,7 +367,7 @@ func ExportChanges(dir string, changes []Change) (Archive, error) {
}
} else {
path := filepath.Join(dir, change.Path)
if err := addTarFile(path, change.Path[1:], tw); err != nil {
if err := addTarFile(path, change.Path[1:], tw, twBuf); err != nil {
utils.Debugf("Can't add file %s to tar: %s\n", path, err)
}
}
+4
View File
@@ -0,0 +1,4 @@
package archive
const twBufSize = 32 * 1024
const trBufSize = 32 * 1024
+4 -1
View File
@@ -1,6 +1,7 @@
package archive
import (
"bufio"
"fmt"
"io"
"io/ioutil"
@@ -32,6 +33,7 @@ func ApplyLayer(dest string, layer ArchiveReader) error {
}
tr := tar.NewReader(layer)
trBuf := bufio.NewReaderSize(nil, trBufSize)
var dirs []*tar.Header
@@ -108,7 +110,8 @@ func ApplyLayer(dest string, layer ArchiveReader) error {
}
}
srcData := io.Reader(tr)
trBuf.Reset(tr)
srcData := io.Reader(trBuf)
srcHdr := hdr
// Hard links into /.wh..wh.plnk don't work, as we don't extract that directory, so
@@ -23,6 +23,7 @@ func New() *libcontainer.Config {
"NET_BIND_SERVICE",
"SYS_CHROOT",
"KILL",
"AUDIT_WRITE",
},
Namespaces: map[string]bool{
"NEWNS": true,
+11 -13
View File
@@ -82,7 +82,7 @@ run**.
**--cpuset**=""
CPUs in which to allow execution (0-3, 0,1)
**-d**, **-detach**=*true*|*false*
**-d**, **--detach**=*true*|*false*
Detached mode. This runs the container in the background. It outputs the new
container's ID and any error messages. At any time you can run **docker ps** in
the other shell to view a list of the running containers. You can reattach to a
@@ -101,12 +101,9 @@ stopping the process by pressing the keys CTRL-P CTRL-Q.
Set custom DNS servers. This option can be used to override the DNS
configuration passed to the container. Typically this is necessary when the
host DNS configuration is invalid for the container (e.g., 127.0.0.1). When this
is the case the **-dns** flags is necessary for every run.
is the case the **--dns** flags is necessary for every run.
**-e**, **--env**=[]
Set environment variables
**-e**, **-env**=*environment*
**-e**, **--env**=*environment*
Set environment variables. This option allows you to specify arbitrary
environment variables that are available for the process that will be launched
inside of the container.
@@ -123,6 +120,7 @@ pass in more options via the COMMAND. But, sometimes an operator may want to run
something else inside the container, so you can override the default ENTRYPOINT
at runtime by using a **--entrypoint** and a string to specify the new
ENTRYPOINT.
**--env-file**=[]
Read in a line delimited file of environment variables
@@ -133,10 +131,10 @@ developer can expose the port using the EXPOSE parameter of the Dockerfile, 2)
the operator can use the **--expose** option with **docker run**, or 3) the
container can be started with the **--link**.
**-h**, **-hostname**=*hostname*
**-h**, **--hostname**=*hostname*
Sets the container host name that is available inside the container.
**-i**, **-interactive**=*true*|*false*
**-i**, **--interactive**=*true*|*false*
When set to true, keep stdin open even if not attached. The default is false.
**--link**=*name*:*alias*
@@ -149,7 +147,7 @@ which interface and port to use.
**--lxc-conf**=[]
(lxc exec-driver only) Add custom lxc options --lxc-conf="lxc.cgroup.cpuset.cpus = 0,1"
**-m**, **-memory**=*memory-limit*
**-m**, **--memory**=*memory-limit*
Allows you to constrain the memory available to a container. If the host
supports swap memory, then the -m memory setting can be larger than physical
RAM. If a limit of 0 is specified, the container's memory is not limited. The
@@ -178,14 +176,14 @@ and foreground Docker containers.
'container:<name|id>': reuses another container network stack
'host': use the host network stack inside the container. Note: the host mode gives the container full access to local system services such as D-bus and is therefore considered insecure.
**-P**, **-publish-all**=*true*|*false*
**-P**, **--publish-all**=*true*|*false*
When set to true publish all exposed ports to the host interfaces. The
default is false. If the operator uses -P (or -p) then Docker will make the
exposed port accessible on the host and the ports will be available to any
client that can reach the host. To find the map between the host ports and the
exposed ports, use **docker port**.
**-p**, **-publish**=[]
**-p**, **--publish**=[]
Publish a container's port to the host (format: ip:hostPort:containerPort |
ip::containerPort | hostPort:containerPort) (use **docker port** to see the
actual mapping)
@@ -217,7 +215,7 @@ interactive shell. The default is value is false.
Username or UID
**-v**, **-volume**=*volume*[:ro|:rw]
**-v**, **--volume**=*volume*[:ro|:rw]
Bind mount a volume to the container.
The **-v** option can be used one or
@@ -241,7 +239,7 @@ default, the volumes are mounted in the same mode (read write or read only) as
the reference container.
**-w**, **-workdir**=*directory*
**-w**, **--workdir**=*directory*
Working directory inside the container. The default working directory for
running binaries within a container is the root directory (/). The developer can
set a different default with the Dockerfile WORKDIR instruction. The operator
@@ -67,6 +67,8 @@ The latter would only require two new commands in docker, e.g.,
(and optionally doing consistency checks). Authentication and authorization
are then delegated to SSH (e.g., with public keys).
The default namespace for a private repository is `library`.
# Endpoints
## Images
@@ -305,7 +307,7 @@ Get all of the tags for the given repo.
**Example Request**:
GET /v1/repositories/foo/bar/tags HTTP/1.1
GET /v1/repositories/reynholm/help-system-server/tags HTTP/1.1
Host: registry-1.docker.io
Accept: application/json
Content-Type: application/json
@@ -341,7 +343,7 @@ Get a tag for the given repo.
**Example Request**:
GET /v1/repositories/foo/bar/tags/latest HTTP/1.1
GET /v1/repositories/reynholm/help-system-server/tags/latest HTTP/1.1
Host: registry-1.docker.io
Accept: application/json
Content-Type: application/json
@@ -375,7 +377,7 @@ Delete the tag for the repo
**Example Request**:
DELETE /v1/repositories/foo/bar/tags/latest HTTP/1.1
DELETE /v1/repositories/reynholm/help-system-server/tags/latest HTTP/1.1
Host: registry-1.docker.io
Accept: application/json
Content-Type: application/json
@@ -408,7 +410,7 @@ Put a tag for the given repo.
**Example Request**:
PUT /v1/repositories/foo/bar/tags/latest HTTP/1.1
PUT /v1/repositories/reynholm/help-system-server/tags/latest HTTP/1.1
Host: registry-1.docker.io
Accept: application/json
Content-Type: application/json
@@ -446,7 +448,7 @@ Delete a repository
**Example Request**:
DELETE /v1/repositories/foo/bar/ HTTP/1.1
DELETE /v1/repositories/reynholm/help-system-server/ HTTP/1.1
Host: registry-1.docker.io
Accept: application/json
Content-Type: application/json
+8 -7
View File
@@ -152,11 +152,16 @@ directory, and the local "./vendor" directory as necessary.
If you're building a binary that may need to be used on platforms that include
AppArmor, you will need to set `DOCKER_BUILDTAGS` as follows:
```bash
export DOCKER_BUILDTAGS='apparmor'
```
If you're building a binary that may need to be used on platforms that include
SELinux, you will need to use the `selinux` build tag:
```bash
export DOCKER_BUILDTAGS='selinux'
```
There are build tags for disabling graphdrivers as well. By default, support
for all graphdrivers are built in.
@@ -175,13 +180,9 @@ To disable aufs:
export DOCKER_BUILDTAGS='exclude_graphdriver_aufs'
```
NOTE: if you need to set more than one build tag, space separate them.
If you're building a binary that may need to be used on platforms that include
SELinux, you will need to set `DOCKER_BUILDTAGS` as follows:
NOTE: if you need to set more than one build tag, space separate them:
```bash
export DOCKER_BUILDTAGS='selinux'
export DOCKER_BUILDTAGS='apparmor selinux exclude_graphdriver_aufs'
```
### Static Daemon
+23 -33
View File
@@ -390,52 +390,42 @@ func (r *Registry) GetRemoteImageJSON(imgID, registry string, token []string) ([
func (r *Registry) GetRemoteImageLayer(imgID, registry string, token []string, imgSize int64) (io.ReadCloser, error) {
var (
retries = 5
headRes *http.Response
client *http.Client
hasResume bool = false
imageURL = fmt.Sprintf("%simages/%s/layer", registry, imgID)
retries = 5
client *http.Client
res *http.Response
imageURL = fmt.Sprintf("%simages/%s/layer", registry, imgID)
)
headReq, err := r.reqFactory.NewRequest("HEAD", imageURL, nil)
if err != nil {
return nil, fmt.Errorf("Error while getting from the server: %s\n", err)
}
setTokenAuth(headReq, token)
for i := 1; i <= retries; i++ {
headRes, client, err = r.doRequest(headReq)
if err != nil && i == retries {
return nil, fmt.Errorf("Eror while making head request: %s\n", err)
} else if err != nil {
time.Sleep(time.Duration(i) * 5 * time.Second)
continue
}
break
}
if headRes.Header.Get("Accept-Ranges") == "bytes" && imgSize > 0 {
hasResume = true
}
req, err := r.reqFactory.NewRequest("GET", imageURL, nil)
if err != nil {
return nil, fmt.Errorf("Error while getting from the server: %s\n", err)
}
setTokenAuth(req, token)
if hasResume {
utils.Debugf("server supports resume")
return utils.ResumableRequestReader(client, req, 5, imgSize), nil
}
utils.Debugf("server doesn't support resume")
res, _, err := r.doRequest(req)
if err != nil {
return nil, err
for i := 1; i <= retries; i++ {
res, client, err = r.doRequest(req)
if err != nil {
res.Body.Close()
if i == retries {
return nil, fmt.Errorf("Server error: Status %d while fetching image layer (%s)",
res.StatusCode, imgID)
}
time.Sleep(time.Duration(i) * 5 * time.Second)
continue
}
break
}
if res.StatusCode != 200 {
res.Body.Close()
return nil, fmt.Errorf("Server error: Status %d while fetching image layer (%s)",
res.StatusCode, imgID)
}
if res.Header.Get("Accept-Ranges") == "bytes" && imgSize > 0 {
utils.Debugf("server supports resume")
return utils.ResumableRequestReaderWithInitialResponse(client, req, 5, imgSize, res), nil
}
utils.Debugf("server doesn't support resume")
return res.Body, nil
}
@@ -24,6 +24,10 @@ func ResumableRequestReader(c *http.Client, r *http.Request, maxfail uint32, tot
return &resumableRequestReader{client: c, request: r, maxFailures: maxfail, totalSize: totalsize}
}
func ResumableRequestReaderWithInitialResponse(c *http.Client, r *http.Request, maxfail uint32, totalsize int64, initialResponse *http.Response) io.ReadCloser {
return &resumableRequestReader{client: c, request: r, maxFailures: maxfail, totalSize: totalsize, currentResponse: initialResponse}
}
func (r *resumableRequestReader) Read(p []byte) (n int, err error) {
if r.client == nil || r.request == nil {
return 0, fmt.Errorf("client and request can't be nil\n")