Compare commits
111 Commits
os-release
...
docs
| Author | SHA1 | Date | |
|---|---|---|---|
| 942363d3ca | |||
| 44f2104028 | |||
| 6117b05e87 | |||
| 7d7ef1188b | |||
| c6d31c934b | |||
| 8df037b7ca | |||
| 72b8e7e3ac | |||
| f9f2dbcb15 | |||
| 3d18cd851b | |||
| 7324d8dd8c | |||
| a3ae93dc2e | |||
| 385676735b | |||
| 3e2e0397f3 | |||
| 512f486e0c | |||
| 745722293d | |||
| 87f58529b2 | |||
| 8f7cdbb060 | |||
| 172c412ae8 | |||
| 67baebe9e7 | |||
| e1eee1290d | |||
| d3fe81f9ba | |||
| 551c4559ad | |||
| 2eaa994b24 | |||
| e9183b35a3 | |||
| 19c08cd7f4 | |||
| e6d84bddc4 | |||
| f5ab4142be | |||
| 7d71532829 | |||
| da5014009c | |||
| 3a2e6b3871 | |||
| e041a26365 | |||
| b7960c1e45 | |||
| 0d03096b65 | |||
| 55e9551aaa | |||
| c65afe6ba8 | |||
| 5745aaed22 | |||
| b6f0f93c94 | |||
| 33b16fef43 | |||
| 9705c349c5 | |||
| 3de34af5d1 | |||
| b3f3abfc94 | |||
| 783baec49c | |||
| c1d9e7c6fb | |||
| 83f6dbe30a | |||
| a97b89b585 | |||
| 29ea36a880 | |||
| ed672d1609 | |||
| 5916664220 | |||
| da4b336233 | |||
| 74df05ccaa | |||
| 2c875215b1 | |||
| be40a48c12 | |||
| 85f7f7cfc7 | |||
| e15f6fca3f | |||
| d3bbaa70cd | |||
| cc6f6cb2e2 | |||
| c967dd289f | |||
| 7895ec25ea | |||
| 5b06c94701 | |||
| 5851e2da60 | |||
| 9eff33735a | |||
| fc7697b050 | |||
| 1bf8954d0d | |||
| dfd9f5989a | |||
| d9581e861d | |||
| c383ceaf37 | |||
| 948912f692 | |||
| d19b1b927b | |||
| 53f5905379 | |||
| 60cbf4da6c | |||
| 183628388c | |||
| fbd2267e7d | |||
| a16ab243e5 | |||
| b3c3c4cddc | |||
| 0fe5aad984 | |||
| 0f5e2fd479 | |||
| 2f7145b1c5 | |||
| 81efe1f32e | |||
| 5ba75ac343 | |||
| 290987fcb4 | |||
| 98855c863d | |||
| b1f394a247 | |||
| a819a60a94 | |||
| 33cdc7f2c4 | |||
| 117860577c | |||
| b0ac5df367 | |||
| c109095a58 | |||
| d394113dfe | |||
| 2af7f63173 | |||
| f156fb7be5 | |||
| 559043b953 | |||
| ba8abcb3dd | |||
| ebf396c6e8 | |||
| 47d52fb872 | |||
| d167338876 | |||
| e6844381f0 | |||
| 589922adf0 | |||
| 689c4e6075 | |||
| 43da1adedb | |||
| 686fe02020 | |||
| 1d02be1c7a | |||
| edb60b950a | |||
| e0e852ee6f | |||
| b537508f8c | |||
| 37e886eb7b | |||
| 50f65742ef | |||
| 56d859d052 | |||
| 546a704c63 | |||
| fa85dc0030 | |||
| 36b6e5884d | |||
| 90991ddb9b |
@@ -1,5 +1,96 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## 1.8.0 (2015-08-11)
|
||||||
|
|
||||||
|
### Distribution
|
||||||
|
|
||||||
|
+ Trusted pull, push and build, disabled by default
|
||||||
|
* Make tar layers deterministic between registries
|
||||||
|
* Don't allow deleting the image of running containers
|
||||||
|
* Check if a tag name to load is a valid digest
|
||||||
|
* Allow one character repository names
|
||||||
|
* Add a more accurate error description for invalid tag name
|
||||||
|
* Make build cache ignore mtime
|
||||||
|
|
||||||
|
### Cli
|
||||||
|
|
||||||
|
+ Add support for DOCKER_CONFIG/--config to specify config file dir
|
||||||
|
+ Add --type flag for docker inspect command
|
||||||
|
+ Add formatting options to `docker ps` with `--format`
|
||||||
|
+ Replace `docker -d` with new subcommand `docker daemon`
|
||||||
|
* Zsh completion updates and improvements
|
||||||
|
* Add some missing events to bash completion
|
||||||
|
* Support daemon urls with base paths in `docker -H`
|
||||||
|
* Validate status= filter to docker ps
|
||||||
|
* Display when a container is in --net=host in docker ps
|
||||||
|
* Extend docker inspect to export image metadata related to graph driver
|
||||||
|
* Restore --default-gateway{,-v6} daemon options
|
||||||
|
* Add missing unpublished ports in docker ps
|
||||||
|
* Allow duration strings in `docker events` as --since/--until
|
||||||
|
* Expose more mounts information in `docker inspect`
|
||||||
|
|
||||||
|
### Runtime
|
||||||
|
|
||||||
|
+ Add new Fluentd logging driver
|
||||||
|
+ Allow `docker import` to load from local files
|
||||||
|
+ Add logging driver for GELF via UDP
|
||||||
|
+ Allow to copy files from host to containers with `docker cp`
|
||||||
|
+ Promote volume drivers from experimental to master
|
||||||
|
+ Add rollover log driver, and --log-driver-opts flag
|
||||||
|
+ Add memory swappiness tuning options
|
||||||
|
* Remove cgroup read-only flag when privileged
|
||||||
|
* Make /proc, /sys, & /dev readonly for readonly containers
|
||||||
|
* Add cgroup bind mount by default
|
||||||
|
* Overlay: Export metadata for container and image in `docker inspect`
|
||||||
|
* Devicemapper: external device activation
|
||||||
|
* Devicemapper: Compare uuid of base device on startup
|
||||||
|
* Remove RC4 from the list of registry cipher suites
|
||||||
|
* Add syslog-facility option
|
||||||
|
* LXC execdriver compatibility with recent LXC versions
|
||||||
|
* Mark LXC execriver as deprecated (to be removed with the migration to runc)
|
||||||
|
|
||||||
|
### Plugins
|
||||||
|
|
||||||
|
* Separate plugin sockets and specs locations
|
||||||
|
* Allow TLS connections to plugins
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
- Add missing 'Names' field to /containers/json API output
|
||||||
|
- Make `docker rmi --dangling` safe when pulling
|
||||||
|
- Devicemapper: Change default basesize to 100G
|
||||||
|
- Go Scheduler issue with sync.Mutex and gcc
|
||||||
|
- Fix issue where Search API endpoint would panic due to empty AuthConfig
|
||||||
|
- Set image canonical names correctly
|
||||||
|
- Check dockerinit only if lxc driver is used
|
||||||
|
- Fix ulimit usage of nproc
|
||||||
|
- Always attach STDIN if -i,--interactive is specified
|
||||||
|
- Show error messages when saving container state fails
|
||||||
|
- Fixed incorrect assumption on --bridge=none treated as disable network
|
||||||
|
- Check for invalid port specifications in host configuration
|
||||||
|
- Fix endpoint leave failure for --net=host mode
|
||||||
|
- Fix goroutine leak in the stats API if the container is not running
|
||||||
|
- Check for apparmor file before reading it
|
||||||
|
- Fix DOCKER_TLS_VERIFY being ignored
|
||||||
|
- Set umask to the default on startup
|
||||||
|
- Correct the message of pause and unpause a non-running container
|
||||||
|
- Adjust disallowed CpuShares in container creation
|
||||||
|
- ZFS: correctly apply selinux context
|
||||||
|
- Display empty string instead of <nil> when IP opt is nil
|
||||||
|
- `docker kill` returns error when container is not running
|
||||||
|
- Fix COPY/ADD quoted/json form
|
||||||
|
- Fix goroutine leak on logs -f with no output
|
||||||
|
- Remove panic in nat package on invalid hostport
|
||||||
|
- Fix container linking in Fedora 22
|
||||||
|
- Fix error caused using default gateways outside of the allocated range
|
||||||
|
- Format times in inspect command with a template as RFC3339Nano
|
||||||
|
- Make registry client to accept 2xx and 3xx http status responses as successful
|
||||||
|
- Fix race issue that caused the daemon to crash with certain layer downloads failed in a specific order.
|
||||||
|
- Fix error when the docker ps format was not valid.
|
||||||
|
- Remove redundant ip forward check.
|
||||||
|
- Fix issue trying to push images to repository mirrors.
|
||||||
|
- Fix error cleaning up network entrypoints when there is an initialization issue.
|
||||||
|
|
||||||
## 1.7.1 (2015-07-14)
|
## 1.7.1 (2015-07-14)
|
||||||
|
|
||||||
#### Runtime
|
#### Runtime
|
||||||
|
|||||||
@@ -137,7 +137,7 @@ RUN set -x \
|
|||||||
&& rm -rf "$GOPATH"
|
&& rm -rf "$GOPATH"
|
||||||
|
|
||||||
# Install notary server
|
# Install notary server
|
||||||
ENV NOTARY_COMMIT 77bced079e83d80f40c1f0a544b1a8a3b97fb052
|
ENV NOTARY_COMMIT 8e8122eb5528f621afcd4e2854c47302f17392f7
|
||||||
RUN set -x \
|
RUN set -x \
|
||||||
&& export GOPATH="$(mktemp -d)" \
|
&& export GOPATH="$(mktemp -d)" \
|
||||||
&& git clone https://github.com/docker/notary.git "$GOPATH/src/github.com/docker/notary" \
|
&& git clone https://github.com/docker/notary.git "$GOPATH/src/github.com/docker/notary" \
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ databases, and backend services without depending on a particular stack
|
|||||||
or provider.
|
or provider.
|
||||||
|
|
||||||
Docker began as an open-source implementation of the deployment engine which
|
Docker began as an open-source implementation of the deployment engine which
|
||||||
powers [dotCloud](https://dotcloud.com), a popular Platform-as-a-Service.
|
powers [dotCloud](https://www.dotcloud.com), a popular Platform-as-a-Service.
|
||||||
It benefits directly from the experience accumulated over several years
|
It benefits directly from the experience accumulated over several years
|
||||||
of large-scale operation and support of hundreds of thousands of
|
of large-scale operation and support of hundreds of thousands of
|
||||||
applications and databases.
|
applications and databases.
|
||||||
|
|||||||
@@ -115,8 +115,9 @@ func (cli *DockerCli) CmdBuild(args ...string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Resolve the FROM lines in the Dockerfile to trusted digest references
|
// Resolve the FROM lines in the Dockerfile to trusted digest references
|
||||||
// using Notary.
|
// using Notary. On a successful build, we must tag the resolved digests
|
||||||
newDockerfile, err := rewriteDockerfileFrom(filepath.Join(contextDir, relDockerfile), cli.trustedReference)
|
// to the original name specified in the Dockerfile.
|
||||||
|
newDockerfile, resolvedTags, err := rewriteDockerfileFrom(filepath.Join(contextDir, relDockerfile), cli.trustedReference)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to process Dockerfile: %v", err)
|
return fmt.Errorf("unable to process Dockerfile: %v", err)
|
||||||
}
|
}
|
||||||
@@ -291,7 +292,20 @@ func (cli *DockerCli) CmdBuild(args ...string) error {
|
|||||||
}
|
}
|
||||||
return Cli.StatusError{Status: jerr.Message, StatusCode: jerr.Code}
|
return Cli.StatusError{Status: jerr.Message, StatusCode: jerr.Code}
|
||||||
}
|
}
|
||||||
return err
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Since the build was successful, now we must tag any of the resolved
|
||||||
|
// images from the above Dockerfile rewrite.
|
||||||
|
for _, resolved := range resolvedTags {
|
||||||
|
if err := cli.tagTrusted(resolved.repoInfo, resolved.digestRef, resolved.tagRef); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// getDockerfileRelPath uses the given context directory for a `docker build`
|
// getDockerfileRelPath uses the given context directory for a `docker build`
|
||||||
@@ -302,6 +316,22 @@ func getDockerfileRelPath(givenContextDir, givenDockerfile string) (absContextDi
|
|||||||
return "", "", fmt.Errorf("unable to get absolute context directory: %v", err)
|
return "", "", fmt.Errorf("unable to get absolute context directory: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The context dir might be a symbolic link, so follow it to the actual
|
||||||
|
// target directory.
|
||||||
|
absContextDir, err = filepath.EvalSymlinks(absContextDir)
|
||||||
|
if err != nil {
|
||||||
|
return "", "", fmt.Errorf("unable to evaluate symlinks in context path: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
stat, err := os.Lstat(absContextDir)
|
||||||
|
if err != nil {
|
||||||
|
return "", "", fmt.Errorf("unable to stat context directory %q: %v", absContextDir, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !stat.IsDir() {
|
||||||
|
return "", "", fmt.Errorf("context must be a directory: %s", absContextDir)
|
||||||
|
}
|
||||||
|
|
||||||
absDockerfile := givenDockerfile
|
absDockerfile := givenDockerfile
|
||||||
if absDockerfile == "" {
|
if absDockerfile == "" {
|
||||||
// No -f/--file was specified so use the default relative to the
|
// No -f/--file was specified so use the default relative to the
|
||||||
@@ -467,14 +497,21 @@ func (td *trustedDockerfile) Close() error {
|
|||||||
return os.Remove(td.File.Name())
|
return os.Remove(td.File.Name())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// resolvedTag records the repository, tag, and resolved digest reference
|
||||||
|
// from a Dockerfile rewrite.
|
||||||
|
type resolvedTag struct {
|
||||||
|
repoInfo *registry.RepositoryInfo
|
||||||
|
digestRef, tagRef registry.Reference
|
||||||
|
}
|
||||||
|
|
||||||
// rewriteDockerfileFrom rewrites the given Dockerfile by resolving images in
|
// rewriteDockerfileFrom rewrites the given Dockerfile by resolving images in
|
||||||
// "FROM <image>" instructions to a digest reference. `translator` is a
|
// "FROM <image>" instructions to a digest reference. `translator` is a
|
||||||
// function that takes a repository name and tag reference and returns a
|
// function that takes a repository name and tag reference and returns a
|
||||||
// trusted digest reference.
|
// trusted digest reference.
|
||||||
func rewriteDockerfileFrom(dockerfileName string, translator func(string, registry.Reference) (registry.Reference, error)) (newDockerfile *trustedDockerfile, err error) {
|
func rewriteDockerfileFrom(dockerfileName string, translator func(string, registry.Reference) (registry.Reference, error)) (newDockerfile *trustedDockerfile, resolvedTags []*resolvedTag, err error) {
|
||||||
dockerfile, err := os.Open(dockerfileName)
|
dockerfile, err := os.Open(dockerfileName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("unable to open Dockerfile: %v", err)
|
return nil, nil, fmt.Errorf("unable to open Dockerfile: %v", err)
|
||||||
}
|
}
|
||||||
defer dockerfile.Close()
|
defer dockerfile.Close()
|
||||||
|
|
||||||
@@ -483,7 +520,7 @@ func rewriteDockerfileFrom(dockerfileName string, translator func(string, regist
|
|||||||
// Make a tempfile to store the rewritten Dockerfile.
|
// Make a tempfile to store the rewritten Dockerfile.
|
||||||
tempFile, err := ioutil.TempFile("", "trusted-dockerfile-")
|
tempFile, err := ioutil.TempFile("", "trusted-dockerfile-")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("unable to make temporary trusted Dockerfile: %v", err)
|
return nil, nil, fmt.Errorf("unable to make temporary trusted Dockerfile: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
trustedFile := &trustedDockerfile{
|
trustedFile := &trustedDockerfile{
|
||||||
@@ -509,21 +546,32 @@ func rewriteDockerfileFrom(dockerfileName string, translator func(string, regist
|
|||||||
if tag == "" {
|
if tag == "" {
|
||||||
tag = tags.DEFAULTTAG
|
tag = tags.DEFAULTTAG
|
||||||
}
|
}
|
||||||
|
|
||||||
|
repoInfo, err := registry.ParseRepositoryInfo(repo)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, fmt.Errorf("unable to parse repository info: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
ref := registry.ParseReference(tag)
|
ref := registry.ParseReference(tag)
|
||||||
|
|
||||||
if !ref.HasDigest() && isTrusted() {
|
if !ref.HasDigest() && isTrusted() {
|
||||||
trustedRef, err := translator(repo, ref)
|
trustedRef, err := translator(repo, ref)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
line = dockerfileFromLinePattern.ReplaceAllLiteralString(line, fmt.Sprintf("FROM %s", trustedRef.ImageName(repo)))
|
line = dockerfileFromLinePattern.ReplaceAllLiteralString(line, fmt.Sprintf("FROM %s", trustedRef.ImageName(repo)))
|
||||||
|
resolvedTags = append(resolvedTags, &resolvedTag{
|
||||||
|
repoInfo: repoInfo,
|
||||||
|
digestRef: trustedRef,
|
||||||
|
tagRef: ref,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
n, err := fmt.Fprintln(tempFile, line)
|
n, err := fmt.Fprintln(tempFile, line)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
trustedFile.size += int64(n)
|
trustedFile.size += int64(n)
|
||||||
@@ -531,7 +579,7 @@ func rewriteDockerfileFrom(dockerfileName string, translator func(string, regist
|
|||||||
|
|
||||||
tempFile.Seek(0, os.SEEK_SET)
|
tempFile.Seek(0, os.SEEK_SET)
|
||||||
|
|
||||||
return trustedFile, scanner.Err()
|
return trustedFile, resolvedTags, scanner.Err()
|
||||||
}
|
}
|
||||||
|
|
||||||
// replaceDockerfileTarWrapper wraps the given input tar archive stream and
|
// replaceDockerfileTarWrapper wraps the given input tar archive stream and
|
||||||
|
|||||||
@@ -232,6 +232,20 @@ func (cli *DockerCli) copyToContainer(srcPath, dstContainer, dstPath string) (er
|
|||||||
// Prepare destination copy info by stat-ing the container path.
|
// Prepare destination copy info by stat-ing the container path.
|
||||||
dstInfo := archive.CopyInfo{Path: dstPath}
|
dstInfo := archive.CopyInfo{Path: dstPath}
|
||||||
dstStat, err := cli.statContainerPath(dstContainer, dstPath)
|
dstStat, err := cli.statContainerPath(dstContainer, dstPath)
|
||||||
|
|
||||||
|
// If the destination is a symbolic link, we should evaluate it.
|
||||||
|
if err == nil && dstStat.Mode&os.ModeSymlink != 0 {
|
||||||
|
linkTarget := dstStat.LinkTarget
|
||||||
|
if !filepath.IsAbs(linkTarget) {
|
||||||
|
// Join with the parent directory.
|
||||||
|
dstParent, _ := archive.SplitPathDirEntry(dstPath)
|
||||||
|
linkTarget = filepath.Join(dstParent, linkTarget)
|
||||||
|
}
|
||||||
|
|
||||||
|
dstInfo.Path = linkTarget
|
||||||
|
dstStat, err = cli.statContainerPath(dstContainer, linkTarget)
|
||||||
|
}
|
||||||
|
|
||||||
// Ignore any error and assume that the parent directory of the destination
|
// Ignore any error and assume that the parent directory of the destination
|
||||||
// path exists, in which case the copy may still succeed. If there is any
|
// path exists, in which case the copy may still succeed. If there is any
|
||||||
// type of conflict (e.g., non-directory overwriting an existing directory
|
// type of conflict (e.g., non-directory overwriting an existing directory
|
||||||
@@ -242,15 +256,26 @@ func (cli *DockerCli) copyToContainer(srcPath, dstContainer, dstPath string) (er
|
|||||||
dstInfo.Exists, dstInfo.IsDir = true, dstStat.Mode.IsDir()
|
dstInfo.Exists, dstInfo.IsDir = true, dstStat.Mode.IsDir()
|
||||||
}
|
}
|
||||||
|
|
||||||
var content io.Reader
|
var (
|
||||||
|
content io.Reader
|
||||||
|
resolvedDstPath string
|
||||||
|
)
|
||||||
|
|
||||||
if srcPath == "-" {
|
if srcPath == "-" {
|
||||||
// Use STDIN.
|
// Use STDIN.
|
||||||
content = os.Stdin
|
content = os.Stdin
|
||||||
|
resolvedDstPath = dstInfo.Path
|
||||||
if !dstInfo.IsDir {
|
if !dstInfo.IsDir {
|
||||||
return fmt.Errorf("destination %q must be a directory", fmt.Sprintf("%s:%s", dstContainer, dstPath))
|
return fmt.Errorf("destination %q must be a directory", fmt.Sprintf("%s:%s", dstContainer, dstPath))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
srcArchive, err := archive.TarResource(srcPath)
|
// Prepare source copy info.
|
||||||
|
srcInfo, err := archive.CopyInfoSourcePath(srcPath)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
srcArchive, err := archive.TarResource(srcInfo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -262,12 +287,6 @@ func (cli *DockerCli) copyToContainer(srcPath, dstContainer, dstPath string) (er
|
|||||||
// it to the specified directory in the container we get the disired
|
// it to the specified directory in the container we get the disired
|
||||||
// copy behavior.
|
// copy behavior.
|
||||||
|
|
||||||
// Prepare source copy info.
|
|
||||||
srcInfo, err := archive.CopyInfoStatPath(srcPath, true)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// See comments in the implementation of `archive.PrepareArchiveCopy`
|
// See comments in the implementation of `archive.PrepareArchiveCopy`
|
||||||
// for exactly what goes into deciding how and whether the source
|
// for exactly what goes into deciding how and whether the source
|
||||||
// archive needs to be altered for the correct copy behavior when it is
|
// archive needs to be altered for the correct copy behavior when it is
|
||||||
@@ -280,12 +299,12 @@ func (cli *DockerCli) copyToContainer(srcPath, dstContainer, dstPath string) (er
|
|||||||
}
|
}
|
||||||
defer preparedArchive.Close()
|
defer preparedArchive.Close()
|
||||||
|
|
||||||
dstPath = dstDir
|
resolvedDstPath = dstDir
|
||||||
content = preparedArchive
|
content = preparedArchive
|
||||||
}
|
}
|
||||||
|
|
||||||
query := make(url.Values, 2)
|
query := make(url.Values, 2)
|
||||||
query.Set("path", filepath.ToSlash(dstPath)) // Normalize the paths used in the API.
|
query.Set("path", filepath.ToSlash(resolvedDstPath)) // Normalize the paths used in the API.
|
||||||
// Do not allow for an existing directory to be overwritten by a non-directory and vice versa.
|
// Do not allow for an existing directory to be overwritten by a non-directory and vice versa.
|
||||||
query.Set("noOverwriteDirNonDir", "true")
|
query.Set("noOverwriteDirNonDir", "true")
|
||||||
|
|
||||||
|
|||||||
@@ -170,9 +170,11 @@ func customFormat(ctx Context, containers []types.Container) {
|
|||||||
format += "\t{{.Size}}"
|
format += "\t{{.Size}}"
|
||||||
}
|
}
|
||||||
|
|
||||||
tmpl, err := template.New("ps template").Parse(format)
|
tmpl, err := template.New("").Parse(format)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
buffer.WriteString(fmt.Sprintf("Invalid `docker ps` format: %v\n", err))
|
buffer.WriteString(fmt.Sprintf("Template parsing error: %v\n", err))
|
||||||
|
buffer.WriteTo(ctx.Output)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, container := range containers {
|
for _, container := range containers {
|
||||||
@@ -181,8 +183,9 @@ func customFormat(ctx Context, containers []types.Container) {
|
|||||||
c: container,
|
c: container,
|
||||||
}
|
}
|
||||||
if err := tmpl.Execute(buffer, containerCtx); err != nil {
|
if err := tmpl.Execute(buffer, containerCtx); err != nil {
|
||||||
buffer = bytes.NewBufferString(fmt.Sprintf("Invalid `docker ps` format: %v\n", err))
|
buffer = bytes.NewBufferString(fmt.Sprintf("Template parsing error: %v\n", err))
|
||||||
break
|
buffer.WriteTo(ctx.Output)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
if table && len(header) == 0 {
|
if table && len(header) == 0 {
|
||||||
header = containerCtx.fullHeader()
|
header = containerCtx.fullHeader()
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package ps
|
package ps
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
@@ -10,7 +11,7 @@ import (
|
|||||||
"github.com/docker/docker/pkg/stringid"
|
"github.com/docker/docker/pkg/stringid"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestContainerContextID(t *testing.T) {
|
func TestContainerPsContext(t *testing.T) {
|
||||||
containerId := stringid.GenerateRandomID()
|
containerId := stringid.GenerateRandomID()
|
||||||
unix := time.Now().Unix()
|
unix := time.Now().Unix()
|
||||||
|
|
||||||
@@ -86,3 +87,16 @@ func TestContainerContextID(t *testing.T) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestContainerPsFormatError(t *testing.T) {
|
||||||
|
out := bytes.NewBufferString("")
|
||||||
|
ctx := Context{
|
||||||
|
Format: "{{InvalidFunction}}",
|
||||||
|
Output: out,
|
||||||
|
}
|
||||||
|
|
||||||
|
customFormat(ctx, make([]types.Container, 0))
|
||||||
|
if out.String() != "Template parsing error: template: :1: function \"InvalidFunction\" not defined\n" {
|
||||||
|
t.Fatalf("Expected format error, got `%v`\n", out.String())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
@@ -176,11 +177,16 @@ func convertTarget(t client.Target) (target, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (cli *DockerCli) getPassphraseRetriever() passphrase.Retriever {
|
func (cli *DockerCli) getPassphraseRetriever() passphrase.Retriever {
|
||||||
baseRetriever := passphrase.PromptRetrieverWithInOut(cli.in, cli.out)
|
aliasMap := map[string]string{
|
||||||
|
"root": "offline",
|
||||||
|
"snapshot": "tagging",
|
||||||
|
"targets": "tagging",
|
||||||
|
}
|
||||||
|
baseRetriever := passphrase.PromptRetrieverWithInOut(cli.in, cli.out, aliasMap)
|
||||||
env := map[string]string{
|
env := map[string]string{
|
||||||
"root": os.Getenv("DOCKER_CONTENT_TRUST_ROOT_PASSPHRASE"),
|
"root": os.Getenv("DOCKER_CONTENT_TRUST_OFFLINE_PASSPHRASE"),
|
||||||
"targets": os.Getenv("DOCKER_CONTENT_TRUST_TARGET_PASSPHRASE"),
|
"snapshot": os.Getenv("DOCKER_CONTENT_TRUST_TAGGING_PASSPHRASE"),
|
||||||
"snapshot": os.Getenv("DOCKER_CONTENT_TRUST_SNAPSHOT_PASSPHRASE"),
|
"targets": os.Getenv("DOCKER_CONTENT_TRUST_TAGGING_PASSPHRASE"),
|
||||||
}
|
}
|
||||||
return func(keyName string, alias string, createNew bool, numAttempts int) (string, bool, error) {
|
return func(keyName string, alias string, createNew bool, numAttempts int) (string, bool, error) {
|
||||||
if v := env[alias]; v != "" {
|
if v := env[alias]; v != "" {
|
||||||
@@ -311,6 +317,22 @@ func (cli *DockerCli) trustedPull(repoInfo *registry.RepositoryInfo, ref registr
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func selectKey(keys map[string]string) string {
|
||||||
|
if len(keys) == 0 {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
keyIDs := []string{}
|
||||||
|
for k := range keys {
|
||||||
|
keyIDs = append(keyIDs, k)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(dmcgowan): let user choose if multiple keys, now pick consistently
|
||||||
|
sort.Strings(keyIDs)
|
||||||
|
|
||||||
|
return keyIDs[0]
|
||||||
|
}
|
||||||
|
|
||||||
func targetStream(in io.Writer) (io.WriteCloser, <-chan []target) {
|
func targetStream(in io.Writer) (io.WriteCloser, <-chan []target) {
|
||||||
r, w := io.Pipe()
|
r, w := io.Pipe()
|
||||||
out := io.MultiWriter(in, w)
|
out := io.MultiWriter(in, w)
|
||||||
@@ -409,16 +431,13 @@ func (cli *DockerCli) trustedPush(repoInfo *registry.RepositoryInfo, tag string,
|
|||||||
|
|
||||||
ks := repo.KeyStoreManager
|
ks := repo.KeyStoreManager
|
||||||
keys := ks.RootKeyStore().ListKeys()
|
keys := ks.RootKeyStore().ListKeys()
|
||||||
var rootKey string
|
|
||||||
|
|
||||||
if len(keys) == 0 {
|
rootKey := selectKey(keys)
|
||||||
|
if rootKey == "" {
|
||||||
rootKey, err = ks.GenRootKey("ecdsa")
|
rootKey, err = ks.GenRootKey("ecdsa")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
// TODO(dmcgowan): let user choose
|
|
||||||
rootKey = keys[0]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cryptoService, err := ks.GetRootCryptoService(rootKey)
|
cryptoService, err := ks.GetRootCryptoService(rootKey)
|
||||||
|
|||||||
@@ -298,7 +298,13 @@ func (s *Server) postContainersKill(version version.Version, w http.ResponseWrit
|
|||||||
}
|
}
|
||||||
|
|
||||||
if err := s.daemon.ContainerKill(name, sig); err != nil {
|
if err := s.daemon.ContainerKill(name, sig); err != nil {
|
||||||
return err
|
_, isStopped := err.(daemon.ErrContainerNotRunning)
|
||||||
|
// Return error that's not caused because the container is stopped.
|
||||||
|
// Return error if the container is not running and the api is >= 1.20
|
||||||
|
// to keep backwards compatibility.
|
||||||
|
if version.GreaterThanOrEqualTo("1.20") || !isStopped {
|
||||||
|
return fmt.Errorf("Cannot kill container %s: %v", name, err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
w.WriteHeader(http.StatusNoContent)
|
w.WriteHeader(http.StatusNoContent)
|
||||||
|
|||||||
@@ -109,7 +109,7 @@ func allocateDaemonPort(addr string) error {
|
|||||||
|
|
||||||
func adjustCpuShares(version version.Version, hostConfig *runconfig.HostConfig) {
|
func adjustCpuShares(version version.Version, hostConfig *runconfig.HostConfig) {
|
||||||
if version.LessThan("1.19") {
|
if version.LessThan("1.19") {
|
||||||
if hostConfig.CpuShares > 0 {
|
if hostConfig != nil && hostConfig.CpuShares > 0 {
|
||||||
// Handle unsupported CpuShares
|
// Handle unsupported CpuShares
|
||||||
if hostConfig.CpuShares < linuxMinCpuShares {
|
if hostConfig.CpuShares < linuxMinCpuShares {
|
||||||
logrus.Warnf("Changing requested CpuShares of %d to minimum allowed of %d", hostConfig.CpuShares, linuxMinCpuShares)
|
logrus.Warnf("Changing requested CpuShares of %d to minimum allowed of %d", hostConfig.CpuShares, linuxMinCpuShares)
|
||||||
|
|||||||
@@ -86,7 +86,7 @@ type ImageInspect struct {
|
|||||||
Id string
|
Id string
|
||||||
Parent string
|
Parent string
|
||||||
Comment string
|
Comment string
|
||||||
Created time.Time
|
Created string
|
||||||
Container string
|
Container string
|
||||||
ContainerConfig *runconfig.Config
|
ContainerConfig *runconfig.Config
|
||||||
DockerVersion string
|
DockerVersion string
|
||||||
@@ -130,14 +130,13 @@ type CopyConfig struct {
|
|||||||
|
|
||||||
// ContainerPathStat is used to encode the header from
|
// ContainerPathStat is used to encode the header from
|
||||||
// GET /containers/{name:.*}/archive
|
// GET /containers/{name:.*}/archive
|
||||||
// "name" is the file or directory name.
|
// "name" is basename of the resource.
|
||||||
// "path" is the absolute path to the resource in the container.
|
|
||||||
type ContainerPathStat struct {
|
type ContainerPathStat struct {
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Path string `json:"path"`
|
Size int64 `json:"size"`
|
||||||
Size int64 `json:"size"`
|
Mode os.FileMode `json:"mode"`
|
||||||
Mode os.FileMode `json:"mode"`
|
Mtime time.Time `json:"mtime"`
|
||||||
Mtime time.Time `json:"mtime"`
|
LinkTarget string `json:"linkTarget"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// GET "/containers/{name:.*}/top"
|
// GET "/containers/{name:.*}/top"
|
||||||
@@ -215,14 +214,14 @@ type ContainerState struct {
|
|||||||
Pid int
|
Pid int
|
||||||
ExitCode int
|
ExitCode int
|
||||||
Error string
|
Error string
|
||||||
StartedAt time.Time
|
StartedAt string
|
||||||
FinishedAt time.Time
|
FinishedAt string
|
||||||
}
|
}
|
||||||
|
|
||||||
// GET "/containers/{name:.*}/json"
|
// GET "/containers/{name:.*}/json"
|
||||||
type ContainerJSONBase struct {
|
type ContainerJSONBase struct {
|
||||||
Id string
|
Id string
|
||||||
Created time.Time
|
Created string
|
||||||
Path string
|
Path string
|
||||||
Args []string
|
Args []string
|
||||||
State *ContainerState
|
State *ContainerState
|
||||||
|
|||||||
@@ -1,25 +0,0 @@
|
|||||||
#include <tunables/global>
|
|
||||||
|
|
||||||
profile docker-default flags=(attach_disconnected,mediate_deleted) {
|
|
||||||
#include <abstractions/base>
|
|
||||||
|
|
||||||
network,
|
|
||||||
capability,
|
|
||||||
file,
|
|
||||||
umount,
|
|
||||||
|
|
||||||
deny @{PROC}/sys/fs/** wklx,
|
|
||||||
deny @{PROC}/sysrq-trigger rwklx,
|
|
||||||
deny @{PROC}/sys/kernel/[^s][^h][^m]* wklx,
|
|
||||||
deny @{PROC}/sys/kernel/*/** wklx,
|
|
||||||
|
|
||||||
deny mount,
|
|
||||||
|
|
||||||
deny /sys/[^f]*/** wklx,
|
|
||||||
deny /sys/f[^s]*/** wklx,
|
|
||||||
deny /sys/fs/[^c]*/** wklx,
|
|
||||||
deny /sys/fs/c[^g]*/** wklx,
|
|
||||||
deny /sys/fs/cg[^r]*/** wklx,
|
|
||||||
deny /sys/firmware/efi/efivars/** rwklx,
|
|
||||||
deny /sys/kernel/security/** rwklx,
|
|
||||||
}
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
@{DOCKER_GRAPH_PATH}=/var/lib/docker
|
@{DOCKER_GRAPH_PATH}=/var/lib/docker
|
||||||
|
|
||||||
profile /usr/bin/docker (attach_disconnected) {
|
profile /usr/bin/docker (attach_disconnected, complain) {
|
||||||
# Prevent following links to these files during container setup.
|
# Prevent following links to these files during container setup.
|
||||||
deny /etc/** mkl,
|
deny /etc/** mkl,
|
||||||
deny /dev/** kl,
|
deny /dev/** kl,
|
||||||
@@ -21,51 +21,131 @@ profile /usr/bin/docker (attach_disconnected) {
|
|||||||
ipc rw,
|
ipc rw,
|
||||||
network,
|
network,
|
||||||
capability,
|
capability,
|
||||||
file,
|
owner /** rw,
|
||||||
|
/var/lib/docker/** rwl,
|
||||||
|
|
||||||
|
# For non-root client use:
|
||||||
|
/dev/urandom r,
|
||||||
|
/run/docker.sock rw,
|
||||||
|
/proc/** r,
|
||||||
|
/sys/kernel/mm/hugepages/ r,
|
||||||
|
/etc/localtime r,
|
||||||
|
|
||||||
ptrace peer=@{profile_name},
|
ptrace peer=@{profile_name},
|
||||||
|
ptrace (read) peer=docker-default,
|
||||||
|
deny ptrace (trace) peer=docker-default,
|
||||||
|
deny ptrace peer=/usr/bin/docker///bin/ps,
|
||||||
|
|
||||||
/usr/bin/docker pix,
|
/usr/bin/docker pix,
|
||||||
/sbin/xtables-multi rCix,
|
/sbin/xtables-multi rCx,
|
||||||
/sbin/iptables rCx,
|
/sbin/iptables rCx,
|
||||||
/sbin/modprobe rCx,
|
/sbin/modprobe rCx,
|
||||||
/sbin/auplink rCx,
|
/sbin/auplink rCx,
|
||||||
|
/bin/kmod rCx,
|
||||||
/usr/bin/xz rCx,
|
/usr/bin/xz rCx,
|
||||||
|
/bin/ps rCx,
|
||||||
|
/bin/cat rCx,
|
||||||
|
/sbin/zfs rCx,
|
||||||
|
|
||||||
# Transitions
|
# Transitions
|
||||||
change_profile -> docker-*,
|
change_profile -> docker-*,
|
||||||
change_profile -> unconfined,
|
change_profile -> unconfined,
|
||||||
|
|
||||||
profile /sbin/iptables {
|
profile /bin/cat (complain) {
|
||||||
signal (receive) peer=/usr/bin/docker,
|
/etc/ld.so.cache r,
|
||||||
capability net_admin,
|
/lib/** r,
|
||||||
}
|
/dev/null rw,
|
||||||
profile /sbin/auplink flags=(attach_disconnected) {
|
/proc r,
|
||||||
signal (receive) peer=/usr/bin/docker,
|
/bin/cat mr,
|
||||||
capability sys_admin,
|
|
||||||
capability dac_override,
|
|
||||||
|
|
||||||
@{DOCKER_GRAPH_PATH}/aufs/** rw,
|
# For reading in 'docker stats':
|
||||||
# For user namespaces:
|
/proc/[0-9]*/net/dev r,
|
||||||
@{DOCKER_GRAPH_PATH}/[0-9]*.[0-9]*/** rw,
|
|
||||||
|
|
||||||
# The following may be removed via delegates
|
|
||||||
/sys/fs/aufs/** r,
|
|
||||||
/lib/** r,
|
|
||||||
/apparmor/.null r,
|
|
||||||
/dev/null rw,
|
|
||||||
/etc/ld.so.cache r,
|
|
||||||
/sbin/auplink rm,
|
|
||||||
/proc/fs/aufs/** rw,
|
|
||||||
/proc/[0-9]*/mounts rw,
|
|
||||||
}
|
}
|
||||||
profile /sbin/modprobe {
|
profile /bin/ps (complain) {
|
||||||
signal (receive) peer=/usr/bin/docker,
|
/etc/ld.so.cache r,
|
||||||
capability sys_module,
|
/etc/localtime r,
|
||||||
file,
|
/etc/passwd r,
|
||||||
|
/etc/nsswitch.conf r,
|
||||||
|
/lib/** r,
|
||||||
|
/proc/[0-9]*/** r,
|
||||||
|
/dev/null rw,
|
||||||
|
/bin/ps mr,
|
||||||
|
|
||||||
|
# We don't need ptrace so we'll deny and ignore the error.
|
||||||
|
deny ptrace (read, trace),
|
||||||
|
|
||||||
|
# Quiet dac_override denials
|
||||||
|
deny capability dac_override,
|
||||||
|
deny capability dac_read_search,
|
||||||
|
deny capability sys_ptrace,
|
||||||
|
|
||||||
|
/dev/tty r,
|
||||||
|
/proc/stat r,
|
||||||
|
/proc/cpuinfo r,
|
||||||
|
/proc/meminfo r,
|
||||||
|
/proc/uptime r,
|
||||||
|
/sys/devices/system/cpu/online r,
|
||||||
|
/proc/sys/kernel/pid_max r,
|
||||||
|
/proc/ r,
|
||||||
|
/proc/tty/drivers r,
|
||||||
|
}
|
||||||
|
profile /sbin/iptables (complain) {
|
||||||
|
signal (receive) peer=/usr/bin/docker,
|
||||||
|
capability net_admin,
|
||||||
|
}
|
||||||
|
profile /sbin/auplink flags=(attach_disconnected, complain) {
|
||||||
|
signal (receive) peer=/usr/bin/docker,
|
||||||
|
capability sys_admin,
|
||||||
|
capability dac_override,
|
||||||
|
|
||||||
|
@{DOCKER_GRAPH_PATH}/aufs/** rw,
|
||||||
|
@{DOCKER_GRAPH_PATH}/tmp/** rw,
|
||||||
|
# For user namespaces:
|
||||||
|
@{DOCKER_GRAPH_PATH}/[0-9]*.[0-9]*/** rw,
|
||||||
|
|
||||||
|
/sys/fs/aufs/** r,
|
||||||
|
/lib/** r,
|
||||||
|
/apparmor/.null r,
|
||||||
|
/dev/null rw,
|
||||||
|
/etc/ld.so.cache r,
|
||||||
|
/sbin/auplink rm,
|
||||||
|
/proc/fs/aufs/** rw,
|
||||||
|
/proc/[0-9]*/mounts rw,
|
||||||
|
}
|
||||||
|
profile /sbin/modprobe /bin/kmod (complain) {
|
||||||
|
signal (receive) peer=/usr/bin/docker,
|
||||||
|
capability sys_module,
|
||||||
|
/etc/ld.so.cache r,
|
||||||
|
/lib/** r,
|
||||||
|
/dev/null rw,
|
||||||
|
/apparmor/.null rw,
|
||||||
|
/sbin/modprobe rm,
|
||||||
|
/bin/kmod rm,
|
||||||
|
/proc/cmdline r,
|
||||||
|
/sys/module/** r,
|
||||||
|
/etc/modprobe.d{/,/**} r,
|
||||||
}
|
}
|
||||||
# xz works via pipes, so we do not need access to the filesystem.
|
# xz works via pipes, so we do not need access to the filesystem.
|
||||||
profile /usr/bin/xz {
|
profile /usr/bin/xz (complain) {
|
||||||
signal (receive) peer=/usr/bin/docker,
|
signal (receive) peer=/usr/bin/docker,
|
||||||
|
/etc/ld.so.cache r,
|
||||||
|
/lib/** r,
|
||||||
|
/usr/bin/xz rm,
|
||||||
|
deny /proc/** rw,
|
||||||
|
deny /sys/** rw,
|
||||||
|
}
|
||||||
|
profile /sbin/xtables-multi (attach_disconnected, complain) {
|
||||||
|
/etc/ld.so.cache r,
|
||||||
|
/lib/** r,
|
||||||
|
/sbin/xtables-multi rm,
|
||||||
|
/apparmor/.null w,
|
||||||
|
/dev/null rw,
|
||||||
|
capability net_raw,
|
||||||
|
capability net_admin,
|
||||||
|
network raw,
|
||||||
|
}
|
||||||
|
profile /sbin/zfs (attach_disconnected, complain) {
|
||||||
|
file,
|
||||||
|
capability,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
FROM debian:jessie
|
FROM debian:jessie
|
||||||
|
|
||||||
RUN apt-get update && apt-get install -y bash-completion btrfs-tools build-essential curl ca-certificates debhelper dh-apparmor dh-systemd git libapparmor-dev libdevmapper-dev libsqlite3-dev --no-install-recommends && rm -rf /var/lib/apt/lists/*
|
RUN apt-get update && apt-get install -y bash-completion btrfs-tools build-essential curl ca-certificates debhelper dh-systemd git libapparmor-dev libdevmapper-dev libsqlite3-dev --no-install-recommends && rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
ENV GO_VERSION 1.4.2
|
ENV GO_VERSION 1.4.2
|
||||||
RUN curl -fSL "https://storage.googleapis.com/golang/go${GO_VERSION}.linux-amd64.tar.gz" | tar xzC /usr/local
|
RUN curl -fSL "https://storage.googleapis.com/golang/go${GO_VERSION}.linux-amd64.tar.gz" | tar xzC /usr/local
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
FROM debian:stretch
|
FROM debian:stretch
|
||||||
|
|
||||||
RUN apt-get update && apt-get install -y bash-completion btrfs-tools build-essential curl ca-certificates debhelper dh-apparmor dh-systemd git libapparmor-dev libdevmapper-dev libsqlite3-dev --no-install-recommends && rm -rf /var/lib/apt/lists/*
|
RUN apt-get update && apt-get install -y bash-completion btrfs-tools build-essential curl ca-certificates debhelper dh-systemd git libapparmor-dev libdevmapper-dev libsqlite3-dev --no-install-recommends && rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
ENV GO_VERSION 1.4.2
|
ENV GO_VERSION 1.4.2
|
||||||
RUN curl -fSL "https://storage.googleapis.com/golang/go${GO_VERSION}.linux-amd64.tar.gz" | tar xzC /usr/local
|
RUN curl -fSL "https://storage.googleapis.com/golang/go${GO_VERSION}.linux-amd64.tar.gz" | tar xzC /usr/local
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
FROM debian:wheezy
|
FROM debian:wheezy
|
||||||
RUN echo deb http://http.debian.net/debian wheezy-backports main > /etc/apt/sources.list.d/wheezy-backports.list
|
RUN echo deb http://http.debian.net/debian wheezy-backports main > /etc/apt/sources.list.d/wheezy-backports.list
|
||||||
|
|
||||||
RUN apt-get update && apt-get install -y bash-completion btrfs-tools build-essential curl ca-certificates debhelper dh-apparmor dh-systemd git libapparmor-dev libdevmapper-dev libsqlite3-dev --no-install-recommends && rm -rf /var/lib/apt/lists/*
|
RUN apt-get update && apt-get install -y bash-completion btrfs-tools build-essential curl ca-certificates debhelper dh-systemd git libapparmor-dev libdevmapper-dev libsqlite3-dev --no-install-recommends && rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
ENV GO_VERSION 1.4.2
|
ENV GO_VERSION 1.4.2
|
||||||
RUN curl -fSL "https://storage.googleapis.com/golang/go${GO_VERSION}.linux-amd64.tar.gz" | tar xzC /usr/local
|
RUN curl -fSL "https://storage.googleapis.com/golang/go${GO_VERSION}.linux-amd64.tar.gz" | tar xzC /usr/local
|
||||||
|
|||||||
@@ -50,7 +50,6 @@ for version in "${versions[@]}"; do
|
|||||||
build-essential # "essential for building Debian packages"
|
build-essential # "essential for building Debian packages"
|
||||||
curl ca-certificates # for downloading Go
|
curl ca-certificates # for downloading Go
|
||||||
debhelper # for easy ".deb" building
|
debhelper # for easy ".deb" building
|
||||||
dh-apparmor # for apparmor debhelper
|
|
||||||
dh-systemd # for systemd debhelper integration
|
dh-systemd # for systemd debhelper integration
|
||||||
git # for "git commit" info in "docker -v"
|
git # for "git commit" info in "docker -v"
|
||||||
libapparmor-dev # for "sys/apparmor.h"
|
libapparmor-dev # for "sys/apparmor.h"
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
FROM ubuntu-debootstrap:precise
|
FROM ubuntu-debootstrap:precise
|
||||||
|
|
||||||
RUN apt-get update && apt-get install -y bash-completion build-essential curl ca-certificates debhelper dh-apparmor git libapparmor-dev libsqlite3-dev --no-install-recommends && rm -rf /var/lib/apt/lists/*
|
RUN apt-get update && apt-get install -y bash-completion build-essential curl ca-certificates debhelper git libapparmor-dev libsqlite3-dev --no-install-recommends && rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
ENV GO_VERSION 1.4.2
|
ENV GO_VERSION 1.4.2
|
||||||
RUN curl -fSL "https://storage.googleapis.com/golang/go${GO_VERSION}.linux-amd64.tar.gz" | tar xzC /usr/local
|
RUN curl -fSL "https://storage.googleapis.com/golang/go${GO_VERSION}.linux-amd64.tar.gz" | tar xzC /usr/local
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
FROM ubuntu-debootstrap:trusty
|
FROM ubuntu-debootstrap:trusty
|
||||||
|
|
||||||
RUN apt-get update && apt-get install -y bash-completion btrfs-tools build-essential curl ca-certificates debhelper dh-apparmor dh-systemd git libapparmor-dev libdevmapper-dev libsqlite3-dev --no-install-recommends && rm -rf /var/lib/apt/lists/*
|
RUN apt-get update && apt-get install -y bash-completion btrfs-tools build-essential curl ca-certificates debhelper dh-systemd git libapparmor-dev libdevmapper-dev libsqlite3-dev --no-install-recommends && rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
ENV GO_VERSION 1.4.2
|
ENV GO_VERSION 1.4.2
|
||||||
RUN curl -fSL "https://storage.googleapis.com/golang/go${GO_VERSION}.linux-amd64.tar.gz" | tar xzC /usr/local
|
RUN curl -fSL "https://storage.googleapis.com/golang/go${GO_VERSION}.linux-amd64.tar.gz" | tar xzC /usr/local
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
FROM ubuntu-debootstrap:vivid
|
FROM ubuntu-debootstrap:vivid
|
||||||
|
|
||||||
RUN apt-get update && apt-get install -y bash-completion btrfs-tools build-essential curl ca-certificates debhelper dh-apparmor dh-systemd git libapparmor-dev libdevmapper-dev libsqlite3-dev --no-install-recommends && rm -rf /var/lib/apt/lists/*
|
RUN apt-get update && apt-get install -y bash-completion btrfs-tools build-essential curl ca-certificates debhelper dh-systemd git libapparmor-dev libdevmapper-dev libsqlite3-dev --no-install-recommends && rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
ENV GO_VERSION 1.4.2
|
ENV GO_VERSION 1.4.2
|
||||||
RUN curl -fSL "https://storage.googleapis.com/golang/go${GO_VERSION}.linux-amd64.tar.gz" | tar xzC /usr/local
|
RUN curl -fSL "https://storage.googleapis.com/golang/go${GO_VERSION}.linux-amd64.tar.gz" | tar xzC /usr/local
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
FROM ubuntu-debootstrap:wily
|
FROM ubuntu-debootstrap:wily
|
||||||
|
|
||||||
RUN apt-get update && apt-get install -y bash-completion btrfs-tools build-essential curl ca-certificates debhelper dh-apparmor dh-systemd git libapparmor-dev libdevmapper-dev libsqlite3-dev --no-install-recommends && rm -rf /var/lib/apt/lists/*
|
RUN apt-get update && apt-get install -y bash-completion btrfs-tools build-essential curl ca-certificates debhelper dh-systemd git libapparmor-dev libdevmapper-dev libsqlite3-dev --no-install-recommends && rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
ENV GO_VERSION 1.4.2
|
ENV GO_VERSION 1.4.2
|
||||||
RUN curl -fSL "https://storage.googleapis.com/golang/go${GO_VERSION}.linux-amd64.tar.gz" | tar xzC /usr/local
|
RUN curl -fSL "https://storage.googleapis.com/golang/go${GO_VERSION}.linux-amd64.tar.gz" | tar xzC /usr/local
|
||||||
|
|||||||
@@ -27,7 +27,7 @@
|
|||||||
# This order should be applied to lists, alternatives and code blocks.
|
# This order should be applied to lists, alternatives and code blocks.
|
||||||
|
|
||||||
__docker_q() {
|
__docker_q() {
|
||||||
docker ${host:+-H "$host"} 2>/dev/null "$@"
|
docker ${host:+-H "$host"} ${config:+--config "$config"} 2>/dev/null "$@"
|
||||||
}
|
}
|
||||||
|
|
||||||
__docker_containers_all() {
|
__docker_containers_all() {
|
||||||
@@ -295,6 +295,10 @@ __docker_complete_log_driver_options() {
|
|||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
__docker_log_levels() {
|
||||||
|
COMPREPLY=( $( compgen -W "debug info warn error fatal" -- "$cur" ) )
|
||||||
|
}
|
||||||
|
|
||||||
# a selection of the available signals that is most likely of interest in the
|
# a selection of the available signals that is most likely of interest in the
|
||||||
# context of docker containers.
|
# context of docker containers.
|
||||||
__docker_signals() {
|
__docker_signals() {
|
||||||
@@ -312,49 +316,24 @@ __docker_signals() {
|
|||||||
COMPREPLY=( $( compgen -W "${signals[*]} ${signals[*]#SIG}" -- "$( echo $cur | tr '[:lower:]' '[:upper:]')" ) )
|
COMPREPLY=( $( compgen -W "${signals[*]} ${signals[*]#SIG}" -- "$( echo $cur | tr '[:lower:]' '[:upper:]')" ) )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# global options that may appear after the docker command
|
||||||
_docker_docker() {
|
_docker_docker() {
|
||||||
local boolean_options="
|
local boolean_options="
|
||||||
--daemon -d
|
$global_boolean_options
|
||||||
--debug -D
|
|
||||||
--help -h
|
--help -h
|
||||||
--icc
|
|
||||||
--ip-forward
|
|
||||||
--ip-masq
|
|
||||||
--iptables
|
|
||||||
--ipv6
|
|
||||||
--selinux-enabled
|
|
||||||
--tls
|
|
||||||
--tlsverify
|
|
||||||
--userland-proxy=false
|
|
||||||
--version -v
|
--version -v
|
||||||
"
|
"
|
||||||
|
|
||||||
case "$prev" in
|
case "$prev" in
|
||||||
--exec-root|--graph|-g)
|
--config)
|
||||||
_filedir -d
|
_filedir -d
|
||||||
return
|
return
|
||||||
;;
|
;;
|
||||||
--log-driver)
|
|
||||||
__docker_log_drivers
|
|
||||||
return
|
|
||||||
;;
|
|
||||||
--log-level|-l)
|
--log-level|-l)
|
||||||
COMPREPLY=( $( compgen -W "debug info warn error fatal" -- "$cur" ) )
|
__docker_log_levels
|
||||||
return
|
return
|
||||||
;;
|
;;
|
||||||
--log-opt)
|
$(__docker_to_extglob "$global_options_with_args") )
|
||||||
__docker_log_driver_options
|
|
||||||
return
|
|
||||||
;;
|
|
||||||
--pidfile|-p|--tlscacert|--tlscert|--tlskey)
|
|
||||||
_filedir
|
|
||||||
return
|
|
||||||
;;
|
|
||||||
--storage-driver|-s)
|
|
||||||
COMPREPLY=( $( compgen -W "aufs devicemapper btrfs overlay" -- "$(echo $cur | tr '[:upper:]' '[:lower:]')" ) )
|
|
||||||
return
|
|
||||||
;;
|
|
||||||
$main_options_with_args_glob )
|
|
||||||
return
|
return
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
@@ -363,10 +342,10 @@ _docker_docker() {
|
|||||||
|
|
||||||
case "$cur" in
|
case "$cur" in
|
||||||
-*)
|
-*)
|
||||||
COMPREPLY=( $( compgen -W "$boolean_options $main_options_with_args" -- "$cur" ) )
|
COMPREPLY=( $( compgen -W "$boolean_options $global_options_with_args" -- "$cur" ) )
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
local counter="$(__docker_pos_first_nonflag $main_options_with_args_glob)"
|
local counter=$( __docker_pos_first_nonflag $(__docker_to_extglob "$global_options_with_args") )
|
||||||
if [ $cword -eq $counter ]; then
|
if [ $cword -eq $counter ]; then
|
||||||
COMPREPLY=( $( compgen -W "${commands[*]} help" -- "$cur" ) )
|
COMPREPLY=( $( compgen -W "${commands[*]} help" -- "$cur" ) )
|
||||||
fi
|
fi
|
||||||
@@ -478,6 +457,84 @@ _docker_create() {
|
|||||||
_docker_run
|
_docker_run
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_docker_daemon() {
|
||||||
|
local boolean_options="
|
||||||
|
$global_boolean_options
|
||||||
|
--help -h
|
||||||
|
--icc=false
|
||||||
|
--ip-forward=false
|
||||||
|
--ip-masq=false
|
||||||
|
--iptables=false
|
||||||
|
--ipv6
|
||||||
|
--selinux-enabled
|
||||||
|
--userland-proxy=false
|
||||||
|
"
|
||||||
|
local options_with_args="
|
||||||
|
$global_options_with_args
|
||||||
|
--api-cors-header
|
||||||
|
--bip
|
||||||
|
--bridge -b
|
||||||
|
--default-gateway
|
||||||
|
--default-gateway-v6
|
||||||
|
--default-ulimit
|
||||||
|
--dns
|
||||||
|
--dns-search
|
||||||
|
--exec-driver -e
|
||||||
|
--exec-opt
|
||||||
|
--exec-root
|
||||||
|
--fixed-cidr
|
||||||
|
--fixed-cidr-v6
|
||||||
|
--graph -g
|
||||||
|
--group -G
|
||||||
|
--insecure-registry
|
||||||
|
--ip
|
||||||
|
--label
|
||||||
|
--log-driver
|
||||||
|
--log-opt
|
||||||
|
--mtu
|
||||||
|
--pidfile -p
|
||||||
|
--registry-mirror
|
||||||
|
--storage-driver -s
|
||||||
|
--storage-opt
|
||||||
|
"
|
||||||
|
|
||||||
|
case "$prev" in
|
||||||
|
--exec-root|--graph|-g)
|
||||||
|
_filedir -d
|
||||||
|
return
|
||||||
|
;;
|
||||||
|
--log-driver)
|
||||||
|
__docker_log_drivers
|
||||||
|
return
|
||||||
|
;;
|
||||||
|
--pidfile|-p|--tlscacert|--tlscert|--tlskey)
|
||||||
|
_filedir
|
||||||
|
return
|
||||||
|
;;
|
||||||
|
--storage-driver|-s)
|
||||||
|
COMPREPLY=( $( compgen -W "aufs devicemapper btrfs overlay" -- "$(echo $cur | tr '[:upper:]' '[:lower:]')" ) )
|
||||||
|
return
|
||||||
|
;;
|
||||||
|
--log-level|-l)
|
||||||
|
__docker_log_levels
|
||||||
|
return
|
||||||
|
;;
|
||||||
|
--log-opt)
|
||||||
|
__docker_log_driver_options
|
||||||
|
return
|
||||||
|
;;
|
||||||
|
$(__docker_to_extglob "$options_with_args") )
|
||||||
|
return
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
case "$cur" in
|
||||||
|
-*)
|
||||||
|
COMPREPLY=( $( compgen -W "$boolean_options $options_with_args" -- "$cur" ) )
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
_docker_diff() {
|
_docker_diff() {
|
||||||
case "$cur" in
|
case "$cur" in
|
||||||
-*)
|
-*)
|
||||||
@@ -685,8 +742,17 @@ _docker_inspect() {
|
|||||||
COMPREPLY=( $( compgen -W "--format -f --type --help" -- "$cur" ) )
|
COMPREPLY=( $( compgen -W "--format -f --type --help" -- "$cur" ) )
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
__docker_containers_and_images
|
case $(__docker_value_of_option --type) in
|
||||||
;;
|
'')
|
||||||
|
__docker_containers_and_images
|
||||||
|
;;
|
||||||
|
container)
|
||||||
|
__docker_containers_all
|
||||||
|
;;
|
||||||
|
image)
|
||||||
|
__docker_image_repos_and_tags_and_ids
|
||||||
|
;;
|
||||||
|
esac
|
||||||
esac
|
esac
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1287,6 +1353,7 @@ _docker() {
|
|||||||
commit
|
commit
|
||||||
cp
|
cp
|
||||||
create
|
create
|
||||||
|
daemon
|
||||||
diff
|
diff
|
||||||
events
|
events
|
||||||
exec
|
exec
|
||||||
@@ -1323,41 +1390,23 @@ _docker() {
|
|||||||
wait
|
wait
|
||||||
)
|
)
|
||||||
|
|
||||||
local main_options_with_args="
|
# These options are valid as global options for all client commands
|
||||||
--api-cors-header
|
# and valid as command options for `docker daemon`
|
||||||
--bip
|
local global_boolean_options="
|
||||||
--bridge -b
|
--debug -D
|
||||||
--default-gateway
|
--tls
|
||||||
--default-gateway-v6
|
--tlsverify
|
||||||
--default-ulimit
|
"
|
||||||
--dns
|
local global_options_with_args="
|
||||||
--dns-search
|
--config
|
||||||
--exec-driver -e
|
|
||||||
--exec-opt
|
|
||||||
--exec-root
|
|
||||||
--fixed-cidr
|
|
||||||
--fixed-cidr-v6
|
|
||||||
--graph -g
|
|
||||||
--group -G
|
|
||||||
--host -H
|
--host -H
|
||||||
--insecure-registry
|
|
||||||
--ip
|
|
||||||
--label
|
|
||||||
--log-driver
|
|
||||||
--log-level -l
|
--log-level -l
|
||||||
--log-opt
|
|
||||||
--mtu
|
|
||||||
--pidfile -p
|
|
||||||
--registry-mirror
|
|
||||||
--storage-driver -s
|
|
||||||
--storage-opt
|
|
||||||
--tlscacert
|
--tlscacert
|
||||||
--tlscert
|
--tlscert
|
||||||
--tlskey
|
--tlskey
|
||||||
"
|
"
|
||||||
|
|
||||||
local main_options_with_args_glob=$(__docker_to_extglob "$main_options_with_args")
|
local host config
|
||||||
local host
|
|
||||||
|
|
||||||
COMPREPLY=()
|
COMPREPLY=()
|
||||||
local cur prev words cword
|
local cur prev words cword
|
||||||
@@ -1372,7 +1421,12 @@ _docker() {
|
|||||||
(( counter++ ))
|
(( counter++ ))
|
||||||
host="${words[$counter]}"
|
host="${words[$counter]}"
|
||||||
;;
|
;;
|
||||||
$main_options_with_args_glob )
|
# save config so that completion can use custom configuration directories
|
||||||
|
--config)
|
||||||
|
(( counter++ ))
|
||||||
|
config="${words[$counter]}"
|
||||||
|
;;
|
||||||
|
$(__docker_to_extglob "$global_options_with_args") )
|
||||||
(( counter++ ))
|
(( counter++ ))
|
||||||
;;
|
;;
|
||||||
-*)
|
-*)
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ After=network.target docker.socket
|
|||||||
Requires=docker.socket
|
Requires=docker.socket
|
||||||
|
|
||||||
[Service]
|
[Service]
|
||||||
|
Type=notify
|
||||||
ExecStart=/usr/bin/docker daemon -H fd://
|
ExecStart=/usr/bin/docker daemon -H fd://
|
||||||
MountFlags=slave
|
MountFlags=slave
|
||||||
LimitNOFILE=1048576
|
LimitNOFILE=1048576
|
||||||
|
|||||||
@@ -70,6 +70,66 @@ func (daemon *Daemon) ContainerExtractToDir(name, path string, noOverwriteDirNon
|
|||||||
return container.ExtractToDir(path, noOverwriteDirNonDir, content)
|
return container.ExtractToDir(path, noOverwriteDirNonDir, content)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// resolvePath resolves the given path in the container to a resource on the
|
||||||
|
// host. Returns a resolved path (absolute path to the resource on the host),
|
||||||
|
// the absolute path to the resource relative to the container's rootfs, and
|
||||||
|
// a error if the path points to outside the container's rootfs.
|
||||||
|
func (container *Container) resolvePath(path string) (resolvedPath, absPath string, err error) {
|
||||||
|
// Consider the given path as an absolute path in the container.
|
||||||
|
absPath = archive.PreserveTrailingDotOrSeparator(filepath.Join(string(filepath.Separator), path), path)
|
||||||
|
|
||||||
|
// Split the absPath into its Directory and Base components. We will
|
||||||
|
// resolve the dir in the scope of the container then append the base.
|
||||||
|
dirPath, basePath := filepath.Split(absPath)
|
||||||
|
|
||||||
|
resolvedDirPath, err := container.GetResourcePath(dirPath)
|
||||||
|
if err != nil {
|
||||||
|
return "", "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
// resolvedDirPath will have been cleaned (no trailing path separators) so
|
||||||
|
// we can manually join it with the base path element.
|
||||||
|
resolvedPath = resolvedDirPath + string(filepath.Separator) + basePath
|
||||||
|
|
||||||
|
return resolvedPath, absPath, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// statPath is the unexported version of StatPath. Locks and mounts should
|
||||||
|
// be aquired before calling this method and the given path should be fully
|
||||||
|
// resolved to a path on the host corresponding to the given absolute path
|
||||||
|
// inside the container.
|
||||||
|
func (container *Container) statPath(resolvedPath, absPath string) (stat *types.ContainerPathStat, err error) {
|
||||||
|
lstat, err := os.Lstat(resolvedPath)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var linkTarget string
|
||||||
|
if lstat.Mode()&os.ModeSymlink != 0 {
|
||||||
|
// Fully evaluate the symlink in the scope of the container rootfs.
|
||||||
|
hostPath, err := container.GetResourcePath(absPath)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
linkTarget, err = filepath.Rel(container.basefs, hostPath)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make it an absolute path.
|
||||||
|
linkTarget = filepath.Join(string(filepath.Separator), linkTarget)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &types.ContainerPathStat{
|
||||||
|
Name: filepath.Base(absPath),
|
||||||
|
Size: lstat.Size(),
|
||||||
|
Mode: lstat.Mode(),
|
||||||
|
Mtime: lstat.ModTime(),
|
||||||
|
LinkTarget: linkTarget,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
// StatPath stats the filesystem resource at the specified path in this
|
// StatPath stats the filesystem resource at the specified path in this
|
||||||
// container. Returns stat info about the resource.
|
// container. Returns stat info about the resource.
|
||||||
func (container *Container) StatPath(path string) (stat *types.ContainerPathStat, err error) {
|
func (container *Container) StatPath(path string) (stat *types.ContainerPathStat, err error) {
|
||||||
@@ -87,39 +147,12 @@ func (container *Container) StatPath(path string) (stat *types.ContainerPathStat
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Consider the given path as an absolute path in the container.
|
resolvedPath, absPath, err := container.resolvePath(path)
|
||||||
absPath := path
|
|
||||||
if !filepath.IsAbs(absPath) {
|
|
||||||
absPath = archive.PreserveTrailingDotOrSeparator(filepath.Join("/", path), path)
|
|
||||||
}
|
|
||||||
|
|
||||||
resolvedPath, err := container.GetResourcePath(absPath)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// A trailing "." or separator has important meaning. For example, if
|
return container.statPath(resolvedPath, absPath)
|
||||||
// `"foo"` is a symlink to some directory `"dir"`, then `os.Lstat("foo")`
|
|
||||||
// will stat the link itself, while `os.Lstat("foo/")` will stat the link
|
|
||||||
// target. If the basename of the path is ".", it means to archive the
|
|
||||||
// contents of the directory with "." as the first path component rather
|
|
||||||
// than the name of the directory. This would cause extraction of the
|
|
||||||
// archive to *not* make another directory, but instead use the current
|
|
||||||
// directory.
|
|
||||||
resolvedPath = archive.PreserveTrailingDotOrSeparator(resolvedPath, absPath)
|
|
||||||
|
|
||||||
lstat, err := os.Lstat(resolvedPath)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return &types.ContainerPathStat{
|
|
||||||
Name: lstat.Name(),
|
|
||||||
Path: absPath,
|
|
||||||
Size: lstat.Size(),
|
|
||||||
Mode: lstat.Mode(),
|
|
||||||
Mtime: lstat.ModTime(),
|
|
||||||
}, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ArchivePath creates an archive of the filesystem resource at the specified
|
// ArchivePath creates an archive of the filesystem resource at the specified
|
||||||
@@ -154,41 +187,25 @@ func (container *Container) ArchivePath(path string) (content io.ReadCloser, sta
|
|||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Consider the given path as an absolute path in the container.
|
resolvedPath, absPath, err := container.resolvePath(path)
|
||||||
absPath := path
|
|
||||||
if !filepath.IsAbs(absPath) {
|
|
||||||
absPath = archive.PreserveTrailingDotOrSeparator(filepath.Join("/", path), path)
|
|
||||||
}
|
|
||||||
|
|
||||||
resolvedPath, err := container.GetResourcePath(absPath)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// A trailing "." or separator has important meaning. For example, if
|
stat, err = container.statPath(resolvedPath, absPath)
|
||||||
// `"foo"` is a symlink to some directory `"dir"`, then `os.Lstat("foo")`
|
|
||||||
// will stat the link itself, while `os.Lstat("foo/")` will stat the link
|
|
||||||
// target. If the basename of the path is ".", it means to archive the
|
|
||||||
// contents of the directory with "." as the first path component rather
|
|
||||||
// than the name of the directory. This would cause extraction of the
|
|
||||||
// archive to *not* make another directory, but instead use the current
|
|
||||||
// directory.
|
|
||||||
resolvedPath = archive.PreserveTrailingDotOrSeparator(resolvedPath, absPath)
|
|
||||||
|
|
||||||
lstat, err := os.Lstat(resolvedPath)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
stat = &types.ContainerPathStat{
|
// We need to rebase the archive entries if the last element of the
|
||||||
Name: lstat.Name(),
|
// resolved path was a symlink that was evaluated and is now different
|
||||||
Path: absPath,
|
// than the requested path. For example, if the given path was "/foo/bar/",
|
||||||
Size: lstat.Size(),
|
// but it resolved to "/var/lib/docker/containers/{id}/foo/baz/", we want
|
||||||
Mode: lstat.Mode(),
|
// to ensure that the archive entries start with "bar" and not "baz". This
|
||||||
Mtime: lstat.ModTime(),
|
// also catches the case when the root directory of the container is
|
||||||
}
|
// requested: we want the archive entries to start with "/" and not the
|
||||||
|
// container ID.
|
||||||
data, err := archive.TarResource(resolvedPath)
|
data, err := archive.TarResourceRebase(resolvedPath, filepath.Base(absPath))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
@@ -227,27 +244,21 @@ func (container *Container) ExtractToDir(path string, noOverwriteDirNonDir bool,
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Consider the given path as an absolute path in the container.
|
// The destination path needs to be resolved to a host path, with all
|
||||||
absPath := path
|
// symbolic links followed in the scope of the container's rootfs. Note
|
||||||
if !filepath.IsAbs(absPath) {
|
// that we do not use `container.resolvePath(path)` here because we need
|
||||||
absPath = archive.PreserveTrailingDotOrSeparator(filepath.Join("/", path), path)
|
// to also evaluate the last path element if it is a symlink. This is so
|
||||||
}
|
// that you can extract an archive to a symlink that points to a directory.
|
||||||
|
|
||||||
|
// Consider the given path as an absolute path in the container.
|
||||||
|
absPath := archive.PreserveTrailingDotOrSeparator(filepath.Join(string(filepath.Separator), path), path)
|
||||||
|
|
||||||
|
// This will evaluate the last path element if it is a symlink.
|
||||||
resolvedPath, err := container.GetResourcePath(absPath)
|
resolvedPath, err := container.GetResourcePath(absPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// A trailing "." or separator has important meaning. For example, if
|
|
||||||
// `"foo"` is a symlink to some directory `"dir"`, then `os.Lstat("foo")`
|
|
||||||
// will stat the link itself, while `os.Lstat("foo/")` will stat the link
|
|
||||||
// target. If the basename of the path is ".", it means to archive the
|
|
||||||
// contents of the directory with "." as the first path component rather
|
|
||||||
// than the name of the directory. This would cause extraction of the
|
|
||||||
// archive to *not* make another directory, but instead use the current
|
|
||||||
// directory.
|
|
||||||
resolvedPath = archive.PreserveTrailingDotOrSeparator(resolvedPath, absPath)
|
|
||||||
|
|
||||||
stat, err := os.Lstat(resolvedPath)
|
stat, err := os.Lstat(resolvedPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -257,23 +268,23 @@ func (container *Container) ExtractToDir(path string, noOverwriteDirNonDir bool,
|
|||||||
return ErrExtractPointNotDirectory
|
return ErrExtractPointNotDirectory
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Need to check if the path is in a volume. If it is, it cannot be in a
|
||||||
|
// read-only volume. If it is not in a volume, the container cannot be
|
||||||
|
// configured with a read-only rootfs.
|
||||||
|
|
||||||
|
// Use the resolved path relative to the container rootfs as the new
|
||||||
|
// absPath. This way we fully follow any symlinks in a volume that may
|
||||||
|
// lead back outside the volume.
|
||||||
baseRel, err := filepath.Rel(container.basefs, resolvedPath)
|
baseRel, err := filepath.Rel(container.basefs, resolvedPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
absPath = filepath.Join("/", baseRel)
|
// Make it an absolute path.
|
||||||
|
absPath = filepath.Join(string(filepath.Separator), baseRel)
|
||||||
|
|
||||||
// Need to check if the path is in a volume. If it is, it cannot be in a
|
toVolume, err := checkIfPathIsInAVolume(container, absPath)
|
||||||
// read-only volume. If it is not in a volume, the container cannot be
|
if err != nil {
|
||||||
// configured with a read-only rootfs.
|
return err
|
||||||
var toVolume bool
|
|
||||||
for _, mnt := range container.MountPoints {
|
|
||||||
if toVolume = mnt.hasResource(absPath); toVolume {
|
|
||||||
if mnt.RW {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
return ErrVolumeReadonly
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if !toVolume && container.hostConfig.ReadonlyRootfs {
|
if !toVolume && container.hostConfig.ReadonlyRootfs {
|
||||||
@@ -295,3 +306,19 @@ func (container *Container) ExtractToDir(path string, noOverwriteDirNonDir bool,
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// checkIfPathIsInAVolume checks if the path is in a volume. If it is, it
|
||||||
|
// cannot be in a read-only volume. If it is not in a volume, the container
|
||||||
|
// cannot be configured with a read-only rootfs.
|
||||||
|
func checkIfPathIsInAVolume(container *Container, absPath string) (bool, error) {
|
||||||
|
var toVolume bool
|
||||||
|
for _, mnt := range container.MountPoints {
|
||||||
|
if toVolume = mnt.hasResource(absPath); toVolume {
|
||||||
|
if mnt.RW {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
return false, ErrVolumeReadonly
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return toVolume, nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -41,6 +41,14 @@ var (
|
|||||||
ErrContainerRootfsReadonly = errors.New("container rootfs is marked read-only")
|
ErrContainerRootfsReadonly = errors.New("container rootfs is marked read-only")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type ErrContainerNotRunning struct {
|
||||||
|
id string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e ErrContainerNotRunning) Error() string {
|
||||||
|
return fmt.Sprintf("Container %s is not running", e.id)
|
||||||
|
}
|
||||||
|
|
||||||
type StreamConfig struct {
|
type StreamConfig struct {
|
||||||
stdout *broadcastwriter.BroadcastWriter
|
stdout *broadcastwriter.BroadcastWriter
|
||||||
stderr *broadcastwriter.BroadcastWriter
|
stderr *broadcastwriter.BroadcastWriter
|
||||||
@@ -371,7 +379,7 @@ func (container *Container) KillSig(sig int) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !container.Running {
|
if !container.Running {
|
||||||
return fmt.Errorf("Container %s is not running", container.ID)
|
return ErrContainerNotRunning{container.ID}
|
||||||
}
|
}
|
||||||
|
|
||||||
// signal to the monitor that it should not restart the container
|
// signal to the monitor that it should not restart the container
|
||||||
@@ -408,7 +416,7 @@ func (container *Container) Pause() error {
|
|||||||
|
|
||||||
// We cannot Pause the container which is not running
|
// We cannot Pause the container which is not running
|
||||||
if !container.Running {
|
if !container.Running {
|
||||||
return fmt.Errorf("Container %s is not running, cannot pause a non-running container", container.ID)
|
return ErrContainerNotRunning{container.ID}
|
||||||
}
|
}
|
||||||
|
|
||||||
// We cannot Pause the container which is already paused
|
// We cannot Pause the container which is already paused
|
||||||
@@ -430,7 +438,7 @@ func (container *Container) Unpause() error {
|
|||||||
|
|
||||||
// We cannot unpause the container which is not running
|
// We cannot unpause the container which is not running
|
||||||
if !container.Running {
|
if !container.Running {
|
||||||
return fmt.Errorf("Container %s is not running, cannot unpause a non-running container", container.ID)
|
return ErrContainerNotRunning{container.ID}
|
||||||
}
|
}
|
||||||
|
|
||||||
// We cannot unpause the container which is not paused
|
// We cannot unpause the container which is not paused
|
||||||
@@ -448,7 +456,7 @@ func (container *Container) Unpause() error {
|
|||||||
|
|
||||||
func (container *Container) Kill() error {
|
func (container *Container) Kill() error {
|
||||||
if !container.IsRunning() {
|
if !container.IsRunning() {
|
||||||
return fmt.Errorf("Container %s is not running", container.ID)
|
return ErrContainerNotRunning{container.ID}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 1. Send SIGKILL
|
// 1. Send SIGKILL
|
||||||
@@ -530,7 +538,7 @@ func (container *Container) Restart(seconds int) error {
|
|||||||
|
|
||||||
func (container *Container) Resize(h, w int) error {
|
func (container *Container) Resize(h, w int) error {
|
||||||
if !container.IsRunning() {
|
if !container.IsRunning() {
|
||||||
return fmt.Errorf("Cannot resize container %s, container is not running", container.ID)
|
return ErrContainerNotRunning{container.ID}
|
||||||
}
|
}
|
||||||
if err := container.command.ProcessConfig.Terminal.Resize(h, w); err != nil {
|
if err := container.command.ProcessConfig.Terminal.Resize(h, w); err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -1080,8 +1088,12 @@ func copyEscapable(dst io.Writer, src io.ReadCloser) (written int64, err error)
|
|||||||
|
|
||||||
func (container *Container) networkMounts() []execdriver.Mount {
|
func (container *Container) networkMounts() []execdriver.Mount {
|
||||||
var mounts []execdriver.Mount
|
var mounts []execdriver.Mount
|
||||||
|
mode := "Z"
|
||||||
|
if container.hostConfig.NetworkMode.IsContainer() {
|
||||||
|
mode = "z"
|
||||||
|
}
|
||||||
if container.ResolvConfPath != "" {
|
if container.ResolvConfPath != "" {
|
||||||
label.SetFileLabel(container.ResolvConfPath, container.MountLabel)
|
label.Relabel(container.ResolvConfPath, container.MountLabel, mode)
|
||||||
mounts = append(mounts, execdriver.Mount{
|
mounts = append(mounts, execdriver.Mount{
|
||||||
Source: container.ResolvConfPath,
|
Source: container.ResolvConfPath,
|
||||||
Destination: "/etc/resolv.conf",
|
Destination: "/etc/resolv.conf",
|
||||||
@@ -1090,7 +1102,7 @@ func (container *Container) networkMounts() []execdriver.Mount {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
if container.HostnamePath != "" {
|
if container.HostnamePath != "" {
|
||||||
label.SetFileLabel(container.HostnamePath, container.MountLabel)
|
label.Relabel(container.HostnamePath, container.MountLabel, mode)
|
||||||
mounts = append(mounts, execdriver.Mount{
|
mounts = append(mounts, execdriver.Mount{
|
||||||
Source: container.HostnamePath,
|
Source: container.HostnamePath,
|
||||||
Destination: "/etc/hostname",
|
Destination: "/etc/hostname",
|
||||||
@@ -1099,7 +1111,7 @@ func (container *Container) networkMounts() []execdriver.Mount {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
if container.HostsPath != "" {
|
if container.HostsPath != "" {
|
||||||
label.SetFileLabel(container.HostsPath, container.MountLabel)
|
label.Relabel(container.HostsPath, container.MountLabel, mode)
|
||||||
mounts = append(mounts, execdriver.Mount{
|
mounts = append(mounts, execdriver.Mount{
|
||||||
Source: container.HostsPath,
|
Source: container.HostsPath,
|
||||||
Destination: "/etc/hosts",
|
Destination: "/etc/hosts",
|
||||||
|
|||||||
@@ -272,7 +272,11 @@ func populateCommand(c *Container, env []string) error {
|
|||||||
BlkioWeight: c.hostConfig.BlkioWeight,
|
BlkioWeight: c.hostConfig.BlkioWeight,
|
||||||
Rlimits: rlimits,
|
Rlimits: rlimits,
|
||||||
OomKillDisable: c.hostConfig.OomKillDisable,
|
OomKillDisable: c.hostConfig.OomKillDisable,
|
||||||
MemorySwappiness: c.hostConfig.MemorySwappiness,
|
MemorySwappiness: -1,
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.hostConfig.MemorySwappiness != nil {
|
||||||
|
resources.MemorySwappiness = *c.hostConfig.MemorySwappiness
|
||||||
}
|
}
|
||||||
|
|
||||||
processConfig := execdriver.ProcessConfig{
|
processConfig := execdriver.ProcessConfig{
|
||||||
|
|||||||
@@ -66,9 +66,6 @@ func (daemon *Daemon) Create(config *runconfig.Config, hostConfig *runconfig.Hos
|
|||||||
if err := daemon.mergeAndVerifyConfig(config, img); err != nil {
|
if err := daemon.mergeAndVerifyConfig(config, img); err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
if !config.NetworkDisabled && daemon.SystemConfig().IPv4ForwardingDisabled {
|
|
||||||
warnings = append(warnings, "IPv4 forwarding is disabled.")
|
|
||||||
}
|
|
||||||
if hostConfig == nil {
|
if hostConfig == nil {
|
||||||
hostConfig = &runconfig.HostConfig{}
|
hostConfig = &runconfig.HostConfig{}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -167,13 +167,16 @@ func (daemon *Daemon) verifyContainerSettings(hostConfig *runconfig.HostConfig,
|
|||||||
if hostConfig.Memory == 0 && hostConfig.MemorySwap > 0 {
|
if hostConfig.Memory == 0 && hostConfig.MemorySwap > 0 {
|
||||||
return warnings, fmt.Errorf("You should always set the Memory limit when using Memoryswap limit, see usage.")
|
return warnings, fmt.Errorf("You should always set the Memory limit when using Memoryswap limit, see usage.")
|
||||||
}
|
}
|
||||||
if hostConfig.MemorySwappiness != -1 && !daemon.SystemConfig().MemorySwappiness {
|
if hostConfig.MemorySwappiness != nil && !daemon.SystemConfig().MemorySwappiness {
|
||||||
warnings = append(warnings, "Your kernel does not support memory swappiness capabilities, memory swappiness discarded.")
|
warnings = append(warnings, "Your kernel does not support memory swappiness capabilities, memory swappiness discarded.")
|
||||||
logrus.Warnf("Your kernel does not support memory swappiness capabilities, memory swappiness discarded.")
|
logrus.Warnf("Your kernel does not support memory swappiness capabilities, memory swappiness discarded.")
|
||||||
hostConfig.MemorySwappiness = -1
|
hostConfig.MemorySwappiness = nil
|
||||||
}
|
}
|
||||||
if hostConfig.MemorySwappiness != -1 && (hostConfig.MemorySwappiness < 0 || hostConfig.MemorySwappiness > 100) {
|
if hostConfig.MemorySwappiness != nil {
|
||||||
return warnings, fmt.Errorf("Invalid value: %d, valid memory swappiness range is 0-100.", hostConfig.MemorySwappiness)
|
swappiness := *hostConfig.MemorySwappiness
|
||||||
|
if swappiness < -1 || swappiness > 100 {
|
||||||
|
return warnings, fmt.Errorf("Invalid value: %v, valid memory swappiness range is 0-100.", swappiness)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if hostConfig.CpuPeriod > 0 && !daemon.SystemConfig().CpuCfsPeriod {
|
if hostConfig.CpuPeriod > 0 && !daemon.SystemConfig().CpuCfsPeriod {
|
||||||
warnings = append(warnings, "Your kernel does not support CPU cfs period. Period discarded.")
|
warnings = append(warnings, "Your kernel does not support CPU cfs period. Period discarded.")
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"path"
|
"path"
|
||||||
|
|
||||||
|
"github.com/Sirupsen/logrus"
|
||||||
"github.com/docker/docker/daemon/execdriver"
|
"github.com/docker/docker/daemon/execdriver"
|
||||||
"github.com/docker/docker/daemon/execdriver/lxc"
|
"github.com/docker/docker/daemon/execdriver/lxc"
|
||||||
"github.com/docker/docker/daemon/execdriver/native"
|
"github.com/docker/docker/daemon/execdriver/native"
|
||||||
@@ -18,6 +19,7 @@ func NewDriver(name string, options []string, root, libPath, initPath string, sy
|
|||||||
// we want to give the lxc driver the full docker root because it needs
|
// we want to give the lxc driver the full docker root because it needs
|
||||||
// to access and write config and template files in /var/lib/docker/containers/*
|
// to access and write config and template files in /var/lib/docker/containers/*
|
||||||
// to be backwards compatible
|
// to be backwards compatible
|
||||||
|
logrus.Warn("LXC built-in support is deprecated.")
|
||||||
return lxc.NewDriver(root, libPath, initPath, sysInfo.AppArmor)
|
return lxc.NewDriver(root, libPath, initPath, sysInfo.AppArmor)
|
||||||
case "native":
|
case "native":
|
||||||
return native.NewDriver(path.Join(root, "execdriver", "native"), initPath, options)
|
return native.NewDriver(path.Join(root, "execdriver", "native"), initPath, options)
|
||||||
|
|||||||
@@ -0,0 +1,145 @@
|
|||||||
|
// +build linux
|
||||||
|
|
||||||
|
package native
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"path"
|
||||||
|
"strings"
|
||||||
|
"text/template"
|
||||||
|
|
||||||
|
"github.com/opencontainers/runc/libcontainer/apparmor"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
apparmorProfilePath = "/etc/apparmor.d/docker"
|
||||||
|
)
|
||||||
|
|
||||||
|
type data struct {
|
||||||
|
Name string
|
||||||
|
Imports []string
|
||||||
|
InnerImports []string
|
||||||
|
}
|
||||||
|
|
||||||
|
const baseTemplate = `
|
||||||
|
{{range $value := .Imports}}
|
||||||
|
{{$value}}
|
||||||
|
{{end}}
|
||||||
|
|
||||||
|
profile {{.Name}} flags=(attach_disconnected,mediate_deleted) {
|
||||||
|
{{range $value := .InnerImports}}
|
||||||
|
{{$value}}
|
||||||
|
{{end}}
|
||||||
|
|
||||||
|
network,
|
||||||
|
capability,
|
||||||
|
file,
|
||||||
|
umount,
|
||||||
|
|
||||||
|
deny @{PROC}/sys/fs/** wklx,
|
||||||
|
deny @{PROC}/fs/** wklx,
|
||||||
|
deny @{PROC}/sysrq-trigger rwklx,
|
||||||
|
deny @{PROC}/mem rwklx,
|
||||||
|
deny @{PROC}/kmem rwklx,
|
||||||
|
deny @{PROC}/kcore rwklx,
|
||||||
|
deny @{PROC}/sys/kernel/[^s][^h][^m]* wklx,
|
||||||
|
deny @{PROC}/sys/kernel/*/** wklx,
|
||||||
|
|
||||||
|
deny mount,
|
||||||
|
|
||||||
|
deny /sys/[^f]*/** wklx,
|
||||||
|
deny /sys/f[^s]*/** wklx,
|
||||||
|
deny /sys/fs/[^c]*/** wklx,
|
||||||
|
deny /sys/fs/c[^g]*/** wklx,
|
||||||
|
deny /sys/fs/cg[^r]*/** wklx,
|
||||||
|
deny /sys/firmware/efi/efivars/** rwklx,
|
||||||
|
deny /sys/kernel/security/** rwklx,
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
func generateProfile(out io.Writer) error {
|
||||||
|
compiled, err := template.New("apparmor_profile").Parse(baseTemplate)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
data := &data{
|
||||||
|
Name: "docker-default",
|
||||||
|
}
|
||||||
|
if tunablesExists() {
|
||||||
|
data.Imports = append(data.Imports, "#include <tunables/global>")
|
||||||
|
} else {
|
||||||
|
data.Imports = append(data.Imports, "@{PROC}=/proc/")
|
||||||
|
}
|
||||||
|
if abstractionsExists() {
|
||||||
|
data.InnerImports = append(data.InnerImports, "#include <abstractions/base>")
|
||||||
|
}
|
||||||
|
if err := compiled.Execute(out, data); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if the tunables/global exist
|
||||||
|
func tunablesExists() bool {
|
||||||
|
_, err := os.Stat("/etc/apparmor.d/tunables/global")
|
||||||
|
return err == nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if abstractions/base exist
|
||||||
|
func abstractionsExists() bool {
|
||||||
|
_, err := os.Stat("/etc/apparmor.d/abstractions/base")
|
||||||
|
return err == nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func installAppArmorProfile() error {
|
||||||
|
if !apparmor.IsEnabled() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure /etc/apparmor.d exists
|
||||||
|
if err := os.MkdirAll(path.Dir(apparmorProfilePath), 0755); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
f, err := os.OpenFile(apparmorProfilePath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := generateProfile(f); err != nil {
|
||||||
|
f.Close()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
f.Close()
|
||||||
|
|
||||||
|
cmd := exec.Command("/sbin/apparmor_parser", "-r", "-W", "docker")
|
||||||
|
// to use the parser directly we have to make sure we are in the correct
|
||||||
|
// dir with the profile
|
||||||
|
cmd.Dir = "/etc/apparmor.d"
|
||||||
|
|
||||||
|
output, err := cmd.CombinedOutput()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Error loading docker apparmor profile: %s (%s)", err, output)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func hasAppArmorProfileLoaded(profile string) error {
|
||||||
|
file, err := os.Open("/sys/kernel/security/apparmor/profiles")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
r := bufio.NewReader(file)
|
||||||
|
for {
|
||||||
|
p, err := r.ReadString('\n')
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if strings.HasPrefix(p, profile+" ") {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -85,7 +85,7 @@ func (d *driver) createContainer(c *execdriver.Command) (*configs.Config, error)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* These paths must be remounted as r/o */
|
/* These paths must be remounted as r/o */
|
||||||
container.ReadonlyPaths = append(container.ReadonlyPaths, "/proc", "/dev")
|
container.ReadonlyPaths = append(container.ReadonlyPaths, "/dev")
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := d.setupMounts(container, c); err != nil {
|
if err := d.setupMounts(container, c); err != nil {
|
||||||
@@ -200,7 +200,6 @@ func (d *driver) setPrivileged(container *configs.Config) (err error) {
|
|||||||
if apparmor.IsEnabled() {
|
if apparmor.IsEnabled() {
|
||||||
container.AppArmorProfile = "unconfined"
|
container.AppArmorProfile = "unconfined"
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import (
|
|||||||
sysinfo "github.com/docker/docker/pkg/system"
|
sysinfo "github.com/docker/docker/pkg/system"
|
||||||
"github.com/docker/docker/pkg/term"
|
"github.com/docker/docker/pkg/term"
|
||||||
"github.com/opencontainers/runc/libcontainer"
|
"github.com/opencontainers/runc/libcontainer"
|
||||||
|
"github.com/opencontainers/runc/libcontainer/apparmor"
|
||||||
"github.com/opencontainers/runc/libcontainer/cgroups/systemd"
|
"github.com/opencontainers/runc/libcontainer/cgroups/systemd"
|
||||||
"github.com/opencontainers/runc/libcontainer/configs"
|
"github.com/opencontainers/runc/libcontainer/configs"
|
||||||
"github.com/opencontainers/runc/libcontainer/system"
|
"github.com/opencontainers/runc/libcontainer/system"
|
||||||
@@ -51,6 +52,20 @@ func NewDriver(root, initPath string, options []string) (*driver, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if apparmor.IsEnabled() {
|
||||||
|
if err := installAppArmorProfile(); err != nil {
|
||||||
|
apparmorProfiles := []string{"docker-default"}
|
||||||
|
|
||||||
|
// Allow daemon to run if loading failed, but are active
|
||||||
|
// (possibly through another run, manually, or via system startup)
|
||||||
|
for _, policy := range apparmorProfiles {
|
||||||
|
if err := hasAppArmorProfileLoaded(policy); err != nil {
|
||||||
|
return nil, fmt.Errorf("AppArmor enabled on system but the %s profile could not be loaded.", policy)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// choose cgroup manager
|
// choose cgroup manager
|
||||||
// this makes sure there are no breaking changes to people
|
// this makes sure there are no breaking changes to people
|
||||||
// who upgrade from versions without native.cgroupdriver opt
|
// who upgrade from versions without native.cgroupdriver opt
|
||||||
|
|||||||
@@ -323,7 +323,7 @@ func (a *Driver) Diff(id, parent string) (archive.Archive, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (a *Driver) applyDiff(id string, diff archive.ArchiveReader) error {
|
func (a *Driver) applyDiff(id string, diff archive.ArchiveReader) error {
|
||||||
return chrootarchive.Untar(diff, path.Join(a.rootPath(), "diff", id), nil)
|
return chrootarchive.UntarUncompressed(diff, path.Join(a.rootPath(), "diff", id), nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DiffSize calculates the changes between the specified id
|
// DiffSize calculates the changes between the specified id
|
||||||
|
|||||||
@@ -77,6 +77,7 @@ type Driver interface {
|
|||||||
// ApplyDiff extracts the changeset from the given diff into the
|
// ApplyDiff extracts the changeset from the given diff into the
|
||||||
// layer with the specified id and parent, returning the size of the
|
// layer with the specified id and parent, returning the size of the
|
||||||
// new layer in bytes.
|
// new layer in bytes.
|
||||||
|
// The archive.ArchiveReader must be an uncompressed stream.
|
||||||
ApplyDiff(id, parent string, diff archive.ArchiveReader) (size int64, err error)
|
ApplyDiff(id, parent string, diff archive.ArchiveReader) (size int64, err error)
|
||||||
// DiffSize calculates the changes between the specified id
|
// DiffSize calculates the changes between the specified id
|
||||||
// and its parent and returns the size in bytes of the changes
|
// and its parent and returns the size in bytes of the changes
|
||||||
|
|||||||
@@ -121,7 +121,7 @@ func (gdw *naiveDiffDriver) ApplyDiff(id, parent string, diff archive.ArchiveRea
|
|||||||
|
|
||||||
start := time.Now().UTC()
|
start := time.Now().UTC()
|
||||||
logrus.Debugf("Start untar layer")
|
logrus.Debugf("Start untar layer")
|
||||||
if size, err = chrootarchive.ApplyLayer(layerFs, diff); err != nil {
|
if size, err = chrootarchive.ApplyUncompressedLayer(layerFs, diff); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
logrus.Debugf("Untar time: %vs", time.Now().UTC().Sub(start).Seconds())
|
logrus.Debugf("Untar time: %vs", time.Now().UTC().Sub(start).Seconds())
|
||||||
|
|||||||
@@ -411,7 +411,7 @@ func (d *Driver) ApplyDiff(id string, parent string, diff archive.ArchiveReader)
|
|||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if size, err = chrootarchive.ApplyLayer(tmpRootDir, diff); err != nil {
|
if size, err = chrootarchive.ApplyUncompressedLayer(tmpRootDir, diff); err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package daemon
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/docker/docker/api/types"
|
"github.com/docker/docker/api/types"
|
||||||
)
|
)
|
||||||
@@ -91,13 +92,13 @@ func (daemon *Daemon) getInspectData(container *Container) (*types.ContainerJSON
|
|||||||
Pid: container.State.Pid,
|
Pid: container.State.Pid,
|
||||||
ExitCode: container.State.ExitCode,
|
ExitCode: container.State.ExitCode,
|
||||||
Error: container.State.Error,
|
Error: container.State.Error,
|
||||||
StartedAt: container.State.StartedAt,
|
StartedAt: container.State.StartedAt.Format(time.RFC3339Nano),
|
||||||
FinishedAt: container.State.FinishedAt,
|
FinishedAt: container.State.FinishedAt.Format(time.RFC3339Nano),
|
||||||
}
|
}
|
||||||
|
|
||||||
contJSONBase := &types.ContainerJSONBase{
|
contJSONBase := &types.ContainerJSONBase{
|
||||||
Id: container.ID,
|
Id: container.ID,
|
||||||
Created: container.Created,
|
Created: container.Created.Format(time.RFC3339Nano),
|
||||||
Path: container.Path,
|
Path: container.Path,
|
||||||
Args: container.Args,
|
Args: container.Args,
|
||||||
State: containerState,
|
State: containerState,
|
||||||
|
|||||||
@@ -1,9 +1,6 @@
|
|||||||
package daemon
|
package daemon
|
||||||
|
|
||||||
import (
|
import "syscall"
|
||||||
"fmt"
|
|
||||||
"syscall"
|
|
||||||
)
|
|
||||||
|
|
||||||
// ContainerKill send signal to the container
|
// ContainerKill send signal to the container
|
||||||
// If no signal is given (sig 0), then Kill with SIGKILL and wait
|
// If no signal is given (sig 0), then Kill with SIGKILL and wait
|
||||||
@@ -18,12 +15,12 @@ func (daemon *Daemon) ContainerKill(name string, sig uint64) error {
|
|||||||
// If no signal is passed, or SIGKILL, perform regular Kill (SIGKILL + wait())
|
// If no signal is passed, or SIGKILL, perform regular Kill (SIGKILL + wait())
|
||||||
if sig == 0 || syscall.Signal(sig) == syscall.SIGKILL {
|
if sig == 0 || syscall.Signal(sig) == syscall.SIGKILL {
|
||||||
if err := container.Kill(); err != nil {
|
if err := container.Kill(); err != nil {
|
||||||
return fmt.Errorf("Cannot kill container %s: %s", name, err)
|
return err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Otherwise, just send the requested signal
|
// Otherwise, just send the requested signal
|
||||||
if err := container.KillSig(int(sig)); err != nil {
|
if err := container.KillSig(int(sig)); err != nil {
|
||||||
return fmt.Errorf("Cannot kill container %s: %s", name, err)
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@@ -93,9 +93,9 @@ func New(ctx logger.Context) (logger.Logger, error) {
|
|||||||
}
|
}
|
||||||
logrus.Debugf("logging driver fluentd configured for container:%s, host:%s, port:%d, tag:%s.", ctx.ContainerID, host, port, tag)
|
logrus.Debugf("logging driver fluentd configured for container:%s, host:%s, port:%d, tag:%s.", ctx.ContainerID, host, port, tag)
|
||||||
|
|
||||||
// logger tries to recoonect 2**64 - 1 times
|
// logger tries to recoonect 2**32 - 1 times
|
||||||
// failed (and panic) after 204 years [ 1.5 ** (2**32 - 1) - 1 seconds]
|
// failed (and panic) after 204 years [ 1.5 ** (2**32 - 1) - 1 seconds]
|
||||||
log, err := fluent.New(fluent.Config{FluentPort: port, FluentHost: host, RetryWait: 1000, MaxRetry: math.MaxUint32})
|
log, err := fluent.New(fluent.Config{FluentPort: port, FluentHost: host, RetryWait: 1000, MaxRetry: math.MaxInt32})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -259,7 +259,8 @@ func (l *JSONFileLogger) readLogs(logWatcher *logger.LogWatcher, config logger.R
|
|||||||
if !config.Follow {
|
if !config.Follow {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if config.Tail == 0 {
|
|
||||||
|
if config.Tail >= 0 {
|
||||||
latestFile.Seek(0, os.SEEK_END)
|
latestFile.Seek(0, os.SEEK_END)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -64,7 +64,12 @@ func NewLogWatcher() *LogWatcher {
|
|||||||
|
|
||||||
// Close notifies the underlying log reader to stop
|
// Close notifies the underlying log reader to stop
|
||||||
func (w *LogWatcher) Close() {
|
func (w *LogWatcher) Close() {
|
||||||
close(w.closeNotifier)
|
// only close if not already closed
|
||||||
|
select {
|
||||||
|
case <-w.closeNotifier:
|
||||||
|
default:
|
||||||
|
close(w.closeNotifier)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// WatchClose returns a channel receiver that receives notification when the watcher has been closed
|
// WatchClose returns a channel receiver that receives notification when the watcher has been closed
|
||||||
|
|||||||
@@ -100,6 +100,7 @@ func migrateKey() (err error) {
|
|||||||
err = os.Remove(oldPath)
|
err = os.Remove(oldPath)
|
||||||
} else {
|
} else {
|
||||||
logrus.Warnf("Key migration failed, key file not removed at %s", oldPath)
|
logrus.Warnf("Key migration failed, key file not removed at %s", oldPath)
|
||||||
|
os.Remove(newPath)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
@@ -226,7 +227,7 @@ func (cli *DaemonCli) CmdDaemon(args ...string) error {
|
|||||||
}
|
}
|
||||||
tlsConfig, err := tlsconfig.Server(*commonFlags.TLSOptions)
|
tlsConfig, err := tlsconfig.Server(*commonFlags.TLSOptions)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.Fatalf("foobar: %v", err)
|
logrus.Fatal(err)
|
||||||
}
|
}
|
||||||
serverConfig.TLSConfig = tlsConfig
|
serverConfig.TLSConfig = tlsConfig
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,8 +6,24 @@ COPY . /src
|
|||||||
|
|
||||||
COPY . /docs/content/
|
COPY . /docs/content/
|
||||||
|
|
||||||
WORKDIR /docs/content
|
RUN svn checkout https://github.com/docker/compose/trunk/docs /docs/content/compose
|
||||||
|
RUN svn checkout https://github.com/docker/swarm/trunk/docs /docs/content/swarm
|
||||||
|
RUN svn checkout https://github.com/docker/machine/trunk/docs /docs/content/machine
|
||||||
|
RUN svn checkout https://github.com/docker/distribution/trunk/docs /docs/content/registry
|
||||||
|
RUN svn checkout https://github.com/kitematic/kitematic/trunk/docs /docs/content/kitematic
|
||||||
|
RUN svn checkout https://github.com/docker/tutorials/trunk/docs /docs/content/
|
||||||
|
RUN svn checkout https://github.com/docker/opensource/trunk/docs /docs/content/opensource
|
||||||
|
|
||||||
RUN /docs/content/touch-up.sh
|
|
||||||
|
|
||||||
WORKDIR /docs
|
|
||||||
|
|
||||||
|
# Sed to process GitHub Markdown
|
||||||
|
# 1-2 Remove comment code from metadata block
|
||||||
|
# 3 Change ](/word to ](/project/ in links
|
||||||
|
# 4 Change ](word.md) to ](/project/word)
|
||||||
|
# 5 Remove .md extension from link text
|
||||||
|
# 6 Change ](../ to ](/project/word)
|
||||||
|
# 7 Change ](../../ to ](/project/ --> not implemented
|
||||||
|
#
|
||||||
|
#
|
||||||
|
RUN /src/pre-process.sh /docs
|
||||||
@@ -87,8 +87,8 @@ own.
|
|||||||
container with this image.
|
container with this image.
|
||||||
|
|
||||||
The container exposes port 8000 on the localhost so that you can connect and
|
The container exposes port 8000 on the localhost so that you can connect and
|
||||||
see your changes. If you are running Boot2Docker, use the `boot2docker ip`
|
see your changes. If you use Docker Machine, the `docker-machine ip
|
||||||
to get the address of your server.
|
<machine-name>` command gives you the address of your server.
|
||||||
|
|
||||||
6. Check your writing for style and mechanical errors.
|
6. Check your writing for style and mechanical errors.
|
||||||
|
|
||||||
@@ -158,18 +158,20 @@ update the root docs pages by running
|
|||||||
|
|
||||||
$ make AWS_S3_BUCKET=dowideit-docs BUILD_ROOT=yes docs-release
|
$ make AWS_S3_BUCKET=dowideit-docs BUILD_ROOT=yes docs-release
|
||||||
|
|
||||||
### Errors publishing using Boot2Docker
|
### Errors publishing using a Docker Machine VM
|
||||||
|
|
||||||
Sometimes, in a Boot2Docker environment, the publishing procedure returns this
|
Sometimes, in a Windows or Mac environment, the publishing procedure returns this
|
||||||
error:
|
error:
|
||||||
|
|
||||||
Post http:///var/run/docker.sock/build?rm=1&t=docker-docs%3Apost-1.2.0-docs_update-2:
|
Post http:///var/run/docker.sock/build?rm=1&t=docker-docs%3Apost-1.2.0-docs_update-2:
|
||||||
dial unix /var/run/docker.sock: no such file or directory.
|
dial unix /var/run/docker.sock: no such file or directory.
|
||||||
|
|
||||||
If this happens, set the Docker host. Run the following command to set the
|
If this happens, set the Docker host. Run the following command to get the
|
||||||
variables in your shell:
|
variables in your shell:
|
||||||
|
|
||||||
$ eval "$(boot2docker shellinit)"
|
docker-machine env <machine-name>
|
||||||
|
|
||||||
|
Then, set your environment accordingly.
|
||||||
|
|
||||||
## Cherry-picking documentation changes to update an existing release.
|
## Cherry-picking documentation changes to update an existing release.
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ parent = "smn_images"
|
|||||||
# Create a base image
|
# Create a base image
|
||||||
|
|
||||||
So you want to create your own [*Base Image*](
|
So you want to create your own [*Base Image*](
|
||||||
/terms/image/#base-image)? Great!
|
/reference/glossary/#base-image)? Great!
|
||||||
|
|
||||||
The specific process will depend heavily on the Linux distribution you
|
The specific process will depend heavily on the Linux distribution you
|
||||||
want to package. We have some examples below, and you are encouraged to
|
want to package. We have some examples below, and you are encouraged to
|
||||||
|
|||||||
@@ -47,10 +47,6 @@ image cache.
|
|||||||
> characters of the full image ID - which can be found using
|
> characters of the full image ID - which can be found using
|
||||||
> `docker inspect` or `docker images --no-trunc=true`.
|
> `docker inspect` or `docker images --no-trunc=true`.
|
||||||
|
|
||||||
> **Note:** if you are using a remote Docker daemon, such as Boot2Docker,
|
|
||||||
> then _do not_ type the `sudo` before the `docker` commands shown in the
|
|
||||||
> documentation's examples.
|
|
||||||
|
|
||||||
## Running an interactive shell
|
## Running an interactive shell
|
||||||
|
|
||||||
To run an interactive shell in the Ubuntu image:
|
To run an interactive shell in the Ubuntu image:
|
||||||
|
|||||||
@@ -11,111 +11,7 @@ weight = 7
|
|||||||
|
|
||||||
# Using certificates for repository client verification
|
# Using certificates for repository client verification
|
||||||
|
|
||||||
In [Running Docker with HTTPS](/articles/https), you learned that, by default,
|
The orginal content was deprecated. For information about configuring
|
||||||
Docker runs via a non-networked Unix socket and TLS must be enabled in order
|
cerficates, see [deploying a registry
|
||||||
to have the Docker client and the daemon communicate securely over HTTPS.
|
server](http://docs.docker.com/registry/deploying/). To reach an older version
|
||||||
|
of this content, refer to an older version of the documentation.
|
||||||
Now, you will see how to allow the Docker registry (i.e., *a server*) to
|
|
||||||
verify that the Docker daemon (i.e., *a client*) has the right to access the
|
|
||||||
images being hosted with *certificate-based client-server authentication*.
|
|
||||||
|
|
||||||
We will show you how to install a Certificate Authority (CA) root certificate
|
|
||||||
for the registry and how to set the client TLS certificate for verification.
|
|
||||||
|
|
||||||
## Understanding the configuration
|
|
||||||
|
|
||||||
A custom certificate is configured by creating a directory under
|
|
||||||
`/etc/docker/certs.d` using the same name as the registry's hostname (e.g.,
|
|
||||||
`localhost`). All `*.crt` files are added to this directory as CA roots.
|
|
||||||
|
|
||||||
> **Note:**
|
|
||||||
> In the absence of any root certificate authorities, Docker
|
|
||||||
> will use the system default (i.e., host's root CA set).
|
|
||||||
|
|
||||||
The presence of one or more `<filename>.key/cert` pairs indicates to Docker
|
|
||||||
that there are custom certificates required for access to the desired
|
|
||||||
repository.
|
|
||||||
|
|
||||||
> **Note:**
|
|
||||||
> If there are multiple certificates, each will be tried in alphabetical
|
|
||||||
> order. If there is an authentication error (e.g., 403, 404, 5xx, etc.), Docker
|
|
||||||
> will continue to try with the next certificate.
|
|
||||||
|
|
||||||
Our example is set up like this:
|
|
||||||
|
|
||||||
/etc/docker/certs.d/ <-- Certificate directory
|
|
||||||
└── localhost <-- Hostname
|
|
||||||
├── client.cert <-- Client certificate
|
|
||||||
├── client.key <-- Client key
|
|
||||||
└── localhost.crt <-- Registry certificate
|
|
||||||
|
|
||||||
## Creating the client certificates
|
|
||||||
|
|
||||||
You will use OpenSSL's `genrsa` and `req` commands to first generate an RSA
|
|
||||||
key and then use the key to create the certificate.
|
|
||||||
|
|
||||||
$ openssl genrsa -out client.key 4096
|
|
||||||
$ openssl req -new -x509 -text -key client.key -out client.cert
|
|
||||||
|
|
||||||
> **Warning:**:
|
|
||||||
> Using TLS and managing a CA is an advanced topic.
|
|
||||||
> You should be familiar with OpenSSL, x509, and TLS before
|
|
||||||
> attempting to use them in production.
|
|
||||||
|
|
||||||
> **Warning:**
|
|
||||||
> These TLS commands will only generate a working set of certificates on Linux.
|
|
||||||
> The version of OpenSSL in Mac OS X is incompatible with the type of
|
|
||||||
> certificate Docker requires.
|
|
||||||
|
|
||||||
## Testing the verification setup
|
|
||||||
|
|
||||||
You can test this setup by using Apache to host a Docker registry.
|
|
||||||
For this purpose, you can copy a registry tree (containing images) inside
|
|
||||||
the Apache root.
|
|
||||||
|
|
||||||
> **Note:**
|
|
||||||
> You can find such an example [here](
|
|
||||||
> http://people.gnome.org/~alexl/v1.tar.gz) - which contains the busybox image.
|
|
||||||
|
|
||||||
Once you set up the registry, you can use the following Apache configuration
|
|
||||||
to implement certificate-based protection.
|
|
||||||
|
|
||||||
# This must be in the root context, otherwise it causes a re-negotiation
|
|
||||||
# which is not supported by the TLS implementation in go
|
|
||||||
SSLVerifyClient optional_no_ca
|
|
||||||
|
|
||||||
<Location /v1>
|
|
||||||
Action cert-protected /cgi-bin/cert.cgi
|
|
||||||
SetHandler cert-protected
|
|
||||||
|
|
||||||
Header set x-docker-registry-version "0.6.2"
|
|
||||||
SetEnvIf Host (.*) custom_host=$1
|
|
||||||
Header set X-Docker-Endpoints "%{custom_host}e"
|
|
||||||
</Location>
|
|
||||||
|
|
||||||
Save the above content as `/etc/httpd/conf.d/registry.conf`, and
|
|
||||||
continue with creating a `cert.cgi` file under `/var/www/cgi-bin/`.
|
|
||||||
|
|
||||||
#!/bin/bash
|
|
||||||
if [ "$HTTPS" != "on" ]; then
|
|
||||||
echo "Status: 403 Not using SSL"
|
|
||||||
echo "x-docker-registry-version: 0.6.2"
|
|
||||||
echo
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
if [ "$SSL_CLIENT_VERIFY" == "NONE" ]; then
|
|
||||||
echo "Status: 403 Client certificate invalid"
|
|
||||||
echo "x-docker-registry-version: 0.6.2"
|
|
||||||
echo
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
echo "Content-length: $(stat --printf='%s' $PATH_TRANSLATED)"
|
|
||||||
echo "x-docker-registry-version: 0.6.2"
|
|
||||||
echo "X-Docker-Endpoints: $SERVER_NAME"
|
|
||||||
echo "X-Docker-Size: 0"
|
|
||||||
echo
|
|
||||||
|
|
||||||
cat $PATH_TRANSLATED
|
|
||||||
|
|
||||||
This CGI script will ensure that all requests to `/v1` *without* a valid
|
|
||||||
certificate will be returned with a `403` (i.e., HTTP forbidden) error.
|
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ These options :
|
|||||||
- Set `tls` to true with the server certificate and key specified using `--tlscert` and `--tlskey` respectively
|
- Set `tls` to true with the server certificate and key specified using `--tlscert` and `--tlskey` respectively
|
||||||
- Listen for connections on `tcp://192.168.59.3:2376`
|
- Listen for connections on `tcp://192.168.59.3:2376`
|
||||||
|
|
||||||
The command line reference has the [complete list of daemon flags](/reference/commandline/cli/#daemon)
|
The command line reference has the [complete list of daemon flags](/reference/commandline/daemon)
|
||||||
with explanations.
|
with explanations.
|
||||||
|
|
||||||
## Ubuntu
|
## Ubuntu
|
||||||
@@ -114,7 +114,7 @@ These options :
|
|||||||
- Set `tls` to true with the server certificate and key specified using `--tlscert` and `--tlskey` respectively
|
- Set `tls` to true with the server certificate and key specified using `--tlscert` and `--tlskey` respectively
|
||||||
- Listen for connections on `tcp://192.168.59.3:2376`
|
- Listen for connections on `tcp://192.168.59.3:2376`
|
||||||
|
|
||||||
The command line reference has the [complete list of daemon flags](/reference/commandline/cli/#daemon)
|
The command line reference has the [complete list of daemon flags](/reference/commandline/daemon)
|
||||||
with explanations.
|
with explanations.
|
||||||
|
|
||||||
|
|
||||||
@@ -207,7 +207,7 @@ These options :
|
|||||||
- Set `tls` to true with the server certificate and key specified using `--tlscert` and `--tlskey` respectively
|
- Set `tls` to true with the server certificate and key specified using `--tlscert` and `--tlskey` respectively
|
||||||
- Listen for connections on `tcp://192.168.59.3:2376`
|
- Listen for connections on `tcp://192.168.59.3:2376`
|
||||||
|
|
||||||
The command line reference has the [complete list of daemon flags](/reference/commandline/cli/#daemon)
|
The command line reference has the [complete list of daemon flags](/reference/commandline/daemon)
|
||||||
with explanations.
|
with explanations.
|
||||||
|
|
||||||
5. Save and close the file.
|
5. Save and close the file.
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ weight = 99
|
|||||||
# Automatically start containers
|
# Automatically start containers
|
||||||
|
|
||||||
As of Docker 1.2,
|
As of Docker 1.2,
|
||||||
[restart policies](/reference/commandline/cli/#restart-policies) are the
|
[restart policies](/reference/run/#restart-policies-restart) are the
|
||||||
built-in Docker mechanism for restarting containers when they exit. If set,
|
built-in Docker mechanism for restarting containers when they exit. If set,
|
||||||
restart policies will be used when the Docker daemon starts up, as typically
|
restart policies will be used when the Docker daemon starts up, as typically
|
||||||
happens after a system boot. Restart policies will ensure that linked containers
|
happens after a system boot. Restart policies will ensure that linked containers
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ First generate CA private and public keys:
|
|||||||
State or Province Name (full name) [Some-State]:Queensland
|
State or Province Name (full name) [Some-State]:Queensland
|
||||||
Locality Name (eg, city) []:Brisbane
|
Locality Name (eg, city) []:Brisbane
|
||||||
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Docker Inc
|
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Docker Inc
|
||||||
Organizational Unit Name (eg, section) []:Boot2Docker
|
Organizational Unit Name (eg, section) []:Sales
|
||||||
Common Name (e.g. server FQDN or YOUR name) []:$HOST
|
Common Name (e.g. server FQDN or YOUR name) []:$HOST
|
||||||
Email Address []:Sven@home.org.au
|
Email Address []:Sven@home.org.au
|
||||||
|
|
||||||
|
|||||||
@@ -11,81 +11,8 @@ weight = 8
|
|||||||
|
|
||||||
# Run a local registry mirror
|
# Run a local registry mirror
|
||||||
|
|
||||||
## Why?
|
The orginal content was deprecated. [An archived
|
||||||
|
version](https://docs.docker.com/v1.6/articles/registry_mirror) is available in
|
||||||
If you have multiple instances of Docker running in your environment
|
the 1.7 documentation. For information about configuring mirrors with the latest
|
||||||
(e.g., multiple physical or virtual machines, all running the Docker
|
Docker Registry version, please file a support request with [the Distribution
|
||||||
daemon), each time one of them requires an image that it doesn't have
|
project](https://github.com/docker/distribution/issues).
|
||||||
it will go out to the internet and fetch it from the public Docker
|
|
||||||
registry. By running a local registry mirror, you can keep most of the
|
|
||||||
image fetch traffic on your local network.
|
|
||||||
|
|
||||||
## How does it work?
|
|
||||||
|
|
||||||
The first time you request an image from your local registry mirror,
|
|
||||||
it pulls the image from the public Docker registry and stores it locally
|
|
||||||
before handing it back to you. On subsequent requests, the local registry
|
|
||||||
mirror is able to serve the image from its own storage.
|
|
||||||
|
|
||||||
## How do I set up a local registry mirror?
|
|
||||||
|
|
||||||
There are two steps to set up and use a local registry mirror.
|
|
||||||
|
|
||||||
### Step 1: Configure your Docker daemons to use the local registry mirror
|
|
||||||
|
|
||||||
You will need to pass the `--registry-mirror` option to your Docker daemon on
|
|
||||||
startup:
|
|
||||||
|
|
||||||
docker daemon --registry-mirror=http://<my-docker-mirror-host>
|
|
||||||
|
|
||||||
For example, if your mirror is serving on `http://10.0.0.2:5000`, you would run:
|
|
||||||
|
|
||||||
docker daemon --registry-mirror=http://10.0.0.2:5000
|
|
||||||
|
|
||||||
**NOTE:**
|
|
||||||
Depending on your local host setup, you may be able to add the
|
|
||||||
`--registry-mirror` options to the `DOCKER_OPTS` variable in
|
|
||||||
`/etc/default/docker`.
|
|
||||||
|
|
||||||
### Step 2: Run the local registry mirror
|
|
||||||
|
|
||||||
You will need to start a local registry mirror service. The
|
|
||||||
[`registry` image](https://registry.hub.docker.com/_/registry/) provides this
|
|
||||||
functionality. For example, to run a local registry mirror that serves on
|
|
||||||
port `5000` and mirrors the content at `registry-1.docker.io`:
|
|
||||||
|
|
||||||
docker run -p 5000:5000 \
|
|
||||||
-e STANDALONE=false \
|
|
||||||
-e MIRROR_SOURCE=https://registry-1.docker.io \
|
|
||||||
-e MIRROR_SOURCE_INDEX=https://index.docker.io \
|
|
||||||
registry
|
|
||||||
|
|
||||||
## Test it out
|
|
||||||
|
|
||||||
With your mirror running, pull an image that you haven't pulled before (using
|
|
||||||
`time` to time it):
|
|
||||||
|
|
||||||
$ time docker pull node:latest
|
|
||||||
Pulling repository node
|
|
||||||
[...]
|
|
||||||
|
|
||||||
real 1m14.078s
|
|
||||||
user 0m0.176s
|
|
||||||
sys 0m0.120s
|
|
||||||
|
|
||||||
Now, remove the image from your local machine:
|
|
||||||
|
|
||||||
$ docker rmi node:latest
|
|
||||||
|
|
||||||
Finally, re-pull the image:
|
|
||||||
|
|
||||||
$ time docker pull node:latest
|
|
||||||
Pulling repository node
|
|
||||||
[...]
|
|
||||||
|
|
||||||
real 0m51.376s
|
|
||||||
user 0m0.120s
|
|
||||||
sys 0m0.116s
|
|
||||||
|
|
||||||
The second time around, the local registry mirror served the image from storage,
|
|
||||||
avoiding a trip out to the internet to refetch it.
|
|
||||||
|
|||||||
@@ -33,17 +33,33 @@ If you want Docker to start at boot, you should also:
|
|||||||
There are a number of ways to configure the daemon flags and environment variables
|
There are a number of ways to configure the daemon flags and environment variables
|
||||||
for your Docker daemon.
|
for your Docker daemon.
|
||||||
|
|
||||||
If the `docker.service` file is set to use an `EnvironmentFile`
|
The recommended way is to use a systemd drop-in file. These are local files in
|
||||||
(often pointing to `/etc/sysconfig/docker`) then you can modify the
|
the `/etc/systemd/system/docker.service.d` directory. This could also be
|
||||||
referenced file.
|
`/etc/systemd/system/docker.service`, which also works for overriding the
|
||||||
|
defaults from `/lib/systemd/system/docker.service`.
|
||||||
|
|
||||||
Check if the `docker.service` uses an `EnvironmentFile`:
|
However, if you had previously used a package which had an `EnvironmentFile`
|
||||||
|
(often pointing to `/etc/sysconfig/docker`) then for backwards compatibility,
|
||||||
|
you drop a file in the `/etc/systemd/system/docker.service.d`
|
||||||
|
directory including the following:
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
EnvironmentFile=-/etc/sysconfig/docker
|
||||||
|
EnvironmentFile=-/etc/sysconfig/docker-storage
|
||||||
|
EnvironmentFile=-/etc/sysconfig/docker-network
|
||||||
|
ExecStart=
|
||||||
|
ExecStart=/usr/bin/docker -d -H fd:// $OPTIONS \
|
||||||
|
$DOCKER_STORAGE_OPTIONS \
|
||||||
|
$DOCKER_NETWORK_OPTIONS \
|
||||||
|
$BLOCK_REGISTRY \
|
||||||
|
$INSECURE_REGISTRY
|
||||||
|
|
||||||
|
To check if the `docker.service` uses an `EnvironmentFile`:
|
||||||
|
|
||||||
$ sudo systemctl show docker | grep EnvironmentFile
|
$ sudo systemctl show docker | grep EnvironmentFile
|
||||||
EnvironmentFile=-/etc/sysconfig/docker (ignore_errors=yes)
|
EnvironmentFile=-/etc/sysconfig/docker (ignore_errors=yes)
|
||||||
|
|
||||||
Alternatively, find out where the service file is located, and look for the
|
Alternatively, find out where the service file is located:
|
||||||
property:
|
|
||||||
|
|
||||||
$ sudo systemctl status docker | grep Loaded
|
$ sudo systemctl status docker | grep Loaded
|
||||||
Loaded: loaded (/usr/lib/systemd/system/docker.service; enabled)
|
Loaded: loaded (/usr/lib/systemd/system/docker.service; enabled)
|
||||||
@@ -69,18 +85,20 @@ In this example, we'll assume that your `docker.service` file looks something li
|
|||||||
|
|
||||||
[Service]
|
[Service]
|
||||||
Type=notify
|
Type=notify
|
||||||
EnvironmentFile=-/etc/sysconfig/docker
|
ExecStart=/usr/bin/docker daemon -H fd://
|
||||||
ExecStart=/usr/bin/docker daemon -H fd:// $OPTIONS
|
|
||||||
LimitNOFILE=1048576
|
LimitNOFILE=1048576
|
||||||
LimitNPROC=1048576
|
LimitNPROC=1048576
|
||||||
|
|
||||||
[Install]
|
[Install]
|
||||||
Also=docker.socket
|
Also=docker.socket
|
||||||
|
|
||||||
This will allow us to add extra flags to the `/etc/sysconfig/docker` file by
|
This will allow us to add extra flags via a drop-in file (mentioned above) by
|
||||||
setting `OPTIONS`:
|
placing a file containing the following in the `/etc/systemd/system/docker.service.d`
|
||||||
|
directory:
|
||||||
|
|
||||||
OPTIONS="--graph /mnt/docker-data --storage-driver btrfs"
|
[Service]
|
||||||
|
ExecStart=
|
||||||
|
ExecStart=/usr/bin/docker daemon -H fd:// --graph /mnt/docker-data --storage-driver btrfs
|
||||||
|
|
||||||
You can also set other environment variables in this file, for example, the
|
You can also set other environment variables in this file, for example, the
|
||||||
`HTTP_PROXY` environment variables described below.
|
`HTTP_PROXY` environment variables described below.
|
||||||
|
|||||||
@@ -1,86 +0,0 @@
|
|||||||
<!--[metadata]>
|
|
||||||
+++
|
|
||||||
title = "Accounts on Docker Hub"
|
|
||||||
description = "Docker Hub accounts"
|
|
||||||
keywords = ["Docker, docker, registry, accounts, plans, Dockerfile, Docker Hub, docs, documentation"]
|
|
||||||
[menu.main]
|
|
||||||
parent = "smn_pubhub"
|
|
||||||
weight = 1
|
|
||||||
+++
|
|
||||||
<![end-metadata]-->
|
|
||||||
|
|
||||||
# Accounts on Docker Hub
|
|
||||||
|
|
||||||
## Docker Hub accounts
|
|
||||||
|
|
||||||
You can `search` for Docker images and `pull` them from [Docker
|
|
||||||
Hub](https://hub.docker.com) without signing in or even having an
|
|
||||||
account. However, in order to `push` images, leave comments or to *star*
|
|
||||||
a repository, you are going to need a [Docker
|
|
||||||
Hub](https://hub.docker.com) account.
|
|
||||||
|
|
||||||
### Registration for a Docker Hub account
|
|
||||||
|
|
||||||
You can get a [Docker Hub](https://hub.docker.com) account by
|
|
||||||
[signing up for one here](https://hub.docker.com/account/signup/). A valid
|
|
||||||
email address is required to register, which you will need to verify for
|
|
||||||
account activation.
|
|
||||||
|
|
||||||
### Email activation process
|
|
||||||
|
|
||||||
You need to have at least one verified email address to be able to use your
|
|
||||||
[Docker Hub](https://hub.docker.com) account. If you can't find the validation email,
|
|
||||||
you can request another by visiting the [Resend Email Confirmation](
|
|
||||||
https://hub.docker.com/account/resend-email-confirmation/) page.
|
|
||||||
|
|
||||||
### Password reset process
|
|
||||||
|
|
||||||
If you can't access your account for some reason, you can reset your password
|
|
||||||
from the [*Password Reset*](https://hub.docker.com/account/forgot-password/)
|
|
||||||
page.
|
|
||||||
|
|
||||||
## Organizations and groups
|
|
||||||
|
|
||||||
A Docker Hub organization contains public and private repositories just like
|
|
||||||
a user account. Access to push, pull or create these organisation owned repositories
|
|
||||||
is allocated by defining groups of users and then assigning group rights to
|
|
||||||
specific repositories. This allows you to distribute limited access
|
|
||||||
Docker images, and to select which Docker Hub users can publish new images.
|
|
||||||
|
|
||||||
### Creating and viewing organizations
|
|
||||||
|
|
||||||
You can see what organizations [you belong to and add new organizations](
|
|
||||||
https://hub.docker.com/account/organizations/) from the Account Settings
|
|
||||||
tab. They are also listed below your user name on your repositories page
|
|
||||||
and in your account profile.
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
### Organization groups
|
|
||||||
|
|
||||||
Users in the `Owners` group of an organization can create and modify the
|
|
||||||
membership of groups.
|
|
||||||
|
|
||||||
Unless they are the organization's `Owner`, users can only see groups of which they
|
|
||||||
are members.
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
### Repository group permissions
|
|
||||||
|
|
||||||
Use organization groups to manage the users that can interact with your repositories.
|
|
||||||
|
|
||||||
You must be in an organization's `Owners` group to create a new group, Hub
|
|
||||||
repository, or automated build. As an `Owner`, you then delegate the following
|
|
||||||
repository access rights to groups:
|
|
||||||
|
|
||||||
| Access Right | Description |
|
|
||||||
|--------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
|
||||||
| `Read` | Users with this right can view, search, and pull a private repository. |
|
|
||||||
| `Write` | Users with this right can push to non-automated repositories on the Docker Hub. |
|
|
||||||
| `Admin` | Users with this right can modify a repository's "Description", "Collaborators" rights. They can also mark a repository as unlisted, change its "Public/Private" status and "Delete" the repository. Finally, `Admin` rights are required to read the build log on a repo. |
|
|
||||||
| | |
|
|
||||||
|
|
||||||
Regardless of their actual access rights, users with unverified email addresses
|
|
||||||
have `Read` access to the repository. Once they have verified their address,
|
|
||||||
they have their full access rights as granted on the organization.
|
|
||||||
@@ -1,465 +0,0 @@
|
|||||||
<!--[metadata]>
|
|
||||||
+++
|
|
||||||
title = "Automated Builds on Docker Hub"
|
|
||||||
description = "Docker Hub Automated Builds"
|
|
||||||
keywords = ["Docker, docker, registry, accounts, plans, Dockerfile, Docker Hub, docs, documentation, trusted, builds, trusted builds, automated builds"]
|
|
||||||
[menu.main]
|
|
||||||
parent = "smn_pubhub"
|
|
||||||
weight = 3
|
|
||||||
+++
|
|
||||||
<![end-metadata]-->
|
|
||||||
|
|
||||||
# Automated Builds on Docker Hub
|
|
||||||
|
|
||||||
## About Automated Builds
|
|
||||||
|
|
||||||
*Automated Builds* are a special feature of Docker Hub which allow you to
|
|
||||||
use [Docker Hub's](https://hub.docker.com) build clusters to automatically
|
|
||||||
create images from a GitHub or Bitbucket repository containing a `Dockerfile`
|
|
||||||
The system will clone your repository and build the image described by the
|
|
||||||
`Dockerfile` using the directory the `Dockerfile` is in (and subdirectories)
|
|
||||||
as the build context. The resulting automated image will then be uploaded
|
|
||||||
to the Docker Hub registry and marked as an *Automated Build*.
|
|
||||||
|
|
||||||
Automated Builds have several advantages:
|
|
||||||
|
|
||||||
* Users of *your* Automated Build can trust that the resulting
|
|
||||||
image was built exactly as specified.
|
|
||||||
* The `Dockerfile` will be available to anyone with access to
|
|
||||||
your repository on the Docker Hub registry.
|
|
||||||
* Because the process is automated, Automated Builds help to
|
|
||||||
make sure that your repository is always up to date.
|
|
||||||
* Not having to push local Docker images to Docker Hub saves
|
|
||||||
you both network bandwidth and time.
|
|
||||||
|
|
||||||
Automated Builds are supported for both public and private repositories
|
|
||||||
on both [GitHub](http://github.com) and [Bitbucket](https://bitbucket.org/).
|
|
||||||
|
|
||||||
To use Automated Builds, you must have an [account on Docker Hub](
|
|
||||||
https://docs.docker.com/userguide/dockerhub/#creating-a-docker-hub-account)
|
|
||||||
and on GitHub and/or Bitbucket. In either case, the account needs
|
|
||||||
to be properly validated and activated before you can link to it.
|
|
||||||
|
|
||||||
The first time you to set up an Automated Build, your
|
|
||||||
[Docker Hub](https://hub.docker.com) account will need to be linked to
|
|
||||||
a GitHub or Bitbucket account.
|
|
||||||
This will allow the registry to see your repositories.
|
|
||||||
|
|
||||||
If you have previously linked your Docker Hub account, and want to view or modify
|
|
||||||
that link, click on the "Manage - Settings" link in the sidebar, and then
|
|
||||||
"Linked Accounts" in your Settings sidebar.
|
|
||||||
|
|
||||||
## Automated Builds from GitHub
|
|
||||||
|
|
||||||
If you've previously linked your Docker Hub account to your GitHub account,
|
|
||||||
you'll be able to skip to the [Creating an Automated Build](#creating-an-automated-build).
|
|
||||||
|
|
||||||
### Linking your Docker Hub account to a GitHub account
|
|
||||||
|
|
||||||
> *Note:*
|
|
||||||
> Automated Builds currently require *read* and *write* access since
|
|
||||||
> [Docker Hub](https://hub.docker.com) needs to setup a GitHub service
|
|
||||||
> hook. We have no choice here, this is how GitHub manages permissions, sorry!
|
|
||||||
> We do guarantee nothing else will be touched in your account.
|
|
||||||
|
|
||||||
To get started, log into your Docker Hub account and click the
|
|
||||||
"+ Add Repository" button at the upper right of the screen. Then select
|
|
||||||
[Automated Build](https://registry.hub.docker.com/builds/add/).
|
|
||||||
|
|
||||||
Select the [GitHub service](https://registry.hub.docker.com/associate/github/).
|
|
||||||
|
|
||||||
When linking to GitHub, you'll need to select either "Public and Private",
|
|
||||||
or "Limited" linking.
|
|
||||||
|
|
||||||
The "Public and Private" option is the easiest to use,
|
|
||||||
as it grants the Docker Hub full access to all of your repositories. GitHub
|
|
||||||
also allows you to grant access to repositories belonging to your GitHub
|
|
||||||
organizations.
|
|
||||||
|
|
||||||
By choosing the "Limited" linking, your Docker Hub account only gets permission
|
|
||||||
to access your public data and public repositories.
|
|
||||||
|
|
||||||
Follow the onscreen instructions to authorize and link your
|
|
||||||
GitHub account to Docker Hub. Once it is linked, you'll be able to
|
|
||||||
choose a source repository from which to create the Automatic Build.
|
|
||||||
|
|
||||||
You will be able to review and revoke Docker Hub's access by visiting the
|
|
||||||
[GitHub User's Applications settings](https://github.com/settings/applications).
|
|
||||||
|
|
||||||
> **Note**: If you delete the GitHub account linkage that is used for one of your
|
|
||||||
> automated build repositories, the previously built images will still be available.
|
|
||||||
> If you re-link to that GitHub account later, the automated build can be started
|
|
||||||
> using the "Start Build" button on the Hub, or if the webhook on the GitHub repository
|
|
||||||
> still exists, will be triggered by any subsequent commits.
|
|
||||||
|
|
||||||
### Auto builds and limited linked GitHub accounts.
|
|
||||||
|
|
||||||
If you selected to link your GitHub account with only a "Limited" link, then
|
|
||||||
after creating your automated build, you will need to either manually trigger a
|
|
||||||
Docker Hub build using the "Start a Build" button, or add the GitHub webhook
|
|
||||||
manually, as described in [GitHub Service Hooks](#github-service-hooks).
|
|
||||||
|
|
||||||
### Changing the GitHub user link
|
|
||||||
|
|
||||||
If you want to remove, or change the level of linking between your GitHub account
|
|
||||||
and the Docker Hub, you need to do this in two places.
|
|
||||||
|
|
||||||
First, remove the "Linked Account" from your Docker Hub "Settings".
|
|
||||||
Then go to your GitHub account's Personal settings, and in the "Applications"
|
|
||||||
section, "Revoke access".
|
|
||||||
|
|
||||||
You can now re-link your account at any time.
|
|
||||||
|
|
||||||
### GitHub organizations
|
|
||||||
|
|
||||||
GitHub organizations and private repositories forked from organizations will be
|
|
||||||
made available to auto build using the "Docker Hub Registry" application, which
|
|
||||||
needs to be added to the organization - and then will apply to all users.
|
|
||||||
|
|
||||||
To check, or request access, go to your GitHub user's "Setting" page, select the
|
|
||||||
"Applications" section from the left side bar, then click the "View" button for
|
|
||||||
"Docker Hub Registry".
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
The organization's administrators may need to go to the Organization's "Third
|
|
||||||
party access" screen in "Settings" to Grant or Deny access to the Docker Hub
|
|
||||||
Registry application. This change will apply to all organization members.
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
More detailed access controls to specific users and GitHub repositories would be
|
|
||||||
managed using the GitHub People and Teams interfaces.
|
|
||||||
|
|
||||||
### Creating an Automated Build
|
|
||||||
|
|
||||||
You can [create an Automated Build](
|
|
||||||
https://registry.hub.docker.com/builds/github/select/) from any of your
|
|
||||||
public or private GitHub repositories that have a `Dockerfile`.
|
|
||||||
|
|
||||||
Once you've selected the source repository, you can then configure:
|
|
||||||
|
|
||||||
- The Hub user/org the repository is built to - either your Hub account name,
|
|
||||||
or the name of any Hub organizations your account is in
|
|
||||||
- The Docker repository name the image is built to
|
|
||||||
- If the Docker repository should be "Public" or "Private"
|
|
||||||
You can change the accessibility options after the repository has been created.
|
|
||||||
If you add a Private repository to a Hub user, then you can only add other users
|
|
||||||
as collaborators, and those users will be able to view and pull all images in that
|
|
||||||
repository. To configure more granular access permissions, such as using groups of
|
|
||||||
users or allow different users access to different image tags, then you need
|
|
||||||
to add the Private repository to a Hub organization that your user has Administrator
|
|
||||||
privilege on.
|
|
||||||
- If you want the GitHub to notify the Docker Hub when a commit is made, and thus trigger
|
|
||||||
a rebuild of all the images in this automated build.
|
|
||||||
|
|
||||||
You can also select one or more
|
|
||||||
- The git branch/tag, which repository sub-directory to use as the context
|
|
||||||
- The Docker image tag name
|
|
||||||
|
|
||||||
You can set a description for the repository by clicking "Description" link in the righthand side bar after the automated build - note that the "Full Description" will be over-written next build from the README.md file.
|
|
||||||
has been created.
|
|
||||||
|
|
||||||
### GitHub private submodules
|
|
||||||
|
|
||||||
If your GitHub repository contains links to private submodules, you'll get an
|
|
||||||
error message in your build.
|
|
||||||
|
|
||||||
Normally, the Docker Hub sets up a deploy key in your GitHub repository.
|
|
||||||
Unfortunately, GitHub only allows a repository deploy key to access a single repository.
|
|
||||||
|
|
||||||
To work around this, you need to create a dedicated user account in GitHub and attach
|
|
||||||
the automated build's deploy key that account. This dedicated build account
|
|
||||||
can be limited to read-only access to just the repositories required to build.
|
|
||||||
|
|
||||||
<table class="table table-bordered">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>Step</th>
|
|
||||||
<th>Screenshot</th>
|
|
||||||
<th>Description</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td>1.</td>
|
|
||||||
<td><img src="/docker-hub/hub-images/gh_org_members.png"></td>
|
|
||||||
<td>First, create the new account in GitHub. It should be given read-only
|
|
||||||
access to the main repository and all submodules that are needed.</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>2.</td>
|
|
||||||
<td><img src="/docker-hub/hub-images/gh_team_members.png"></td>
|
|
||||||
<td>This can be accomplished by adding the account to a read-only team in
|
|
||||||
the organization(s) where the main GitHub repository and all submodule
|
|
||||||
repositories are kept.</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>3.</td>
|
|
||||||
<td><img src="/docker-hub/hub-images/gh_repo_deploy_key.png"></td>
|
|
||||||
<td>Next, remove the deploy key from the main GitHub repository. This can be done in the GitHub repository's "Deploy keys" Settings section.</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>4.</td>
|
|
||||||
<td><img src="/docker-hub/hub-images/deploy_key.png"></td>
|
|
||||||
<td>Your automated build's deploy key is in the "Build Details" menu
|
|
||||||
under "Deploy keys".</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>5.</td>
|
|
||||||
<td><img src="/docker-hub/hub-images/gh_add_ssh_user_key.png"></td>
|
|
||||||
<td>In your dedicated GitHub User account, add the deploy key from your
|
|
||||||
Docker Hub Automated Build.</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
### GitHub service hooks
|
|
||||||
|
|
||||||
The GitHub Service hook allows GitHub to notify the Docker Hub when something has
|
|
||||||
been committed to that git repository. You will need to add the Service Hook manually
|
|
||||||
if your GitHub account is "Limited" linked to the Docker Hub.
|
|
||||||
|
|
||||||
Follow the steps below to configure the GitHub Service hooks for your Automated Build:
|
|
||||||
|
|
||||||
<table class="table table-bordered">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>Step</th>
|
|
||||||
<th>Screenshot</th>
|
|
||||||
<th>Description</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td>1.</td>
|
|
||||||
<td><img src="/docker-hub/hub-images/gh_settings.png"></td>
|
|
||||||
<td>Log in to GitHub.com, and go to your Repository page. Click on "Settings" on
|
|
||||||
the right side of the page. You must have admin privileges to the repository in order to do this.</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>2.</td>
|
|
||||||
<td><img src="/docker-hub/hub-images/gh_menu.png" alt="Webhooks & Services"></td>
|
|
||||||
<td>Click on "Webhooks & Services" on the left side of the page.</td></tr>
|
|
||||||
<tr><td>3.</td>
|
|
||||||
<td><img src="/docker-hub/hub-images/gh_service_hook.png" alt="Find the service labeled Docker"></td>
|
|
||||||
<td>Find the service labeled "Docker" (or click on "Add service") and click on it.</td></tr>
|
|
||||||
<tr><td>4.</td>
|
|
||||||
<td><img src="/docker-hub/hub-images/gh_docker-service.png" alt="Activate Service Hooks"></td>
|
|
||||||
<td>Make sure the "Active" checkbox is selected and click the "Update service" button to save your changes.</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
## Automated Builds with Bitbucket
|
|
||||||
|
|
||||||
In order to setup an Automated Build, you need to first link your
|
|
||||||
[Docker Hub](https://hub.docker.com) account with a Bitbucket account.
|
|
||||||
This will allow the registry to see your repositories.
|
|
||||||
|
|
||||||
To get started, log into your Docker Hub account and click the
|
|
||||||
"+ Add Repository" button at the upper right of the screen. Then
|
|
||||||
select [Automated Build](https://registry.hub.docker.com/builds/add/).
|
|
||||||
|
|
||||||
Select the [Bitbucket source](
|
|
||||||
https://registry.hub.docker.com/associate/bitbucket/).
|
|
||||||
|
|
||||||
Then follow the onscreen instructions to authorize and link your
|
|
||||||
Bitbucket account to Docker Hub. Once it is linked, you'll be able
|
|
||||||
to choose a repository from which to create the Automatic Build.
|
|
||||||
|
|
||||||
### Creating an Automated Build
|
|
||||||
|
|
||||||
You can [create an Automated Build](
|
|
||||||
https://registry.hub.docker.com/builds/bitbucket/select/) from any of your
|
|
||||||
public or private Bitbucket repositories with a `Dockerfile`.
|
|
||||||
|
|
||||||
### Adding a Hook
|
|
||||||
|
|
||||||
When you link your Docker Hub account, a `POST` hook should get automatically
|
|
||||||
added to your Bitbucket repository. Follow the steps below to confirm or modify the
|
|
||||||
Bitbucket hooks for your Automated Build:
|
|
||||||
|
|
||||||
<table class="table table-bordered">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>Step</th>
|
|
||||||
<th>Screenshot</th>
|
|
||||||
<th>Description</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td>1.</td>
|
|
||||||
<td><img src="/docker-hub/hub-images/bb_menu.png" alt="Settings" width="180"></td>
|
|
||||||
<td>Log in to Bitbucket.org and go to your Repository page. Click on "Settings" on
|
|
||||||
the far left side of the page, under "Navigation". You must have admin privileges
|
|
||||||
to the repository in order to do this.</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>2.</td>
|
|
||||||
<td><img src="/docker-hub/hub-images/bb_hooks.png" alt="Hooks" width="180"></td>
|
|
||||||
<td>Click on "Hooks" on the near left side of the page, under "Settings".</td></tr>
|
|
||||||
<tr>
|
|
||||||
<td>3.</td>
|
|
||||||
<td><img src="/docker-hub/hub-images/bb_post-hook.png" alt="Docker Post Hook"></td><td>You should now see a list of hooks associated with the repo, including a <code>POST</code> hook that points at
|
|
||||||
registry.hub.docker.com/hooks/bitbucket.</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
|
|
||||||
## The Dockerfile and Automated Builds
|
|
||||||
|
|
||||||
During the build process, Docker will copy the contents of your `Dockerfile`.
|
|
||||||
It will also add it to the [Docker Hub](https://hub.docker.com) for the Docker
|
|
||||||
community (for public repositories) or approved team members/orgs (for private
|
|
||||||
repositories) to see on the repository page.
|
|
||||||
|
|
||||||
### README.md
|
|
||||||
|
|
||||||
If you have a `README.md` file in your repository, it will be used as the
|
|
||||||
repository's full description.The build process will look for a
|
|
||||||
`README.md` in the same directory as your `Dockerfile`.
|
|
||||||
|
|
||||||
> **Warning:**
|
|
||||||
> If you change the full description after a build, it will be
|
|
||||||
> rewritten the next time the Automated Build has been built. To make changes,
|
|
||||||
> modify the `README.md` from the Git repository.
|
|
||||||
|
|
||||||
## Remote Build triggers
|
|
||||||
|
|
||||||
If you need a way to trigger Automated Builds outside of GitHub or Bitbucket,
|
|
||||||
you can set up a build trigger. When you turn on the build trigger for an
|
|
||||||
Automated Build, it will give you a URL to which you can send POST requests.
|
|
||||||
This will trigger the Automated Build, much as with a GitHub webhook.
|
|
||||||
|
|
||||||
Build triggers are available under the Settings menu of each Automated Build
|
|
||||||
repository on the Docker Hub.
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
You can use `curl` to trigger a build:
|
|
||||||
|
|
||||||
```
|
|
||||||
$ curl --data "build=true" -X POST https://registry.hub.docker.com/u/svendowideit/testhook/trigger/be579c
|
|
||||||
82-7c0e-11e4-81c4-0242ac110020/
|
|
||||||
OK
|
|
||||||
```
|
|
||||||
|
|
||||||
> **Note:**
|
|
||||||
> You can only trigger one build at a time and no more than one
|
|
||||||
> every five minutes. If you already have a build pending, or if you
|
|
||||||
> recently submitted a build request, those requests *will be ignored*.
|
|
||||||
> To verify everything is working correctly, check the logs of last
|
|
||||||
> ten triggers on the settings page .
|
|
||||||
|
|
||||||
## Webhooks
|
|
||||||
|
|
||||||
Automated Builds also include a Webhooks feature. Webhooks can be called
|
|
||||||
after a successful repository push is made. This includes when a new tag is added
|
|
||||||
to an existing image.
|
|
||||||
|
|
||||||
The webhook call will generate a HTTP POST with the following JSON
|
|
||||||
payload:
|
|
||||||
|
|
||||||
```
|
|
||||||
{
|
|
||||||
"callback_url": "https://registry.hub.docker.com/u/svendowideit/testhook/hook/2141b5bi5i5b02bec211i4eeih0242eg11000a/",
|
|
||||||
"push_data": {
|
|
||||||
"images": [
|
|
||||||
"27d47432a69bca5f2700e4dff7de0388ed65f9d3fb1ec645e2bc24c223dc1cc3",
|
|
||||||
"51a9c7c1f8bb2fa19bcd09789a34e63f35abb80044bc10196e304f6634cc582c",
|
|
||||||
...
|
|
||||||
],
|
|
||||||
"pushed_at": 1.417566161e+09,
|
|
||||||
"pusher": "trustedbuilder"
|
|
||||||
},
|
|
||||||
"repository": {
|
|
||||||
"comment_count": 0,
|
|
||||||
"date_created": 1.417494799e+09,
|
|
||||||
"description": "",
|
|
||||||
"dockerfile": "#\n# BUILD\u0009\u0009docker build -t svendowideit/apt-cacher .\n# RUN\u0009\u0009docker run -d -p 3142:3142 -name apt-cacher-run apt-cacher\n#\n# and then you can run containers with:\n# \u0009\u0009docker run -t -i -rm -e http_proxy http://192.168.1.2:3142/ debian bash\n#\nFROM\u0009\u0009ubuntu\nMAINTAINER\u0009SvenDowideit@home.org.au\n\n\nVOLUME\u0009\u0009[\"/var/cache/apt-cacher-ng\"]\nRUN\u0009\u0009apt-get update ; apt-get install -yq apt-cacher-ng\n\nEXPOSE \u0009\u00093142\nCMD\u0009\u0009chmod 777 /var/cache/apt-cacher-ng ; /etc/init.d/apt-cacher-ng start ; tail -f /var/log/apt-cacher-ng/*\n",
|
|
||||||
"full_description": "Docker Hub based automated build from a GitHub repo",
|
|
||||||
"is_official": false,
|
|
||||||
"is_private": true,
|
|
||||||
"is_trusted": true,
|
|
||||||
"name": "testhook",
|
|
||||||
"namespace": "svendowideit",
|
|
||||||
"owner": "svendowideit",
|
|
||||||
"repo_name": "svendowideit/testhook",
|
|
||||||
"repo_url": "https://registry.hub.docker.com/u/svendowideit/testhook/",
|
|
||||||
"star_count": 0,
|
|
||||||
"status": "Active"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Webhooks are available under the Settings menu of each Repository.
|
|
||||||
Use a tool like [requestb.in](http://requestb.in/) to test your webhook.
|
|
||||||
|
|
||||||
> **Note**: The Docker Hub servers use an elastic IP range, so you can't
|
|
||||||
> filter requests by IP.
|
|
||||||
|
|
||||||
### Webhook chains
|
|
||||||
|
|
||||||
Webhook chains allow you to chain calls to multiple services. For example,
|
|
||||||
you can use this to trigger a deployment of your container only after
|
|
||||||
it has been successfully tested, then update a separate Changelog once the
|
|
||||||
deployment is complete.
|
|
||||||
After clicking the "Add webhook" button, simply add as many URLs as necessary
|
|
||||||
in your chain.
|
|
||||||
|
|
||||||
The first webhook in a chain will be called after a successful push. Subsequent
|
|
||||||
URLs will be contacted after the callback has been validated.
|
|
||||||
|
|
||||||
### Validating a callback
|
|
||||||
|
|
||||||
In order to validate a callback in a webhook chain, you need to
|
|
||||||
|
|
||||||
1. Retrieve the `callback_url` value in the request's JSON payload.
|
|
||||||
1. Send a POST request to this URL containing a valid JSON body.
|
|
||||||
|
|
||||||
> **Note**: A chain request will only be considered complete once the last
|
|
||||||
> callback has been validated.
|
|
||||||
|
|
||||||
To help you debug or simply view the results of your webhook(s),
|
|
||||||
view the "History" of the webhook available on its settings page.
|
|
||||||
|
|
||||||
### Callback JSON data
|
|
||||||
|
|
||||||
The following parameters are recognized in callback data:
|
|
||||||
|
|
||||||
* `state` (required): Accepted values are `success`, `failure` and `error`.
|
|
||||||
If the state isn't `success`, the webhook chain will be interrupted.
|
|
||||||
* `description`: A string containing miscellaneous information that will be
|
|
||||||
available on the Docker Hub. Maximum 255 characters.
|
|
||||||
* `context`: A string containing the context of the operation. Can be retrieved
|
|
||||||
from the Docker Hub. Maximum 100 characters.
|
|
||||||
* `target_url`: The URL where the results of the operation can be found. Can be
|
|
||||||
retrieved on the Docker Hub.
|
|
||||||
|
|
||||||
*Example callback payload:*
|
|
||||||
|
|
||||||
{
|
|
||||||
"state": "success",
|
|
||||||
"description": "387 tests PASSED",
|
|
||||||
"context": "Continuous integration by Acme CI",
|
|
||||||
"target_url": "http://ci.acme.com/results/afd339c1c3d27"
|
|
||||||
}
|
|
||||||
|
|
||||||
## Repository links
|
|
||||||
|
|
||||||
Repository links are a way to associate one Automated Build with
|
|
||||||
another. If one gets updated, the linking system triggers a rebuild
|
|
||||||
for the other Automated Build. This makes it easy to keep all your
|
|
||||||
Automated Builds up to date.
|
|
||||||
|
|
||||||
To add a link, go to the repository for the Automated Build you want to
|
|
||||||
link to and click on *Repository Links* under the Settings menu at
|
|
||||||
right. Then, enter the name of the repository that you want have linked.
|
|
||||||
|
|
||||||
> **Warning:**
|
|
||||||
> You can add more than one repository link, however, you should
|
|
||||||
> do so very carefully. Creating a two way relationship between Automated Builds will
|
|
||||||
> cause an endless build loop.
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
<!--[metadata]>
|
|
||||||
+++
|
|
||||||
draft = true
|
|
||||||
title = "The Docker Hub Registry help"
|
|
||||||
description = "The Docker Registry help documentation home"
|
|
||||||
keywords = ["Docker, docker, registry, accounts, plans, Dockerfile, Docker Hub, docs, documentation"]
|
|
||||||
[menu.main]
|
|
||||||
parent = "smn_pubhub"
|
|
||||||
+++
|
|
||||||
<![end-metadata]-->
|
|
||||||
|
|
||||||
# The Docker Hub Registry help
|
|
||||||
|
|
||||||
## Introduction
|
|
||||||
|
|
||||||
For your questions about the [Docker Hub](https://hub.docker.com) registry you
|
|
||||||
can use [this documentation](docs.md).
|
|
||||||
|
|
||||||
If you can not find something you are looking for, please feel free to
|
|
||||||
[contact us](https://docker.com/resources/support/).
|
|
||||||
|
Before Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 52 KiB |
|
Before Width: | Height: | Size: 47 KiB |
|
Before Width: | Height: | Size: 31 KiB |
|
Before Width: | Height: | Size: 19 KiB |
|
Before Width: | Height: | Size: 21 KiB |
|
Before Width: | Height: | Size: 40 KiB |
|
Before Width: | Height: | Size: 5.5 KiB |
|
Before Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 32 KiB |
|
Before Width: | Height: | Size: 19 KiB |
|
Before Width: | Height: | Size: 4.7 KiB |
|
Before Width: | Height: | Size: 35 KiB |
|
Before Width: | Height: | Size: 28 KiB |
|
Before Width: | Height: | Size: 30 KiB |
|
Before Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 28 KiB |
@@ -1,38 +0,0 @@
|
|||||||
<!--[metadata]>
|
|
||||||
+++
|
|
||||||
title = "The Docker Hub"
|
|
||||||
description = "The Docker Help documentation home"
|
|
||||||
keywords = ["Docker, docker, registry, accounts, plans, Dockerfile, Docker Hub, docs, documentation, accounts, organizations, repositories, groups"]
|
|
||||||
[menu.main]
|
|
||||||
parent = "smn_pubhub"
|
|
||||||
+++
|
|
||||||
<![end-metadata]-->
|
|
||||||
|
|
||||||
# Docker Hub
|
|
||||||
|
|
||||||
The [Docker Hub](https://hub.docker.com) provides a cloud-based platform service
|
|
||||||
for distributed applications, including container image distribution and change
|
|
||||||
management, user and team collaboration, and lifecycle workflow automation.
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
## [Finding and pulling images](./userguide.md)
|
|
||||||
|
|
||||||
Find out how to [use the Docker Hub](./userguide.md) to find and pull Docker
|
|
||||||
images to run or build upon.
|
|
||||||
|
|
||||||
## [Accounts](./accounts.md)
|
|
||||||
|
|
||||||
[Learn how to create](./accounts.md) a Docker Hub
|
|
||||||
account and manage your organizations and groups.
|
|
||||||
|
|
||||||
## [Your Repositories](./repos.md)
|
|
||||||
|
|
||||||
Find out how to share your Docker images in [Docker Hub
|
|
||||||
repositories](./repos.md) and how to store and manage private images.
|
|
||||||
|
|
||||||
## [Automated builds](./builds.md)
|
|
||||||
|
|
||||||
Learn how to automate your build and deploy pipeline with [Automated
|
|
||||||
Builds](./builds.md)
|
|
||||||
|
|
||||||
@@ -1,113 +0,0 @@
|
|||||||
<!--[metadata]>
|
|
||||||
+++
|
|
||||||
title = "Official Repositories on Docker Hub"
|
|
||||||
description = "Guidelines for Official Repositories on Docker Hub"
|
|
||||||
keywords = ["Docker, docker, registry, accounts, plans, Dockerfile, Docker Hub, docs, official, image, documentation"]
|
|
||||||
[menu.main]
|
|
||||||
parent = "smn_pubhub"
|
|
||||||
weight = 4
|
|
||||||
+++
|
|
||||||
<![end-metadata]-->
|
|
||||||
|
|
||||||
# Official Repositories on Docker Hub
|
|
||||||
|
|
||||||
The Docker [Official Repositories](http://registry.hub.docker.com/official) are
|
|
||||||
a curated set of Docker repositories that are promoted on Docker Hub. They are
|
|
||||||
designed to:
|
|
||||||
|
|
||||||
* Provide essential base OS repositories (for example,
|
|
||||||
[`ubuntu`](https://registry.hub.docker.com/_/ubuntu/),
|
|
||||||
[`centos`](https://registry.hub.docker.com/_/centos/)) that serve as the
|
|
||||||
starting point for the majority of users.
|
|
||||||
|
|
||||||
* Provide drop-in solutions for popular programming language runtimes, data
|
|
||||||
stores, and other services, similar to what a Platform-as-a-Service (PAAS)
|
|
||||||
would offer.
|
|
||||||
|
|
||||||
* Exemplify [`Dockerfile` best practices](/articles/dockerfile_best-practices)
|
|
||||||
and provide clear documentation to serve as a reference for other `Dockerfile`
|
|
||||||
authors.
|
|
||||||
|
|
||||||
* Ensure that security updates are applied in a timely manner. This is
|
|
||||||
particularly important as many Official Repositories are some of the most
|
|
||||||
popular on Docker Hub.
|
|
||||||
|
|
||||||
* Provide a channel for software vendors to redistribute up-to-date and
|
|
||||||
supported versions of their products. Organization accounts on Docker Hub can
|
|
||||||
also serve this purpose, without the careful review or restrictions on what
|
|
||||||
can be published.
|
|
||||||
|
|
||||||
Docker, Inc. sponsors a dedicated team that is responsible for reviewing and
|
|
||||||
publishing all Official Repositories content. This team works in collaboration
|
|
||||||
with upstream software maintainers, security experts, and the broader Docker
|
|
||||||
community.
|
|
||||||
|
|
||||||
While it is preferable to have upstream software authors maintaining their
|
|
||||||
corresponding Official Repositories, this is not a strict requirement. Creating
|
|
||||||
and maintaining images for Official Repositories is a public process. It takes
|
|
||||||
place openly on GitHub where participation is encouraged. Anyone can provide
|
|
||||||
feedback, contribute code, suggest process changes, or even propose a new
|
|
||||||
Official Repository.
|
|
||||||
|
|
||||||
## Should I use Official Repositories?
|
|
||||||
|
|
||||||
New Docker users are encouraged to use the Official Repositories in their
|
|
||||||
projects. These repositories have clear documentation, promote best practices,
|
|
||||||
and are designed for the most common use cases. Advanced users are encouraged to
|
|
||||||
review the Official Repositories as part of their `Dockerfile` learning process.
|
|
||||||
|
|
||||||
A common rationale for diverging from Official Repositories is to optimize for
|
|
||||||
image size. For instance, many of the programming language stack images contain
|
|
||||||
a complete build toolchain to support installation of modules that depend on
|
|
||||||
optimized code. An advanced user could build a custom image with just the
|
|
||||||
necessary pre-compiled libraries to save space.
|
|
||||||
|
|
||||||
A number of language stacks such as
|
|
||||||
[`python`](https://registry.hub.docker.com/_/python/) and
|
|
||||||
[`ruby`](https://registry.hub.docker.com/_/ruby/) have `-slim` tag variants
|
|
||||||
designed to fill the need for optimization. Even when these "slim" variants are
|
|
||||||
insufficient, it is still recommended to inherit from an Official Repository
|
|
||||||
base OS image to leverage the ongoing maintenance work, rather than duplicating
|
|
||||||
these efforts.
|
|
||||||
|
|
||||||
## How can I get involved?
|
|
||||||
|
|
||||||
All Official Repositories contain a **User Feedback** section in their
|
|
||||||
documentation which covers the details for that specific repository. In most
|
|
||||||
cases, the GitHub repository which contains the Dockerfiles for an Official
|
|
||||||
Repository also has an active issue tracker. General feedback and support
|
|
||||||
questions should be directed to `#docker-library` on Freenode IRC.
|
|
||||||
|
|
||||||
## How do I create a new Official Repository?
|
|
||||||
|
|
||||||
From a high level, an Official Repository starts out as a proposal in the form
|
|
||||||
of a set of GitHub pull requests. You'll find detailed and objective proposal
|
|
||||||
requirements in the following GitHub repositories:
|
|
||||||
|
|
||||||
* [docker-library/official-images](https://github.com/docker-library/official-images)
|
|
||||||
|
|
||||||
* [docker-library/docs](https://github.com/docker-library/docs)
|
|
||||||
|
|
||||||
The Official Repositories team, with help from community contributors, formally
|
|
||||||
review each proposal and provide feedback to the author. This initial review
|
|
||||||
process may require a bit of back and forth before the proposal is accepted.
|
|
||||||
|
|
||||||
There are also subjective considerations during the review process. These
|
|
||||||
subjective concerns boil down to the basic question: "is this image generally
|
|
||||||
useful?" For example, the [`python`](https://registry.hub.docker.com/_/python/)
|
|
||||||
Official Repository is "generally useful" to the large Python developer
|
|
||||||
community, whereas an obscure text adventure game written in Python last week is
|
|
||||||
not.
|
|
||||||
|
|
||||||
When a new proposal is accepted, the author becomes responsible for keeping
|
|
||||||
their images up-to-date and responding to user feedback. The Official
|
|
||||||
Repositories team becomes responsible for publishing the images and
|
|
||||||
documentation on Docker Hub. Updates to the Official Repository follow the same
|
|
||||||
pull request process, though with less review. The Official Repositories team
|
|
||||||
ultimately acts as a gatekeeper for all changes, which helps mitigate the risk
|
|
||||||
of quality and security issues from being introduced.
|
|
||||||
|
|
||||||
> **Note**: If you are interested in proposing an Official Repository, but would
|
|
||||||
> like to discuss it with Docker, Inc. privately first, please send your
|
|
||||||
> inquiries to partners@docker.com. There is no fast-track or pay-for-status
|
|
||||||
> option.
|
|
||||||
@@ -1,193 +0,0 @@
|
|||||||
<!--[metadata]>
|
|
||||||
+++
|
|
||||||
title = "Your Repositories on Docker Hub"
|
|
||||||
description = "Your Repositories on Docker Hub"
|
|
||||||
keywords = ["Docker, docker, registry, accounts, plans, Dockerfile, Docker Hub, webhooks, docs, documentation"]
|
|
||||||
[menu.main]
|
|
||||||
parent = "smn_pubhub"
|
|
||||||
weight = 2
|
|
||||||
+++
|
|
||||||
<![end-metadata]-->
|
|
||||||
|
|
||||||
# Your Hub repositories
|
|
||||||
|
|
||||||
Docker Hub repositories make it possible for you to share images with co-workers,
|
|
||||||
customers or the Docker community at large. If you're building your images internally,
|
|
||||||
either on your own Docker daemon, or using your own Continuous integration services,
|
|
||||||
you can push them to a Docker Hub repository that you add to your Docker Hub user or
|
|
||||||
organization account.
|
|
||||||
|
|
||||||
Alternatively, if the source code for your Docker image is on GitHub or Bitbucket,
|
|
||||||
you can use an "Automated build" repository, which is built by the Docker Hub
|
|
||||||
services. See the [automated builds documentation](./builds.md) to read about
|
|
||||||
the extra functionality provided by those services.
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
Your Docker Hub repositories have a number of useful features.
|
|
||||||
|
|
||||||
## Stars
|
|
||||||
|
|
||||||
Your repositories can be starred and you can star repositories in
|
|
||||||
return. Stars are a way to show that you like a repository. They are
|
|
||||||
also an easy way of bookmarking your favorites.
|
|
||||||
|
|
||||||
## Comments
|
|
||||||
|
|
||||||
You can interact with other members of the Docker community and maintainers by
|
|
||||||
leaving comments on repositories. If you find any comments that are not
|
|
||||||
appropriate, you can flag them for review.
|
|
||||||
|
|
||||||
## Collaborators and their role
|
|
||||||
|
|
||||||
A collaborator is someone you want to give access to a private
|
|
||||||
repository. Once designated, they can `push` and `pull` to your
|
|
||||||
repositories. They will not be allowed to perform any administrative
|
|
||||||
tasks such as deleting the repository or changing its status from
|
|
||||||
private to public.
|
|
||||||
|
|
||||||
> **Note:**
|
|
||||||
> A collaborator cannot add other collaborators. Only the owner of
|
|
||||||
> the repository has administrative access.
|
|
||||||
|
|
||||||
You can also assign more granular collaborator rights ("Read", "Write", or "Admin")
|
|
||||||
on Docker Hub by using organizations and groups. For more information
|
|
||||||
see the [accounts documentation](accounts/).
|
|
||||||
|
|
||||||
## Private repositories
|
|
||||||
|
|
||||||
Private repositories allow you to have repositories that contain images
|
|
||||||
that you want to keep private, either to your own account or within an
|
|
||||||
organization or group.
|
|
||||||
|
|
||||||
To work with a private repository on [Docker
|
|
||||||
Hub](https://hub.docker.com), you will need to add one via the [Add
|
|
||||||
Repository](https://registry.hub.docker.com/account/repositories/add/)
|
|
||||||
link. You get one private repository for free with your Docker Hub
|
|
||||||
account. If you need more accounts you can upgrade your [Docker
|
|
||||||
Hub](https://registry.hub.docker.com/plans/) plan.
|
|
||||||
|
|
||||||
Once the private repository is created, you can `push` and `pull` images
|
|
||||||
to and from it using Docker.
|
|
||||||
|
|
||||||
> *Note:* You need to be signed in and have access to work with a
|
|
||||||
> private repository.
|
|
||||||
|
|
||||||
Private repositories are just like public ones. However, it isn't
|
|
||||||
possible to browse them or search their content on the public registry.
|
|
||||||
They do not get cached the same way as a public repository either.
|
|
||||||
|
|
||||||
It is possible to give access to a private repository to those whom you
|
|
||||||
designate (i.e., collaborators) from its Settings page. From there, you
|
|
||||||
can also switch repository status (*public* to *private*, or
|
|
||||||
vice-versa). You will need to have an available private repository slot
|
|
||||||
open before you can do such a switch. If you don't have any available,
|
|
||||||
you can always upgrade your [Docker
|
|
||||||
Hub](https://registry.hub.docker.com/plans/) plan.
|
|
||||||
|
|
||||||
## Webhooks
|
|
||||||
|
|
||||||
A webhook is an HTTP call-back triggered by a specific event.
|
|
||||||
You can use a Hub repository webhook to notify people, services, and other
|
|
||||||
applications after a new image is pushed to your repository (this also happens
|
|
||||||
for Automated builds). For example, you can trigger an automated test or
|
|
||||||
deployment to happen as soon as the image is available.
|
|
||||||
|
|
||||||
To get started adding webhooks, go to the desired repository in the Hub,
|
|
||||||
and click "Webhooks" under the "Settings" box.
|
|
||||||
A webhook is called only after a successful `push` is
|
|
||||||
made. The webhook calls are HTTP POST requests with a JSON payload
|
|
||||||
similar to the example shown below.
|
|
||||||
|
|
||||||
*Example webhook JSON payload:*
|
|
||||||
|
|
||||||
```
|
|
||||||
{
|
|
||||||
"callback_url": "https://registry.hub.docker.com/u/svendowideit/busybox/hook/2141bc0cdec4hebec411i4c1g40242eg110020/",
|
|
||||||
"push_data": {
|
|
||||||
"images": [
|
|
||||||
"27d47432a69bca5f2700e4dff7de0388ed65f9d3fb1ec645e2bc24c223dc1cc3",
|
|
||||||
"51a9c7c1f8bb2fa19bcd09789a34e63f35abb80044bc10196e304f6634cc582c",
|
|
||||||
...
|
|
||||||
],
|
|
||||||
"pushed_at": 1.417566822e+09,
|
|
||||||
"pusher": "svendowideit"
|
|
||||||
},
|
|
||||||
"repository": {
|
|
||||||
"comment_count": 0,
|
|
||||||
"date_created": 1.417566665e+09,
|
|
||||||
"description": "",
|
|
||||||
"full_description": "webhook triggered from a 'docker push'",
|
|
||||||
"is_official": false,
|
|
||||||
"is_private": false,
|
|
||||||
"is_trusted": false,
|
|
||||||
"name": "busybox",
|
|
||||||
"namespace": "svendowideit",
|
|
||||||
"owner": "svendowideit",
|
|
||||||
"repo_name": "svendowideit/busybox",
|
|
||||||
"repo_url": "https://registry.hub.docker.com/u/svendowideit/busybox/",
|
|
||||||
"star_count": 0,
|
|
||||||
"status": "Active"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
<TODO: does it tell you what tag was updated?>
|
|
||||||
|
|
||||||
For testing, you can try an HTTP request tool like [requestb.in](http://requestb.in/).
|
|
||||||
|
|
||||||
> **Note**: The Docker Hub servers use an elastic IP range, so you can't
|
|
||||||
> filter requests by IP.
|
|
||||||
|
|
||||||
### Webhook chains
|
|
||||||
|
|
||||||
Webhook chains allow you to chain calls to multiple services. For example,
|
|
||||||
you can use this to trigger a deployment of your container only after
|
|
||||||
it has been successfully tested, then update a separate Changelog once the
|
|
||||||
deployment is complete.
|
|
||||||
After clicking the "Add webhook" button, simply add as many URLs as necessary
|
|
||||||
in your chain.
|
|
||||||
|
|
||||||
The first webhook in a chain will be called after a successful push. Subsequent
|
|
||||||
URLs will be contacted after the callback has been validated.
|
|
||||||
|
|
||||||
### Validating a callback
|
|
||||||
|
|
||||||
In order to validate a callback in a webhook chain, you need to
|
|
||||||
|
|
||||||
1. Retrieve the `callback_url` value in the request's JSON payload.
|
|
||||||
1. Send a POST request to this URL containing a valid JSON body.
|
|
||||||
|
|
||||||
> **Note**: A chain request will only be considered complete once the last
|
|
||||||
> callback has been validated.
|
|
||||||
|
|
||||||
To help you debug or simply view the results of your webhook(s),
|
|
||||||
view the "History" of the webhook available on its settings page.
|
|
||||||
|
|
||||||
#### Callback JSON data
|
|
||||||
|
|
||||||
The following parameters are recognized in callback data:
|
|
||||||
|
|
||||||
* `state` (required): Accepted values are `success`, `failure` and `error`.
|
|
||||||
If the state isn't `success`, the webhook chain will be interrupted.
|
|
||||||
* `description`: A string containing miscellaneous information that will be
|
|
||||||
available on the Docker Hub. Maximum 255 characters.
|
|
||||||
* `context`: A string containing the context of the operation. Can be retrieved
|
|
||||||
from the Docker Hub. Maximum 100 characters.
|
|
||||||
* `target_url`: The URL where the results of the operation can be found. Can be
|
|
||||||
retrieved on the Docker Hub.
|
|
||||||
|
|
||||||
*Example callback payload:*
|
|
||||||
|
|
||||||
{
|
|
||||||
"state": "success",
|
|
||||||
"description": "387 tests PASSED",
|
|
||||||
"context": "Continuous integration by Acme CI",
|
|
||||||
"target_url": "http://ci.acme.com/results/afd339c1c3d27"
|
|
||||||
}
|
|
||||||
|
|
||||||
## Mark as unlisted
|
|
||||||
|
|
||||||
By marking a repository as unlisted, you can create a publicly pullable repository
|
|
||||||
which will not be in the Hub or commandline search. This allows you to have a limited
|
|
||||||
release, but does not restrict access to anyone that is told, or guesses the repository
|
|
||||||
name.
|
|
||||||
@@ -1,63 +0,0 @@
|
|||||||
<!--[metadata]>
|
|
||||||
+++
|
|
||||||
title = "Docker Hub user guide"
|
|
||||||
description = "Docker Hub user guide"
|
|
||||||
keywords = ["Docker, docker, registry, Docker Hub, docs, documentation"]
|
|
||||||
[menu.main]
|
|
||||||
parent = "smn_pubhub"
|
|
||||||
+++
|
|
||||||
<![end-metadata]-->
|
|
||||||
|
|
||||||
# Using the Docker Hub
|
|
||||||
|
|
||||||
Docker Hub is used to find and pull Docker images to run or build upon, and to
|
|
||||||
distribute and build images for other users to use.
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
## Finding repositories and images
|
|
||||||
|
|
||||||
There are two ways you can search for public repositories and images available
|
|
||||||
on the Docker Hub. You can use the "Search" tool on the Docker Hub website, or
|
|
||||||
you can `search` for all the repositories and images using the Docker commandline
|
|
||||||
tool:
|
|
||||||
|
|
||||||
$ docker search ubuntu
|
|
||||||
|
|
||||||
Both will show you a list of the currently available public repositories on the
|
|
||||||
Docker Hub which match the provided keyword.
|
|
||||||
|
|
||||||
If a repository is private or marked as unlisted, it won't be in the repository
|
|
||||||
search results. To see all the repositories you have access to and their statuses,
|
|
||||||
you can look at your profile page on [Docker Hub](https://hub.docker.com).
|
|
||||||
|
|
||||||
## Pulling, running and building images
|
|
||||||
|
|
||||||
You can find more information on [working with Docker images](../userguide/dockerimages.md).
|
|
||||||
|
|
||||||
## Official Repositories
|
|
||||||
|
|
||||||
The Docker Hub contains a number of [Official
|
|
||||||
Repositories](http://registry.hub.docker.com/official). These are
|
|
||||||
certified repositories from vendors and contributors to Docker. They
|
|
||||||
contain Docker images from vendors like Canonical, Oracle, and Red Hat
|
|
||||||
that you can use to build applications and services.
|
|
||||||
|
|
||||||
If you use Official Repositories you know you're using an optimized and
|
|
||||||
up-to-date image to power your applications.
|
|
||||||
|
|
||||||
> **Note:**
|
|
||||||
> If you would like to contribute an Official Repository for your
|
|
||||||
> organization, see [Official Repositories on Docker
|
|
||||||
> Hub](/docker-hub/official_repos) for more information.
|
|
||||||
|
|
||||||
## Building and shipping your own repositories and images
|
|
||||||
|
|
||||||
The Docker Hub provides you and your team with a place to build and ship Docker images.
|
|
||||||
|
|
||||||
Collections of Docker images are managed using repositories -
|
|
||||||
|
|
||||||
You can configure two types of repositories to manage on the Docker Hub:
|
|
||||||
[Repositories](./repos.md), which allow you to push images to the Hub from your local Docker daemon,
|
|
||||||
and [Automated Builds](./builds.md), which allow you to configure GitHub or Bitbucket to
|
|
||||||
trigger the Hub to rebuild repositories when changes are made to the repository.
|
|
||||||
@@ -31,6 +31,12 @@ Follow the instructions in the plugin's documentation.
|
|||||||
|
|
||||||
The following plugins exist:
|
The following plugins exist:
|
||||||
|
|
||||||
|
* The [Blockbridge plugin](https://github.com/blockbridge/blockbridge-docker-volume)
|
||||||
|
is a volume plugin that provides access to an extensible set of
|
||||||
|
container-based persistent storage options. It supports single and multi-host Docker
|
||||||
|
environments with features that include tenant isolation, automated
|
||||||
|
provisioning, encryption, secure deletion, snapshots and QoS.
|
||||||
|
|
||||||
* The [Flocker plugin](https://clusterhq.com/docker-plugin/) is a volume plugin
|
* The [Flocker plugin](https://clusterhq.com/docker-plugin/) is a volume plugin
|
||||||
which provides multi-host portable volumes for Docker, enabling you to run
|
which provides multi-host portable volumes for Docker, enabling you to run
|
||||||
databases and other stateful containers and move them around across a cluster
|
databases and other stateful containers and move them around across a cluster
|
||||||
|
|||||||
@@ -64,8 +64,7 @@ a container. To exit the container type `exit`.
|
|||||||
If you want your containers to be able to access the external network you must
|
If you want your containers to be able to access the external network you must
|
||||||
enable the `net.ipv4.ip_forward` rule.
|
enable the `net.ipv4.ip_forward` rule.
|
||||||
This can be done using YaST by browsing to the
|
This can be done using YaST by browsing to the
|
||||||
`Network Devices -> Network Settings -> Routing` menu and ensuring that the
|
`System -> Network Settings -> Routing` menu (for openSUSE Tumbleweed and later) or `Network Devices -> Network Settings -> Routing` menu (for SUSE Linux Enterprise 12 and previous openSUSE versions) and ensuring that the `Enable IPv4 Forwarding` box is checked.
|
||||||
`Enable IPv4 Forwarding` box is checked.
|
|
||||||
|
|
||||||
This option cannot be changed when networking is handled by the Network Manager.
|
This option cannot be changed when networking is handled by the Network Manager.
|
||||||
In such cases the `/etc/sysconfig/SuSEfirewall2` file needs to be edited by
|
In such cases the `/etc/sysconfig/SuSEfirewall2` file needs to be edited by
|
||||||
|
|||||||
@@ -96,7 +96,7 @@ which is officially supported by Docker.
|
|||||||
>command fails for the Docker repo during installation. To work around this,
|
>command fails for the Docker repo during installation. To work around this,
|
||||||
>add the key directly using the following:
|
>add the key directly using the following:
|
||||||
>
|
>
|
||||||
> $ wget -qO- https://get.docker.com/gpg | sudo apt-key add -
|
> $ curl -sSL https://get.docker.com/gpg | sudo apt-key add -
|
||||||
|
|
||||||
### Uninstallation
|
### Uninstallation
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ installation mechanisms. Using these packages ensures you get the latest release
|
|||||||
of Docker. If you wish to install using Fedora-managed packages, consult your
|
of Docker. If you wish to install using Fedora-managed packages, consult your
|
||||||
Fedora release documentation for information on Fedora's Docker support.
|
Fedora release documentation for information on Fedora's Docker support.
|
||||||
|
|
||||||
##Prerequisites
|
## Prerequisites
|
||||||
|
|
||||||
Docker requires a 64-bit installation regardless of your Fedora version. Also, your kernel must be 3.10 at minimum. To check your current kernel
|
Docker requires a 64-bit installation regardless of your Fedora version. Also, your kernel must be 3.10 at minimum. To check your current kernel
|
||||||
version, open a terminal and use `uname -r` to display your kernel version:
|
version, open a terminal and use `uname -r` to display your kernel version:
|
||||||
@@ -206,6 +206,24 @@ If you need to add an HTTP Proxy, set a different directory or partition for the
|
|||||||
Docker runtime files, or make other customizations, read our Systemd article to
|
Docker runtime files, or make other customizations, read our Systemd article to
|
||||||
learn how to [customize your Systemd Docker daemon options](/articles/systemd/).
|
learn how to [customize your Systemd Docker daemon options](/articles/systemd/).
|
||||||
|
|
||||||
|
## Running Docker with a manually-defined network
|
||||||
|
|
||||||
|
If you manually configure your network using `systemd-network` with `systemd` version 219 or higher, containers you start with Docker may be unable to access your network.
|
||||||
|
Beginning with version 220, the forwarding setting for a given network (`net.ipv4.conf.<interface>.forwarding`) defaults to *off*. This setting prevents IP forwarding. It also conflicts with Docker which enables the `net.ipv4.conf.all.forwarding` setting within a container.
|
||||||
|
|
||||||
|
To work around this, edit the `<interface>.network` file in
|
||||||
|
`/usr/lib/systemd/network/` on your Docker host (ex: `/usr/lib/systemd/network/80-container-host0.network`) add the following block:
|
||||||
|
|
||||||
|
```
|
||||||
|
[Network]
|
||||||
|
...
|
||||||
|
IPForward=kernel
|
||||||
|
# OR
|
||||||
|
IPForward=true
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
This configuration allows IP forwarding from the container as expected.
|
||||||
|
|
||||||
## Uninstall
|
## Uninstall
|
||||||
|
|
||||||
|
|||||||
|
After Width: | Height: | Size: 155 KiB |
|
After Width: | Height: | Size: 137 KiB |
|
After Width: | Height: | Size: 30 KiB |
|
After Width: | Height: | Size: 28 KiB |
|
After Width: | Height: | Size: 152 KiB |
|
After Width: | Height: | Size: 134 KiB |
|
Before Width: | Height: | Size: 28 KiB |
|
After Width: | Height: | Size: 58 KiB |
|
After Width: | Height: | Size: 86 KiB |
|
After Width: | Height: | Size: 92 KiB |
|
After Width: | Height: | Size: 49 KiB |
|
After Width: | Height: | Size: 117 KiB |
|
Before Width: | Height: | Size: 68 KiB |
@@ -10,37 +10,34 @@ parent = "smn_engine"
|
|||||||
|
|
||||||
# Mac OS X
|
# Mac OS X
|
||||||
|
|
||||||
You can install Docker using Boot2Docker to run `docker` commands at your command-line.
|
> **Note**: This release of Docker deprecates the Boot2Docker command line in
|
||||||
Choose this installation if you are familiar with the command-line or plan to
|
> favor of Docker Machine. Use the Docker Toolbox to install Docker Machine as
|
||||||
contribute to the Docker project on GitHub.
|
> well as the other Docker tools.
|
||||||
|
|
||||||
[<img src="/installation/images/kitematic.png" alt="Download Kitematic"
|
You install Docker using Docker Toolbox. Docker Toolbox includes the following Docker tools:
|
||||||
style="float:right;">](https://kitematic.com/download)
|
|
||||||
|
|
||||||
Alternatively, you may want to try <a id="inlinelink" href="https://kitematic.com/"
|
* Docker Machine for running the `docker-machine` binary
|
||||||
target="_blank">Kitematic</a>, an application that lets you set up Docker and
|
* Docker Engine for running the `docker` binary
|
||||||
run containers using a graphical user interface (GUI).
|
* Docker Compose for running the `docker-compose` binary
|
||||||
|
* Kitematic, the Docker GUI
|
||||||
## Command-line Docker with Boot2Docker
|
* a shell preconfigured for a Docker command-line environment
|
||||||
|
* Oracle VM VirtualBox
|
||||||
|
|
||||||
Because the Docker daemon uses Linux-specific kernel features, you can't run
|
Because the Docker daemon uses Linux-specific kernel features, you can't run
|
||||||
Docker natively in OS X. Instead, you must install the Boot2Docker application.
|
Docker natively in OS X. Instead, you must use `docker-machine` to create and
|
||||||
The application includes a VirtualBox Virtual Machine (VM), Docker itself, and the
|
attach to a virtual machine (VM). This machine is a Linux VM that hosts Docker
|
||||||
Boot2Docker management tool.
|
for you on your Mac.
|
||||||
|
|
||||||
The Boot2Docker management tool is a lightweight Linux virtual machine made
|
|
||||||
specifically to run the Docker daemon on Mac OS X. The VirtualBox VM runs
|
|
||||||
completely from RAM, is a small ~24MB download, and boots in approximately 5s.
|
|
||||||
|
|
||||||
**Requirements**
|
**Requirements**
|
||||||
|
|
||||||
Your Mac must be running OS X 10.6 "Snow Leopard" or newer to run Boot2Docker.
|
Your Mac must be running OS X 10.8 "Mountain Lion" or newer to install the
|
||||||
|
Docker Toolbox.
|
||||||
|
|
||||||
### Learn the key concepts before installing
|
### Learn the key concepts before installing
|
||||||
|
|
||||||
In a Docker installation on Linux, your machine is both the localhost and the
|
In a Docker installation on Linux, your physical machine is both the localhost
|
||||||
Docker host. In networking, localhost means your computer. The Docker host is
|
and the Docker host. In networking, localhost means your computer. The Docker
|
||||||
the machine on which the containers run.
|
host is the computer on which the containers run.
|
||||||
|
|
||||||
On a typical Linux installation, the Docker client, the Docker daemon, and any
|
On a typical Linux installation, the Docker client, the Docker daemon, and any
|
||||||
containers run directly on your localhost. This means you can address ports on a
|
containers run directly on your localhost. This means you can address ports on a
|
||||||
@@ -49,135 +46,243 @@ Docker container using standard localhost addressing such as `localhost:8000` or
|
|||||||
|
|
||||||

|

|
||||||
|
|
||||||
In an OS X installation, the `docker` daemon is running inside a Linux virtual
|
In an OS X installation, the `docker` daemon is running inside a Linux VM called
|
||||||
machine provided by Boot2Docker.
|
`default`. The `default` is a lightweight Linux VM made specifically to run
|
||||||
|
the Docker daemon on Mac OS X. The VM runs completely from RAM, is a small ~24MB
|
||||||
|
download, and boots in approximately 5s.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
In OS X, the Docker host address is the address of the Linux VM.
|
In OS X, the Docker host address is the address of the Linux VM. When you start
|
||||||
When you start the `boot2docker` process, the VM is assigned an IP address. Under
|
the VM with `docker-machine` it is assigned an IP address. When you start a
|
||||||
`boot2docker` ports on a container map to ports on the VM. To see this in
|
container, the ports on a container map to ports on the VM. To see this in
|
||||||
practice, work through the exercises on this page.
|
practice, work through the exercises on this page.
|
||||||
|
|
||||||
|
|
||||||
### Installation
|
### Installation
|
||||||
|
|
||||||
1. Go to the [boot2docker/osx-installer ](
|
If you have VirtualBox running, you must shut it down before running the
|
||||||
https://github.com/boot2docker/osx-installer/releases/latest) release page.
|
installer.
|
||||||
|
|
||||||
4. Download Boot2Docker by clicking `Boot2Docker-x.x.x.pkg` in the "Downloads"
|
1. Go to the [Docker Toolbox](https://www.docker.com/toolbox) page.
|
||||||
section.
|
|
||||||
|
|
||||||
3. Install Boot2Docker by double-clicking the package.
|
2. Click the installer link to download.
|
||||||
|
|
||||||
The installer places Boot2Docker and VirtualBox in your "Applications" folder.
|
3. Install Docker Toolbox by double-clicking the package or by right-clicking
|
||||||
|
and choosing "Open" from the pop-up menu.
|
||||||
|
|
||||||
The installation places the `docker` and `boot2docker` binaries in your
|
The installer launches the "Install Docker Toolbox" dialog.
|
||||||
`/usr/local/bin` directory.
|
|
||||||
|

|
||||||
|
|
||||||
|
4. Press "Continue" to install the toolbox.
|
||||||
|
|
||||||
|
The installer presents you with options to customize the standard
|
||||||
|
installation.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
By default, the standard Docker Toolbox installation:
|
||||||
|
|
||||||
|
* installs binaries for the Docker tools in `/usr/local/bin`
|
||||||
|
* makes these binaries available to all users
|
||||||
|
* updates any existing VirtualBox installation
|
||||||
|
|
||||||
|
Change these defaults by pressing "Customize" or "Change
|
||||||
|
Install Location."
|
||||||
|
|
||||||
|
5. Press "Install" to perform the standard installation.
|
||||||
|
|
||||||
|
The system prompts you for your password.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
6. Provide your password to continue with the installation.
|
||||||
|
|
||||||
|
When it completes, the installer provides you with some information you can
|
||||||
|
use to complete some common tasks.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
7. Press "Close" to exit.
|
||||||
|
|
||||||
|
|
||||||
## Start the Boot2Docker Application
|
## Running a Docker Container
|
||||||
|
|
||||||
To run a Docker container, you first start the `boot2docker` VM and then issue
|
To run a Docker container, you:
|
||||||
`docker` commands to create, load, and manage containers. You can launch
|
|
||||||
`boot2docker` from your Applications folder or from the command line.
|
|
||||||
|
|
||||||
> **NOTE**: Boot2Docker is designed as a development tool. You should not use
|
* create a new (or start an existing) Docker virtual machine
|
||||||
> it in production environments.
|
* switch your environment to your new VM
|
||||||
|
* use the `docker` client to create, load, and manage containers
|
||||||
|
|
||||||
### From the Applications folder
|
Once you create a machine, you can reuse it as often as you like. Like any
|
||||||
|
VirtualBox VM, it maintains its configuration between uses.
|
||||||
|
|
||||||
When you launch the "Boot2Docker" application from your "Applications" folder, the
|
There are two ways to use the installed tools, from the Docker Quickstart Terminal or
|
||||||
application:
|
[from your shell](#from-your-shell).
|
||||||
|
|
||||||
* opens a terminal window
|
### From the Docker Quickstart Terminal
|
||||||
|
|
||||||
* creates a $HOME/.boot2docker directory
|
1. Open the "Applications" folder or the "Launchpad".
|
||||||
|
|
||||||
* creates a VirtualBox ISO and certs
|
2. Find the Docker Quickstart Terminal and double-click to launch it.
|
||||||
|
|
||||||
* starts a VirtualBox VM running the `docker` daemon
|
The application:
|
||||||
|
|
||||||
Once the launch completes, you can run `docker` commands. A good way to verify
|
* opens a terminal window
|
||||||
your setup succeeded is to run the `hello-world` container.
|
* creates a VM called `default` if it doesn't exists, starts the VM if it does
|
||||||
|
* points the terminal environment to this VM
|
||||||
|
|
||||||
$ docker run hello-world
|
Once the launch completes, the Docker Quickstart Terminal reports:
|
||||||
Unable to find image 'hello-world:latest' locally
|
|
||||||
511136ea3c5a: Pull complete
|

|
||||||
31cbccb51277: Pull complete
|
|
||||||
e45a5af57b00: Pull complete
|
Now, you can run `docker` commands.
|
||||||
hello-world:latest: The image you are pulling has been verified.
|
|
||||||
Important: image verification is a tech preview feature and should not be
|
|
||||||
relied on to provide security.
|
|
||||||
Status: Downloaded newer image for hello-world:latest
|
|
||||||
Hello from Docker.
|
|
||||||
This message shows that your installation appears to be working correctly.
|
|
||||||
|
|
||||||
To generate this message, Docker took the following steps:
|
3. Verify your setup succeeded by running the `hello-world` container.
|
||||||
1. The Docker client contacted the Docker daemon.
|
|
||||||
2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
|
|
||||||
(Assuming it was not already locally available.)
|
|
||||||
3. The Docker daemon created a new container from that image which runs the
|
|
||||||
executable that produces the output you are currently reading.
|
|
||||||
4. The Docker daemon streamed that output to the Docker client, which sent it
|
|
||||||
to your terminal.
|
|
||||||
|
|
||||||
To try something more ambitious, you can run an Ubuntu container with:
|
$ docker run hello-world
|
||||||
$ docker run -it ubuntu bash
|
Unable to find image 'hello-world:latest' locally
|
||||||
|
511136ea3c5a: Pull complete
|
||||||
|
31cbccb51277: Pull complete
|
||||||
|
e45a5af57b00: Pull complete
|
||||||
|
hello-world:latest: The image you are pulling has been verified.
|
||||||
|
Important: image verification is a tech preview feature and should not be
|
||||||
|
relied on to provide security.
|
||||||
|
Status: Downloaded newer image for hello-world:latest
|
||||||
|
Hello from Docker.
|
||||||
|
This message shows that your installation appears to be working correctly.
|
||||||
|
|
||||||
For more examples and ideas, visit:
|
To generate this message, Docker took the following steps:
|
||||||
http://docs.docker.com/userguide/
|
1. The Docker client contacted the Docker daemon.
|
||||||
|
2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
|
||||||
|
(Assuming it was not already locally available.)
|
||||||
|
3. The Docker daemon created a new container from that image which runs the
|
||||||
|
executable that produces the output you are currently reading.
|
||||||
|
4. The Docker daemon streamed that output to the Docker client, which sent it
|
||||||
|
to your terminal.
|
||||||
|
|
||||||
|
To try something more ambitious, you can run an Ubuntu container with:
|
||||||
|
$ docker run -it ubuntu bash
|
||||||
|
|
||||||
|
For more examples and ideas, visit:
|
||||||
|
http://docs.docker.com/userguide/
|
||||||
|
|
||||||
|
|
||||||
A more typical way to start and stop `boot2docker` is using the command line.
|
A more typical way to interact with the Docker tools is from your regular shell command line.
|
||||||
|
|
||||||
### From your command line
|
### From your shell
|
||||||
|
|
||||||
Initialize and run `boot2docker` from the command line, do the following:
|
This section assumes you are running a Bash shell. You may be running a
|
||||||
|
different shell such as C Shell but the commands are the same.
|
||||||
|
|
||||||
1. Create a new Boot2Docker VM.
|
1. Create a new Docker VM.
|
||||||
|
|
||||||
$ boot2docker init
|
$ docker-machine create --driver virtualbox default
|
||||||
|
Creating VirtualBox VM...
|
||||||
|
Creating SSH key...
|
||||||
|
Starting VirtualBox VM...
|
||||||
|
Starting VM...
|
||||||
|
To see how to connect Docker to this machine, run: docker-machine env default
|
||||||
|
|
||||||
This creates a new virtual machine. You only need to run this command once.
|
This creates a new `default` in VirtualBox.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
2. Start the `boot2docker` VM.
|
The command also creates a machine configuration in the
|
||||||
|
`~/.docker/machine/machines/default` directory. You only need to run the
|
||||||
|
`create` command once. Then, you can use `docker-machine` to start, stop,
|
||||||
|
query, and otherwise manage the VM from the command line.
|
||||||
|
|
||||||
|
2. List your available machines.
|
||||||
|
|
||||||
$ boot2docker start
|
$ docker-machine ls
|
||||||
|
NAME ACTIVE DRIVER STATE URL SWARM
|
||||||
|
default * virtualbox Running tcp://192.168.99.101:2376
|
||||||
|
|
||||||
|
If you have previously installed the deprecated Boot2Docker application or
|
||||||
|
run the Docker Quickstart Terminal, you may have a `dev` VM as well. When you
|
||||||
|
created `default`, the `docker-machine` command provided instructions
|
||||||
|
for learning how to connect the VM.
|
||||||
|
|
||||||
3. Display the environment variables for the Docker client.
|
3. Get the environment commands for your new VM.
|
||||||
|
|
||||||
$ boot2docker shellinit
|
$ docker-machine env default
|
||||||
Writing /Users/mary/.boot2docker/certs/boot2docker-vm/ca.pem
|
export DOCKER_TLS_VERIFY="1"
|
||||||
Writing /Users/mary/.boot2docker/certs/boot2docker-vm/cert.pem
|
export DOCKER_HOST="tcp://192.168.99.101:2376"
|
||||||
Writing /Users/mary/.boot2docker/certs/boot2docker-vm/key.pem
|
export DOCKER_CERT_PATH="/Users/mary/.docker/machine/machines/default"
|
||||||
export DOCKER_HOST=tcp://192.168.59.103:2376
|
export DOCKER_MACHINE_NAME="default"
|
||||||
export DOCKER_CERT_PATH=/Users/mary/.boot2docker/certs/boot2docker-vm
|
# Run this command to configure your shell:
|
||||||
export DOCKER_TLS_VERIFY=1
|
# eval "$(docker-machine env default)"
|
||||||
|
|
||||||
|
4. Connect your shell to the `default` machine.
|
||||||
|
|
||||||
The specific paths and address on your machine will be different.
|
$ eval "$(docker-machine env default)"
|
||||||
|
|
||||||
4. To set the environment variables in your shell do the following:
|
|
||||||
|
|
||||||
$ eval "$(boot2docker shellinit)"
|
|
||||||
|
|
||||||
You can also set them manually by using the `export` commands `boot2docker`
|
|
||||||
returns.
|
|
||||||
|
|
||||||
5. Run the `hello-world` container to verify your setup.
|
5. Run the `hello-world` container to verify your setup.
|
||||||
|
|
||||||
$ docker run hello-world
|
$ docker run hello-world
|
||||||
|
|
||||||
|
|
||||||
## Basic Boot2Docker exercises
|
## Learn about your Toolbox installation
|
||||||
|
|
||||||
At this point, you should have `boot2docker` running and the `docker` client
|
Toolbox installs the Docker Engine binary, the Docker binary on your system. When you
|
||||||
environment initialized. To verify this, run the following commands:
|
use the Docker Quickstart Terminal or create a `default` manually, Docker
|
||||||
|
Machine updates the `~/.docker/machine/machines/default` folder to your
|
||||||
|
system. This folder contains the configuration for the VM.
|
||||||
|
|
||||||
$ boot2docker status
|
You can create multiple VMs on your system with Docker Machine. So, you may have
|
||||||
$ docker version
|
more than one VM folder if you have more than one VM. To remove a VM, use the
|
||||||
|
`docker-machine rm <machine-name>` command.
|
||||||
|
|
||||||
Work through this section to try some practical container tasks using `boot2docker` VM.
|
## Migrate from Boot2Docker
|
||||||
|
|
||||||
|
If you were using Boot2Docker previously, you have a pre-existing Docker
|
||||||
|
`boot2docker-vm` VM on your local system. To allow Docker Machine to manage
|
||||||
|
this older VM, you can migrate it.
|
||||||
|
|
||||||
|
1. Open a terminal or the Docker CLI on your system.
|
||||||
|
|
||||||
|
2. Type the following command.
|
||||||
|
|
||||||
|
$ docker-machine create -d virtualbox --virtualbox-import-boot2docker-vm boot2docker-vm docker-vm
|
||||||
|
|
||||||
|
3. Use the `docker-machine` command to interact with the migrated VM.
|
||||||
|
|
||||||
|
The `docker-machine` subcommands are slightly different than the `boot2docker`
|
||||||
|
subcommands. The table below lists the equivalent `docker-machine` subcommand
|
||||||
|
and what it does:
|
||||||
|
|
||||||
|
| `boot2docker` | `docker-machine` | `docker-machine` description |
|
||||||
|
|----------------|------------------|----------------------------------------------------------|
|
||||||
|
| init | create | Creates a new docker host. |
|
||||||
|
| up | start | Starts a stopped machine. |
|
||||||
|
| ssh | ssh | Runs a command or interactive ssh session on the machine.|
|
||||||
|
| save | - | Not applicable. |
|
||||||
|
| down | stop | Stops a running machine. |
|
||||||
|
| poweroff | stop | Stops a running machine. |
|
||||||
|
| reset | restart | Restarts a running machine. |
|
||||||
|
| config | inspect | Prints machine configuration details. |
|
||||||
|
| status | ls | Lists all machines and their status. |
|
||||||
|
| info | inspect | Displays a machine's details. |
|
||||||
|
| ip | ip | Displays the machine's ip address. |
|
||||||
|
| shellinit | env | Displays shell commands needed to configure your shell to interact with a machine |
|
||||||
|
| delete | rm | Removes a machine. |
|
||||||
|
| download | - | Not applicable. |
|
||||||
|
| upgrade | upgrade | Upgrades a machine's Docker client to the latest stable release. |
|
||||||
|
|
||||||
|
|
||||||
|
## Example of Docker on Mac OS X
|
||||||
|
|
||||||
|
Work through this section to try some practical container tasks on a VM. At this
|
||||||
|
point, you should have a VM running and be connected to it through your shell.
|
||||||
|
To verify this, run the following commands:
|
||||||
|
|
||||||
|
$ docker-machine ls
|
||||||
|
NAME ACTIVE DRIVER STATE URL SWARM
|
||||||
|
default * virtualbox Running tcp://192.168.99.100:2376
|
||||||
|
|
||||||
|
The `ACTIVE` machine, in this case `default`, is the one your environment is pointing to.
|
||||||
|
|
||||||
### Access container ports
|
### Access container ports
|
||||||
|
|
||||||
@@ -212,11 +317,11 @@ Work through this section to try some practical container tasks using `boot2dock
|
|||||||
|
|
||||||
This didn't work. The reason it doesn't work is your `DOCKER_HOST` address is
|
This didn't work. The reason it doesn't work is your `DOCKER_HOST` address is
|
||||||
not the localhost address (0.0.0.0) but is instead the address of the
|
not the localhost address (0.0.0.0) but is instead the address of the
|
||||||
`boot2docker` VM.
|
your Docker VM.
|
||||||
|
|
||||||
5. Get the address of the `boot2docker` VM.
|
5. Get the address of the `default` VM.
|
||||||
|
|
||||||
$ boot2docker ip
|
$ docker-machine ip default
|
||||||
192.168.59.103
|
192.168.59.103
|
||||||
|
|
||||||
6. Enter the `http://192.168.59.103:49157` address in your browser:
|
6. Enter the `http://192.168.59.103:49157` address in your browser:
|
||||||
@@ -232,7 +337,7 @@ Work through this section to try some practical container tasks using `boot2dock
|
|||||||
|
|
||||||
### Mount a volume on the container
|
### Mount a volume on the container
|
||||||
|
|
||||||
When you start `boot2docker`, it automatically shares your `/Users` directory
|
When you start a container it automatically shares your `/Users/username` directory
|
||||||
with the VM. You can use this share point to mount directories onto your container.
|
with the VM. You can use this share point to mount directories onto your container.
|
||||||
The next exercise demonstrates how to do this.
|
The next exercise demonstrates how to do this.
|
||||||
|
|
||||||
@@ -254,7 +359,8 @@ The next exercise demonstrates how to do this.
|
|||||||
|
|
||||||
5. Start a new `nginx` container and replace the `html` folder with your `site` directory.
|
5. Start a new `nginx` container and replace the `html` folder with your `site` directory.
|
||||||
|
|
||||||
$ docker run -d -P -v $HOME/site:/usr/share/nginx/html --name mysite nginx
|
$ docker run -d -P -v $HOME/site:/usr/share/nginx/html \
|
||||||
|
--name mysite nginx
|
||||||
|
|
||||||
6. Get the `mysite` container's port.
|
6. Get the `mysite` container's port.
|
||||||
|
|
||||||
@@ -274,85 +380,53 @@ The next exercise demonstrates how to do this.
|
|||||||
|
|
||||||

|

|
||||||
|
|
||||||
9. Stop and then remove your running `mysite` container.
|
10. Stop and then remove your running `mysite` container.
|
||||||
|
|
||||||
$ docker stop mysite
|
$ docker stop mysite
|
||||||
$ docker rm mysite
|
$ docker rm mysite
|
||||||
|
|
||||||
## Upgrade Boot2Docker
|
|
||||||
|
|
||||||
If you running Boot2Docker 1.4.1 or greater, you can upgrade Boot2Docker from
|
## Upgrade Docker Toolbox
|
||||||
the command line. If you are running an older version, you should use the
|
|
||||||
package provided by the `boot2docker` repository.
|
|
||||||
|
|
||||||
### From the command line
|
To upgrade Docker Toolbox, download an re-run [the Docker Toolbox
|
||||||
|
installer](https://docker.com/toolbox/).
|
||||||
To upgrade from 1.4.1 or greater, you can do this:
|
|
||||||
|
|
||||||
1. Open a terminal on your local machine.
|
|
||||||
|
|
||||||
2. Stop the `boot2docker` application.
|
|
||||||
|
|
||||||
$ boot2docker stop
|
|
||||||
|
|
||||||
3. Run the upgrade command.
|
|
||||||
|
|
||||||
$ boot2docker upgrade
|
|
||||||
|
|
||||||
|
|
||||||
### Use the installer
|
## Uninstall Docker Toolbox
|
||||||
|
|
||||||
To upgrade any version of Boot2Docker, do this:
|
To uninstall, do the following:
|
||||||
|
|
||||||
1. Open a terminal on your local machine.
|
1. List your machines.
|
||||||
|
|
||||||
2. Stop the `boot2docker` application.
|
$ docker-machine ls
|
||||||
|
NAME ACTIVE DRIVER STATE URL SWARM
|
||||||
|
dev * virtualbox Running tcp://192.168.99.100:2376
|
||||||
|
my-docker-machine virtualbox Stopped
|
||||||
|
default virtualbox Stopped
|
||||||
|
|
||||||
$ boot2docker stop
|
2. Remove each machine.
|
||||||
|
|
||||||
3. Go to the [boot2docker/osx-installer ](
|
$ docker-machine rm dev
|
||||||
https://github.com/boot2docker/osx-installer/releases/latest) release page.
|
Successfully removed dev
|
||||||
|
|
||||||
|
Removing a machine deletes its VM from VirtualBox and from the
|
||||||
|
`~/.docker/machine/machines` directory.
|
||||||
|
|
||||||
4. Download Boot2Docker by clicking `Boot2Docker-x.x.x.pkg` in the "Downloads"
|
3. Remove the Docker Quickstart Terminal and Kitematic from your "Applications" folder.
|
||||||
section.
|
|
||||||
|
|
||||||
2. Install Boot2Docker by double-clicking the package.
|
4. Remove the `docker`, `docker-compose`, and `docker-machine` commands from the `/usr/local/bin` folder.
|
||||||
|
|
||||||
The installer places Boot2Docker in your "Applications" folder.
|
$ rm /usr/local/bin/docker
|
||||||
|
|
||||||
|
5. Delete the `~/.docker` folder from your system.
|
||||||
|
|
||||||
|
|
||||||
## Uninstallation
|
## Learning more
|
||||||
|
|
||||||
1. Go to the [boot2docker/osx-installer ](
|
Use `docker-machine help` to list the full command line reference for Docker Machine. For more
|
||||||
https://github.com/boot2docker/osx-installer/releases/latest) release page.
|
information about using SSH or SCP to access a VM, see [the Docker Machine
|
||||||
|
documentation](https://docs.docker.com/machine/).
|
||||||
|
|
||||||
2. Download the source code by clicking `Source code (zip)` or
|
You can continue with the [Docker User Guide](/userguide). If you are
|
||||||
`Source code (tar.gz)` in the "Downloads" section.
|
interested in using the Kitematic GUI, see the [Kitermatic user
|
||||||
|
guide](/kitematic/userguide/).
|
||||||
3. Extract the source code.
|
|
||||||
|
|
||||||
4. Open a terminal on your local machine.
|
|
||||||
|
|
||||||
5. Change to the directory where you extracted the source code:
|
|
||||||
|
|
||||||
$ cd <path to extracted source code>
|
|
||||||
|
|
||||||
6. Make sure the uninstall.sh script is executable:
|
|
||||||
|
|
||||||
$ chmod +x uninstall.sh
|
|
||||||
|
|
||||||
7. Run the uninstall.sh script:
|
|
||||||
|
|
||||||
$ ./uninstall.sh
|
|
||||||
|
|
||||||
|
|
||||||
## Learning more and acknowledgement
|
|
||||||
|
|
||||||
Use `boot2docker help` to list the full command line reference. For more
|
|
||||||
information about using SSH or SCP to access the Boot2Docker VM, see the README
|
|
||||||
at [Boot2Docker repository](https://github.com/boot2docker/boot2docker).
|
|
||||||
|
|
||||||
Thanks to Chris Jones whose [blog](http://viget.com/extend/how-to-use-docker-on-os-x-the-missing-guide)
|
|
||||||
inspired me to redo this page.
|
|
||||||
|
|
||||||
Continue with the [Docker User Guide](/userguide).
|
|
||||||