mirror of
https://github.com/clearlinux/docker.git
synced 2026-08-20 12:45:50 +00:00
Compare commits
42 Commits
v1.7.0-rc2
...
v1.7.0-rc3
| Author | SHA1 | Date | |
|---|---|---|---|
| 94159c9559 | |||
| 73e41874b6 | |||
| 64552d0b49 | |||
| 84b21b55b9 | |||
| 7ffbd7eaee | |||
| 469534c855 | |||
| 85d6e7c4ec | |||
| a1f16a3738 | |||
| 2ef2967570 | |||
| ceda1e75a4 | |||
| 2519689e99 | |||
| 009ba67dd0 | |||
| 4743f3b3aa | |||
| 759cdd8ed6 | |||
| ff770d33cd | |||
| 1d3f7cc012 | |||
| 5291de79ae | |||
| 821f9450fc | |||
| 6a04940f86 | |||
| cf13497ca8 | |||
| 2b15a888cd | |||
| 455ad3afe2 | |||
| b5086a7494 | |||
| 80157b35ac | |||
| 4ebcd0d544 | |||
| 3e4284bd7c | |||
| eb4798a10e | |||
| 6c90a239ed | |||
| 8e81f3711f | |||
| d10ed90080 | |||
| 7223584e10 | |||
| c4ba3a8352 | |||
| 33588c23c3 | |||
| 6a5cbd0dd4 | |||
| 495640005a | |||
| 5c408158a6 | |||
| ede1c3f0c2 | |||
| 09295a1453 | |||
| 1f6eca7b99 | |||
| 8f211fde46 | |||
| 5c70b1eadd | |||
| b3adf94d81 |
@@ -30,5 +30,8 @@ docs/_build
|
||||
docs/_static
|
||||
docs/_templates
|
||||
docs/changed-files
|
||||
# generated by man/man/md2man-all.sh
|
||||
man/man1
|
||||
man/man5
|
||||
pyenv
|
||||
vendor/pkg/
|
||||
|
||||
@@ -1,5 +1,39 @@
|
||||
# Changelog
|
||||
|
||||
## 1.7.0 (2015-06-16)
|
||||
|
||||
#### Runtime
|
||||
+ Experimental feature: support for out-of-process volume plugins
|
||||
+ Experimental feature: support for out-of-process network plugins
|
||||
* Logging: syslog logging driver is available
|
||||
* The userland proxy can be disabled in favor of hairpin NAT using the daemon’s `--userland-proxy=false` flag
|
||||
* The `exec` command supports the `-u|--user` flag to specify the new process owner
|
||||
+ Default gateway for containers can be specified daemon-wide using the `--default-gateway` and `--default-gateway-v6` flags
|
||||
+ The CPU CFS (Completely Fair Scheduler) quota can be set in `docker run` using `--cpu-quota`
|
||||
+ Container block IO can be controlled in `docker run` using`--blkio-weight`
|
||||
+ ZFS support
|
||||
+ The `docker logs` command supports a `--since` argument
|
||||
+ UTS namespace can be shared with the host with `docker run --uts=host`
|
||||
|
||||
#### Quality
|
||||
* Networking stack was entirely rewritten as part of the libnetwork effort
|
||||
* Engine internals refactoring
|
||||
* Volumes code was entirely rewritten to support the plugins effort
|
||||
+ Sending SIGUSR1 to a daemon will dump all goroutines stacks without exiting
|
||||
|
||||
#### Build
|
||||
+ Support ${variable:-value} and ${variable:+value} syntax for environment variables
|
||||
+ Support resource management flags `--cgroup-parent`, `--cpu-period`, `--cpu-quota`, `--cpuset-cpus`, `--cpuset-mems`
|
||||
+ git context changes with branches and directories
|
||||
* The .dockerignore file support exclusion rules
|
||||
|
||||
#### Distribution
|
||||
+ Client support for v2 mirroring support for the official registry
|
||||
|
||||
#### Bugfixes
|
||||
* Firewalld is now supported and will automatically be used when available
|
||||
* mounting --device recursively
|
||||
|
||||
## 1.6.2 (2015-05-13)
|
||||
|
||||
#### Runtime
|
||||
|
||||
@@ -30,7 +30,7 @@ security@docker.com and not by creating a github issue.
|
||||
|
||||
A common method for distributing applications and sandboxing their
|
||||
execution is to use virtual machines, or VMs. Typical VM formats are
|
||||
VMWare's vmdk, Oracle Virtualbox's vdi, and Amazon EC2's ami. In theory
|
||||
VMware's vmdk, Oracle Virtualbox's vdi, and Amazon EC2's ami. In theory
|
||||
these formats should allow every developer to automatically package
|
||||
their application into a "machine" for easy distribution and deployment.
|
||||
In practice, that almost never happens, for a few reasons:
|
||||
|
||||
+14
-33
@@ -36,7 +36,6 @@ import (
|
||||
"github.com/docker/docker/pkg/version"
|
||||
"github.com/docker/docker/runconfig"
|
||||
"github.com/docker/docker/utils"
|
||||
"github.com/docker/libnetwork/portallocator"
|
||||
)
|
||||
|
||||
type ServerConfig struct {
|
||||
@@ -399,6 +398,7 @@ func (s *Server) getEvents(version version.Version, w http.ResponseWriter, r *ht
|
||||
}
|
||||
until = u
|
||||
}
|
||||
|
||||
timer := time.NewTimer(0)
|
||||
timer.Stop()
|
||||
if until > 0 {
|
||||
@@ -457,6 +457,9 @@ func (s *Server) getEvents(version version.Version, w http.ResponseWriter, r *ht
|
||||
}
|
||||
|
||||
current, l := es.Subscribe()
|
||||
if since == -1 {
|
||||
current = nil
|
||||
}
|
||||
defer es.Evict(l)
|
||||
for _, ev := range current {
|
||||
if ev.Time < since {
|
||||
@@ -572,7 +575,16 @@ func (s *Server) getContainersStats(version version.Version, w http.ResponseWrit
|
||||
return fmt.Errorf("Missing parameter")
|
||||
}
|
||||
|
||||
return s.daemon.ContainerStats(vars["name"], boolValueOrDefault(r, "stream", true), ioutils.NewWriteFlusher(w))
|
||||
stream := boolValueOrDefault(r, "stream", true)
|
||||
var out io.Writer
|
||||
if !stream {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
out = w
|
||||
} else {
|
||||
out = ioutils.NewWriteFlusher(w)
|
||||
}
|
||||
|
||||
return s.daemon.ContainerStats(vars["name"], stream, out)
|
||||
}
|
||||
|
||||
func (s *Server) getContainersLogs(version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||
@@ -656,10 +668,6 @@ func (s *Server) postCommit(version version.Version, w http.ResponseWriter, r *h
|
||||
return err
|
||||
}
|
||||
|
||||
if c == nil {
|
||||
c = &runconfig.Config{}
|
||||
}
|
||||
|
||||
containerCommitConfig := &daemon.ContainerCommitConfig{
|
||||
Pause: pause,
|
||||
Repo: r.Form.Get("repo"),
|
||||
@@ -1576,30 +1584,3 @@ func createRouter(s *Server) *mux.Router {
|
||||
|
||||
return r
|
||||
}
|
||||
|
||||
func allocateDaemonPort(addr string) error {
|
||||
host, port, err := net.SplitHostPort(addr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
intPort, err := strconv.Atoi(port)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var hostIPs []net.IP
|
||||
if parsedIP := net.ParseIP(host); parsedIP != nil {
|
||||
hostIPs = append(hostIPs, parsedIP)
|
||||
} else if hostIPs, err = net.LookupIP(host); err != nil {
|
||||
return fmt.Errorf("failed to lookup %s address in host specification", host)
|
||||
}
|
||||
|
||||
pa := portallocator.Get()
|
||||
for _, hostIP := range hostIPs {
|
||||
if _, err := pa.RequestPort(hostIP, "tcp", intPort); err != nil {
|
||||
return fmt.Errorf("failed to allocate daemon listening port %d (err: %v)", intPort, err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -6,10 +6,12 @@ import (
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"github.com/docker/docker/daemon"
|
||||
"github.com/docker/docker/pkg/sockets"
|
||||
"github.com/docker/docker/pkg/systemd"
|
||||
"github.com/docker/libnetwork/portallocator"
|
||||
)
|
||||
|
||||
// newServer sets up the required serverClosers and does protocol specific checking.
|
||||
@@ -67,3 +69,30 @@ func (s *Server) AcceptConnections(d *daemon.Daemon) {
|
||||
close(s.start)
|
||||
}
|
||||
}
|
||||
|
||||
func allocateDaemonPort(addr string) error {
|
||||
host, port, err := net.SplitHostPort(addr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
intPort, err := strconv.Atoi(port)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var hostIPs []net.IP
|
||||
if parsedIP := net.ParseIP(host); parsedIP != nil {
|
||||
hostIPs = append(hostIPs, parsedIP)
|
||||
} else if hostIPs, err = net.LookupIP(host); err != nil {
|
||||
return fmt.Errorf("failed to lookup %s address in host specification", host)
|
||||
}
|
||||
|
||||
pa := portallocator.Get()
|
||||
for _, hostIP := range hostIPs {
|
||||
if _, err := pa.RequestPort(hostIP, "tcp", intPort); err != nil {
|
||||
return fmt.Errorf("failed to allocate daemon listening port %d (err: %v)", intPort, err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ import (
|
||||
)
|
||||
|
||||
// NewServer sets up the required Server and does protocol specific checking.
|
||||
func (s *Server) newServer(proto, addr string) (Server, error) {
|
||||
func (s *Server) newServer(proto, addr string) (serverCloser, error) {
|
||||
var (
|
||||
err error
|
||||
l net.Listener
|
||||
@@ -22,6 +22,7 @@ func (s *Server) newServer(proto, addr string) (Server, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
default:
|
||||
return nil, errors.New("Invalid protocol format. Windows only supports tcp.")
|
||||
}
|
||||
@@ -43,3 +44,7 @@ func (s *Server) AcceptConnections(d *daemon.Daemon) {
|
||||
close(s.start)
|
||||
}
|
||||
}
|
||||
|
||||
func allocateDaemonPort(addr string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
+2
-2
@@ -94,9 +94,9 @@ type ImageInspect struct {
|
||||
|
||||
// GET "/containers/json"
|
||||
type Port struct {
|
||||
IP string
|
||||
IP string `json:",omitempty"`
|
||||
PrivatePort int
|
||||
PublicPort int
|
||||
PublicPort int `json:",omitempty"`
|
||||
Type string
|
||||
}
|
||||
|
||||
|
||||
@@ -221,6 +221,10 @@ func Commit(d *daemon.Daemon, name string, c *daemon.ContainerCommitConfig) (str
|
||||
return "", err
|
||||
}
|
||||
|
||||
if c.Config == nil {
|
||||
c.Config = &runconfig.Config{}
|
||||
}
|
||||
|
||||
newConfig, err := BuildFromConfig(d, c.Config, c.Changes)
|
||||
if err != nil {
|
||||
return "", err
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[Unit]
|
||||
Description=Docker Application Container Engine
|
||||
Documentation=http://docs.docker.com
|
||||
Documentation=https://docs.docker.com
|
||||
After=network.target docker.socket
|
||||
Requires=docker.socket
|
||||
|
||||
|
||||
@@ -80,7 +80,7 @@ sudo mkdir -m 755 dev
|
||||
# effectively: febootstrap-minimize --keep-zoneinfo --keep-rpmdb --keep-services "$target"
|
||||
# locales
|
||||
sudo rm -rf usr/{{lib,share}/locale,{lib,lib64}/gconv,bin/localedef,sbin/build-locale-archive}
|
||||
# docs
|
||||
# docs and man pages
|
||||
sudo rm -rf usr/share/{man,doc,info,gnome/help}
|
||||
# cracklib
|
||||
sudo rm -rf usr/share/cracklib
|
||||
|
||||
@@ -10,7 +10,7 @@ shift
|
||||
# effectively: febootstrap-minimize --keep-zoneinfo --keep-rpmdb --keep-services "$target"
|
||||
# locales
|
||||
rm -rf usr/{{lib,share}/locale,{lib,lib64}/gconv,bin/localedef,sbin/build-locale-archive}
|
||||
# docs
|
||||
# docs and man pages
|
||||
rm -rf usr/share/{man,doc,info,gnome/help}
|
||||
# cracklib
|
||||
rm -rf usr/share/cracklib
|
||||
|
||||
+5
-38
@@ -1,8 +1,6 @@
|
||||
package daemon
|
||||
|
||||
import (
|
||||
"net"
|
||||
|
||||
"github.com/docker/docker/opts"
|
||||
flag "github.com/docker/docker/pkg/mflag"
|
||||
"github.com/docker/docker/runconfig"
|
||||
@@ -16,9 +14,7 @@ const (
|
||||
// CommonConfig defines the configuration of a docker daemon which are
|
||||
// common across platforms.
|
||||
type CommonConfig struct {
|
||||
AutoRestart bool
|
||||
// Bridge holds bridge network specific configuration.
|
||||
Bridge bridgeConfig
|
||||
AutoRestart bool
|
||||
Context map[string][]string
|
||||
CorsHeaders string
|
||||
DisableNetwork bool
|
||||
@@ -26,8 +22,10 @@ type CommonConfig struct {
|
||||
DnsSearch []string
|
||||
EnableCors bool
|
||||
ExecDriver string
|
||||
ExecOptions []string
|
||||
ExecRoot string
|
||||
GraphDriver string
|
||||
GraphOptions []string
|
||||
Labels []string
|
||||
LogConfig runconfig.LogConfig
|
||||
Mtu int
|
||||
@@ -36,57 +34,26 @@ type CommonConfig struct {
|
||||
TrustKeyPath string
|
||||
}
|
||||
|
||||
// bridgeConfig stores all the bridge driver specific
|
||||
// configuration.
|
||||
type bridgeConfig struct {
|
||||
EnableIPv6 bool
|
||||
EnableIPTables bool
|
||||
EnableIPForward bool
|
||||
EnableIPMasq bool
|
||||
EnableUserlandProxy bool
|
||||
DefaultIP net.IP
|
||||
Iface string
|
||||
IP string
|
||||
FixedCIDR string
|
||||
FixedCIDRv6 string
|
||||
DefaultGatewayIPv4 string
|
||||
DefaultGatewayIPv6 string
|
||||
InterContainerCommunication bool
|
||||
}
|
||||
|
||||
// InstallCommonFlags adds command-line options to the top-level flag parser for
|
||||
// the current process.
|
||||
// Subsequent calls to `flag.Parse` will populate config with values parsed
|
||||
// from the command-line.
|
||||
|
||||
func (config *Config) InstallCommonFlags() {
|
||||
opts.ListVar(&config.GraphOptions, []string{"-storage-opt"}, "Set storage driver options")
|
||||
opts.ListVar(&config.ExecOptions, []string{"-exec-opt"}, "Set exec driver options")
|
||||
flag.StringVar(&config.Pidfile, []string{"p", "-pidfile"}, defaultPidFile, "Path to use for daemon PID file")
|
||||
flag.StringVar(&config.Root, []string{"g", "-graph"}, defaultGraph, "Root of the Docker runtime")
|
||||
flag.StringVar(&config.ExecRoot, []string{"-exec-root"}, "/var/run/docker", "Root of the Docker execdriver")
|
||||
flag.BoolVar(&config.AutoRestart, []string{"#r", "#-restart"}, true, "--restart on the daemon has been deprecated in favor of --restart policies on docker run")
|
||||
flag.BoolVar(&config.Bridge.EnableIPTables, []string{"#iptables", "-iptables"}, true, "Enable addition of iptables rules")
|
||||
flag.BoolVar(&config.Bridge.EnableIPForward, []string{"#ip-forward", "-ip-forward"}, true, "Enable net.ipv4.ip_forward")
|
||||
flag.BoolVar(&config.Bridge.EnableIPMasq, []string{"-ip-masq"}, true, "Enable IP masquerading")
|
||||
flag.BoolVar(&config.Bridge.EnableIPv6, []string{"-ipv6"}, false, "Enable IPv6 networking")
|
||||
flag.StringVar(&config.Bridge.IP, []string{"#bip", "-bip"}, "", "Specify network bridge IP")
|
||||
flag.StringVar(&config.Bridge.Iface, []string{"b", "-bridge"}, "", "Attach containers to a network bridge")
|
||||
flag.StringVar(&config.Bridge.FixedCIDR, []string{"-fixed-cidr"}, "", "IPv4 subnet for fixed IPs")
|
||||
flag.StringVar(&config.Bridge.FixedCIDRv6, []string{"-fixed-cidr-v6"}, "", "IPv6 subnet for fixed IPs")
|
||||
flag.StringVar(&config.Bridge.DefaultGatewayIPv4, []string{"-default-gateway"}, "", "Container default gateway IPv4 address")
|
||||
flag.StringVar(&config.Bridge.DefaultGatewayIPv6, []string{"-default-gateway-v6"}, "", "Container default gateway IPv6 address")
|
||||
flag.BoolVar(&config.Bridge.InterContainerCommunication, []string{"#icc", "-icc"}, true, "Enable inter-container communication")
|
||||
flag.StringVar(&config.GraphDriver, []string{"s", "-storage-driver"}, "", "Storage driver to use")
|
||||
flag.StringVar(&config.ExecDriver, []string{"e", "-exec-driver"}, defaultExec, "Exec driver to use")
|
||||
flag.IntVar(&config.Mtu, []string{"#mtu", "-mtu"}, 0, "Set the containers network MTU")
|
||||
flag.BoolVar(&config.EnableCors, []string{"#api-enable-cors", "#-api-enable-cors"}, false, "Enable CORS headers in the remote API, this is deprecated by --api-cors-header")
|
||||
flag.StringVar(&config.CorsHeaders, []string{"-api-cors-header"}, "", "Set CORS headers in the remote API")
|
||||
opts.IPVar(&config.Bridge.DefaultIP, []string{"#ip", "-ip"}, "0.0.0.0", "Default IP when binding container ports")
|
||||
// FIXME: why the inconsistency between "hosts" and "sockets"?
|
||||
opts.IPListVar(&config.Dns, []string{"#dns", "-dns"}, "DNS server to use")
|
||||
opts.DnsSearchListVar(&config.DnsSearch, []string{"-dns-search"}, "DNS search domains to use")
|
||||
opts.LabelListVar(&config.Labels, []string{"-label"}, "Set key=value labels to the daemon")
|
||||
flag.StringVar(&config.LogConfig.Type, []string{"-log-driver"}, "json-file", "Default driver for container logs")
|
||||
opts.LogOptsVar(config.LogConfig.Config, []string{"-log-opt"}, "Set log driver options")
|
||||
flag.BoolVar(&config.Bridge.EnableUserlandProxy, []string{"-userland-proxy"}, true, "Use userland proxy for loopback traffic")
|
||||
|
||||
}
|
||||
|
||||
+36
-4
@@ -1,6 +1,8 @@
|
||||
package daemon
|
||||
|
||||
import (
|
||||
"net"
|
||||
|
||||
"github.com/docker/docker/opts"
|
||||
flag "github.com/docker/docker/pkg/mflag"
|
||||
"github.com/docker/docker/pkg/ulimit"
|
||||
@@ -19,13 +21,32 @@ type Config struct {
|
||||
CommonConfig
|
||||
|
||||
// Fields below here are platform specific.
|
||||
|
||||
// Bridge holds bridge network specific configuration.
|
||||
Bridge bridgeConfig
|
||||
EnableSelinuxSupport bool
|
||||
ExecOptions []string
|
||||
GraphOptions []string
|
||||
SocketGroup string
|
||||
Ulimits map[string]*ulimit.Ulimit
|
||||
}
|
||||
|
||||
// bridgeConfig stores all the bridge driver specific
|
||||
// configuration.
|
||||
type bridgeConfig struct {
|
||||
EnableIPv6 bool
|
||||
EnableIPTables bool
|
||||
EnableIPForward bool
|
||||
EnableIPMasq bool
|
||||
EnableUserlandProxy bool
|
||||
DefaultIP net.IP
|
||||
Iface string
|
||||
IP string
|
||||
FixedCIDR string
|
||||
FixedCIDRv6 string
|
||||
DefaultGatewayIPv4 net.IP
|
||||
DefaultGatewayIPv6 net.IP
|
||||
InterContainerCommunication bool
|
||||
}
|
||||
|
||||
// InstallFlags adds command-line options to the top-level flag parser for
|
||||
// the current process.
|
||||
// Subsequent calls to `flag.Parse` will populate config with values parsed
|
||||
@@ -35,10 +56,21 @@ func (config *Config) InstallFlags() {
|
||||
config.InstallCommonFlags()
|
||||
|
||||
// Then platform-specific install flags
|
||||
opts.ListVar(&config.GraphOptions, []string{"-storage-opt"}, "Set storage driver options")
|
||||
opts.ListVar(&config.ExecOptions, []string{"-exec-opt"}, "Set exec driver options")
|
||||
flag.BoolVar(&config.EnableSelinuxSupport, []string{"-selinux-enabled"}, false, "Enable selinux support")
|
||||
flag.StringVar(&config.SocketGroup, []string{"G", "-group"}, "docker", "Group for the unix socket")
|
||||
config.Ulimits = make(map[string]*ulimit.Ulimit)
|
||||
opts.UlimitMapVar(config.Ulimits, []string{"-default-ulimit"}, "Set default ulimits for containers")
|
||||
flag.BoolVar(&config.Bridge.EnableIPTables, []string{"#iptables", "-iptables"}, true, "Enable addition of iptables rules")
|
||||
flag.BoolVar(&config.Bridge.EnableIPForward, []string{"#ip-forward", "-ip-forward"}, true, "Enable net.ipv4.ip_forward")
|
||||
flag.BoolVar(&config.Bridge.EnableIPMasq, []string{"-ip-masq"}, true, "Enable IP masquerading")
|
||||
flag.BoolVar(&config.Bridge.EnableIPv6, []string{"-ipv6"}, false, "Enable IPv6 networking")
|
||||
flag.StringVar(&config.Bridge.IP, []string{"#bip", "-bip"}, "", "Specify network bridge IP")
|
||||
flag.StringVar(&config.Bridge.Iface, []string{"b", "-bridge"}, "", "Attach containers to a network bridge")
|
||||
flag.StringVar(&config.Bridge.FixedCIDR, []string{"-fixed-cidr"}, "", "IPv4 subnet for fixed IPs")
|
||||
flag.StringVar(&config.Bridge.FixedCIDRv6, []string{"-fixed-cidr-v6"}, "", "IPv6 subnet for fixed IPs")
|
||||
opts.IPVar(&config.Bridge.DefaultGatewayIPv4, []string{"-default-gateway"}, "", "Container default gateway IPv4 address")
|
||||
opts.IPVar(&config.Bridge.DefaultGatewayIPv6, []string{"-default-gateway-v6"}, "", "Container default gateway IPv6 address")
|
||||
flag.BoolVar(&config.Bridge.InterContainerCommunication, []string{"#icc", "-icc"}, true, "Enable inter-container communication")
|
||||
opts.IPVar(&config.Bridge.DefaultIP, []string{"#ip", "-ip"}, "0.0.0.0", "Default IP when binding container ports")
|
||||
flag.BoolVar(&config.Bridge.EnableUserlandProxy, []string{"-userland-proxy"}, true, "Use userland proxy for loopback traffic")
|
||||
}
|
||||
|
||||
+4
-1
@@ -73,7 +73,10 @@ type CommonContainer struct {
|
||||
MountLabel, ProcessLabel string
|
||||
RestartCount int
|
||||
UpdateDns bool
|
||||
MountPoints map[string]*mountPoint
|
||||
|
||||
MountPoints map[string]*mountPoint
|
||||
Volumes map[string]string // Deprecated since 1.7, kept for backwards compatibility
|
||||
VolumesRW map[string]bool // Deprecated since 1.7, kept for backwards compatibility
|
||||
|
||||
hostConfig *runconfig.HostConfig
|
||||
command *execdriver.Command
|
||||
|
||||
@@ -15,6 +15,10 @@ import (
|
||||
)
|
||||
|
||||
func (daemon *Daemon) ContainerCreate(name string, config *runconfig.Config, hostConfig *runconfig.HostConfig) (string, []string, error) {
|
||||
if config == nil {
|
||||
return "", nil, fmt.Errorf("Config cannot be empty in order to create a container")
|
||||
}
|
||||
|
||||
warnings, err := daemon.verifyHostConfig(hostConfig)
|
||||
if err != nil {
|
||||
return "", warnings, err
|
||||
|
||||
+52
-36
@@ -50,8 +50,6 @@ import (
|
||||
"github.com/docker/docker/volume/local"
|
||||
)
|
||||
|
||||
const defaultVolumesPathName = "volumes"
|
||||
|
||||
var (
|
||||
validContainerNameChars = `[a-zA-Z0-9][a-zA-Z0-9_.-]`
|
||||
validContainerNamePattern = regexp.MustCompile(`^/?` + validContainerNameChars + `+$`)
|
||||
@@ -158,12 +156,7 @@ func (daemon *Daemon) containerRoot(id string) string {
|
||||
// This is typically done at startup.
|
||||
func (daemon *Daemon) load(id string) (*Container, error) {
|
||||
container := &Container{
|
||||
CommonContainer: CommonContainer{
|
||||
State: NewState(),
|
||||
root: daemon.containerRoot(id),
|
||||
MountPoints: make(map[string]*mountPoint),
|
||||
execCommands: newExecStore(),
|
||||
},
|
||||
CommonContainer: daemon.newBaseContainer(id),
|
||||
}
|
||||
|
||||
if err := container.FromDisk(); err != nil {
|
||||
@@ -526,25 +519,21 @@ func (daemon *Daemon) newContainer(name string, config *runconfig.Config, imgID
|
||||
daemon.generateHostname(id, config)
|
||||
entrypoint, args := daemon.getEntrypointAndArgs(config.Entrypoint, config.Cmd)
|
||||
|
||||
base := daemon.newBaseContainer(id)
|
||||
base.Created = time.Now().UTC()
|
||||
base.Path = entrypoint
|
||||
base.Args = args //FIXME: de-duplicate from config
|
||||
base.Config = config
|
||||
base.hostConfig = &runconfig.HostConfig{}
|
||||
base.ImageID = imgID
|
||||
base.NetworkSettings = &network.Settings{}
|
||||
base.Name = name
|
||||
base.Driver = daemon.driver.String()
|
||||
base.ExecDriver = daemon.execDriver.Name()
|
||||
|
||||
container := &Container{
|
||||
CommonContainer: CommonContainer{
|
||||
ID: id, // FIXME: we should generate the ID here instead of receiving it as an argument
|
||||
Created: time.Now().UTC(),
|
||||
Path: entrypoint,
|
||||
Args: args, //FIXME: de-duplicate from config
|
||||
Config: config,
|
||||
hostConfig: &runconfig.HostConfig{},
|
||||
ImageID: imgID,
|
||||
NetworkSettings: &network.Settings{},
|
||||
Name: name,
|
||||
Driver: daemon.driver.String(),
|
||||
ExecDriver: daemon.execDriver.Name(),
|
||||
State: NewState(),
|
||||
execCommands: newExecStore(),
|
||||
MountPoints: map[string]*mountPoint{},
|
||||
},
|
||||
CommonContainer: base,
|
||||
}
|
||||
container.root = daemon.containerRoot(container.ID)
|
||||
|
||||
return container, err
|
||||
}
|
||||
@@ -792,7 +781,7 @@ func NewDaemon(config *Config, registryService *registry.Service) (daemon *Daemo
|
||||
return nil, err
|
||||
}
|
||||
|
||||
volumesDriver, err := local.New(filepath.Join(config.Root, defaultVolumesPathName))
|
||||
volumesDriver, err := local.New(config.Root)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -963,6 +952,14 @@ func initNetworkController(config *Config) (libnetwork.NetworkController, error)
|
||||
netOption["FixedCIDRv6"] = fCIDRv6
|
||||
}
|
||||
|
||||
if config.Bridge.DefaultGatewayIPv4 != nil {
|
||||
netOption["DefaultGatewayIPv4"] = config.Bridge.DefaultGatewayIPv4
|
||||
}
|
||||
|
||||
if config.Bridge.DefaultGatewayIPv6 != nil {
|
||||
netOption["DefaultGatewayIPv6"] = config.Bridge.DefaultGatewayIPv6
|
||||
}
|
||||
|
||||
// --ip processing
|
||||
if config.Bridge.DefaultIP != nil {
|
||||
netOption["DefaultBindingIP"] = config.Bridge.DefaultIP
|
||||
@@ -982,16 +979,6 @@ func initNetworkController(config *Config) (libnetwork.NetworkController, error)
|
||||
}
|
||||
|
||||
func (daemon *Daemon) Shutdown() error {
|
||||
if daemon.containerGraph != nil {
|
||||
if err := daemon.containerGraph.Close(); err != nil {
|
||||
logrus.Errorf("Error during container graph.Close(): %v", err)
|
||||
}
|
||||
}
|
||||
if daemon.driver != nil {
|
||||
if err := daemon.driver.Cleanup(); err != nil {
|
||||
logrus.Errorf("Error during graph storage driver.Cleanup(): %v", err)
|
||||
}
|
||||
}
|
||||
if daemon.containers != nil {
|
||||
group := sync.WaitGroup{}
|
||||
logrus.Debug("starting clean shutdown of all containers...")
|
||||
@@ -1013,6 +1000,23 @@ func (daemon *Daemon) Shutdown() error {
|
||||
}
|
||||
}
|
||||
group.Wait()
|
||||
|
||||
// trigger libnetwork GC only if it's initialized
|
||||
if daemon.netController != nil {
|
||||
daemon.netController.GC()
|
||||
}
|
||||
}
|
||||
|
||||
if daemon.containerGraph != nil {
|
||||
if err := daemon.containerGraph.Close(); err != nil {
|
||||
logrus.Errorf("Error during container graph.Close(): %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
if daemon.driver != nil {
|
||||
if err := daemon.driver.Cleanup(); err != nil {
|
||||
logrus.Errorf("Error during graph storage driver.Cleanup(): %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -1246,3 +1250,15 @@ func (daemon *Daemon) setHostConfig(container *Container, hostConfig *runconfig.
|
||||
container.toDisk()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (daemon *Daemon) newBaseContainer(id string) CommonContainer {
|
||||
return CommonContainer{
|
||||
ID: id,
|
||||
State: NewState(),
|
||||
MountPoints: make(map[string]*mountPoint),
|
||||
Volumes: make(map[string]string),
|
||||
VolumesRW: make(map[string]bool),
|
||||
execCommands: newExecStore(),
|
||||
root: daemon.containerRoot(id),
|
||||
}
|
||||
}
|
||||
|
||||
+220
-7
@@ -12,6 +12,8 @@ import (
|
||||
"github.com/docker/docker/pkg/stringid"
|
||||
"github.com/docker/docker/pkg/truncindex"
|
||||
"github.com/docker/docker/volume"
|
||||
"github.com/docker/docker/volume/drivers"
|
||||
"github.com/docker/docker/volume/local"
|
||||
)
|
||||
|
||||
//
|
||||
@@ -178,10 +180,11 @@ func TestLoadWithVolume(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
daemon := &Daemon{
|
||||
repository: tmp,
|
||||
root: tmp,
|
||||
daemon, err := initDaemonForVolumesTest(tmp)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer volumedrivers.Unregister(volume.DefaultDriverName)
|
||||
|
||||
c, err := daemon.load(containerId)
|
||||
if err != nil {
|
||||
@@ -214,7 +217,7 @@ func TestLoadWithVolume(t *testing.T) {
|
||||
t.Fatalf("Expected mount driver local, was %s\n", m.Driver)
|
||||
}
|
||||
|
||||
newVolumeContent := filepath.Join(volumePath, "helo")
|
||||
newVolumeContent := filepath.Join(volumePath, local.VolumeDataPathName, "helo")
|
||||
b, err := ioutil.ReadFile(newVolumeContent)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -265,10 +268,11 @@ func TestLoadWithBindMount(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
daemon := &Daemon{
|
||||
repository: tmp,
|
||||
root: tmp,
|
||||
daemon, err := initDaemonForVolumesTest(tmp)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer volumedrivers.Unregister(volume.DefaultDriverName)
|
||||
|
||||
c, err := daemon.load(containerId)
|
||||
if err != nil {
|
||||
@@ -301,3 +305,212 @@ func TestLoadWithBindMount(t *testing.T) {
|
||||
t.Fatalf("Expected mount point to be RW but it was not\n")
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoadWithVolume17RC(t *testing.T) {
|
||||
tmp, err := ioutil.TempDir("", "docker-daemon-test-")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.RemoveAll(tmp)
|
||||
|
||||
containerId := "d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e"
|
||||
containerPath := filepath.Join(tmp, containerId)
|
||||
if err := os.MkdirAll(containerPath, 0755); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
hostVolumeId := "6a3c03fc4a4e588561a543cc3bdd50089e27bd11bbb0e551e19bf735e2514101"
|
||||
volumePath := filepath.Join(tmp, "volumes", hostVolumeId)
|
||||
|
||||
if err := os.MkdirAll(volumePath, 0755); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
content := filepath.Join(volumePath, "helo")
|
||||
if err := ioutil.WriteFile(content, []byte("HELO"), 0644); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
config := `{"State":{"Running":true,"Paused":false,"Restarting":false,"OOMKilled":false,"Dead":false,"Pid":2464,"ExitCode":0,
|
||||
"Error":"","StartedAt":"2015-05-26T16:48:53.869308965Z","FinishedAt":"0001-01-01T00:00:00Z"},
|
||||
"ID":"d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e","Created":"2015-05-26T16:48:53.7987917Z","Path":"top",
|
||||
"Args":[],"Config":{"Hostname":"d59df5276e7b","Domainname":"","User":"","Memory":0,"MemorySwap":0,"CpuShares":0,"Cpuset":"",
|
||||
"AttachStdin":false,"AttachStdout":false,"AttachStderr":false,"PortSpecs":null,"ExposedPorts":null,"Tty":true,"OpenStdin":true,
|
||||
"StdinOnce":false,"Env":null,"Cmd":["top"],"Image":"ubuntu:latest","Volumes":null,"WorkingDir":"","Entrypoint":null,
|
||||
"NetworkDisabled":false,"MacAddress":"","OnBuild":null,"Labels":{}},"Image":"07f8e8c5e66084bef8f848877857537ffe1c47edd01a93af27e7161672ad0e95",
|
||||
"NetworkSettings":{"IPAddress":"172.17.0.1","IPPrefixLen":16,"MacAddress":"02:42:ac:11:00:01","LinkLocalIPv6Address":"fe80::42:acff:fe11:1",
|
||||
"LinkLocalIPv6PrefixLen":64,"GlobalIPv6Address":"","GlobalIPv6PrefixLen":0,"Gateway":"172.17.42.1","IPv6Gateway":"","Bridge":"docker0","PortMapping":null,"Ports":{}},
|
||||
"ResolvConfPath":"/var/lib/docker/containers/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e/resolv.conf",
|
||||
"HostnamePath":"/var/lib/docker/containers/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e/hostname",
|
||||
"HostsPath":"/var/lib/docker/containers/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e/hosts",
|
||||
"LogPath":"/var/lib/docker/containers/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e-json.log",
|
||||
"Name":"/ubuntu","Driver":"aufs","ExecDriver":"native-0.2","MountLabel":"","ProcessLabel":"","AppArmorProfile":"","RestartCount":0,
|
||||
"UpdateDns":false,"MountPoints":{"/vol1":{"Name":"6a3c03fc4a4e588561a543cc3bdd50089e27bd11bbb0e551e19bf735e2514101","Destination":"/vol1","Driver":"local","RW":true,"Source":"","Relabel":""}},"AppliedVolumesFrom":null}`
|
||||
|
||||
if err = ioutil.WriteFile(filepath.Join(containerPath, "config.json"), []byte(config), 0644); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
hostConfig := `{"Binds":[],"ContainerIDFile":"","LxcConf":[],"Memory":0,"MemorySwap":0,"CpuShares":0,"CpusetCpus":"",
|
||||
"Privileged":false,"PortBindings":{},"Links":null,"PublishAllPorts":false,"Dns":null,"DnsSearch":null,"ExtraHosts":null,"VolumesFrom":null,
|
||||
"Devices":[],"NetworkMode":"bridge","IpcMode":"","PidMode":"","CapAdd":null,"CapDrop":null,"RestartPolicy":{"Name":"no","MaximumRetryCount":0},
|
||||
"SecurityOpt":null,"ReadonlyRootfs":false,"Ulimits":null,"LogConfig":{"Type":"","Config":null},"CgroupParent":""}`
|
||||
if err = ioutil.WriteFile(filepath.Join(containerPath, "hostconfig.json"), []byte(hostConfig), 0644); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
daemon, err := initDaemonForVolumesTest(tmp)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer volumedrivers.Unregister(volume.DefaultDriverName)
|
||||
|
||||
c, err := daemon.load(containerId)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
err = daemon.verifyVolumesInfo(c)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if len(c.MountPoints) != 1 {
|
||||
t.Fatalf("Expected 1 volume mounted, was 0\n")
|
||||
}
|
||||
|
||||
m := c.MountPoints["/vol1"]
|
||||
if m.Name != hostVolumeId {
|
||||
t.Fatalf("Expected mount name to be %s, was %s\n", hostVolumeId, m.Name)
|
||||
}
|
||||
|
||||
if m.Destination != "/vol1" {
|
||||
t.Fatalf("Expected mount destination /vol1, was %s\n", m.Destination)
|
||||
}
|
||||
|
||||
if !m.RW {
|
||||
t.Fatalf("Expected mount point to be RW but it was not\n")
|
||||
}
|
||||
|
||||
if m.Driver != volume.DefaultDriverName {
|
||||
t.Fatalf("Expected mount driver local, was %s\n", m.Driver)
|
||||
}
|
||||
|
||||
newVolumeContent := filepath.Join(volumePath, local.VolumeDataPathName, "helo")
|
||||
b, err := ioutil.ReadFile(newVolumeContent)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if string(b) != "HELO" {
|
||||
t.Fatalf("Expected HELO, was %s\n", string(b))
|
||||
}
|
||||
}
|
||||
|
||||
func TestRemoveLocalVolumesFollowingSymlinks(t *testing.T) {
|
||||
tmp, err := ioutil.TempDir("", "docker-daemon-test-")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.RemoveAll(tmp)
|
||||
|
||||
containerId := "d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e"
|
||||
containerPath := filepath.Join(tmp, containerId)
|
||||
if err := os.MkdirAll(containerPath, 0755); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
hostVolumeId := stringid.GenerateRandomID()
|
||||
vfsPath := filepath.Join(tmp, "vfs", "dir", hostVolumeId)
|
||||
volumePath := filepath.Join(tmp, "volumes", hostVolumeId)
|
||||
|
||||
if err := os.MkdirAll(vfsPath, 0755); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := os.MkdirAll(volumePath, 0755); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
content := filepath.Join(vfsPath, "helo")
|
||||
if err := ioutil.WriteFile(content, []byte("HELO"), 0644); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
config := `{"State":{"Running":true,"Paused":false,"Restarting":false,"OOMKilled":false,"Dead":false,"Pid":2464,"ExitCode":0,
|
||||
"Error":"","StartedAt":"2015-05-26T16:48:53.869308965Z","FinishedAt":"0001-01-01T00:00:00Z"},
|
||||
"ID":"d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e","Created":"2015-05-26T16:48:53.7987917Z","Path":"top",
|
||||
"Args":[],"Config":{"Hostname":"d59df5276e7b","Domainname":"","User":"","Memory":0,"MemorySwap":0,"CpuShares":0,"Cpuset":"",
|
||||
"AttachStdin":false,"AttachStdout":false,"AttachStderr":false,"PortSpecs":null,"ExposedPorts":null,"Tty":true,"OpenStdin":true,
|
||||
"StdinOnce":false,"Env":null,"Cmd":["top"],"Image":"ubuntu:latest","Volumes":null,"WorkingDir":"","Entrypoint":null,
|
||||
"NetworkDisabled":false,"MacAddress":"","OnBuild":null,"Labels":{}},"Image":"07f8e8c5e66084bef8f848877857537ffe1c47edd01a93af27e7161672ad0e95",
|
||||
"NetworkSettings":{"IPAddress":"172.17.0.1","IPPrefixLen":16,"MacAddress":"02:42:ac:11:00:01","LinkLocalIPv6Address":"fe80::42:acff:fe11:1",
|
||||
"LinkLocalIPv6PrefixLen":64,"GlobalIPv6Address":"","GlobalIPv6PrefixLen":0,"Gateway":"172.17.42.1","IPv6Gateway":"","Bridge":"docker0","PortMapping":null,"Ports":{}},
|
||||
"ResolvConfPath":"/var/lib/docker/containers/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e/resolv.conf",
|
||||
"HostnamePath":"/var/lib/docker/containers/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e/hostname",
|
||||
"HostsPath":"/var/lib/docker/containers/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e/hosts",
|
||||
"LogPath":"/var/lib/docker/containers/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e-json.log",
|
||||
"Name":"/ubuntu","Driver":"aufs","ExecDriver":"native-0.2","MountLabel":"","ProcessLabel":"","AppArmorProfile":"","RestartCount":0,
|
||||
"UpdateDns":false,"Volumes":{"/vol1":"%s"},"VolumesRW":{"/vol1":true},"AppliedVolumesFrom":null}`
|
||||
|
||||
cfg := fmt.Sprintf(config, vfsPath)
|
||||
if err = ioutil.WriteFile(filepath.Join(containerPath, "config.json"), []byte(cfg), 0644); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
hostConfig := `{"Binds":[],"ContainerIDFile":"","LxcConf":[],"Memory":0,"MemorySwap":0,"CpuShares":0,"CpusetCpus":"",
|
||||
"Privileged":false,"PortBindings":{},"Links":null,"PublishAllPorts":false,"Dns":null,"DnsSearch":null,"ExtraHosts":null,"VolumesFrom":null,
|
||||
"Devices":[],"NetworkMode":"bridge","IpcMode":"","PidMode":"","CapAdd":null,"CapDrop":null,"RestartPolicy":{"Name":"no","MaximumRetryCount":0},
|
||||
"SecurityOpt":null,"ReadonlyRootfs":false,"Ulimits":null,"LogConfig":{"Type":"","Config":null},"CgroupParent":""}`
|
||||
if err = ioutil.WriteFile(filepath.Join(containerPath, "hostconfig.json"), []byte(hostConfig), 0644); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
daemon, err := initDaemonForVolumesTest(tmp)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer volumedrivers.Unregister(volume.DefaultDriverName)
|
||||
|
||||
c, err := daemon.load(containerId)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
err = daemon.verifyVolumesInfo(c)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if len(c.MountPoints) != 1 {
|
||||
t.Fatalf("Expected 1 volume mounted, was 0\n")
|
||||
}
|
||||
|
||||
m := c.MountPoints["/vol1"]
|
||||
v, err := createVolume(m.Name, m.Driver)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if err := removeVolume(v); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
fi, err := os.Stat(vfsPath)
|
||||
if err == nil || !os.IsNotExist(err) {
|
||||
t.Fatalf("Expected vfs path to not exist: %v - %v\n", fi, err)
|
||||
}
|
||||
}
|
||||
|
||||
func initDaemonForVolumesTest(tmp string) (*Daemon, error) {
|
||||
daemon := &Daemon{
|
||||
repository: tmp,
|
||||
root: tmp,
|
||||
}
|
||||
|
||||
volumesDriver, err := local.New(tmp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
volumedrivers.Register(volumesDriver, volumesDriver.Name())
|
||||
|
||||
return daemon, nil
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ func InitContainer(c *Command) *configs.Config {
|
||||
container.Devices = c.AutoCreatedDevices
|
||||
container.Rootfs = c.Rootfs
|
||||
container.Readonlyfs = c.ReadonlyRootfs
|
||||
container.Privatefs = true
|
||||
|
||||
// check to see if we are running in ramdisk to disable pivot root
|
||||
container.NoPivotRoot = os.Getenv("DOCKER_RAMDISK") != ""
|
||||
|
||||
@@ -124,7 +124,7 @@ func (d *driver) Run(c *execdriver.Command, pipes *execdriver.Pipes, startCallba
|
||||
dataPath = d.containerDir(c.ID)
|
||||
)
|
||||
|
||||
if c.Network.NamespacePath == "" && c.Network.ContainerID == "" {
|
||||
if c.Network == nil || (c.Network.NamespacePath == "" && c.Network.ContainerID == "") {
|
||||
return execdriver.ExitStatus{ExitCode: -1}, fmt.Errorf("empty namespace path for non-container network")
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@ import (
|
||||
"github.com/docker/docker/daemon/graphdriver"
|
||||
"github.com/docker/docker/pkg/mount"
|
||||
"github.com/docker/docker/pkg/parsers"
|
||||
"github.com/docker/libcontainer/label"
|
||||
zfs "github.com/mistifyio/go-zfs"
|
||||
)
|
||||
|
||||
@@ -281,14 +282,15 @@ func (d *Driver) Remove(id string) error {
|
||||
func (d *Driver) Get(id, mountLabel string) (string, error) {
|
||||
mountpoint := d.MountPath(id)
|
||||
filesystem := d.ZfsPath(id)
|
||||
log.Debugf(`[zfs] mount("%s", "%s", "%s")`, filesystem, mountpoint, mountLabel)
|
||||
options := label.FormatMountLabel("", mountLabel)
|
||||
log.Debugf(`[zfs] mount("%s", "%s", "%s")`, filesystem, mountpoint, options)
|
||||
|
||||
// Create the target directories if they don't exist
|
||||
if err := os.MkdirAll(mountpoint, 0755); err != nil && !os.IsExist(err) {
|
||||
return "", err
|
||||
}
|
||||
|
||||
err := mount.Mount(filesystem, mountpoint, "zfs", mountLabel)
|
||||
err := mount.Mount(filesystem, mountpoint, "zfs", options)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("error creating zfs mount of %s to %s: %v", filesystem, mountpoint, err)
|
||||
}
|
||||
|
||||
+24
-16
@@ -15,31 +15,39 @@ func (daemon *Daemon) ContainerStats(name string, stream bool, out io.Writer) er
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var pre_cpu_stats types.CpuStats
|
||||
for first_v := range updates {
|
||||
first_update := first_v.(*execdriver.ResourceStats)
|
||||
first_stats := convertToAPITypes(first_update.Stats)
|
||||
pre_cpu_stats = first_stats.CpuStats
|
||||
pre_cpu_stats.SystemUsage = first_update.SystemUsage
|
||||
break
|
||||
}
|
||||
enc := json.NewEncoder(out)
|
||||
for v := range updates {
|
||||
|
||||
var preCpuStats types.CpuStats
|
||||
getStat := func(v interface{}) *types.Stats {
|
||||
update := v.(*execdriver.ResourceStats)
|
||||
ss := convertToAPITypes(update.Stats)
|
||||
ss.PreCpuStats = pre_cpu_stats
|
||||
ss.PreCpuStats = preCpuStats
|
||||
ss.MemoryStats.Limit = uint64(update.MemoryLimit)
|
||||
ss.Read = update.Read
|
||||
ss.CpuStats.SystemUsage = update.SystemUsage
|
||||
pre_cpu_stats = ss.CpuStats
|
||||
if err := enc.Encode(ss); err != nil {
|
||||
preCpuStats = ss.CpuStats
|
||||
return ss
|
||||
}
|
||||
|
||||
enc := json.NewEncoder(out)
|
||||
|
||||
if !stream {
|
||||
// prime the cpu stats so they aren't 0 in the final output
|
||||
s := getStat(<-updates)
|
||||
|
||||
// now pull stats again with the cpu stats primed
|
||||
s = getStat(<-updates)
|
||||
err := enc.Encode(s)
|
||||
daemon.UnsubscribeToContainerStats(name, updates)
|
||||
return err
|
||||
}
|
||||
|
||||
for v := range updates {
|
||||
s := getStat(v)
|
||||
if err := enc.Encode(s); err != nil {
|
||||
// TODO: handle the specific broken pipe
|
||||
daemon.UnsubscribeToContainerStats(name, updates)
|
||||
return err
|
||||
}
|
||||
if !stream {
|
||||
break
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
+81
-69
@@ -1,7 +1,6 @@
|
||||
package daemon
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
@@ -12,6 +11,7 @@ import (
|
||||
"github.com/docker/docker/pkg/chrootarchive"
|
||||
"github.com/docker/docker/runconfig"
|
||||
"github.com/docker/docker/volume"
|
||||
"github.com/docker/docker/volume/local"
|
||||
"github.com/docker/libcontainer/label"
|
||||
)
|
||||
|
||||
@@ -53,6 +53,13 @@ func (m *mountPoint) Path() string {
|
||||
return m.Source
|
||||
}
|
||||
|
||||
// BackwardsCompatible decides whether this mount point can be
|
||||
// used in old versions of Docker or not.
|
||||
// Only bind mounts and local volumes can be used in old versions of Docker.
|
||||
func (m *mountPoint) BackwardsCompatible() bool {
|
||||
return len(m.Source) > 0 || m.Driver == volume.DefaultDriverName
|
||||
}
|
||||
|
||||
func parseBindMount(spec string, mountLabel string, config *runconfig.Config) (*mountPoint, error) {
|
||||
bind := &mountPoint{
|
||||
RW: true,
|
||||
@@ -232,8 +239,20 @@ func (daemon *Daemon) registerMountPoints(container *Container, hostConfig *runc
|
||||
mountPoints[bind.Destination] = bind
|
||||
}
|
||||
|
||||
// Keep backwards compatible structures
|
||||
bcVolumes := map[string]string{}
|
||||
bcVolumesRW := map[string]bool{}
|
||||
for _, m := range mountPoints {
|
||||
if m.BackwardsCompatible() {
|
||||
bcVolumes[m.Destination] = m.Path()
|
||||
bcVolumesRW[m.Destination] = m.RW
|
||||
}
|
||||
}
|
||||
|
||||
container.Lock()
|
||||
container.MountPoints = mountPoints
|
||||
container.Volumes = bcVolumes
|
||||
container.VolumesRW = bcVolumesRW
|
||||
container.Unlock()
|
||||
|
||||
return nil
|
||||
@@ -242,81 +261,74 @@ func (daemon *Daemon) registerMountPoints(container *Container, hostConfig *runc
|
||||
// verifyVolumesInfo ports volumes configured for the containers pre docker 1.7.
|
||||
// It reads the container configuration and creates valid mount points for the old volumes.
|
||||
func (daemon *Daemon) verifyVolumesInfo(container *Container) error {
|
||||
jsonPath, err := container.jsonPath()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
f, err := os.Open(jsonPath)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
// Inspect old structures only when we're upgrading from old versions
|
||||
// to versions >= 1.7 and the MountPoints has not been populated with volumes data.
|
||||
if len(container.MountPoints) == 0 && len(container.Volumes) > 0 {
|
||||
for destination, hostPath := range container.Volumes {
|
||||
vfsPath := filepath.Join(daemon.root, "vfs", "dir")
|
||||
rw := container.VolumesRW != nil && container.VolumesRW[destination]
|
||||
|
||||
type oldContVolCfg struct {
|
||||
Volumes map[string]string
|
||||
VolumesRW map[string]bool
|
||||
}
|
||||
|
||||
vols := oldContVolCfg{
|
||||
Volumes: make(map[string]string),
|
||||
VolumesRW: make(map[string]bool),
|
||||
}
|
||||
if err := json.NewDecoder(f).Decode(&vols); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for destination, hostPath := range vols.Volumes {
|
||||
vfsPath := filepath.Join(daemon.root, "vfs", "dir")
|
||||
rw := vols.VolumesRW != nil && vols.VolumesRW[destination]
|
||||
|
||||
if strings.HasPrefix(hostPath, vfsPath) {
|
||||
id := filepath.Base(hostPath)
|
||||
if err := daemon.migrateVolume(id, hostPath); err != nil {
|
||||
return err
|
||||
if strings.HasPrefix(hostPath, vfsPath) {
|
||||
id := filepath.Base(hostPath)
|
||||
if err := migrateVolume(id, hostPath); err != nil {
|
||||
return err
|
||||
}
|
||||
container.addLocalMountPoint(id, destination, rw)
|
||||
} else { // Bind mount
|
||||
id, source, err := parseVolumeSource(hostPath)
|
||||
// We should not find an error here coming
|
||||
// from the old configuration, but who knows.
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
container.addBindMountPoint(id, source, destination, rw)
|
||||
}
|
||||
container.addLocalMountPoint(id, destination, rw)
|
||||
} else { // Bind mount
|
||||
id, source, err := parseVolumeSource(hostPath)
|
||||
// We should not find an error here coming
|
||||
// from the old configuration, but who knows.
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
container.addBindMountPoint(id, source, destination, rw)
|
||||
}
|
||||
}
|
||||
|
||||
return container.ToDisk()
|
||||
}
|
||||
|
||||
// migrateVolume moves the contents of a volume created pre Docker 1.7
|
||||
// to the location expected by the local driver. Steps:
|
||||
// 1. Save old directory that includes old volume's config json file.
|
||||
// 2. Move virtual directory with content to where the local driver expects it to be.
|
||||
// 3. Remove the backup of the old volume config.
|
||||
func (daemon *Daemon) migrateVolume(id, vfs string) error {
|
||||
volumeInfo := filepath.Join(daemon.root, defaultVolumesPathName, id)
|
||||
backup := filepath.Join(daemon.root, defaultVolumesPathName, id+".back")
|
||||
|
||||
var err error
|
||||
if err = os.Rename(volumeInfo, backup); err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() {
|
||||
// Put old configuration back in place in case one of the next steps fails.
|
||||
} else if len(container.MountPoints) > 0 {
|
||||
// Volumes created with a Docker version >= 1.7. We verify integrity in case of data created
|
||||
// with Docker 1.7 RC versions that put the information in
|
||||
// DOCKER_ROOT/volumes/VOLUME_ID rather than DOCKER_ROOT/volumes/VOLUME_ID/_container_data.
|
||||
l, err := getVolumeDriver(volume.DefaultDriverName)
|
||||
if err != nil {
|
||||
os.Rename(backup, volumeInfo)
|
||||
return err
|
||||
}
|
||||
}()
|
||||
|
||||
if err = os.Rename(vfs, volumeInfo); err != nil {
|
||||
return err
|
||||
}
|
||||
for _, m := range container.MountPoints {
|
||||
if m.Driver != volume.DefaultDriverName {
|
||||
continue
|
||||
}
|
||||
dataPath := l.(*local.Root).DataPath(m.Name)
|
||||
volumePath := filepath.Dir(dataPath)
|
||||
|
||||
if err = os.RemoveAll(backup); err != nil {
|
||||
logrus.Errorf("Unable to remove volume info backup directory %s: %v", backup, err)
|
||||
d, err := ioutil.ReadDir(volumePath)
|
||||
if err != nil {
|
||||
// If the volume directory doesn't exist yet it will be recreated,
|
||||
// so we only return the error when there is a different issue.
|
||||
if !os.IsNotExist(err) {
|
||||
return err
|
||||
}
|
||||
// Do not check when the volume directory does not exist.
|
||||
continue
|
||||
}
|
||||
if validVolumeLayout(d) {
|
||||
continue
|
||||
}
|
||||
|
||||
if err := os.Mkdir(dataPath, 0755); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Move data inside the data directory
|
||||
for _, f := range d {
|
||||
oldp := filepath.Join(volumePath, f.Name())
|
||||
newp := filepath.Join(dataPath, f.Name())
|
||||
if err := os.Rename(oldp, newp); err != nil {
|
||||
logrus.Errorf("Unable to move %s to %s\n", oldp, newp)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return container.ToDisk()
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
@@ -10,6 +10,8 @@ import (
|
||||
|
||||
"github.com/docker/docker/daemon/execdriver"
|
||||
"github.com/docker/docker/pkg/system"
|
||||
"github.com/docker/docker/volume"
|
||||
"github.com/docker/docker/volume/local"
|
||||
)
|
||||
|
||||
// copyOwnership copies the permissions and uid:gid of the source file
|
||||
@@ -68,3 +70,50 @@ func (m mounts) Swap(i, j int) {
|
||||
func (m mounts) parts(i int) int {
|
||||
return len(strings.Split(filepath.Clean(m[i].Destination), string(os.PathSeparator)))
|
||||
}
|
||||
|
||||
// migrateVolume links the contents of a volume created pre Docker 1.7
|
||||
// into the location expected by the local driver.
|
||||
// It creates a symlink from DOCKER_ROOT/vfs/dir/VOLUME_ID to DOCKER_ROOT/volumes/VOLUME_ID/_container_data.
|
||||
// It preserves the volume json configuration generated pre Docker 1.7 to be able to
|
||||
// downgrade from Docker 1.7 to Docker 1.6 without losing volume compatibility.
|
||||
func migrateVolume(id, vfs string) error {
|
||||
l, err := getVolumeDriver(volume.DefaultDriverName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
newDataPath := l.(*local.Root).DataPath(id)
|
||||
fi, err := os.Stat(newDataPath)
|
||||
if err != nil && !os.IsNotExist(err) {
|
||||
return err
|
||||
}
|
||||
|
||||
if fi != nil && fi.IsDir() {
|
||||
return nil
|
||||
}
|
||||
|
||||
return os.Symlink(vfs, newDataPath)
|
||||
}
|
||||
|
||||
// validVolumeLayout checks whether the volume directory layout
|
||||
// is valid to work with Docker post 1.7 or not.
|
||||
func validVolumeLayout(files []os.FileInfo) bool {
|
||||
if len(files) == 1 && files[0].Name() == local.VolumeDataPathName && files[0].IsDir() {
|
||||
return true
|
||||
}
|
||||
|
||||
if len(files) != 2 {
|
||||
return false
|
||||
}
|
||||
|
||||
for _, f := range files {
|
||||
if f.Name() == "config.json" ||
|
||||
(f.Name() == local.VolumeDataPathName && f.Mode()&os.ModeSymlink == os.ModeSymlink) {
|
||||
// Old volume configuration, we ignore it
|
||||
continue
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -2,7 +2,11 @@
|
||||
|
||||
package daemon
|
||||
|
||||
import "github.com/docker/docker/daemon/execdriver"
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/docker/docker/daemon/execdriver"
|
||||
)
|
||||
|
||||
// Not supported on Windows
|
||||
func copyOwnership(source, destination string) error {
|
||||
@@ -12,3 +16,11 @@ func copyOwnership(source, destination string) error {
|
||||
func (container *Container) setupMounts() ([]execdriver.Mount, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func migrateVolume(id, vfs string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func validVolumeLayout(files []os.FileInfo) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -1,5 +1,2 @@
|
||||
# generated by man/man/md2man-all.sh
|
||||
man1/
|
||||
man5/
|
||||
# avoid commiting the awsconfig file used for releases
|
||||
awsconfig
|
||||
|
||||
+4
-17
@@ -280,24 +280,11 @@ aws cloudfront create-invalidation --profile docs.docker.com --distribution-id
|
||||
aws cloudfront create-invalidation --profile docs.docker.com --distribution-id $DISTRIBUTION_ID --invalidation-batch '{"Paths":{"Quantity":1, "Items":["/v1.1/reference/api/docker_io_oauth_api/"]},"CallerReference":"6Mar2015sventest1"}'
|
||||
```
|
||||
|
||||
### Generate the man pages for Mac OSX
|
||||
### Generate the man pages
|
||||
|
||||
When using Docker on Mac OSX the man pages will be missing by default. You can manually generate them by following these steps:
|
||||
For information on generating man pages (short for manual page), see [the man
|
||||
page directory](https://github.com/docker/docker/tree/master/docker) in this
|
||||
project.
|
||||
|
||||
1. Checkout the docker source. You must clone into your `/Users` directory because Boot2Docker can only share this path
|
||||
with the docker containers.
|
||||
|
||||
$ git clone https://github.com/docker/docker.git
|
||||
|
||||
2. Build the docker image.
|
||||
|
||||
$ cd docker/docs/man
|
||||
$ docker build -t docker/md2man .
|
||||
|
||||
3. Build the man pages.
|
||||
|
||||
$ docker run -v /Users/<path-to-git-dir>/docker/docs/man:/docs:rw -w /docs -i docker/md2man /docs/md2man-all.sh
|
||||
|
||||
4. Copy the generated man pages to `/usr/share/man`
|
||||
|
||||
$ cp -R man* /usr/share/man/
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
Docker Documentation
|
||||
====================
|
||||
|
||||
This directory contains the Docker user manual in the Markdown format.
|
||||
Do *not* edit the man pages in the man1 directory. Instead, amend the
|
||||
Markdown (*.md) files.
|
||||
|
||||
# Generating man pages from the Markdown files
|
||||
|
||||
The recommended approach for generating the man pages is via a Docker
|
||||
container using the supplied `Dockerfile` to create an image with the correct
|
||||
environment. This uses `go-md2man`, a pure Go Markdown to man page generator.
|
||||
|
||||
## Building the md2man image
|
||||
|
||||
There is a `Dockerfile` provided in the `docker/docs/man` directory.
|
||||
|
||||
Using this `Dockerfile`, create a Docker image tagged `docker/md2man`:
|
||||
|
||||
docker build -t docker/md2man .
|
||||
|
||||
## Utilizing the image
|
||||
|
||||
Once the image is built, run a container using the image with *volumes*:
|
||||
|
||||
docker run -v /<path-to-git-dir>/docker/docs/man:/docs:rw \
|
||||
-w /docs -i docker/md2man /docs/md2man-all.sh
|
||||
|
||||
The `md2man` Docker container will process the Markdown files and generate
|
||||
the man pages inside the `docker/docs/man/man1` directory using
|
||||
Docker volumes. For more information on Docker volumes see the man page for
|
||||
`docker run` and also look at the article [Sharing Directories via Volumes]
|
||||
(https://docs.docker.com/use/working_with_volumes/).
|
||||
+1
-6
@@ -1,5 +1,5 @@
|
||||
site_name: Docker Documentation
|
||||
#site_url: http://docs.docker.com/
|
||||
#site_url: https://docs.docker.com/
|
||||
site_url: /
|
||||
site_description: Documentation for fast and lightweight Docker container based virtualization framework.
|
||||
site_favicon: img/favicon.png
|
||||
@@ -27,11 +27,6 @@ pages:
|
||||
- ['index.md', 'About', 'Docker']
|
||||
- ['introduction/understanding-docker.md', 'About', 'Understanding Docker']
|
||||
- ['release-notes.md', 'About', 'Release notes']
|
||||
# Experimental
|
||||
- ['experimental/experimental.md', 'About', 'Experimental Features']
|
||||
- ['experimental/plugin_api.md', '**HIDDEN**']
|
||||
- ['experimental/plugins_volume.md', '**HIDDEN**']
|
||||
- ['experimental/plugins.md', '**HIDDEN**']
|
||||
- ['reference/glossary.md', 'About', 'Glossary']
|
||||
- ['introduction/index.md', '**HIDDEN**']
|
||||
|
||||
|
||||
@@ -24,14 +24,28 @@ If you want Docker to start at boot, you should also:
|
||||
## Custom Docker daemon options
|
||||
|
||||
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`
|
||||
(often pointing to `/etc/sysconfig/docker`) then you can modify the
|
||||
referenced file.
|
||||
|
||||
Or, you may need to edit the `docker.service` file, which can be in
|
||||
`/usr/lib/systemd/system`, `/etc/systemd/service`, or `/lib/systemd/system`.
|
||||
Check if the `docker.service` uses an `EnvironmentFile`:
|
||||
|
||||
$ sudo systemctl show docker | grep EnvironmentFile
|
||||
EnvironmentFile=-/etc/sysconfig/docker (ignore_errors=yes)
|
||||
|
||||
Alternatively, find out where the service file is located, and look for the
|
||||
property:
|
||||
|
||||
$ sudo systemctl status docker | grep Loaded
|
||||
Loaded: loaded (/usr/lib/systemd/system/docker.service; enabled)
|
||||
$ sudo grep EnvironmentFile /usr/lib/systemd/system/docker.service
|
||||
EnvironmentFile=-/etc/sysconfig/docker
|
||||
|
||||
You can customize the Docker daemon options using override files as explained in the
|
||||
[HTTP Proxy example](#http-proxy) below. The files located in `/usr/lib/systemd/system`
|
||||
or `/lib/systemd/system` contain the default options and should not be edited.
|
||||
|
||||
### Runtime directory and storage driver
|
||||
|
||||
@@ -42,7 +56,7 @@ In this example, we'll assume that your `docker.service` file looks something li
|
||||
|
||||
[Unit]
|
||||
Description=Docker Application Container Engine
|
||||
Documentation=http://docs.docker.com
|
||||
Documentation=https://docs.docker.com
|
||||
After=network.target docker.socket
|
||||
Requires=docker.socket
|
||||
|
||||
@@ -90,6 +104,11 @@ Flush changes:
|
||||
|
||||
$ sudo systemctl daemon-reload
|
||||
|
||||
Verify that the configuration has been loaded:
|
||||
|
||||
$ sudo systemctl show docker --property Environment
|
||||
Environment=HTTP_PROXY=http://proxy.example.com:80/
|
||||
|
||||
Restart Docker:
|
||||
|
||||
$ sudo systemctl restart docker
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
no_version_dropdown: true
|
||||
page_title: Docker Hub Enterprise: Admin guide
|
||||
page_description: Documentation describing administration of Docker Hub Enterprise
|
||||
page_keywords: docker, documentation, about, technology, hub, enterprise
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
no_version_dropdown: true
|
||||
page_title: Docker Hub Enterprise: Configuration options
|
||||
page_description: Configuration instructions for Docker Hub Enterprise
|
||||
page_keywords: docker, documentation, about, technology, understanding, enterprise, hub, registry
|
||||
@@ -136,11 +137,11 @@ Continue by following the steps corresponding to your chosen OS.
|
||||
|
||||
```
|
||||
$ export DOMAIN_NAME=dhe.yourdomain.com
|
||||
$ openssl s_client -connect $DOMAIN_NAME:443 -showcerts </dev/null 2>/dev/null | openssl x509 -outform PEM | tee /usr/local/share/ca-certificates/$DOMAIN_NAME.crt
|
||||
$ update-ca-certificates
|
||||
$ openssl s_client -connect $DOMAIN_NAME:443 -showcerts </dev/null 2>/dev/null | openssl x509 -outform PEM | sudo tee /usr/local/share/ca-certificates/$DOMAIN_NAME.crt
|
||||
$ sudo update-ca-certificates
|
||||
Updating certificates in /etc/ssl/certs... 1 added, 0 removed; done.
|
||||
Running hooks in /etc/ca-certificates/update.d....done.
|
||||
$ service docker restart
|
||||
$ sudo service docker restart
|
||||
docker stop/waiting
|
||||
docker start/running, process 29291
|
||||
```
|
||||
@@ -149,9 +150,9 @@ Continue by following the steps corresponding to your chosen OS.
|
||||
|
||||
```
|
||||
$ export DOMAIN_NAME=dhe.yourdomain.com
|
||||
$ openssl s_client -connect $DOMAIN_NAME:443 -showcerts </dev/null 2>/dev/null | openssl x509 -outform PEM | tee /etc/pki/ca-trust/source/anchors/$DOMAIN_NAME.crt
|
||||
$ update-ca-trust
|
||||
$ /bin/systemctl restart docker.service
|
||||
$ openssl s_client -connect $DOMAIN_NAME:443 -showcerts </dev/null 2>/dev/null | openssl x509 -outform PEM | sudo tee /etc/pki/ca-trust/source/anchors/$DOMAIN_NAME.crt
|
||||
$ sudo update-ca-trust
|
||||
$ sudo /bin/systemctl restart docker.service
|
||||
```
|
||||
|
||||
#### Boot2Docker 1.6.0
|
||||
@@ -257,7 +258,7 @@ API.
|
||||
* *Yaml configuration file*: This file (`/usr/local/etc/dhe/storage.yml`) is
|
||||
used to configure the image storage services. The editable text of the file is
|
||||
displayed in the dialog box. The schema of this file is identical to that used
|
||||
by the [Registry 2.0](http://docs.docker.com/registry/configuration/).
|
||||
by the [Registry 2.0](https://docs.docker.com/registry/configuration/).
|
||||
* If you are using the file system driver to provide local image storage, you will need to specify a root directory which will get mounted as a sub-path of
|
||||
`/var/local/dhe/image-storage`. The default value of this root directory is
|
||||
`/local`, so the full path to it is `/var/local/dhe/image-storage/local`.
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
no_version_dropdown: true
|
||||
page_title: Docker Hub Enterprise: Overview
|
||||
page_description: Docker Hub Enterprise
|
||||
page_keywords: docker, documentation, about, technology, understanding, enterprise, hub, registry
|
||||
@@ -31,6 +32,12 @@ DHE is perfect for:
|
||||
|
||||
DHE is built on [version 2 of the Docker registry](https://github.com/docker/distribution).
|
||||
|
||||
> **Note:** This initial release of DHE has limited access. To get access,
|
||||
> you will need an account on [Docker Hub](https://hub.docker.com/). Once you're
|
||||
> logged in to the Hub with your account, visit the
|
||||
> [early access registration page](https://registry.hub.docker.com/earlyaccess/)
|
||||
> and follow the steps there to get signed up.
|
||||
|
||||
## Available Documentation
|
||||
|
||||
The following documentation for DHE is available:
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
no_version_dropdown: true
|
||||
page_title: Docker Hub Enterprise: Install
|
||||
page_description: Installation instructions for Docker Hub Enterprise
|
||||
page_keywords: docker, documentation, about, technology, understanding, enterprise, hub, registry
|
||||
@@ -20,6 +21,12 @@ Specifically, installation requires completion of these steps, in order:
|
||||
3. Install DHE
|
||||
4. Add your license to your DHE instance
|
||||
|
||||
> **Note:** This initial release of DHE has limited access. To get access,
|
||||
> you will need an account on [Docker Hub](https://hub.docker.com/). Once you're
|
||||
> logged in to the Hub with your account, visit the
|
||||
> [early access registration page](https://registry.hub.docker.com/earlyaccess/)
|
||||
> and follow the steps there to get signed up.
|
||||
|
||||
## Licensing
|
||||
|
||||
In order to run DHE, you will need to acquire a license, either by purchasing
|
||||
@@ -108,6 +115,8 @@ following to install commercially supported Docker Engine and its dependencies:
|
||||
|
||||
```
|
||||
$ sudo apt-get update && sudo apt-get upgrade
|
||||
$ sudo apt-get install -y linux-image-extra-virtual
|
||||
$ sudo reboot
|
||||
$ chmod 755 docker-cs-engine-deb.sh
|
||||
$ sudo ./docker-cs-engine-deb.sh
|
||||
$ sudo apt-get install docker-engine-cs
|
||||
@@ -139,19 +148,25 @@ so upgrading the Engine only requires you to run the update commands on your ser
|
||||
|
||||
### RHEL 7.0/7.1 upgrade
|
||||
|
||||
To upgrade CS Docker Engine, run the following command:
|
||||
The following commands will stop the running DHE, upgrade CS Docker Engine,
|
||||
and then start DHE again:
|
||||
|
||||
```
|
||||
$ sudo bash -c "$(sudo docker run dockerhubenterprise/manager stop)"
|
||||
$ sudo yum update
|
||||
$ sudo systemctl daemon-reload && sudo systemctl restart docker
|
||||
$ sudo bash -c "$(sudo docker run dockerhubenterprise/manager start)"
|
||||
```
|
||||
|
||||
### Ubuntu 14.04 LTS upgrade
|
||||
|
||||
To upgrade CS Docker Engine, run the following command:
|
||||
The following commands will stop the running DHE, upgrade CS Docker Engine,
|
||||
and then start DHE again:
|
||||
|
||||
```
|
||||
$ sudo apt-get update && sudo apt-get dist-upgrade docker-engine-cs
|
||||
$ sudo bash -c "$(sudo docker run dockerhubenterprise/manager stop)"
|
||||
$ sudo apt-get update && sudo apt-get dist-upgrade docker-engine-cs
|
||||
$ sudo bash -c "$(sudo docker run dockerhubenterprise/manager start)"
|
||||
```
|
||||
|
||||
## Installing Docker Hub Enterprise
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
no_version_dropdown: true
|
||||
page_title: Docker Hub Enterprise: Quick-start: Basic Workflow
|
||||
page_description: Brief tutorial on the basics of Docker Hub Enterprise user workflow
|
||||
page_keywords: docker, documentation, about, technology, understanding, enterprise, hub, registry, image, repository
|
||||
@@ -8,7 +9,7 @@ page_keywords: docker, documentation, about, technology, understanding, enterpri
|
||||
## Overview
|
||||
|
||||
This Quick Start Guide will give you a hands-on look at the basics of using
|
||||
Docker Hub Enterprise (DHE), Docker’s on-premise image storage application.
|
||||
Docker Hub Enterprise (DHE), Docker's on-premise image storage application.
|
||||
This guide will walk you through using DHE to complete a typical, and critical,
|
||||
part of building a development pipeline: setting up a Jenkins instance. Once you
|
||||
complete the task, you should have a good idea of how DHE works and how it might
|
||||
@@ -17,9 +18,9 @@ be useful to you.
|
||||
Specifically, this guide demonstrates the process of retrieving the
|
||||
[official Docker image for Jenkins](https://registry.hub.docker.com/_/jenkins/),
|
||||
customizing it to suit your needs, and then hosting it on your private instance
|
||||
of DHE located inside your enterprise’s firewalled environment. Your developers
|
||||
of DHE located inside your enterprise's firewalled environment. Your developers
|
||||
will then be able to retrieve the custom Jenkins image in order to use it to
|
||||
build CI/CD infrastructure for their projects, no matter the platform they’re
|
||||
build CI/CD infrastructure for their projects, no matter the platform they're
|
||||
working from, be it a laptop, a VM, or a cloud provider.
|
||||
|
||||
The guide will walk you through the following steps:
|
||||
@@ -44,7 +45,7 @@ You should be able to complete this guide in about thirty minutes.
|
||||
> **Note:** This guide assumes you are familiar with basic Docker concepts such
|
||||
> as images, containers, and registries. If you need to learn more about Docker
|
||||
> fundamentals, please consult the
|
||||
> [Docker user guide](http://docs.docker.com/userguide/).
|
||||
> [Docker user guide](https://docs.docker.com/userguide/).
|
||||
|
||||
First, you will retrieve a copy of the official Jenkins image from the Docker Hub. By default, if
|
||||
Docker can't find an image locally, it will attempt to pull the image from the
|
||||
@@ -72,12 +73,12 @@ Docker will start the process of pulling the image from the Hub. Once it has com
|
||||
|
||||
## Customizing the Jenkins image
|
||||
|
||||
Now that you have a local copy of the Jenkins image, you’ll customize it so that
|
||||
Now that you have a local copy of the Jenkins image, you'll customize it so that
|
||||
the containers it builds will integrate with your infrastructure. To do this,
|
||||
you’ll create a custom Docker image that adds a Jenkins plugin that provides
|
||||
fine grained user management. You’ll also configure Jenkins to be more secure by
|
||||
you'll create a custom Docker image that adds a Jenkins plugin that provides
|
||||
fine grained user management. You'll also configure Jenkins to be more secure by
|
||||
disabling HTTP access and forcing it to use HTTPS.
|
||||
You’ll do this by using a `Dockerfile` and the `docker build` command.
|
||||
You'll do this by using a `Dockerfile` and the `docker build` command.
|
||||
|
||||
> **Note:** These are obviously just a couple of examples of the many ways you
|
||||
> can modify and configure Jenkins. Feel free to add or substitute whatever
|
||||
@@ -105,11 +106,11 @@ line:
|
||||
|
||||
(The plugin version used above was the latest version at the time of writing.)
|
||||
|
||||
2. You will also need to make copies of the server’s private key and certificate. Give the copies the following names — `https.key` and `https.pem`.
|
||||
2. You will also need to make copies of the server's private key and certificate. Give the copies the following names - `https.key` and `https.pem`.
|
||||
|
||||
> **Note:** Because creating new keys varies widely by platform and
|
||||
> implementation, this guide won’t cover key generation. We assume you have
|
||||
> access to existing keys. If you don’t have access, or can’t generate keys
|
||||
> implementation, this guide won't cover key generation. We assume you have
|
||||
> access to existing keys. If you don't have access, or can't generate keys
|
||||
> yourself, feel free to skip the steps involving them and HTTPS config. The
|
||||
> guide will still walk you through building a custom Jenkins image and pushing
|
||||
> and pulling that image using DHE.
|
||||
@@ -142,7 +143,7 @@ defining with the `Dockerfile`.
|
||||
The `RUN` instruction will execute the `/usr/local/bin/plugins.sh` script with
|
||||
the newly copied `plugins` file, which will install the listed plugin.
|
||||
|
||||
The next two `COPY` instructions copy the server’s private key and certificate
|
||||
The next two `COPY` instructions copy the server's private key and certificate
|
||||
into the required directories within the new image.
|
||||
|
||||
The `ENV` instruction creates an environment variable called `JENKINS_OPT` in
|
||||
@@ -156,8 +157,8 @@ tell Jenkins to disable HTTP and operate over HTTPS.
|
||||
|
||||
The `Dockerfile`, the `plugins` file, as well as the private key and
|
||||
certificate, must all be in the same directory because the `docker build`
|
||||
command uses the directory that contains the `Dockerfile` as its “build
|
||||
context”. Only files contained within that “build context” will be included in
|
||||
command uses the directory that contains the `Dockerfile` as its "build
|
||||
context". Only files contained within that "build context" will be included in
|
||||
the image being built.
|
||||
|
||||
### Building your custom image
|
||||
@@ -169,7 +170,7 @@ custom image using the
|
||||
|
||||
docker build -t dhe.yourdomain.com/ci-infrastructure/jnkns-img .
|
||||
|
||||
> **Note:** Don’t miss the period (`.`) at the end of the command above. This
|
||||
> **Note:** Don't miss the period (`.`) at the end of the command above. This
|
||||
> tells the `docker build` command to use the current working directory as the
|
||||
> "build context".
|
||||
|
||||
@@ -214,7 +215,7 @@ image pulled earlier:
|
||||
> ?scope=repository%3Ahello-world%3Apull%2Cpush&service=dhe.yourdomain.com
|
||||
> request failed with status: 401 Unauthorized
|
||||
|
||||
Now that you’ve created the custom image, it can be pushed to DHE using the
|
||||
Now that you've created the custom image, it can be pushed to DHE using the
|
||||
[`docker push`command](https://docs.docker.com/reference/commandline/cli/#push):
|
||||
|
||||
$ docker push dhe.yourdomain.com/ci-infrastructure/jnkns-img
|
||||
@@ -263,7 +264,7 @@ in the output of the `docker images` command:
|
||||
|
||||
## Launching a custom Jenkins container
|
||||
|
||||
Now that you’ve successfully pulled the customized Jenkins image from DHE, you
|
||||
Now that you've successfully pulled the customized Jenkins image from DHE, you
|
||||
can create a container from it with the
|
||||
[`docker run` command](https://docs.docker.com/reference/commandline/cli/#run):
|
||||
|
||||
@@ -299,7 +300,7 @@ You can view the newly launched a container, called `jenkins01`, using the
|
||||
|
||||
The previous `docker run` command mapped port `1973` on the container to port
|
||||
`1973` on the Docker host, so the Jenkins Web UI can be accessed at
|
||||
`https://<docker-host>:1973` (Don’t forget the `s` at the end of `https`.)
|
||||
`https://<docker-host>:1973` (Don't forget the `s` at the end of `https`.)
|
||||
|
||||
> **Note:** If you are using a self-signed certificate, you may get a security
|
||||
> warning from your browser telling you that the certificate is self-signed and
|
||||
@@ -315,7 +316,7 @@ plugin should be present with the `Uninstall` button available to the right.
|
||||

|
||||
|
||||
In another browser session, try to access Jenkins via the default HTTP port 8080
|
||||
— `http://<docker-host>:8080`. This should result in a “connection timeout,”
|
||||
`http://<docker-host>:8080`. This should result in a "connection timeout",
|
||||
showing that Jenkins is not available on its default port 8080 over HTTP.
|
||||
|
||||
This demonstration shows your Jenkins image has been configured correctly for
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
no_version_dropdown: true
|
||||
page_title: Docker Hub Enterprise: Release notes
|
||||
page_description: Release notes for Docker Hub Enterprise
|
||||
page_keywords: docker, documentation, about, technology, understanding, enterprise, hub, registry, release
|
||||
|
||||
@@ -27,7 +27,7 @@ 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](
|
||||
http://docs.docker.com/userguide/dockerhub/#creating-a-docker-hub-account)
|
||||
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.
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# example Dockerfile for http://docs.docker.com/examples/postgresql_service/
|
||||
# example Dockerfile for https://docs.docker.com/examples/postgresql_service/
|
||||
#
|
||||
|
||||
FROM ubuntu
|
||||
|
||||
@@ -21,7 +21,7 @@ Start by creating a new `Dockerfile`:
|
||||
> suitably secure.
|
||||
|
||||
#
|
||||
# example Dockerfile for http://docs.docker.com/examples/postgresql_service/
|
||||
# example Dockerfile for https://docs.docker.com/examples/postgresql_service/
|
||||
#
|
||||
|
||||
FROM ubuntu
|
||||
|
||||
@@ -4,7 +4,7 @@ page_keywords: Docker, Docker documentation, Windows, requirements, virtualbox,
|
||||
|
||||
# Windows
|
||||
> **Note:**
|
||||
> Docker has been tested on Windows 7.1 and 8; it may also run on older versions.
|
||||
> Docker has been tested on Windows 7 and 8.1; it may also run on older versions.
|
||||
> Your processor needs to support hardware virtualization.
|
||||
|
||||
The Docker Engine uses Linux-specific kernel features, so to run it on Windows
|
||||
|
||||
@@ -75,9 +75,9 @@ Always rebase and squash your commits before making a pull request.
|
||||
|
||||
6. Edit and save your commit message.
|
||||
|
||||
`git commit -s`
|
||||
$ git commit -s
|
||||
|
||||
Make sure your message includes <a href="./set-up-git" target="_blank>your signature</a>.
|
||||
Make sure your message includes <a href="../set-up-git" target="_blank">your signature</a>.
|
||||
|
||||
7. Force push any changes to your fork on GitHub.
|
||||
|
||||
|
||||
@@ -102,7 +102,7 @@ Run the entire test suite on your current repository:
|
||||
|
||||
* creates a new binary
|
||||
* cross-compiles all the binaries for the various operating systems
|
||||
* runs the all the tests in the system
|
||||
* runs all the tests in the system
|
||||
|
||||
It can take several minutes to run all the tests. When they complete
|
||||
successfully, you see the output concludes with something like this:
|
||||
|
||||
@@ -178,9 +178,9 @@ You should pull and rebase frequently as you work.
|
||||
|
||||
6. Edit and save your commit message.
|
||||
|
||||
`git commit -s`
|
||||
$ git commit -s
|
||||
|
||||
Make sure your message includes <a href="./set-up-git" target="_blank>your signature</a>.
|
||||
Make sure your message includes <a href="../set-up-git" target="_blank">your signature</a>.
|
||||
|
||||
7. Force push any changes to your fork on GitHub.
|
||||
|
||||
|
||||
@@ -492,7 +492,7 @@ change them using `docker run --env <key>=<value>`.
|
||||
ADD has two forms:
|
||||
|
||||
- `ADD <src>... <dest>`
|
||||
- `ADD ["<src>"... "<dest>"]` (this form is required for paths containing
|
||||
- `ADD ["<src>",... "<dest>"]` (this form is required for paths containing
|
||||
whitespace)
|
||||
|
||||
The `ADD` instruction copies new files, directories or remote file URLs from `<src>`
|
||||
@@ -596,7 +596,7 @@ The copy obeys the following rules:
|
||||
COPY has two forms:
|
||||
|
||||
- `COPY <src>... <dest>`
|
||||
- `COPY ["<src>"... "<dest>"]` (this form is required for paths containing
|
||||
- `COPY ["<src>",... "<dest>"]` (this form is required for paths containing
|
||||
whitespace)
|
||||
|
||||
The `COPY` instruction copies new files or directories from `<src>`
|
||||
|
||||
@@ -1115,6 +1115,9 @@ and Docker images will report:
|
||||
|
||||
untag, delete
|
||||
|
||||
If you do not provide the --since option, the command
|
||||
returns only new and/or live events.
|
||||
|
||||
#### Filtering
|
||||
|
||||
The filtering flag (`-f` or `--filter`) format is of "key=value". If you would like to use
|
||||
|
||||
@@ -1115,8 +1115,10 @@ container's `/etc/hosts` entry will be automatically updated.
|
||||
|
||||
## VOLUME (shared filesystems)
|
||||
|
||||
-v=[]: Create a bind mount with: [host-dir]:[container-dir]:[rw|ro].
|
||||
If "container-dir" is missing, then docker creates a new volume.
|
||||
-v=[]: Create a bind mount with: [host-dir:]container-dir[:rw|ro].
|
||||
If 'host-dir' is missing, then docker creates a new volume.
|
||||
If neither 'rw' or 'ro' is specified then the volume is mounted
|
||||
in read-write mode.
|
||||
--volumes-from="": Mount all volumes from the given container(s)
|
||||
|
||||
The volumes commands are complex enough to have their own documentation
|
||||
|
||||
@@ -22,13 +22,13 @@ repository](https://github.com/docker/docker/blob/master/CHANGELOG.md).
|
||||
|
||||
| Feature | Description |
|
||||
|------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| Container and Image Labels | Labels allow you to attach user-defined metadata to containers and images that can be used by your tools. For additional information on using labels, see [Apply custom metadata](http://docs.docker.com/userguide/labels-custom-metadata/#add-labels-to-images-the-label-instruction) in the documentation. |
|
||||
| Container and Image Labels | Labels allow you to attach user-defined metadata to containers and images that can be used by your tools. For additional information on using labels, see [Apply custom metadata](https://docs.docker.com/userguide/labels-custom-metadata/#add-labels-to-images-the-label-instruction) in the documentation. |
|
||||
| Windows Client preview | The Windows Client can be used just like the Mac OS X client is today with a remote host. Our testing infrastructure was scaled out to accommodate Windows Client testing on every PR to the Engine. See the Azure blog for [details on using this new client](http://azure.microsoft.com/blog/2015/04/16/docker-client-for-windows-is-now-available). |
|
||||
| Logging drivers | The new logging driver follows the exec driver and storage driver concepts already available in Engine today. There is a new option `--log-driver` to `docker run` command. See the `run` reference for a [description on how to use this option](http://docs.docker.com/reference/run/#logging-drivers-log-driver). |
|
||||
| Image digests | When you pull, build, or run images, you specify them in the form `namespace/repository:tag`, or even just `repository`. In this release, you are now able to pull, run, build and refer to images by a new content addressable identifier called a “digest” with the syntax `namespace/repo@digest`. See the the command line reference for [examples of using the digest](http://docs.docker.com/reference/commandline/cli/#listing-image-digests). |
|
||||
| Custom cgroups | Containers are made from a combination of namespaces, capabilities, and cgroups. Docker already supports custom namespaces and capabilities. Additionally, in this release we’ve added support for custom cgroups. Using the `--cgroup-parent` flag, you can pass a specific `cgroup` to run a container in. See [the command line reference for more information](http://docs.docker.com/reference/commandline/cli/#create). |
|
||||
| Ulimits | You can now specify the default `ulimit` settings for all containers when configuring the daemon. For example:`docker -d --default-ulimit nproc=1024:2048` See [Default Ulimits](http://docs.docker.com/reference/commandline/cli/#default-ulimits) in this documentation. |
|
||||
| Commit and import Dockerfile | You can now make changes to images on the fly without having to re-build the entire image. The feature `commit --change` and `import --change` allows you to apply standard changes to a new image. These are expressed in the Dockerfile syntax and used to modify the image. For details on how to use these, see the [commit](http://docs.docker.com/reference/commandline/cli/#commit) and [import](http://docs.docker.com/reference/commandline/cli/#import). |
|
||||
| Logging drivers | The new logging driver follows the exec driver and storage driver concepts already available in Engine today. There is a new option `--log-driver` to `docker run` command. See the `run` reference for a [description on how to use this option](https://docs.docker.com/reference/run/#logging-drivers-log-driver). |
|
||||
| Image digests | When you pull, build, or run images, you specify them in the form `namespace/repository:tag`, or even just `repository`. In this release, you are now able to pull, run, build and refer to images by a new content addressable identifier called a “digest” with the syntax `namespace/repo@digest`. See the the command line reference for [examples of using the digest](https://docs.docker.com/reference/commandline/cli/#listing-image-digests). |
|
||||
| Custom cgroups | Containers are made from a combination of namespaces, capabilities, and cgroups. Docker already supports custom namespaces and capabilities. Additionally, in this release we’ve added support for custom cgroups. Using the `--cgroup-parent` flag, you can pass a specific `cgroup` to run a container in. See [the command line reference for more information](https://docs.docker.com/reference/commandline/cli/#create). |
|
||||
| Ulimits | You can now specify the default `ulimit` settings for all containers when configuring the daemon. For example:`docker -d --default-ulimit nproc=1024:2048` See [Default Ulimits](https://docs.docker.com/reference/commandline/cli/#default-ulimits) in this documentation. |
|
||||
| Commit and import Dockerfile | You can now make changes to images on the fly without having to re-build the entire image. The feature `commit --change` and `import --change` allows you to apply standard changes to a new image. These are expressed in the Dockerfile syntax and used to modify the image. For details on how to use these, see the [commit](https://docs.docker.com/reference/commandline/cli/#commit) and [import](https://docs.docker.com/reference/commandline/cli/#import). |
|
||||
|
||||
### Known issues in Engine
|
||||
|
||||
@@ -62,15 +62,15 @@ around a new set of distribution APIs
|
||||
- **Webhook notifications**: You can now configure the Registry to send Webhooks
|
||||
when images are pushed. Spin off a CI build, send a notification to IRC –
|
||||
whatever you want! Included in the documentation is a detailed [notification
|
||||
specification](http://docs.docker.com/registry/notifications/).
|
||||
specification](https://docs.docker.com/registry/notifications/).
|
||||
|
||||
- **Native TLS support**: This release makes it easier to secure a registry with
|
||||
TLS. This documentation includes [expanded examples of secure
|
||||
deployments](http://docs.docker.com/registry/deploying/).
|
||||
deployments](https://docs.docker.com/registry/deploying/).
|
||||
|
||||
- **New Distribution APIs**: This release includes an expanded set of new
|
||||
distribution APIs. You can read the [detailed specification
|
||||
here](http://docs.docker.com/registry/spec/api/).
|
||||
here](https://docs.docker.com/registry/spec/api/).
|
||||
|
||||
|
||||
## Docker Compose 1.2
|
||||
@@ -86,7 +86,7 @@ with the keyword “extends”. With extends, you can refer to a service defined
|
||||
elsewhere and include its configuration in a locally-defined service, while also
|
||||
adding or overriding configuration as necessary. The documentation describes
|
||||
[how to use extends in your
|
||||
configuration](http://docs.docker.com/compose/extends/#extending-services-in-
|
||||
configuration](https://docs.docker.com/compose/extends/#extending-services-in-
|
||||
compose).
|
||||
|
||||
- **Relative directory handling may cause breaking change**: Compose now treats
|
||||
@@ -103,7 +103,7 @@ another directory.
|
||||
|
||||
You'll find the [release for download on
|
||||
GitHub](https://github.com/docker/swarm/releases/tag/v0.2.0) and [the
|
||||
documentation here](http://docs.docker.com/swarm/). This release includes the
|
||||
documentation here](https://docs.docker.com/swarm/). This release includes the
|
||||
following features:
|
||||
|
||||
- **Spread strategy**: A new strategy for scheduling containers on your cluster
|
||||
@@ -119,7 +119,7 @@ make it possible to use Swarm with clustering systems such as Mesos.
|
||||
|
||||
You'll find the [release for download on
|
||||
GitHub](https://github.com/docker/machine/releases) and [the documentation
|
||||
here](http://docs.docker.com/machine/). For a complete list of machine changes
|
||||
here](https://docs.docker.com/machine/). For a complete list of machine changes
|
||||
see [the changelog in the project
|
||||
repository](https://github.com/docker/machine/blob/master/CHANGES.md#020-2015-03
|
||||
-22).
|
||||
|
||||
@@ -94,7 +94,7 @@ community.
|
||||
## Features of Docker Hub
|
||||
|
||||
Let's take a closer look at some of the features of Docker Hub. You can find more
|
||||
information [here](http://docs.docker.com/docker-hub/).
|
||||
information [here](https://docs.docker.com/docker-hub/).
|
||||
|
||||
* Private repositories
|
||||
* Organizations and teams
|
||||
@@ -163,7 +163,7 @@ a webhook you can specify a target URL and a JSON payload that will be
|
||||
delivered when the image is pushed.
|
||||
|
||||
See the Docker Hub documentation for [more information on
|
||||
webhooks](http://docs.docker.com/docker-hub/repos/#webhooks)
|
||||
webhooks](https://docs.docker.com/docker-hub/repos/#webhooks)
|
||||
|
||||
## Next steps
|
||||
|
||||
|
||||
@@ -110,7 +110,7 @@ Go to [Docker Swarm user guide](/swarm/).
|
||||
* [Docker homepage](http://www.docker.com/)
|
||||
* [Docker Hub](https://hub.docker.com)
|
||||
* [Docker blog](http://blog.docker.com/)
|
||||
* [Docker documentation](http://docs.docker.com/)
|
||||
* [Docker documentation](https://docs.docker.com/)
|
||||
* [Docker Getting Started Guide](http://www.docker.com/gettingstarted/)
|
||||
* [Docker code on GitHub](https://github.com/docker/docker)
|
||||
* [Docker mailing
|
||||
|
||||
@@ -1,12 +1,8 @@
|
||||
page_title: Overview of Experimental Features
|
||||
page_keywords: experimental, Docker, feature
|
||||
# Docker Experimental Features
|
||||
|
||||
# Experimental Features in this Release
|
||||
|
||||
This page contains a list of features in the Docker engine which are
|
||||
experimental as of the current release. Experimental features are **not** ready
|
||||
for production. They are provided for test and evaluation in your sandbox
|
||||
environments.
|
||||
This page contains a list of features in the Docker engine which are
|
||||
experimental. Experimental features are **not** ready for production. They are
|
||||
provided for test and evaluation in your sandbox environments.
|
||||
|
||||
The information below describes each feature and the Github pull requests and
|
||||
issues associated with it. If necessary, links are provided to additional
|
||||
@@ -15,6 +11,8 @@ please feel free to provide any feedback on these features you wish.
|
||||
|
||||
## Install Docker experimental
|
||||
|
||||
Unlike the regular Docker binary, the experimental channels is built and updated nightly on https://experimental.docker.com. From one day to the next, new features may appear, while existing experimental features may be refined or entirely removed.
|
||||
|
||||
1. Verify that you have `wget` installed.
|
||||
|
||||
$ which wget
|
||||
@@ -44,8 +42,13 @@ please feel free to provide any feedback on these features you wish.
|
||||
|
||||
This command downloads a test image and runs it in a container.
|
||||
|
||||
## Experimental features in this Release
|
||||
## Current experimental features
|
||||
|
||||
* [Support for Docker plugins](plugins.md)
|
||||
* [Volume plugins](plugins_volume.md)
|
||||
|
||||
## How to comment on an experimental feature
|
||||
|
||||
Each feature's documentation includes a list of proposal pull requests or PRs associated with the feature. If you want to comment on or suggest a change to a feature, please add it to the existing feature PR.
|
||||
|
||||
Issues or problems with a feature? Inquire for help on the `#docker` IRC channel or in on the [Docker Google group](https://groups.google.com/forum/#!forum/docker-user).
|
||||
@@ -1,7 +1,3 @@
|
||||
page_title: Plugin API documentation
|
||||
page_description: Documentation for writing a Docker plugin.
|
||||
page_keywords: docker, plugins, api, extensions
|
||||
|
||||
# Experimental: Docker Plugin API
|
||||
|
||||
Docker plugins are out-of-process extensions which add capabilities to the
|
||||
@@ -1,6 +1,3 @@
|
||||
page_title: Experimental feature - Plugins
|
||||
page_keywords: experimental, Docker, plugins
|
||||
|
||||
# Experimental: Extend Docker with a plugin
|
||||
|
||||
You can extend the capabilities of the Docker Engine by loading third-party
|
||||
@@ -1,6 +1,3 @@
|
||||
page_title: Experimental feature - Volume plugins
|
||||
page_keywords: experimental, Docker, plugins, volume
|
||||
|
||||
# Experimental: Docker volume plugins
|
||||
|
||||
Docker volume plugins enable Docker deployments to be integrated with external
|
||||
@@ -133,6 +133,21 @@ do_install() {
|
||||
exit 0
|
||||
;;
|
||||
|
||||
'opensuse project'|opensuse|'suse linux'|sled)
|
||||
(
|
||||
set -x
|
||||
$sh_c 'sleep 3; zypper -n install docker'
|
||||
)
|
||||
if command_exists docker && [ -e /var/run/docker.sock ]; then
|
||||
(
|
||||
set -x
|
||||
$sh_c 'docker version'
|
||||
) || true
|
||||
fi
|
||||
echo_docker_as_nonroot
|
||||
exit 0
|
||||
;;
|
||||
|
||||
ubuntu|debian|linuxmint|'elementary os'|kali)
|
||||
export DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
docs/man/man*/*
|
||||
man/man*/*
|
||||
|
||||
@@ -9,7 +9,7 @@ override_dh_gencontrol:
|
||||
|
||||
override_dh_auto_build:
|
||||
./hack/make.sh dynbinary
|
||||
# ./docs/man/md2man-all.sh runs outside the build container (if at all), since we don't have go-md2man here
|
||||
# ./man/md2man-all.sh runs outside the build container (if at all), since we don't have go-md2man here
|
||||
|
||||
override_dh_auto_test:
|
||||
./bundles/$(VERSION)/dynbinary/docker -v
|
||||
|
||||
@@ -71,7 +71,7 @@ depending on a particular stack or provider.
|
||||
|
||||
%build
|
||||
./hack/make.sh dynbinary
|
||||
# ./docs/man/md2man-all.sh runs outside the build container (if at all), since we don't have go-md2man here
|
||||
# ./man/md2man-all.sh runs outside the build container (if at all), since we don't have go-md2man here
|
||||
|
||||
%check
|
||||
./bundles/%{_origversion}/dynbinary/docker -v
|
||||
@@ -113,9 +113,9 @@ install -p -m 644 contrib/completion/fish/docker.fish $RPM_BUILD_ROOT/usr/share/
|
||||
|
||||
# install manpages
|
||||
install -d %{buildroot}%{_mandir}/man1
|
||||
install -p -m 644 docs/man/man1/*.1 $RPM_BUILD_ROOT/%{_mandir}/man1
|
||||
install -p -m 644 man/man1/*.1 $RPM_BUILD_ROOT/%{_mandir}/man1
|
||||
install -d %{buildroot}%{_mandir}/man5
|
||||
install -p -m 644 docs/man/man5/*.5 $RPM_BUILD_ROOT/%{_mandir}/man5
|
||||
install -p -m 644 man/man5/*.5 $RPM_BUILD_ROOT/%{_mandir}/man5
|
||||
|
||||
# add vimfiles
|
||||
install -d $RPM_BUILD_ROOT/usr/share/vim/vimfiles/doc
|
||||
|
||||
+1
-1
@@ -35,7 +35,7 @@ set -e
|
||||
debDate="$(date --rfc-2822)"
|
||||
|
||||
# if go-md2man is available, pre-generate the man pages
|
||||
./docs/man/md2man-all.sh -q || true
|
||||
./man/md2man-all.sh -q || true
|
||||
# TODO decide if it's worth getting go-md2man in _each_ builder environment to avoid this
|
||||
|
||||
# TODO add a configurable knob for _which_ debs to build so we don't have to modify the file or build all of them every time we need to test
|
||||
|
||||
+1
-1
@@ -38,7 +38,7 @@ set -e
|
||||
rpmDate="$(date +'%a %b %d %Y')"
|
||||
|
||||
# if go-md2man is available, pre-generate the man pages
|
||||
./docs/man/md2man-all.sh -q || true
|
||||
./man/md2man-all.sh -q || true
|
||||
# TODO decide if it's worth getting go-md2man in _each_ builder environment to avoid this
|
||||
|
||||
# TODO add a configurable knob for _which_ rpms to build so we don't have to modify the file or build all of them every time we need to test
|
||||
|
||||
+2
-2
@@ -60,10 +60,10 @@ bundle_ubuntu() {
|
||||
cp contrib/completion/fish/docker.fish "$DIR/etc/fish/completions/"
|
||||
|
||||
# Include contributed man pages
|
||||
docs/man/md2man-all.sh -q
|
||||
man/md2man-all.sh -q
|
||||
manRoot="$DIR/usr/share/man"
|
||||
mkdir -p "$manRoot"
|
||||
for manDir in docs/man/man?; do
|
||||
for manDir in man/man?; do
|
||||
manBase="$(basename "$manDir")" # "man1"
|
||||
for manFile in "$manDir"/*; do
|
||||
manName="$(basename "$manFile")" # "docker-build.1"
|
||||
|
||||
+4
-4
@@ -251,9 +251,10 @@ release_ubuntu() {
|
||||
exit 1
|
||||
}
|
||||
|
||||
local debfiles=( "bundles/$VERSION/ubuntu/"*.deb )
|
||||
|
||||
# Sign our packages
|
||||
dpkg-sig -g "--passphrase $GPG_PASSPHRASE" -k releasedocker \
|
||||
--sign builder "bundles/$VERSION/ubuntu/"*.deb
|
||||
dpkg-sig -g "--passphrase $GPG_PASSPHRASE" -k releasedocker --sign builder "${debfiles[@]}"
|
||||
|
||||
# Setup the APT repo
|
||||
APTDIR=bundles/$VERSION/ubuntu/apt
|
||||
@@ -266,8 +267,7 @@ Architectures: amd64 i386
|
||||
EOF
|
||||
|
||||
# Add the DEB package to the APT repo
|
||||
DEBFILE=( bundles/$VERSION/ubuntu/lxc-docker*.deb )
|
||||
reprepro -b "$APTDIR" includedeb docker "$DEBFILE"
|
||||
reprepro -b "$APTDIR" includedeb docker "${debfiles[@]}"
|
||||
|
||||
# Sign
|
||||
for F in $(find $APTDIR -name Release); do
|
||||
|
||||
+3
-3
@@ -55,8 +55,8 @@ clone hg code.google.com/p/go.net 84a4013f96e0
|
||||
clone hg code.google.com/p/gosqlite 74691fb6f837
|
||||
|
||||
#get libnetwork packages
|
||||
clone git github.com/docker/libnetwork f72ad20491e8c46d9664da3f32a0eddb301e7c8d
|
||||
clone git github.com/vishvananda/netns 008d17ae001344769b031375bdb38a86219154c6
|
||||
clone git github.com/docker/libnetwork e578e95aa101441481411ff1d620f343895f24fe
|
||||
clone git github.com/vishvananda/netns 5478c060110032f972e86a1f844fdb9a2f008f2c
|
||||
clone git github.com/vishvananda/netlink 8eb64238879fed52fd51c5b30ad20b928fb4c36c
|
||||
|
||||
# get distribution packages
|
||||
@@ -69,7 +69,7 @@ mv tmp-digest src/github.com/docker/distribution/digest
|
||||
mkdir -p src/github.com/docker/distribution/registry
|
||||
mv tmp-api src/github.com/docker/distribution/registry/api
|
||||
|
||||
clone git github.com/docker/libcontainer a37b2a4f152e2a1c9de596f54c051cb889de0691
|
||||
clone git github.com/docker/libcontainer v2.1.1
|
||||
# libcontainer deps (see src/github.com/docker/libcontainer/update-vendor.sh)
|
||||
clone git github.com/coreos/go-systemd v2
|
||||
clone git github.com/godbus/dbus v2
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"net/http/httputil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@@ -84,6 +85,45 @@ func (s *DockerSuite) TestContainerApiGetJSONNoFieldsOmitted(c *check.C) {
|
||||
}
|
||||
}
|
||||
|
||||
type containerPs struct {
|
||||
Names []string
|
||||
Ports []map[string]interface{}
|
||||
}
|
||||
|
||||
// regression test for non-empty fields from #13901
|
||||
func (s *DockerSuite) TestContainerPsOmitFields(c *check.C) {
|
||||
name := "pstest"
|
||||
port := 80
|
||||
runCmd := exec.Command(dockerBinary, "run", "-d", "--name", name, "--expose", strconv.Itoa(port), "busybox", "sleep", "5")
|
||||
_, err := runCommand(runCmd)
|
||||
c.Assert(err, check.IsNil)
|
||||
|
||||
status, body, err := sockRequest("GET", "/containers/json?all=1", nil)
|
||||
c.Assert(status, check.Equals, http.StatusOK)
|
||||
c.Assert(err, check.IsNil)
|
||||
|
||||
var resp []containerPs
|
||||
err = json.Unmarshal(body, &resp)
|
||||
c.Assert(err, check.IsNil)
|
||||
|
||||
var foundContainer *containerPs
|
||||
for _, container := range resp {
|
||||
for _, testName := range container.Names {
|
||||
if "/"+name == testName {
|
||||
foundContainer = &container
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
c.Assert(len(foundContainer.Ports), check.Equals, 1)
|
||||
c.Assert(foundContainer.Ports[0]["PrivatePort"], check.Equals, float64(port))
|
||||
_, ok := foundContainer.Ports[0]["PublicPort"]
|
||||
c.Assert(ok, check.Not(check.Equals), true)
|
||||
_, ok = foundContainer.Ports[0]["IP"]
|
||||
c.Assert(ok, check.Not(check.Equals), true)
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestContainerApiGetExport(c *check.C) {
|
||||
name := "exportcontainer"
|
||||
runCmd := exec.Command(dockerBinary, "run", "--name", name, "busybox", "touch", "/test")
|
||||
@@ -785,6 +825,19 @@ func (s *DockerSuite) TestContainerApiCreate(c *check.C) {
|
||||
}
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestContainerApiCreateEmptyConfig(c *check.C) {
|
||||
config := map[string]interface{}{}
|
||||
|
||||
status, b, err := sockRequest("POST", "/containers/create", config)
|
||||
c.Assert(err, check.IsNil)
|
||||
c.Assert(status, check.Equals, http.StatusInternalServerError)
|
||||
|
||||
expected := "Config cannot be empty in order to create a container\n"
|
||||
if body := string(b); body != expected {
|
||||
c.Fatalf("Expected to get %q, got %q", expected, body)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestContainerApiCreateWithHostName(c *check.C) {
|
||||
hostName := "test-host"
|
||||
config := map[string]interface{}{
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/go-check/check"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
func (s *DockerSuite) TestCliStatsNoStreamGetCpu(c *check.C) {
|
||||
out, _ := dockerCmd(c, "run", "-d", "--cpu-quota=2000", "busybox", "/bin/sh", "-c", "while true;do echo 'Hello';done")
|
||||
|
||||
id := strings.TrimSpace(out)
|
||||
if err := waitRun(id); err != nil {
|
||||
c.Fatal(err)
|
||||
}
|
||||
ch := make(chan error)
|
||||
var v *types.Stats
|
||||
go func() {
|
||||
_, body, err := sockRequestRaw("GET", fmt.Sprintf("/containers/%s/stats?stream=1", id), nil, "")
|
||||
if err != nil {
|
||||
ch <- err
|
||||
}
|
||||
dec := json.NewDecoder(body)
|
||||
if err := dec.Decode(&v); err != nil {
|
||||
ch <- err
|
||||
}
|
||||
ch <- nil
|
||||
}()
|
||||
select {
|
||||
case e := <-ch:
|
||||
if e == nil {
|
||||
var cpuPercent = 0.0
|
||||
cpuDelta := float64(v.CpuStats.CpuUsage.TotalUsage - v.PreCpuStats.CpuUsage.TotalUsage)
|
||||
systemDelta := float64(v.CpuStats.SystemUsage - v.PreCpuStats.SystemUsage)
|
||||
cpuPercent = (cpuDelta / systemDelta) * float64(len(v.CpuStats.CpuUsage.PercpuUsage)) * 100.0
|
||||
if cpuPercent < 1.8 || cpuPercent > 2.2 {
|
||||
c.Fatal("docker stats with no-stream get cpu usage failed")
|
||||
}
|
||||
|
||||
}
|
||||
case <-time.After(4 * time.Second):
|
||||
c.Fatal("docker stats with no-stream timeout")
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/go-check/check"
|
||||
)
|
||||
|
||||
func (s *DockerSuite) TestCliStatsNoStreamGetCpu(c *check.C) {
|
||||
out, _ := dockerCmd(c, "run", "-d", "busybox", "/bin/sh", "-c", "while true;do echo 'Hello'; usleep 100000; done")
|
||||
|
||||
id := strings.TrimSpace(out)
|
||||
err := waitRun(id)
|
||||
c.Assert(err, check.IsNil)
|
||||
|
||||
resp, body, err := sockRequestRaw("GET", fmt.Sprintf("/containers/%s/stats?stream=false", id), nil, "")
|
||||
c.Assert(err, check.IsNil)
|
||||
c.Assert(resp.ContentLength > 0, check.Equals, true, check.Commentf("should not use chunked encoding"))
|
||||
c.Assert(resp.Header.Get("Content-Type"), check.Equals, "application/json")
|
||||
|
||||
var v *types.Stats
|
||||
err = json.NewDecoder(body).Decode(&v)
|
||||
c.Assert(err, check.IsNil)
|
||||
|
||||
var cpuPercent = 0.0
|
||||
cpuDelta := float64(v.CpuStats.CpuUsage.TotalUsage - v.PreCpuStats.CpuUsage.TotalUsage)
|
||||
systemDelta := float64(v.CpuStats.SystemUsage - v.PreCpuStats.SystemUsage)
|
||||
cpuPercent = (cpuDelta / systemDelta) * float64(len(v.CpuStats.CpuUsage.PercpuUsage)) * 100.0
|
||||
if cpuPercent == 0 {
|
||||
c.Fatalf("docker stats with no-stream get cpu usage failed: was %v", cpuPercent)
|
||||
}
|
||||
}
|
||||
@@ -526,6 +526,49 @@ func (s *DockerDaemonSuite) TestDaemonBridgeFixedCidr(c *check.C) {
|
||||
}
|
||||
}
|
||||
|
||||
func (s *DockerDaemonSuite) TestDaemonDefaultGatewayIPv4Implicit(c *check.C) {
|
||||
defaultNetworkBridge := "docker0"
|
||||
deleteInterface(c, defaultNetworkBridge)
|
||||
|
||||
d := s.d
|
||||
|
||||
bridgeIp := "192.169.1.1"
|
||||
bridgeIpNet := fmt.Sprintf("%s/24", bridgeIp)
|
||||
|
||||
err := d.StartWithBusybox("--bip", bridgeIpNet)
|
||||
c.Assert(err, check.IsNil)
|
||||
defer d.Restart()
|
||||
|
||||
expectedMessage := fmt.Sprintf("default via %s dev", bridgeIp)
|
||||
out, err := d.Cmd("run", "busybox", "ip", "-4", "route", "list", "0/0")
|
||||
c.Assert(strings.Contains(out, expectedMessage), check.Equals, true,
|
||||
check.Commentf("Implicit default gateway should be bridge IP %s, but default route was '%s'",
|
||||
bridgeIp, strings.TrimSpace(out)))
|
||||
deleteInterface(c, defaultNetworkBridge)
|
||||
}
|
||||
|
||||
func (s *DockerDaemonSuite) TestDaemonDefaultGatewayIPv4Explicit(c *check.C) {
|
||||
defaultNetworkBridge := "docker0"
|
||||
deleteInterface(c, defaultNetworkBridge)
|
||||
|
||||
d := s.d
|
||||
|
||||
bridgeIp := "192.169.1.1"
|
||||
bridgeIpNet := fmt.Sprintf("%s/24", bridgeIp)
|
||||
gatewayIp := "192.169.1.254"
|
||||
|
||||
err := d.StartWithBusybox("--bip", bridgeIpNet, "--default-gateway", gatewayIp)
|
||||
c.Assert(err, check.IsNil)
|
||||
defer d.Restart()
|
||||
|
||||
expectedMessage := fmt.Sprintf("default via %s dev", gatewayIp)
|
||||
out, err := d.Cmd("run", "busybox", "ip", "-4", "route", "list", "0/0")
|
||||
c.Assert(strings.Contains(out, expectedMessage), check.Equals, true,
|
||||
check.Commentf("Explicit default gateway should be %s, but default route was '%s'",
|
||||
gatewayIp, strings.TrimSpace(out)))
|
||||
deleteInterface(c, defaultNetworkBridge)
|
||||
}
|
||||
|
||||
func (s *DockerDaemonSuite) TestDaemonIP(c *check.C) {
|
||||
d := s.d
|
||||
|
||||
@@ -1158,6 +1201,7 @@ func (s *DockerDaemonSuite) TestCleanupMountsAfterCrash(c *check.C) {
|
||||
}
|
||||
|
||||
func (s *DockerDaemonSuite) TestRunContainerWithBridgeNone(c *check.C) {
|
||||
testRequires(c, NativeExecDriver)
|
||||
c.Assert(s.d.StartWithBusybox("-b", "none"), check.IsNil)
|
||||
|
||||
out, err := s.d.Cmd("run", "--rm", "busybox", "ip", "l")
|
||||
@@ -1173,6 +1217,7 @@ func (s *DockerDaemonSuite) TestDaemonRestartWithContainerRunning(t *check.C) {
|
||||
if out, err := s.d.Cmd("run", "-ti", "-d", "--name", "test", "busybox"); err != nil {
|
||||
t.Fatal(out, err)
|
||||
}
|
||||
|
||||
if err := s.d.Restart(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -1181,3 +1226,41 @@ func (s *DockerDaemonSuite) TestDaemonRestartWithContainerRunning(t *check.C) {
|
||||
t.Fatal(out, err)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *DockerDaemonSuite) TestDaemonRestartCleanupNetns(c *check.C) {
|
||||
if err := s.d.StartWithBusybox(); err != nil {
|
||||
c.Fatal(err)
|
||||
}
|
||||
out, err := s.d.Cmd("run", "--name", "netns", "-d", "busybox", "top")
|
||||
if err != nil {
|
||||
c.Fatal(out, err)
|
||||
}
|
||||
if out, err := s.d.Cmd("stop", "netns"); err != nil {
|
||||
c.Fatal(out, err)
|
||||
}
|
||||
|
||||
// Construct netns file name from container id
|
||||
out = strings.TrimSpace(out)
|
||||
nsFile := out[:12]
|
||||
|
||||
// Test if the file still exists
|
||||
out, _, err = runCommandWithOutput(exec.Command("stat", "-c", "%n", "/var/run/docker/netns/"+nsFile))
|
||||
out = strings.TrimSpace(out)
|
||||
c.Assert(err, check.IsNil, check.Commentf("Output: %s", out))
|
||||
c.Assert(out, check.Equals, "/var/run/docker/netns/"+nsFile, check.Commentf("Output: %s", out))
|
||||
|
||||
// Remove the container and restart the daemon
|
||||
if out, err := s.d.Cmd("rm", "netns"); err != nil {
|
||||
c.Fatal(out, err)
|
||||
}
|
||||
|
||||
if err := s.d.Restart(); err != nil {
|
||||
c.Fatal(err)
|
||||
}
|
||||
|
||||
// Test again and see now the netns file does not exist
|
||||
out, _, err = runCommandWithOutput(exec.Command("stat", "-c", "%n", "/var/run/docker/netns/"+nsFile))
|
||||
out = strings.TrimSpace(out)
|
||||
c.Assert(err, check.Not(check.IsNil), check.Commentf("Output: %s", out))
|
||||
// c.Assert(out, check.Equals, "", check.Commentf("Output: %s", out))
|
||||
}
|
||||
|
||||
@@ -563,3 +563,10 @@ func (s *DockerSuite) TestEventsStreaming(c *check.C) {
|
||||
// ignore, done
|
||||
}
|
||||
}
|
||||
|
||||
// #13753
|
||||
func (s *DockerSuite) TestEventsDefaultEmpty(c *check.C) {
|
||||
dockerCmd(c, "run", "-d", "busybox")
|
||||
out, _ := dockerCmd(c, "events", fmt.Sprintf("--until=%d", daemonTime(c).Unix()))
|
||||
c.Assert(strings.TrimSpace(out), check.Equals, "")
|
||||
}
|
||||
|
||||
@@ -98,3 +98,20 @@ func (s *DockerSuite) TestNetworkLocalhostTCPNat(c *check.C) {
|
||||
c.Fatalf("Expected message %q but received %q", msg, final)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestNetworkLoopbackNat(c *check.C) {
|
||||
testRequires(c, SameHostDaemon, NativeExecDriver)
|
||||
msg := "it works"
|
||||
startServerContainer(c, msg, 8080)
|
||||
endpoint := getExternalAddress(c)
|
||||
runCmd := exec.Command(dockerBinary, "run", "-t", "--net=container:server", "busybox",
|
||||
"sh", "-c", fmt.Sprintf("stty raw && nc -w 5 %s 8080", endpoint.String()))
|
||||
out, _, err := runCommandWithOutput(runCmd)
|
||||
if err != nil {
|
||||
c.Fatal(out, err)
|
||||
}
|
||||
final := strings.TrimRight(string(out), "\n")
|
||||
if final != msg {
|
||||
c.Fatalf("Expected message %q but received %q", msg, final)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"os/exec"
|
||||
"regexp"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
@@ -221,3 +223,96 @@ func (s *DockerSuite) TestPortExposeHostBinding(c *check.C) {
|
||||
c.Error("Port is still bound after the Container is removed")
|
||||
}
|
||||
}
|
||||
|
||||
func stopRemoveContainer(id string, c *check.C) {
|
||||
runCmd := exec.Command(dockerBinary, "rm", "-f", id)
|
||||
_, _, err := runCommandWithOutput(runCmd)
|
||||
c.Assert(err, check.IsNil)
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestUnpublishedPortsInPsOutput(c *check.C) {
|
||||
// Run busybox with command line expose (equivalent to EXPOSE in image's Dockerfile) for the following ports
|
||||
port1 := 80
|
||||
port2 := 443
|
||||
expose1 := fmt.Sprintf("--expose=%d", port1)
|
||||
expose2 := fmt.Sprintf("--expose=%d", port2)
|
||||
runCmd := exec.Command(dockerBinary, "run", "-d", expose1, expose2, "busybox", "sleep", "5")
|
||||
out, _, err := runCommandWithOutput(runCmd)
|
||||
c.Assert(err, check.IsNil)
|
||||
|
||||
// Check docker ps o/p for last created container reports the unpublished ports
|
||||
unpPort1 := fmt.Sprintf("%d/tcp", port1)
|
||||
unpPort2 := fmt.Sprintf("%d/tcp", port2)
|
||||
runCmd = exec.Command(dockerBinary, "ps", "-n=1")
|
||||
out, _, err = runCommandWithOutput(runCmd)
|
||||
c.Assert(err, check.IsNil)
|
||||
if !strings.Contains(out, unpPort1) || !strings.Contains(out, unpPort2) {
|
||||
c.Errorf("Missing unpublished ports(s) (%s, %s) in docker ps output: %s", unpPort1, unpPort2, out)
|
||||
}
|
||||
|
||||
// Run the container forcing to publish the exposed ports
|
||||
runCmd = exec.Command(dockerBinary, "run", "-d", "-P", expose1, expose2, "busybox", "sleep", "5")
|
||||
out, _, err = runCommandWithOutput(runCmd)
|
||||
c.Assert(err, check.IsNil)
|
||||
|
||||
// Check docker ps o/p for last created container reports the exposed ports in the port bindings
|
||||
expBndRegx1 := regexp.MustCompile(`0.0.0.0:\d\d\d\d\d->` + unpPort1)
|
||||
expBndRegx2 := regexp.MustCompile(`0.0.0.0:\d\d\d\d\d->` + unpPort2)
|
||||
runCmd = exec.Command(dockerBinary, "ps", "-n=1")
|
||||
out, _, err = runCommandWithOutput(runCmd)
|
||||
c.Assert(err, check.IsNil)
|
||||
if !expBndRegx1.MatchString(out) || !expBndRegx2.MatchString(out) {
|
||||
c.Errorf("Cannot find expected port binding ports(s) (0.0.0.0:xxxxx->%s, 0.0.0.0:xxxxx->%s) in docker ps output:\n%s",
|
||||
unpPort1, unpPort2, out)
|
||||
}
|
||||
|
||||
// Run the container specifying explicit port bindings for the exposed ports
|
||||
offset := 10000
|
||||
pFlag1 := fmt.Sprintf("%d:%d", offset+port1, port1)
|
||||
pFlag2 := fmt.Sprintf("%d:%d", offset+port2, port2)
|
||||
runCmd = exec.Command(dockerBinary, "run", "-d", "-p", pFlag1, "-p", pFlag2, expose1, expose2, "busybox", "sleep", "5")
|
||||
out, _, err = runCommandWithOutput(runCmd)
|
||||
c.Assert(err, check.IsNil)
|
||||
id := strings.TrimSpace(out)
|
||||
|
||||
// Check docker ps o/p for last created container reports the specified port mappings
|
||||
expBnd1 := fmt.Sprintf("0.0.0.0:%d->%s", offset+port1, unpPort1)
|
||||
expBnd2 := fmt.Sprintf("0.0.0.0:%d->%s", offset+port2, unpPort2)
|
||||
runCmd = exec.Command(dockerBinary, "ps", "-n=1")
|
||||
out, _, err = runCommandWithOutput(runCmd)
|
||||
c.Assert(err, check.IsNil)
|
||||
if !strings.Contains(out, expBnd1) || !strings.Contains(out, expBnd2) {
|
||||
c.Errorf("Cannot find expected port binding(s) (%s, %s) in docker ps output: %s", expBnd1, expBnd2, out)
|
||||
}
|
||||
// Remove container now otherwise it will interfeer with next test
|
||||
stopRemoveContainer(id, c)
|
||||
|
||||
// Run the container with explicit port bindings and no exposed ports
|
||||
runCmd = exec.Command(dockerBinary, "run", "-d", "-p", pFlag1, "-p", pFlag2, "busybox", "sleep", "5")
|
||||
out, _, err = runCommandWithOutput(runCmd)
|
||||
c.Assert(err, check.IsNil)
|
||||
id = strings.TrimSpace(out)
|
||||
|
||||
// Check docker ps o/p for last created container reports the specified port mappings
|
||||
runCmd = exec.Command(dockerBinary, "ps", "-n=1")
|
||||
out, _, err = runCommandWithOutput(runCmd)
|
||||
c.Assert(err, check.IsNil)
|
||||
if !strings.Contains(out, expBnd1) || !strings.Contains(out, expBnd2) {
|
||||
c.Errorf("Cannot find expected port binding(s) (%s, %s) in docker ps output: %s", expBnd1, expBnd2, out)
|
||||
}
|
||||
// Remove container now otherwise it will interfeer with next test
|
||||
stopRemoveContainer(id, c)
|
||||
|
||||
// Run the container with one unpublished exposed port and one explicit port binding
|
||||
runCmd = exec.Command(dockerBinary, "run", "-d", expose1, "-p", pFlag2, "busybox", "sleep", "5")
|
||||
out, _, err = runCommandWithOutput(runCmd)
|
||||
c.Assert(err, check.IsNil)
|
||||
|
||||
// Check docker ps o/p for last created container reports the specified unpublished port and port mapping
|
||||
runCmd = exec.Command(dockerBinary, "ps", "-n=1")
|
||||
out, _, err = runCommandWithOutput(runCmd)
|
||||
c.Assert(err, check.IsNil)
|
||||
if !strings.Contains(out, unpPort1) || !strings.Contains(out, expBnd2) {
|
||||
c.Errorf("Missing unpublished ports or port binding (%s, %s) in docker ps output: %s", unpPort1, expBnd2, out)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,6 +53,7 @@ func (s *DockerSuite) TestRunEchoStdoutWithMemoryLimit(c *check.C) {
|
||||
|
||||
// should run without memory swap
|
||||
func (s *DockerSuite) TestRunWithoutMemoryswapLimit(c *check.C) {
|
||||
testRequires(c, NativeExecDriver)
|
||||
runCmd := exec.Command(dockerBinary, "run", "-m", "16m", "--memory-swap", "-1", "busybox", "true")
|
||||
out, _, err := runCommandWithOutput(runCmd)
|
||||
if err != nil {
|
||||
@@ -3200,6 +3201,7 @@ func (s *DockerSuite) TestRunPublishPort(c *check.C) {
|
||||
|
||||
// Issue #10184.
|
||||
func (s *DockerSuite) TestDevicePermissions(c *check.C) {
|
||||
testRequires(c, NativeExecDriver)
|
||||
const permissions = "crw-rw-rw-"
|
||||
out, status := dockerCmd(c, "run", "--device", "/dev/fuse:/dev/fuse:mrw", "busybox:latest", "ls", "-l", "/dev/fuse")
|
||||
if status != 0 {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
FROM golang:1.3
|
||||
FROM golang:1.4
|
||||
RUN mkdir -p /go/src/github.com/cpuguy83
|
||||
RUN mkdir -p /go/src/github.com/cpuguy83 \
|
||||
&& git clone -b v1 https://github.com/cpuguy83/go-md2man.git /go/src/github.com/cpuguy83/go-md2man \
|
||||
&& git clone -b v1.0.1 https://github.com/cpuguy83/go-md2man.git /go/src/github.com/cpuguy83/go-md2man \
|
||||
&& cd /go/src/github.com/cpuguy83/go-md2man \
|
||||
&& go get -v ./...
|
||||
CMD ["/go/bin/go-md2man", "--help"]
|
||||
@@ -196,7 +196,7 @@ A Dockerfile is similar to a Makefile.
|
||||
ADD <src> <dest>
|
||||
|
||||
# Required for paths with whitespace
|
||||
ADD ["<src>", "<dest>"]
|
||||
ADD ["<src>",... "<dest>"]
|
||||
```
|
||||
|
||||
The **ADD** instruction copies new files, directories
|
||||
@@ -215,7 +215,7 @@ A Dockerfile is similar to a Makefile.
|
||||
COPY <src> <dest>
|
||||
|
||||
# Required for paths with whitespace
|
||||
COPY ["<src>", "<dest>"]
|
||||
COPY ["<src>",... "<dest>"]
|
||||
```
|
||||
|
||||
The **COPY** instruction copies new files from `<src>` and
|
||||
@@ -0,0 +1,44 @@
|
||||
Docker Documentation
|
||||
====================
|
||||
|
||||
This directory contains the Docker user manual in the Markdown format.
|
||||
Do *not* edit the man pages in the man1 directory. Instead, amend the
|
||||
Markdown (*.md) files.
|
||||
|
||||
# Generating man pages from the Markdown files
|
||||
|
||||
The recommended approach for generating the man pages is via a Docker
|
||||
container using the supplied `Dockerfile` to create an image with the correct
|
||||
environment. This uses `go-md2man`, a pure Go Markdown to man page generator.
|
||||
|
||||
### Generate the man pages
|
||||
|
||||
On Linux installations, Docker includes a set of man pages you can access by typing `man command-name` on the command line. For example, `man docker` displays the `docker` man page. When using Docker on Mac OSX the man pages are not automatically included.
|
||||
|
||||
You can generate and install the `man` pages yourself by following these steps:
|
||||
|
||||
1. Checkout the `docker` source.
|
||||
|
||||
$ git clone https://github.com/docker/docker.git
|
||||
|
||||
If you are using Boot2Docker, you must clone into your `/Users` directory
|
||||
because Boot2Docker can only share this path with the docker containers.
|
||||
|
||||
2. Build the docker image.
|
||||
|
||||
$ cd docker/man
|
||||
$ docker build -t docker/md2man .
|
||||
|
||||
3. Build the man pages.
|
||||
|
||||
$ docker run -v <path-to-git-dir>/docker/man:/man:rw -w /man -i docker/md2man /man/md2man-all.sh
|
||||
|
||||
The `md2man` Docker container processes the Markdown files and generates
|
||||
a `man1` and `man5` subdirectories in the `docker/man` directory.
|
||||
|
||||
4. Copy the generated man pages to `/usr/share/man`
|
||||
|
||||
$ cp -R man* /usr/share/man/
|
||||
|
||||
|
||||
|
||||
@@ -63,7 +63,12 @@ Again the output container IDs have been shortened for the purposes of this docu
|
||||
2015-01-28T20:25:45.000000000-08:00 c21f6c22ba27: (from whenry/testimage:latest) die
|
||||
2015-01-28T20:25:46.000000000-08:00 c21f6c22ba27: (from whenry/testimage:latest) stop
|
||||
|
||||
|
||||
If you do not provide the --since option, the command returns only new and/or
|
||||
live events.
|
||||
|
||||
# HISTORY
|
||||
April 2014, Originally compiled by William Henry (whenry at redhat dot com)
|
||||
based on docker.com source material and internal work.
|
||||
June 2014, updated by Sven Dowideit <SvenDowideit@home.org.au>
|
||||
June 2015, updated by Brian Goff <cpuguy83@gmail.com>
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user