mirror of
https://github.com/clearlinux/docker.git
synced 2026-08-19 20:26:54 +00:00
Compare commits
18 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| f8f912ac2a | |||
| cc712e6de4 | |||
| e698770d40 | |||
| ac6a9ce95f | |||
| b03b8a23d2 | |||
| 34815f3fa6 | |||
| 7e8cceb05a | |||
| 72d9ba5ac9 | |||
| fcc44248ef | |||
| c090014053 | |||
| 6906fb0693 | |||
| 50fe5319c4 | |||
| 53b80bdc9c | |||
| 44a8cf337b | |||
| 0baf609845 | |||
| e45e9e8fbc | |||
| 62fa0ac765 | |||
| 1b6403b9f1 |
@@ -1,5 +1,30 @@
|
||||
# Changelog
|
||||
|
||||
## 1.7.1 (2015-07-02)
|
||||
|
||||
#### Runtime
|
||||
|
||||
- Fix default user spawning exec process with `docker exec`
|
||||
- Make `--bridge=none` to not configure the network bridge
|
||||
- Publish networking stats properly
|
||||
- Fix implicit devicemapper selection with static binaries
|
||||
- Fix socket connections that hanged internitently
|
||||
- Fix bridge interface creation on CentOS/RHEL 6.6
|
||||
- Fix local dns lookups added to resolv.conf
|
||||
|
||||
#### Remote API
|
||||
|
||||
- Fix unmarshalling of Command and Entrypoint
|
||||
- Set limit for minimum client version supported
|
||||
- Validate port specification
|
||||
- Return proper errors when attach/reattach fail
|
||||
|
||||
#### Distribution
|
||||
|
||||
- Fix pulling private images
|
||||
- Fix fallback between registry V2 and V1
|
||||
|
||||
|
||||
## 1.7.0 (2015-06-16)
|
||||
|
||||
#### Runtime
|
||||
|
||||
@@ -138,7 +138,7 @@ func (cli *DockerCli) hijack(method, path string, setRawTerminal bool, in io.Rea
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
req, err := http.NewRequest(method, fmt.Sprintf("/v%s%s", api.APIVERSION, path), params)
|
||||
req, err := http.NewRequest(method, fmt.Sprintf("/v%s%s", api.Version, path), params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
+1
-1
@@ -53,7 +53,7 @@ func (cli *DockerCli) clientRequest(method, path string, in io.Reader, headers m
|
||||
if expectedPayload && in == nil {
|
||||
in = bytes.NewReader([]byte{})
|
||||
}
|
||||
req, err := http.NewRequest(method, fmt.Sprintf("/v%s%s", api.APIVERSION, path), in)
|
||||
req, err := http.NewRequest(method, fmt.Sprintf("/v%s%s", api.Version, path), in)
|
||||
if err != nil {
|
||||
return nil, "", -1, err
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ func (cli *DockerCli) CmdVersion(args ...string) error {
|
||||
if dockerversion.VERSION != "" {
|
||||
fmt.Fprintf(cli.out, "Client version: %s\n", dockerversion.VERSION)
|
||||
}
|
||||
fmt.Fprintf(cli.out, "Client API version: %s\n", api.APIVERSION)
|
||||
fmt.Fprintf(cli.out, "Client API version: %s\n", api.Version)
|
||||
fmt.Fprintf(cli.out, "Go version (client): %s\n", runtime.Version())
|
||||
if dockerversion.GITCOMMIT != "" {
|
||||
fmt.Fprintf(cli.out, "Git commit (client): %s\n", dockerversion.GITCOMMIT)
|
||||
|
||||
+8
-2
@@ -16,8 +16,14 @@ import (
|
||||
|
||||
// Common constants for daemon and client.
|
||||
const (
|
||||
APIVERSION version.Version = "1.19" // Current REST API version
|
||||
DefaultDockerfileName string = "Dockerfile" // Default filename with Docker commands, read by docker build
|
||||
// Current REST API version
|
||||
Version version.Version = "1.19"
|
||||
|
||||
// Minimun REST API version supported
|
||||
MinVersion version.Version = "1.12"
|
||||
|
||||
// Default filename with Docker commands, read by docker build
|
||||
DefaultDockerfileName string = "Dockerfile"
|
||||
)
|
||||
|
||||
type ByPrivatePort []types.Port
|
||||
|
||||
+29
-17
@@ -247,7 +247,7 @@ func (s *Server) postAuth(version version.Version, w http.ResponseWriter, r *htt
|
||||
func (s *Server) getVersion(version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||
v := &types.Version{
|
||||
Version: dockerversion.VERSION,
|
||||
ApiVersion: api.APIVERSION,
|
||||
ApiVersion: api.Version,
|
||||
GitCommit: dockerversion.GITCOMMIT,
|
||||
GoVersion: runtime.Version(),
|
||||
Os: runtime.GOOS,
|
||||
@@ -1101,6 +1101,11 @@ func (s *Server) postContainersAttach(version version.Version, w http.ResponseWr
|
||||
return fmt.Errorf("Missing parameter")
|
||||
}
|
||||
|
||||
cont, err := s.daemon.Get(vars["name"])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
inStream, outStream, err := hijackServer(w)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -1124,7 +1129,7 @@ func (s *Server) postContainersAttach(version version.Version, w http.ResponseWr
|
||||
Multiplex: version.GreaterThanOrEqualTo("1.6"),
|
||||
}
|
||||
|
||||
if err := s.daemon.ContainerAttachWithLogs(vars["name"], attachWithLogsConfig); err != nil {
|
||||
if err := s.daemon.ContainerAttachWithLogs(cont, attachWithLogsConfig); err != nil {
|
||||
fmt.Fprintf(outStream, "Error attaching: %s\n", err)
|
||||
}
|
||||
|
||||
@@ -1139,6 +1144,11 @@ func (s *Server) wsContainersAttach(version version.Version, w http.ResponseWrit
|
||||
return fmt.Errorf("Missing parameter")
|
||||
}
|
||||
|
||||
cont, err := s.daemon.Get(vars["name"])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
h := websocket.Handler(func(ws *websocket.Conn) {
|
||||
defer ws.Close()
|
||||
|
||||
@@ -1150,7 +1160,7 @@ func (s *Server) wsContainersAttach(version version.Version, w http.ResponseWrit
|
||||
Stream: boolValue(r, "stream"),
|
||||
}
|
||||
|
||||
if err := s.daemon.ContainerWsAttachWithLogs(vars["name"], wsAttachWithLogsConfig); err != nil {
|
||||
if err := s.daemon.ContainerWsAttachWithLogs(cont, wsAttachWithLogsConfig); err != nil {
|
||||
logrus.Errorf("Error attaching websocket: %s", err)
|
||||
}
|
||||
})
|
||||
@@ -1207,18 +1217,17 @@ func (s *Server) getImagesByName(version version.Version, w http.ResponseWriter,
|
||||
|
||||
func (s *Server) postBuild(version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||
var (
|
||||
authConfig = &cliconfig.AuthConfig{}
|
||||
configFileEncoded = r.Header.Get("X-Registry-Config")
|
||||
configFile = &cliconfig.ConfigFile{}
|
||||
buildConfig = builder.NewBuildConfig()
|
||||
authConfigs = map[string]cliconfig.AuthConfig{}
|
||||
authConfigsEncoded = r.Header.Get("X-Registry-Config")
|
||||
buildConfig = builder.NewBuildConfig()
|
||||
)
|
||||
|
||||
if configFileEncoded != "" {
|
||||
configFileJson := base64.NewDecoder(base64.URLEncoding, strings.NewReader(configFileEncoded))
|
||||
if err := json.NewDecoder(configFileJson).Decode(configFile); err != nil {
|
||||
if authConfigsEncoded != "" {
|
||||
authConfigsJSON := base64.NewDecoder(base64.URLEncoding, strings.NewReader(authConfigsEncoded))
|
||||
if err := json.NewDecoder(authConfigsJSON).Decode(&authConfigs); err != nil {
|
||||
// for a pull it is not an error if no auth was given
|
||||
// to increase compatibility with the existing api it is defaulting to be empty
|
||||
configFile = &cliconfig.ConfigFile{}
|
||||
// to increase compatibility with the existing api it is defaulting
|
||||
// to be empty.
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1245,8 +1254,7 @@ func (s *Server) postBuild(version version.Version, w http.ResponseWriter, r *ht
|
||||
buildConfig.SuppressOutput = boolValue(r, "q")
|
||||
buildConfig.NoCache = boolValue(r, "nocache")
|
||||
buildConfig.ForceRemove = boolValue(r, "forcerm")
|
||||
buildConfig.AuthConfig = authConfig
|
||||
buildConfig.ConfigFile = configFile
|
||||
buildConfig.AuthConfigs = authConfigs
|
||||
buildConfig.MemorySwap = int64ValueOrZero(r, "memswap")
|
||||
buildConfig.Memory = int64ValueOrZero(r, "memory")
|
||||
buildConfig.CpuShares = int64ValueOrZero(r, "cpushares")
|
||||
@@ -1475,14 +1483,18 @@ func makeHttpHandler(logging bool, localMethod string, localRoute string, handle
|
||||
}
|
||||
version := version.Version(mux.Vars(r)["version"])
|
||||
if version == "" {
|
||||
version = api.APIVERSION
|
||||
version = api.Version
|
||||
}
|
||||
if corsHeaders != "" {
|
||||
writeCorsHeaders(w, r, corsHeaders)
|
||||
}
|
||||
|
||||
if version.GreaterThan(api.APIVERSION) {
|
||||
http.Error(w, fmt.Errorf("client and server don't have same version (client API version: %s, server API version: %s)", version, api.APIVERSION).Error(), http.StatusBadRequest)
|
||||
if version.GreaterThan(api.Version) {
|
||||
http.Error(w, fmt.Errorf("client is newer than server (client API version: %s, server API version: %s)", version, api.Version).Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
if version.LessThan(api.MinVersion) {
|
||||
http.Error(w, fmt.Errorf("client is too old, minimum supported API version is %s, please upgrade your client to a newer version", api.MinVersion).Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -98,8 +98,8 @@ type Builder struct {
|
||||
// the final configs of the Dockerfile but dont want the layers
|
||||
disableCommit bool
|
||||
|
||||
AuthConfig *cliconfig.AuthConfig
|
||||
ConfigFile *cliconfig.ConfigFile
|
||||
// Registry server auth configs used to pull images when handling `FROM`.
|
||||
AuthConfigs map[string]cliconfig.AuthConfig
|
||||
|
||||
// Deprecated, original writer used for ImagePull. To be removed.
|
||||
OutOld io.Writer
|
||||
|
||||
@@ -21,6 +21,7 @@ import (
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
"github.com/docker/docker/builder/parser"
|
||||
"github.com/docker/docker/cliconfig"
|
||||
"github.com/docker/docker/daemon"
|
||||
"github.com/docker/docker/graph"
|
||||
imagepkg "github.com/docker/docker/image"
|
||||
@@ -446,15 +447,19 @@ func (b *Builder) pullImage(name string) (*imagepkg.Image, error) {
|
||||
tag = "latest"
|
||||
}
|
||||
|
||||
pullRegistryAuth := b.AuthConfig
|
||||
if len(b.ConfigFile.AuthConfigs) > 0 {
|
||||
pullRegistryAuth := &cliconfig.AuthConfig{}
|
||||
if len(b.AuthConfigs) > 0 {
|
||||
// The request came with a full auth config file, we prefer to use that
|
||||
repoInfo, err := b.Daemon.RegistryService.ResolveRepository(remote)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
resolvedAuth := registry.ResolveAuthConfig(b.ConfigFile, repoInfo.Index)
|
||||
pullRegistryAuth = &resolvedAuth
|
||||
|
||||
resolvedConfig := registry.ResolveAuthConfig(
|
||||
&cliconfig.ConfigFile{AuthConfigs: b.AuthConfigs},
|
||||
repoInfo.Index,
|
||||
)
|
||||
pullRegistryAuth = &resolvedConfig
|
||||
}
|
||||
|
||||
imagePullConfig := &graph.ImagePullConfig{
|
||||
|
||||
+4
-7
@@ -53,8 +53,7 @@ type Config struct {
|
||||
CpuSetCpus string
|
||||
CpuSetMems string
|
||||
CgroupParent string
|
||||
AuthConfig *cliconfig.AuthConfig
|
||||
ConfigFile *cliconfig.ConfigFile
|
||||
AuthConfigs map[string]cliconfig.AuthConfig
|
||||
|
||||
Stdout io.Writer
|
||||
Context io.ReadCloser
|
||||
@@ -79,9 +78,8 @@ func (b *Config) WaitCancelled() <-chan struct{} {
|
||||
|
||||
func NewBuildConfig() *Config {
|
||||
return &Config{
|
||||
AuthConfig: &cliconfig.AuthConfig{},
|
||||
ConfigFile: &cliconfig.ConfigFile{},
|
||||
cancelled: make(chan struct{}),
|
||||
AuthConfigs: map[string]cliconfig.AuthConfig{},
|
||||
cancelled: make(chan struct{}),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -160,8 +158,7 @@ func Build(d *daemon.Daemon, buildConfig *Config) error {
|
||||
Pull: buildConfig.Pull,
|
||||
OutOld: buildConfig.Stdout,
|
||||
StreamFormatter: sf,
|
||||
AuthConfig: buildConfig.AuthConfig,
|
||||
ConfigFile: buildConfig.ConfigFile,
|
||||
AuthConfigs: buildConfig.AuthConfigs,
|
||||
dockerfileName: buildConfig.DockerfileName,
|
||||
cpuShares: buildConfig.CpuShares,
|
||||
cpuPeriod: buildConfig.CpuPeriod,
|
||||
|
||||
+2
-12
@@ -14,12 +14,7 @@ type ContainerAttachWithLogsConfig struct {
|
||||
Multiplex bool
|
||||
}
|
||||
|
||||
func (daemon *Daemon) ContainerAttachWithLogs(name string, c *ContainerAttachWithLogsConfig) error {
|
||||
container, err := daemon.Get(name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
func (daemon *Daemon) ContainerAttachWithLogs(container *Container, c *ContainerAttachWithLogsConfig) error {
|
||||
var errStream io.Writer
|
||||
|
||||
if !container.Config.Tty && c.Multiplex {
|
||||
@@ -51,11 +46,6 @@ type ContainerWsAttachWithLogsConfig struct {
|
||||
Logs, Stream bool
|
||||
}
|
||||
|
||||
func (daemon *Daemon) ContainerWsAttachWithLogs(name string, c *ContainerWsAttachWithLogsConfig) error {
|
||||
container, err := daemon.Get(name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
func (daemon *Daemon) ContainerWsAttachWithLogs(container *Container, c *ContainerWsAttachWithLogsConfig) error {
|
||||
return container.AttachWithLogs(c.InStream, c.OutStream, c.ErrStream, c.Logs, c.Stream)
|
||||
}
|
||||
|
||||
+18
-18
@@ -14,24 +14,24 @@ const (
|
||||
// CommonConfig defines the configuration of a docker daemon which are
|
||||
// common across platforms.
|
||||
type CommonConfig struct {
|
||||
AutoRestart bool
|
||||
Context map[string][]string
|
||||
CorsHeaders string
|
||||
DisableNetwork bool
|
||||
Dns []string
|
||||
DnsSearch []string
|
||||
EnableCors bool
|
||||
ExecDriver string
|
||||
ExecOptions []string
|
||||
ExecRoot string
|
||||
GraphDriver string
|
||||
GraphOptions []string
|
||||
Labels []string
|
||||
LogConfig runconfig.LogConfig
|
||||
Mtu int
|
||||
Pidfile string
|
||||
Root string
|
||||
TrustKeyPath string
|
||||
AutoRestart bool
|
||||
Context map[string][]string
|
||||
CorsHeaders string
|
||||
DisableBridge bool
|
||||
Dns []string
|
||||
DnsSearch []string
|
||||
EnableCors bool
|
||||
ExecDriver string
|
||||
ExecOptions []string
|
||||
ExecRoot string
|
||||
GraphDriver string
|
||||
GraphOptions []string
|
||||
Labels []string
|
||||
LogConfig runconfig.LogConfig
|
||||
Mtu int
|
||||
Pidfile string
|
||||
Root string
|
||||
TrustKeyPath string
|
||||
}
|
||||
|
||||
// InstallCommonFlags adds command-line options to the top-level flag parser for
|
||||
|
||||
@@ -469,7 +469,7 @@ func (container *Container) buildJoinOptions() ([]libnetwork.EndpointOption, err
|
||||
logrus.Error(err)
|
||||
}
|
||||
|
||||
if c != nil && !container.daemon.config.DisableNetwork && container.hostConfig.NetworkMode.IsPrivate() {
|
||||
if c != nil && !container.daemon.config.DisableBridge && container.hostConfig.NetworkMode.IsPrivate() {
|
||||
logrus.Debugf("Update /etc/hosts of %s for alias %s with ip %s", c.ID, ref.Name, container.NetworkSettings.IPAddress)
|
||||
joinOptions = append(joinOptions, libnetwork.JoinOptionParentUpdate(c.NetworkSettings.EndpointID, ref.Name, container.NetworkSettings.IPAddress))
|
||||
if c.NetworkSettings.EndpointID != "" {
|
||||
@@ -753,6 +753,11 @@ func (container *Container) AllocateNetwork() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
if mode.IsBridge() && container.daemon.config.DisableBridge {
|
||||
container.Config.NetworkDisabled = true
|
||||
return nil
|
||||
}
|
||||
|
||||
var err error
|
||||
|
||||
n, err := container.daemon.netController.NetworkByName(string(mode))
|
||||
@@ -817,10 +822,6 @@ func (container *Container) initializeNetworking() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
if container.daemon.config.DisableNetwork {
|
||||
container.Config.NetworkDisabled = true
|
||||
}
|
||||
|
||||
if container.hostConfig.NetworkMode.IsHost() {
|
||||
container.Config.Hostname, err = os.Hostname()
|
||||
if err != nil {
|
||||
@@ -939,7 +940,7 @@ func (container *Container) getNetworkedContainer() (*Container, error) {
|
||||
}
|
||||
|
||||
func (container *Container) ReleaseNetwork() {
|
||||
if container.hostConfig.NetworkMode.IsContainer() || container.daemon.config.DisableNetwork {
|
||||
if container.hostConfig.NetworkMode.IsContainer() || container.Config.NetworkDisabled {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
+30
-15
@@ -32,6 +32,7 @@ import (
|
||||
"github.com/docker/docker/daemon/network"
|
||||
"github.com/docker/docker/graph"
|
||||
"github.com/docker/docker/image"
|
||||
"github.com/docker/docker/nat"
|
||||
"github.com/docker/docker/pkg/archive"
|
||||
"github.com/docker/docker/pkg/broadcastwriter"
|
||||
"github.com/docker/docker/pkg/fileutils"
|
||||
@@ -682,7 +683,7 @@ func NewDaemon(config *Config, registryService *registry.Service) (daemon *Daemo
|
||||
if !config.Bridge.EnableIPTables && config.Bridge.EnableIPMasq {
|
||||
config.Bridge.EnableIPMasq = false
|
||||
}
|
||||
config.DisableNetwork = config.Bridge.Iface == disableNetworkBridge
|
||||
config.DisableBridge = config.Bridge.Iface == disableNetworkBridge
|
||||
|
||||
// Check that the system is supported and we have sufficient privileges
|
||||
if runtime.GOOS != "linux" {
|
||||
@@ -819,11 +820,9 @@ func NewDaemon(config *Config, registryService *registry.Service) (daemon *Daemo
|
||||
return nil, fmt.Errorf("Couldn't create Tag store: %s", err)
|
||||
}
|
||||
|
||||
if !config.DisableNetwork {
|
||||
d.netController, err = initNetworkController(config)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Error initializing network controller: %v", err)
|
||||
}
|
||||
d.netController, err = initNetworkController(config)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Error initializing network controller: %v", err)
|
||||
}
|
||||
|
||||
graphdbPath := path.Join(config.Root, "linkgraph.db")
|
||||
@@ -911,12 +910,22 @@ func initNetworkController(config *Config) (libnetwork.NetworkController, error)
|
||||
return nil, fmt.Errorf("Error creating default \"host\" network: %v", err)
|
||||
}
|
||||
|
||||
// Initialize default driver "bridge"
|
||||
if !config.DisableBridge {
|
||||
// Initialize default driver "bridge"
|
||||
if err := initBridgeDriver(controller, config); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return controller, nil
|
||||
}
|
||||
|
||||
func initBridgeDriver(controller libnetwork.NetworkController, config *Config) error {
|
||||
option := options.Generic{
|
||||
"EnableIPForwarding": config.Bridge.EnableIPForward}
|
||||
|
||||
if err := controller.ConfigureNetworkDriver("bridge", options.Generic{netlabel.GenericData: option}); err != nil {
|
||||
return nil, fmt.Errorf("Error initializing bridge driver: %v", err)
|
||||
return fmt.Errorf("Error initializing bridge driver: %v", err)
|
||||
}
|
||||
|
||||
netOption := options.Generic{
|
||||
@@ -931,7 +940,7 @@ func initNetworkController(config *Config) (libnetwork.NetworkController, error)
|
||||
if config.Bridge.IP != "" {
|
||||
ip, bipNet, err := net.ParseCIDR(config.Bridge.IP)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
|
||||
bipNet.IP = ip
|
||||
@@ -941,7 +950,7 @@ func initNetworkController(config *Config) (libnetwork.NetworkController, error)
|
||||
if config.Bridge.FixedCIDR != "" {
|
||||
_, fCIDR, err := net.ParseCIDR(config.Bridge.FixedCIDR)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
|
||||
netOption["FixedCIDR"] = fCIDR
|
||||
@@ -950,7 +959,7 @@ func initNetworkController(config *Config) (libnetwork.NetworkController, error)
|
||||
if config.Bridge.FixedCIDRv6 != "" {
|
||||
_, fCIDRv6, err := net.ParseCIDR(config.Bridge.FixedCIDRv6)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
|
||||
netOption["FixedCIDRv6"] = fCIDRv6
|
||||
@@ -970,16 +979,15 @@ func initNetworkController(config *Config) (libnetwork.NetworkController, error)
|
||||
}
|
||||
|
||||
// Initialize default network on "bridge" with the same name
|
||||
_, err = controller.NewNetwork("bridge", "bridge",
|
||||
_, err := controller.NewNetwork("bridge", "bridge",
|
||||
libnetwork.NetworkOptionGeneric(options.Generic{
|
||||
netlabel.GenericData: netOption,
|
||||
netlabel.EnableIPv6: config.Bridge.EnableIPv6,
|
||||
}))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Error creating default \"bridge\" network: %v", err)
|
||||
return fmt.Errorf("Error creating default \"bridge\" network: %v", err)
|
||||
}
|
||||
|
||||
return controller, nil
|
||||
return nil
|
||||
}
|
||||
|
||||
func (daemon *Daemon) Shutdown() error {
|
||||
@@ -1190,6 +1198,13 @@ func (daemon *Daemon) verifyHostConfig(hostConfig *runconfig.HostConfig) ([]stri
|
||||
return warnings, nil
|
||||
}
|
||||
|
||||
for port := range hostConfig.PortBindings {
|
||||
_, portStr := nat.SplitProtoPort(string(port))
|
||||
if _, err := nat.ParsePort(portStr); err != nil {
|
||||
return warnings, fmt.Errorf("Invalid port specification: %s", portStr)
|
||||
}
|
||||
}
|
||||
|
||||
if hostConfig.LxcConf.Len() > 0 && !strings.Contains(daemon.ExecutionDriver().Name(), "lxc") {
|
||||
return warnings, fmt.Errorf("Cannot use --lxc-conf with execdriver: %s", daemon.ExecutionDriver().Name())
|
||||
}
|
||||
|
||||
+6
-2
@@ -109,7 +109,6 @@ func (d *Daemon) getActiveContainer(name string) (*Container, error) {
|
||||
}
|
||||
|
||||
func (d *Daemon) ContainerExecCreate(config *runconfig.ExecConfig) (string, error) {
|
||||
|
||||
// Not all drivers support Exec (LXC for example)
|
||||
if err := checkExecSupport(d.execDriver.Name()); err != nil {
|
||||
return "", err
|
||||
@@ -123,11 +122,16 @@ func (d *Daemon) ContainerExecCreate(config *runconfig.ExecConfig) (string, erro
|
||||
cmd := runconfig.NewCommand(config.Cmd...)
|
||||
entrypoint, args := d.getEntrypointAndArgs(runconfig.NewEntrypoint(), cmd)
|
||||
|
||||
user := config.User
|
||||
if len(user) == 0 {
|
||||
user = container.Config.User
|
||||
}
|
||||
|
||||
processConfig := execdriver.ProcessConfig{
|
||||
Tty: config.Tty,
|
||||
Entrypoint: entrypoint,
|
||||
Arguments: args,
|
||||
User: config.User,
|
||||
User: user,
|
||||
}
|
||||
|
||||
execConfig := &execConfig{
|
||||
|
||||
@@ -30,8 +30,7 @@ var (
|
||||
DefaultDataLoopbackSize int64 = 100 * 1024 * 1024 * 1024
|
||||
DefaultMetaDataLoopbackSize int64 = 2 * 1024 * 1024 * 1024
|
||||
DefaultBaseFsSize uint64 = 10 * 1024 * 1024 * 1024
|
||||
DefaultThinpBlockSize uint32 = 128 // 64K = 128 512b sectors
|
||||
DefaultUdevSyncOverride bool = false
|
||||
DefaultThinpBlockSize uint32 = 128 // 64K = 128 512b sectors
|
||||
MaxDeviceId int = 0xffffff // 24 bit, pool limit
|
||||
DeviceIdMapSz int = (MaxDeviceId + 1) / 8
|
||||
// We retry device removal so many a times that even error messages
|
||||
@@ -90,22 +89,21 @@ type DeviceSet struct {
|
||||
deviceIdMap []byte
|
||||
|
||||
// Options
|
||||
dataLoopbackSize int64
|
||||
metaDataLoopbackSize int64
|
||||
baseFsSize uint64
|
||||
filesystem string
|
||||
mountOptions string
|
||||
mkfsArgs []string
|
||||
dataDevice string // block or loop dev
|
||||
dataLoopFile string // loopback file, if used
|
||||
metadataDevice string // block or loop dev
|
||||
metadataLoopFile string // loopback file, if used
|
||||
doBlkDiscard bool
|
||||
thinpBlockSize uint32
|
||||
thinPoolDevice string
|
||||
Transaction `json:"-"`
|
||||
overrideUdevSyncCheck bool
|
||||
deferredRemove bool // use deferred removal
|
||||
dataLoopbackSize int64
|
||||
metaDataLoopbackSize int64
|
||||
baseFsSize uint64
|
||||
filesystem string
|
||||
mountOptions string
|
||||
mkfsArgs []string
|
||||
dataDevice string // block or loop dev
|
||||
dataLoopFile string // loopback file, if used
|
||||
metadataDevice string // block or loop dev
|
||||
metadataLoopFile string // loopback file, if used
|
||||
doBlkDiscard bool
|
||||
thinpBlockSize uint32
|
||||
thinPoolDevice string
|
||||
Transaction `json:"-"`
|
||||
deferredRemove bool // use deferred removal
|
||||
}
|
||||
|
||||
type DiskUsage struct {
|
||||
@@ -1033,10 +1031,7 @@ func (devices *DeviceSet) initDevmapper(doInit bool) error {
|
||||
|
||||
// https://github.com/docker/docker/issues/4036
|
||||
if supported := devicemapper.UdevSetSyncSupport(true); !supported {
|
||||
logrus.Errorf("Udev sync is not supported. This will lead to unexpected behavior, data loss and errors. For more information, see https://docs.docker.com/reference/commandline/cli/#daemon-storage-driver-option")
|
||||
if !devices.overrideUdevSyncCheck {
|
||||
return graphdriver.ErrNotSupported
|
||||
}
|
||||
logrus.Warn("Udev sync is not supported. This will lead to unexpected behavior, data loss and errors. For more information, see https://docs.docker.com/reference/commandline/cli/#daemon-storage-driver-option")
|
||||
}
|
||||
|
||||
if err := os.MkdirAll(devices.metadataDir(), 0700); err != nil && !os.IsExist(err) {
|
||||
@@ -1704,16 +1699,15 @@ func NewDeviceSet(root string, doInit bool, options []string) (*DeviceSet, error
|
||||
devicemapper.SetDevDir("/dev")
|
||||
|
||||
devices := &DeviceSet{
|
||||
root: root,
|
||||
MetaData: MetaData{Devices: make(map[string]*DevInfo)},
|
||||
dataLoopbackSize: DefaultDataLoopbackSize,
|
||||
metaDataLoopbackSize: DefaultMetaDataLoopbackSize,
|
||||
baseFsSize: DefaultBaseFsSize,
|
||||
overrideUdevSyncCheck: DefaultUdevSyncOverride,
|
||||
filesystem: "ext4",
|
||||
doBlkDiscard: true,
|
||||
thinpBlockSize: DefaultThinpBlockSize,
|
||||
deviceIdMap: make([]byte, DeviceIdMapSz),
|
||||
root: root,
|
||||
MetaData: MetaData{Devices: make(map[string]*DevInfo)},
|
||||
dataLoopbackSize: DefaultDataLoopbackSize,
|
||||
metaDataLoopbackSize: DefaultMetaDataLoopbackSize,
|
||||
baseFsSize: DefaultBaseFsSize,
|
||||
filesystem: "ext4",
|
||||
doBlkDiscard: true,
|
||||
thinpBlockSize: DefaultThinpBlockSize,
|
||||
deviceIdMap: make([]byte, DeviceIdMapSz),
|
||||
}
|
||||
|
||||
foundBlkDiscard := false
|
||||
@@ -1770,12 +1764,6 @@ func NewDeviceSet(root string, doInit bool, options []string) (*DeviceSet, error
|
||||
}
|
||||
// convert to 512b sectors
|
||||
devices.thinpBlockSize = uint32(size) >> 9
|
||||
case "dm.override_udev_sync_check":
|
||||
devices.overrideUdevSyncCheck, err = strconv.ParseBool(val)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
case "dm.use_deferred_removal":
|
||||
EnableDeferredRemoval, err = strconv.ParseBool(val)
|
||||
if err != nil {
|
||||
|
||||
@@ -13,7 +13,6 @@ func init() {
|
||||
DefaultDataLoopbackSize = 300 * 1024 * 1024
|
||||
DefaultMetaDataLoopbackSize = 200 * 1024 * 1024
|
||||
DefaultBaseFsSize = 300 * 1024 * 1024
|
||||
DefaultUdevSyncOverride = true
|
||||
if err := graphtest.InitLoopbacks(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
"github.com/docker/docker/autogen/dockerversion"
|
||||
"github.com/docker/docker/pkg/archive"
|
||||
)
|
||||
|
||||
@@ -22,9 +23,10 @@ var (
|
||||
// All registred drivers
|
||||
drivers map[string]InitFunc
|
||||
|
||||
ErrNotSupported = errors.New("driver not supported")
|
||||
ErrPrerequisites = errors.New("prerequisites for driver not satisfied (wrong filesystem?)")
|
||||
ErrIncompatibleFS = fmt.Errorf("backing file system is unsupported for this graph driver")
|
||||
ErrNotSupported = errors.New("driver not supported")
|
||||
ErrPrerequisites = errors.New("prerequisites for driver not satisfied (wrong filesystem?)")
|
||||
ErrIncompatibleFS = fmt.Errorf("backing file system is unsupported for this graph driver")
|
||||
ErrDeviceMapperWithStaticDocker = fmt.Errorf("devicemapper storage driver cannot reliably be used with a statically linked docker binary: please either pick a different storage driver, install a dynamically linked docker binary, or force this unreliable setup anyway by specifying --storage-driver=devicemapper")
|
||||
)
|
||||
|
||||
type InitFunc func(root string, options []string) (Driver, error)
|
||||
@@ -110,36 +112,35 @@ func New(root string, options []string) (driver Driver, err error) {
|
||||
}
|
||||
|
||||
// Guess for prior driver
|
||||
priorDrivers := scanPriorDrivers(root)
|
||||
for _, name := range priority {
|
||||
if name == "vfs" {
|
||||
// don't use vfs even if there is state present.
|
||||
continue
|
||||
priorDriver, err := scanPriorDrivers(root)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(priorDriver) != 0 {
|
||||
// Do not allow devicemapper when it's not explicit and the Docker binary was built statically.
|
||||
if staticWithDeviceMapper(priorDriver) {
|
||||
return nil, ErrDeviceMapperWithStaticDocker
|
||||
}
|
||||
for _, prior := range priorDrivers {
|
||||
// of the state found from prior drivers, check in order of our priority
|
||||
// which we would prefer
|
||||
if prior == name {
|
||||
driver, err = GetDriver(name, root, options)
|
||||
if err != nil {
|
||||
// unlike below, we will return error here, because there is prior
|
||||
// state, and now it is no longer supported/prereq/compatible, so
|
||||
// something changed and needs attention. Otherwise the daemon's
|
||||
// images would just "disappear".
|
||||
logrus.Errorf("[graphdriver] prior storage driver %q failed: %s", name, err)
|
||||
return nil, err
|
||||
}
|
||||
if err := checkPriorDriver(name, root); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
logrus.Infof("[graphdriver] using prior storage driver %q", name)
|
||||
return driver, nil
|
||||
}
|
||||
|
||||
driver, err = GetDriver(priorDriver, root, options)
|
||||
if err != nil {
|
||||
// unlike below, we will return error here, because there is prior
|
||||
// state, and now it is no longer supported/prereq/compatible, so
|
||||
// something changed and needs attention. Otherwise the daemon's
|
||||
// images would just "disappear".
|
||||
logrus.Errorf("[graphdriver] prior storage driver %q failed: %s", priorDriver, err)
|
||||
return nil, err
|
||||
}
|
||||
logrus.Infof("[graphdriver] using prior storage driver %q", priorDriver)
|
||||
return driver, nil
|
||||
}
|
||||
|
||||
// Check for priority drivers first
|
||||
for _, name := range priority {
|
||||
if staticWithDeviceMapper(name) {
|
||||
continue
|
||||
}
|
||||
driver, err = GetDriver(name, root, options)
|
||||
if err != nil {
|
||||
if err == ErrNotSupported || err == ErrPrerequisites || err == ErrIncompatibleFS {
|
||||
@@ -151,7 +152,10 @@ func New(root string, options []string) (driver Driver, err error) {
|
||||
}
|
||||
|
||||
// Check all registered drivers if no priority driver is found
|
||||
for _, initFunc := range drivers {
|
||||
for name, initFunc := range drivers {
|
||||
if staticWithDeviceMapper(name) {
|
||||
continue
|
||||
}
|
||||
if driver, err = initFunc(root, options); err != nil {
|
||||
if err == ErrNotSupported || err == ErrPrerequisites || err == ErrIncompatibleFS {
|
||||
continue
|
||||
@@ -163,31 +167,31 @@ func New(root string, options []string) (driver Driver, err error) {
|
||||
return nil, fmt.Errorf("No supported storage backend found")
|
||||
}
|
||||
|
||||
// scanPriorDrivers returns an un-ordered scan of directories of prior storage drivers
|
||||
func scanPriorDrivers(root string) []string {
|
||||
priorDrivers := []string{}
|
||||
// scanPriorDrivers returns a previosly used driver.
|
||||
// it returns an error when there are several drivers scanned.
|
||||
func scanPriorDrivers(root string) (string, error) {
|
||||
var priorDrivers []string
|
||||
for driver := range drivers {
|
||||
p := filepath.Join(root, driver)
|
||||
if _, err := os.Stat(p); err == nil {
|
||||
if _, err := os.Stat(p); err == nil && driver != "vfs" {
|
||||
priorDrivers = append(priorDrivers, driver)
|
||||
}
|
||||
}
|
||||
return priorDrivers
|
||||
}
|
||||
|
||||
func checkPriorDriver(name, root string) error {
|
||||
priorDrivers := []string{}
|
||||
for _, prior := range scanPriorDrivers(root) {
|
||||
if prior != name && prior != "vfs" {
|
||||
if _, err := os.Stat(filepath.Join(root, prior)); err == nil {
|
||||
priorDrivers = append(priorDrivers, prior)
|
||||
}
|
||||
}
|
||||
if len(priorDrivers) > 1 {
|
||||
return "", multipleDriversError(root, priorDrivers)
|
||||
}
|
||||
|
||||
if len(priorDrivers) > 0 {
|
||||
|
||||
return errors.New(fmt.Sprintf("%q contains other graphdrivers: %s; Please cleanup or explicitly choose storage driver (-s <DRIVER>)", root, strings.Join(priorDrivers, ",")))
|
||||
if len(priorDrivers) == 0 {
|
||||
return "", nil
|
||||
}
|
||||
return nil
|
||||
return priorDrivers[0], nil
|
||||
}
|
||||
|
||||
func multipleDriversError(root string, drivers []string) error {
|
||||
return fmt.Errorf("%q contains several graphdrivers: %s; Please cleanup or explicitly choose storage driver (--storage-driver <DRIVER>)", root, strings.Join(drivers, ", "))
|
||||
}
|
||||
|
||||
func staticWithDeviceMapper(name string) bool {
|
||||
return name == "devicemapper" && dockerversion.IAMSTATIC == "true"
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"github.com/docker/docker/daemon/execdriver"
|
||||
"github.com/docker/libcontainer"
|
||||
"github.com/docker/libcontainer/cgroups"
|
||||
"github.com/docker/libnetwork/sandbox"
|
||||
)
|
||||
|
||||
func (daemon *Daemon) ContainerStats(name string, stream bool, out io.Writer) error {
|
||||
@@ -19,6 +20,10 @@ func (daemon *Daemon) ContainerStats(name string, stream bool, out io.Writer) er
|
||||
var preCpuStats types.CpuStats
|
||||
getStat := func(v interface{}) *types.Stats {
|
||||
update := v.(*execdriver.ResourceStats)
|
||||
// Retrieve the nw statistics from libnetwork and inject them in the Stats
|
||||
if nwStats, err := daemon.getNetworkStats(name); err == nil {
|
||||
update.Stats.Interfaces = nwStats
|
||||
}
|
||||
ss := convertToAPITypes(update.Stats)
|
||||
ss.PreCpuStats = preCpuStats
|
||||
ss.MemoryStats.Limit = uint64(update.MemoryLimit)
|
||||
@@ -118,3 +123,46 @@ func copyBlkioEntry(entries []cgroups.BlkioStatEntry) []types.BlkioStatEntry {
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func (daemon *Daemon) getNetworkStats(name string) ([]*libcontainer.NetworkInterface, error) {
|
||||
var list []*libcontainer.NetworkInterface
|
||||
|
||||
c, err := daemon.Get(name)
|
||||
if err != nil {
|
||||
return list, err
|
||||
}
|
||||
|
||||
nw, err := daemon.netController.NetworkByID(c.NetworkSettings.NetworkID)
|
||||
if err != nil {
|
||||
return list, err
|
||||
}
|
||||
ep, err := nw.EndpointByID(c.NetworkSettings.EndpointID)
|
||||
if err != nil {
|
||||
return list, err
|
||||
}
|
||||
|
||||
stats, err := ep.Statistics()
|
||||
if err != nil {
|
||||
return list, err
|
||||
}
|
||||
|
||||
// Convert libnetwork nw stats into libcontainer nw stats
|
||||
for ifName, ifStats := range stats {
|
||||
list = append(list, convertLnNetworkStats(ifName, ifStats))
|
||||
}
|
||||
|
||||
return list, nil
|
||||
}
|
||||
|
||||
func convertLnNetworkStats(name string, stats *sandbox.InterfaceStatistics) *libcontainer.NetworkInterface {
|
||||
n := &libcontainer.NetworkInterface{Name: name}
|
||||
n.RxBytes = stats.RxBytes
|
||||
n.RxPackets = stats.RxPackets
|
||||
n.RxErrors = stats.RxErrors
|
||||
n.RxDropped = stats.RxDropped
|
||||
n.TxBytes = stats.TxBytes
|
||||
n.TxPackets = stats.TxPackets
|
||||
n.TxErrors = stats.TxErrors
|
||||
n.TxDropped = stats.TxDropped
|
||||
return n
|
||||
}
|
||||
|
||||
+6
-17
@@ -4,21 +4,10 @@ MAINTAINER Mary Anthony <mary@docker.com> (@moxiegirl)
|
||||
# To get the git info for this repo
|
||||
COPY . /src
|
||||
|
||||
COPY . /docs/content/engine/
|
||||
COPY . /docs/content/
|
||||
|
||||
# Sed to process GitHub Markdown
|
||||
# 1-2 Remove comment code from metadata block
|
||||
# 3 Remove .md extension from link text
|
||||
# 4 Change ](/ to ](/project/ in links
|
||||
# 5 Change ](word) to ](/project/word)
|
||||
# 6 Change ](../../ to ](/project/
|
||||
# 7 Change ](../ to ](/project/word)
|
||||
#
|
||||
#
|
||||
RUN find /docs/content/engine -type f -name "*.md" -exec sed -i.old \
|
||||
-e '/^<!.*metadata]>/g' \
|
||||
-e '/^<!.*end-metadata.*>/g' \
|
||||
-e 's/\([(]\)\(.*\)\(\.md\)/\1\2/g' \
|
||||
-e 's/\(\]\)\([(]\)\(\/\)/\1\2\/engine\//g' \
|
||||
-e 's/\(\][(]\)\([A-z]*[)]\)/\]\(\/engine\/\2/g' \
|
||||
-e 's/\(\][(]\)\(\.\.\/\)/\1\/engine\//g' {} \;
|
||||
WORKDIR /docs/content
|
||||
|
||||
RUN /docs/content/touch-up.sh
|
||||
|
||||
WORKDIR /docs
|
||||
|
||||
@@ -47,7 +47,9 @@ image cache.
|
||||
> characters of the full image ID - which can be found using
|
||||
> `docker inspect` or `docker images --no-trunc=true`
|
||||
|
||||
{{ include "no-remote-sudo.md" }}
|
||||
> **Note:** if you are using a remote Docker daemon, such as Boot2Docker,
|
||||
> then _do not_ type the `sudo` before the `docker` commands shown in the
|
||||
> documentation's examples.
|
||||
|
||||
## Running an interactive shell
|
||||
|
||||
|
||||
@@ -4,7 +4,8 @@ title = "Using certificates for repository client verification"
|
||||
description = "How to set up and use certificates with a registry to verify access"
|
||||
keywords = ["Usage, registry, repository, client, root, certificate, docker, apache, ssl, tls, documentation, examples, articles, tutorials"]
|
||||
[menu.main]
|
||||
parent = "smn_registry"
|
||||
parent = "mn_docker_hub"
|
||||
weight = 7
|
||||
+++
|
||||
<![end-metadata]-->
|
||||
|
||||
|
||||
@@ -4,7 +4,8 @@ title = "Run a local registry mirror"
|
||||
description = "How to set up and run a local registry mirror"
|
||||
keywords = ["docker, registry, mirror, examples"]
|
||||
[menu.main]
|
||||
parent = "smn_registry"
|
||||
parent = "mn_docker_hub"
|
||||
weight = 8
|
||||
+++
|
||||
<![end-metadata]-->
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ description = "Docker Hub accounts"
|
||||
keywords = ["Docker, docker, registry, accounts, plans, Dockerfile, Docker Hub, docs, documentation"]
|
||||
[menu.main]
|
||||
parent = "smn_pubhub"
|
||||
weight = 1
|
||||
+++
|
||||
<![end-metadata]-->
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ description = "Docker Hub Automated Builds"
|
||||
keywords = ["Docker, docker, registry, accounts, plans, Dockerfile, Docker Hub, docs, documentation, trusted, builds, trusted builds, automated builds"]
|
||||
[menu.main]
|
||||
parent = "smn_pubhub"
|
||||
weight = 3
|
||||
+++
|
||||
<![end-metadata]-->
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<!--[metadata]>
|
||||
+++
|
||||
draft = true
|
||||
title = "The Docker Hub Registry help"
|
||||
description = "The Docker Registry help documentation home"
|
||||
keywords = ["Docker, docker, registry, accounts, plans, Dockerfile, Docker Hub, docs, documentation"]
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<!--[metadata]>
|
||||
+++
|
||||
title = "The Docker Hub help"
|
||||
title = "The Docker Hub"
|
||||
description = "The Docker Help documentation home"
|
||||
keywords = ["Docker, docker, registry, accounts, plans, Dockerfile, Docker Hub, docs, documentation, accounts, organizations, repositories, groups"]
|
||||
[menu.main]
|
||||
|
||||
@@ -5,6 +5,7 @@ description = "Guidelines for Official Repositories on Docker Hub"
|
||||
keywords = ["Docker, docker, registry, accounts, plans, Dockerfile, Docker Hub, docs, official, image, documentation"]
|
||||
[menu.main]
|
||||
parent = "smn_pubhub"
|
||||
weight = 4
|
||||
+++
|
||||
<![end-metadata]-->
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ description = "Your Repositories on Docker Hub"
|
||||
keywords = ["Docker, docker, registry, accounts, plans, Dockerfile, Docker Hub, webhooks, docs, documentation"]
|
||||
[menu.main]
|
||||
parent = "smn_pubhub"
|
||||
weight = 2
|
||||
+++
|
||||
<![end-metadata]-->
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ title = "Dockerizing a CouchDB service"
|
||||
description = "Sharing data between 2 couchdb databases"
|
||||
keywords = ["docker, example, package installation, networking, couchdb, data volumes"]
|
||||
[menu.main]
|
||||
parent = "smn_remoteapi"
|
||||
parent = "smn_applied"
|
||||
+++
|
||||
<![end-metadata]-->
|
||||
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
> **Note:** if you are using a remote Docker daemon, such as Boot2Docker,
|
||||
> then _do not_ type the `sudo` before the `docker` commands shown in the
|
||||
> documentation's examples.
|
||||
+137
-105
@@ -12,153 +12,185 @@ parent = "smn_linux"
|
||||
|
||||
Docker is supported on the following versions of CentOS:
|
||||
|
||||
- [*CentOS 7 (64-bit)*](#installing-docker-centos-7)
|
||||
- [*CentOS 6.5 (64-bit)*](#installing-docker-centos-6.5) or later
|
||||
* CentOS 7.X
|
||||
* CentOS 6.5 or higher
|
||||
|
||||
These instructions are likely work for other binary compatible EL6/EL7 distributions
|
||||
such as Scientific Linux, but they haven't been tested.
|
||||
Installation on other binary compatible EL6/EL7 distributions such as Scientific
|
||||
Linux might succeed, but Docker does not test or support Docker on these
|
||||
distributions.
|
||||
|
||||
Please note that due to the current Docker limitations, Docker is able to
|
||||
run only on the **64 bit** architecture.
|
||||
This page instructs you to install using Docker-managed release packages and
|
||||
installation mechanisms. Using these packages ensures you get the latest release
|
||||
of Docker. If you wish to install using CentOS-managed packages, consult your
|
||||
CentOS documentation.
|
||||
|
||||
## Kernel support
|
||||
## Prerequisites
|
||||
|
||||
Currently the CentOS project will only support Docker when running on kernels
|
||||
shipped by the distribution. There are kernel changes which will cause issues
|
||||
if one decides to step outside that box and run non-distribution kernel packages.
|
||||
Docker requires a 64-bit installation regardless of your CentOS version. Also,
|
||||
your kernel must be 3.10 at minimum. CentOS 7 runs the 3.10 kernel, 6.5 does
|
||||
not. We make an exception for CentOS 6.5. To run Docker on
|
||||
[CentOS-6.5](https://www.centos.org) or later, you need kernel 2.6.32-431 or
|
||||
higher.
|
||||
|
||||
To run Docker on [CentOS-6.5](http://www.centos.org) or later, you will need
|
||||
kernel version 2.6.32-431 or higher as this has specific kernel fixes to allow
|
||||
Docker to run.
|
||||
To check your current kernel version, open a terminal and use `uname -r` to
|
||||
display your kernel version:
|
||||
|
||||
## CentOS-7
|
||||
$ uname -r
|
||||
2.6.32-431.el6.x86_64
|
||||
|
||||
### Installation
|
||||
Finally, is it recommended that you fully update your system. Please keep in
|
||||
mind that CentOS 6 should be fully patched to fix any potential kernel bugs. Any
|
||||
reported kernel bugs may have already been fixed on the latest kernel packages
|
||||
|
||||
Docker is included by default in the CentOS-Extras repository. To install
|
||||
run the following command:
|
||||
## Install
|
||||
|
||||
$ sudo yum install docker
|
||||
You use the same installation procedure for all versions of CentOS,
|
||||
only the package you install differs. There are two packages to choose from:
|
||||
|
||||
Please continue with the [Starting the Docker daemon](#starting-the-docker-daemon).
|
||||
<table>
|
||||
<tr>
|
||||
<th>Version</th>
|
||||
<th>Package name</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>6.5 and higher</td>
|
||||
<td>
|
||||
<p>
|
||||
<a href="https://get.docker.com/rpm/1.7.0/centos-6/RPMS/x86_64/docker-engine-1.7.0-1.el6.x86_64.rpm">
|
||||
https://get.docker.com/rpm/1.7.0/centos-6/RPMS/x86_64/docker-engine-1.7.0-1.el6.x86_64.rpm</a>
|
||||
<p>
|
||||
<a href="https://get.docker.com/rpm/1.7.0/centos-6/SRPMS/docker-engine-1.7.0-1.el6.src.rpm">
|
||||
https://get.docker.com/rpm/1.7.0/centos-6/SRPMS/docker-engine-1.7.0-1.el6.src.rpm</a>
|
||||
<p>
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>7.X</td>
|
||||
<td>
|
||||
<p>
|
||||
<a href="https://get.docker.com/rpm/1.7.0/centos-7/RPMS/x86_64/docker-engine-1.7.0-1.el7.centos.x86_64.rpm">
|
||||
https://get.docker.com/rpm/1.7.0/centos-7/RPMS/x86_64/docker-engine-1.7.0-1.el7.centos.x86_64.rpm</a>
|
||||
</p>
|
||||
<p>
|
||||
<a href="https://get.docker.com/rpm/1.7.0/centos-7/SRPMS/docker-engine-1.7.0-1.el7.centos.src.rpm">
|
||||
https://get.docker.com/rpm/1.7.0/centos-7/SRPMS/docker-engine-1.7.0-1.el7.centos.src.rpm</a>
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
### Uninstallation
|
||||
|
||||
To uninstall the Docker package:
|
||||
This procedure depicts an installation on version 6.5. If you are installing on
|
||||
7.X, substitute that package for your installation.
|
||||
|
||||
$ sudo yum -y remove docker
|
||||
1. Log into your machine as a user with `sudo` or `root` privileges.
|
||||
|
||||
The above command will not remove images, containers, volumes, or user created
|
||||
configuration files on your host. If you wish to delete all images, containers,
|
||||
and volumes run the following command:
|
||||
2. Make sure your existing packages are up-to-date.
|
||||
|
||||
$ rm -rf /var/lib/docker
|
||||
$ sudo yum update
|
||||
|
||||
3. Download the Docker RPM to the current directory.
|
||||
|
||||
$ curl -O -sSL https://get.docker.com/rpm/1.7.0/centos-6/RPMS/x86_64/docker-engine-1.7.0-1.el6.x86_64.rpm
|
||||
|
||||
You must delete the user created configuration files manually.
|
||||
4. Use `yum` to install the package.
|
||||
|
||||
## CentOS-6.5
|
||||
$ sudo yum localinstall --nogpgcheck docker-engine-1.7.0-1.el6.x86_64.rpm
|
||||
|
||||
### Installation
|
||||
5. Start the Docker daemon.
|
||||
|
||||
For CentOS-6.5, the Docker package is part of [Extra Packages
|
||||
for Enterprise Linux (EPEL)](https://fedoraproject.org/wiki/EPEL) repository,
|
||||
a community effort to create and maintain additional packages for the RHEL distribution.
|
||||
$ sudo service docker start
|
||||
|
||||
Firstly, you need to ensure you have the EPEL repository enabled. Please
|
||||
follow the [EPEL installation instructions](
|
||||
https://fedoraproject.org/wiki/EPEL#How_can_I_use_these_extra_packages.3F).
|
||||
6. Verify `docker` is installed correctly by running a test image in a container.
|
||||
|
||||
For CentOS-6, there is a package name conflict with a system tray application
|
||||
and its executable, so the Docker RPM package was called `docker-io`.
|
||||
$ sudo docker run hello-world
|
||||
Unable to find image 'hello-world:latest' locally
|
||||
latest: Pulling from hello-world
|
||||
a8219747be10: Pull complete
|
||||
91c95931e552: Already exists
|
||||
hello-world:latest: The image you are pulling has been verified. Important: image verification is a tech preview feature and should not be relied on to provide security.
|
||||
Digest: sha256:aa03e5d0d5553b4c3473e89c8619cf79df368babd1.7.0cf5daeb82aab55838d
|
||||
Status: Downloaded newer image for hello-world:latest
|
||||
Hello from Docker.
|
||||
This message shows that your installation appears to be working correctly.
|
||||
|
||||
To proceed with `docker-io` installation on CentOS-6, you may need to remove the
|
||||
`docker` package first.
|
||||
To generate this message, Docker took the following steps:
|
||||
1. The Docker client contacted the Docker daemon.
|
||||
2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
|
||||
(Assuming it was not already locally available.)
|
||||
3. The Docker daemon created a new container from that image which runs the
|
||||
executable that produces the output you are currently reading.
|
||||
4. The Docker daemon streamed that output to the Docker client, which sent it
|
||||
to your terminal.
|
||||
|
||||
$ sudo yum -y remove docker
|
||||
To try something more ambitious, you can run an Ubuntu container with:
|
||||
$ docker run -it ubuntu bash
|
||||
|
||||
Next, let's install the `docker-io` package which will install Docker on our host.
|
||||
For more examples and ideas, visit:
|
||||
http://docs.docker.com/userguide/
|
||||
|
||||
## Create a docker group
|
||||
|
||||
$ sudo yum install docker-io
|
||||
The `docker` daemon binds to a Unix socket instead of a TCP port. By default
|
||||
that Unix socket is owned by the user `root` and other users can access it with
|
||||
`sudo`. For this reason, `docker` daemon always runs as the `root` user.
|
||||
|
||||
Please continue with the [Starting the Docker daemon](#starting-the-docker-daemon).
|
||||
To avoid having to use `sudo` when you use the `docker` command, create a Unix
|
||||
group called `docker` and add users to it. When the `docker` daemon starts, it
|
||||
makes the ownership of the Unix socket read/writable by the `docker` group.
|
||||
|
||||
### Uninstallation
|
||||
>**Warning**: The `docker` group is equivalent to the `root` user; For details
|
||||
>on how this impacts security in your system, see [*Docker Daemon Attack
|
||||
>Surface*](/articles/security/#docker-daemon-attack-surface) for details.
|
||||
|
||||
To uninstall the Docker package:
|
||||
To create the `docker` group and add your user:
|
||||
|
||||
$ sudo yum -y remove docker-io
|
||||
1. Log into Centos as a user with `sudo` privileges.
|
||||
|
||||
The above command will not remove images, containers, volumes, or user created
|
||||
configuration files on your host. If you wish to delete all images, containers,
|
||||
and volumes run the following command:
|
||||
2. Create the `docker` group and add your user.
|
||||
|
||||
$ rm -rf /var/lib/docker
|
||||
`sudo usermod -aG docker your_username`
|
||||
|
||||
You must delete the user created configuration files manually.
|
||||
3. Log out and log back in.
|
||||
|
||||
## Manual installation of latest Docker release
|
||||
This ensures your user is running with the correct permissions.
|
||||
|
||||
While using a package is the recommended way of installing Docker,
|
||||
the above package might not be the current release version. If you need the latest
|
||||
version, [you can install the binary directly](
|
||||
https://docs.docker.com/installation/binaries/).
|
||||
4. Verify your work by running `docker` without `sudo`.
|
||||
|
||||
When installing the binary without a package, you may want
|
||||
to integrate Docker with Systemd. For this, install the two unit files
|
||||
(service and socket) from [the GitHub
|
||||
repository](https://github.com/docker/docker/tree/master/contrib/init/systemd)
|
||||
to `/etc/systemd/system`.
|
||||
$ docker run hello-world
|
||||
|
||||
## Start the docker daemon at boot
|
||||
|
||||
Please continue with the [Starting the Docker daemon](#starting-the-docker-daemon).
|
||||
To ensure Docker starts when you boot your system, do the following:
|
||||
|
||||
## Starting the Docker daemon
|
||||
|
||||
Once Docker is installed, you will need to start the docker daemon.
|
||||
|
||||
$ sudo service docker start
|
||||
|
||||
If we want Docker to start at boot, we should also:
|
||||
|
||||
$ sudo chkconfig docker on
|
||||
|
||||
Now let's verify that Docker is working. First we'll need to get the latest
|
||||
`centos` image.
|
||||
|
||||
$ sudo docker pull centos
|
||||
|
||||
Next we'll make sure that we can see the image by running:
|
||||
|
||||
$ sudo docker images centos
|
||||
|
||||
This should generate some output similar to:
|
||||
|
||||
$ sudo docker images centos
|
||||
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
|
||||
centos latest 0b443ba03958 2 hours ago 297.6 MB
|
||||
|
||||
Run a simple bash shell to test the image:
|
||||
|
||||
$ sudo docker run -i -t centos /bin/bash
|
||||
|
||||
If everything is working properly, you'll get a simple bash prompt. Type
|
||||
`exit` to continue.
|
||||
|
||||
## Custom daemon options
|
||||
$ sudo chkconfig docker on
|
||||
|
||||
If you need to add an HTTP Proxy, set a different directory or partition for the
|
||||
Docker runtime files, or make other customizations, read our Systemd article to
|
||||
learn how to [customize your Systemd Docker daemon options](/articles/systemd/).
|
||||
|
||||
## Dockerfiles
|
||||
The CentOS Project provides a number of sample Dockerfiles which you may use
|
||||
either as templates or to familiarize yourself with docker. These templates
|
||||
are available on GitHub at [https://github.com/CentOS/CentOS-Dockerfiles](
|
||||
https://github.com/CentOS/CentOS-Dockerfiles)
|
||||
|
||||
**Done!** You can either continue with the [Docker User
|
||||
Guide](/userguide/) or explore and build on the images yourself.
|
||||
## Uninstall
|
||||
|
||||
## Issues?
|
||||
You can uninstall the Docker software with `yum`.
|
||||
|
||||
If you have any issues - please report them directly in the
|
||||
[CentOS bug tracker](http://bugs.centos.org).
|
||||
1. List the package you have installed.
|
||||
|
||||
$ yum list installed | grep docker
|
||||
yum list installed | grep docker
|
||||
docker-engine.x86_64 1.7.0-1.el6
|
||||
@/docker-engine-1.7.0-1.el6.x86_64.rpm
|
||||
|
||||
2. Remove the package.
|
||||
|
||||
$ sudo yum -y remove docker-engine.x86_64
|
||||
|
||||
This command does not remove images, containers, volumes, or user-created
|
||||
configuration files on your host.
|
||||
|
||||
3. To delete all images, containers, and volumes, run the following command:
|
||||
|
||||
$ rm -rf /var/lib/docker
|
||||
|
||||
4. Locate and delete any user-created configuration files.
|
||||
+171
-61
@@ -12,111 +12,221 @@ parent = "smn_linux"
|
||||
|
||||
Docker is supported on the following versions of Fedora:
|
||||
|
||||
- [*Fedora 20 (64-bit)*](#fedora-20-installation)
|
||||
- [*Fedora 21 and later (64-bit)*](#fedora-21-and-later-installation)
|
||||
- Fedora 20
|
||||
- Fedora 21
|
||||
- Fedora 22
|
||||
|
||||
Currently the Fedora project will only support Docker when running on kernels
|
||||
shipped by the distribution. There are kernel changes which will cause issues
|
||||
if one decides to step outside that box and run non-distribution kernel packages.
|
||||
This page instructs you to install using Docker-managed release packages and
|
||||
installation mechanisms. Using these packages ensures you get the latest release
|
||||
of Docker. If you wish to install using Fedora-managed packages, consult your
|
||||
Fedora release documentation for information on Fedora's Docker support.
|
||||
|
||||
## Fedora 21 and later
|
||||
##Prerequisites
|
||||
|
||||
### Installation
|
||||
Docker requires a 64-bit installation regardless of your Fedora version. Also, your kernel must be 3.10 at minimum. To check your current kernel
|
||||
version, open a terminal and use `uname -r` to display your kernel version:
|
||||
|
||||
Install the Docker package which will install Docker on our host.
|
||||
$ uname -r
|
||||
3.19.5-100.fc20.x86_64
|
||||
|
||||
$ sudo yum -y install docker
|
||||
If your kernel is at a older version, you must update it.
|
||||
|
||||
To update the Docker package:
|
||||
Finally, is it recommended that you fully update your system. Please keep in
|
||||
mind that your system should be fully patched to fix any potential kernel bugs. Any
|
||||
reported kernel bugs may have already been fixed on the latest kernel packages
|
||||
|
||||
$ sudo yum -y update docker
|
||||
|
||||
Please continue with the [Starting the Docker daemon](#starting-the-docker-daemon).
|
||||
## Install
|
||||
|
||||
### Uninstallation
|
||||
You use the same installation procedure for all versions of Fedora,
|
||||
only the package you install differs. There are two packages to choose from:
|
||||
|
||||
To uninstall the Docker package:
|
||||
<table>
|
||||
<tr>
|
||||
<th>Version</th>
|
||||
<th>Package name</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Fedora 20</td>
|
||||
<td>
|
||||
<p>
|
||||
<a href="https://get.docker.com/rpm/1.7.0/fedora-20/RPMS/x86_64/docker-engine-1.7.0-1.fc20.x86_64.rpm">
|
||||
https://get.docker.com/rpm/1.7.0/fedora-20/RPMS/x86_64/docker-engine-1.7.0-1.fc20.x86_64.rpm</a>
|
||||
</p>
|
||||
</td>
|
||||
<p>
|
||||
<a href="https://get.docker.com/rpm/1.7.0/fedora-20/SRPMS/docker-engine-1.7.0-1.fc20.src.rpm">
|
||||
https://get.docker.com/rpm/1.7.0/fedora-20/SRPMS/docker-engine-1.7.0-1.fc20.src.rpm/a>
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Fedora 21</td>
|
||||
<td>
|
||||
<p>
|
||||
<a href="https://get.docker.com/rpm/1.7.0/fedora-21/RPMS/x86_64/docker-engine-1.7.0-1.fc21.x86_64.rpm">
|
||||
https://get.docker.com/rpm/1.7.0/fedora-21/RPMS/x86_64/docker-engine-1.7.0-1.fc21.x86_64.rpm</a>
|
||||
</p>
|
||||
</td>
|
||||
<p>
|
||||
<a href="https://get.docker.com/rpm/1.7.0/fedora-21/SRPMS/docker-engine-1.7.0-1.fc21.src.rpm">
|
||||
https://get.docker.com/rpm/1.7.0/fedora-21/SRPMS/docker-engine-1.7.0-1.fc21.src.rpm/a>
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Fedora 22</td>
|
||||
<td>
|
||||
<p>
|
||||
<a href="https://get.docker.com/rpm/1.7.0/fedora-22/RPMS/x86_64/docker-engine-1.7.0-1.fc22.x86_64.rpm">
|
||||
https://get.docker.com/rpm/1.7.0/fedora-22/RPMS/x86_64/docker-engine-1.7.0-1.fc22.x86_64.rpm</a>
|
||||
</p>
|
||||
</td>
|
||||
<p>
|
||||
<a href="https://get.docker.com/rpm/1.7.0/fedora-22/SRPMS/docker-engine-1.7.0-1.fc22.src.rpm">
|
||||
https://get.docker.com/rpm/1.7.0/fedora-22/SRPMS/docker-engine-1.7.0-1.fc22.src.rpm/a>
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
$ sudo yum -y remove docker
|
||||
|
||||
The above command will not remove images, containers, volumes, or user created
|
||||
configuration files on your host. If you wish to delete all images, containers,
|
||||
and volumes run the following command:
|
||||
This procedure depicts an installation on version 21. If you are installing on
|
||||
20 or 22, substitute that package for your installation.
|
||||
|
||||
$ rm -rf /var/lib/docker
|
||||
1. Log into your machine as a user with `sudo` or `root` privileges.
|
||||
|
||||
You must delete the user created configuration files manually.
|
||||
2. Make sure you don't have an older version of Docker installed.
|
||||
|
||||
## Fedora 20
|
||||
$ yum list installed | grep docker
|
||||
|
||||
If you have an older version, remove it using the `yum -y remove <packagename>` command.
|
||||
|
||||
### Installation
|
||||
3. Download the Docker RPM to the current directory.
|
||||
|
||||
$ curl -O -sSL https://url_to_package/docker-engine-1.7.0-0.1.fc21.x86_64.rpm
|
||||
|
||||
For `Fedora 20`, there is a package name conflict with a system tray application
|
||||
and its executable, so the Docker RPM package was called `docker-io`.
|
||||
4. Use `yum` to install the package.
|
||||
|
||||
To proceed with `docker-io` installation on Fedora 20, please remove the `docker`
|
||||
package first.
|
||||
$ sudo yum localinstall --nogpgcheck docker-engine-1.7.0-0.1.fc21.x86_64.rpm
|
||||
|
||||
$ sudo yum -y remove docker
|
||||
$ sudo yum -y install docker-io
|
||||
5. Start the Docker daemon.
|
||||
|
||||
To update the Docker package:
|
||||
$ sudo service docker start
|
||||
|
||||
$ sudo yum -y update docker-io
|
||||
6. Verify `docker` is installed correctly by running a test image in a container.
|
||||
|
||||
Please continue with the [Starting the Docker daemon](#starting-the-docker-daemon).
|
||||
$ sudo docker run hello-world
|
||||
Unable to find image 'hello-world:latest' locally
|
||||
latest: Pulling from hello-world
|
||||
a8219747be10: Pull complete
|
||||
91c95931e552: Already exists
|
||||
hello-world:latest: The image you are pulling has been verified. Important: image verification is a tech preview feature and should not be relied on to provide security.
|
||||
Digest: sha256:aa03e5d0d5553b4c3473e89c8619cf79df368babd18681cf5daeb82aab55838d
|
||||
Status: Downloaded newer image for hello-world:latest
|
||||
Hello from Docker.
|
||||
This message shows that your installation appears to be working correctly.
|
||||
|
||||
### Uninstallation
|
||||
To generate this message, Docker took the following steps:
|
||||
1. The Docker client contacted the Docker daemon.
|
||||
2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
|
||||
(Assuming it was not already locally available.)
|
||||
3. The Docker daemon created a new container from that image which runs the
|
||||
executable that produces the output you are currently reading.
|
||||
4. The Docker daemon streamed that output to the Docker client, which sent it
|
||||
to your terminal.
|
||||
|
||||
To uninstall the Docker package:
|
||||
To try something more ambitious, you can run an Ubuntu container with:
|
||||
$ docker run -it ubuntu bash
|
||||
|
||||
$ sudo yum -y remove docker-io
|
||||
For more examples and ideas, visit:
|
||||
http://docs.docker.com/userguide/
|
||||
|
||||
## Create a docker group
|
||||
|
||||
The above command will not remove images, containers, volumes, or user created
|
||||
configuration files on your host. If you wish to delete all images, containers,
|
||||
and volumes run the following command:
|
||||
The `docker` daemon binds to a Unix socket instead of a TCP port. By default
|
||||
that Unix socket is owned by the user `root` and other users can access it with
|
||||
`sudo`. For this reason, `docker` daemon always runs as the `root` user.
|
||||
|
||||
$ rm -rf /var/lib/docker
|
||||
To avoid having to use `sudo` when you use the `docker` command, create a Unix
|
||||
group called `docker` and add users to it. When the `docker` daemon starts, it
|
||||
makes the ownership of the Unix socket read/writable by the `docker` group.
|
||||
|
||||
You must delete the user created configuration files manually.
|
||||
>**Warning**: The `docker` group is equivalent to the `root` user; For details
|
||||
>on how this impacts security in your system, see [*Docker Daemon Attack
|
||||
>Surface*](/articles/security/#docker-daemon-attack-surface) for details.
|
||||
|
||||
## Starting the Docker daemon
|
||||
To create the `docker` group and add your user:
|
||||
|
||||
Now that it's installed, let's start the Docker daemon.
|
||||
1. Log into your system as a user with `sudo` privileges.
|
||||
|
||||
$ sudo systemctl start docker
|
||||
2. Create the `docker` group and add your user.
|
||||
|
||||
If we want Docker to start at boot, we should also:
|
||||
`sudo usermod -aG docker your_username`
|
||||
|
||||
$ sudo systemctl enable docker
|
||||
3. Log out and log back in.
|
||||
|
||||
Now let's verify that Docker is working.
|
||||
This ensures your user is running with the correct permissions.
|
||||
|
||||
$ sudo docker run -i -t fedora /bin/bash
|
||||
4. Verify your work by running `docker` without `sudo`.
|
||||
|
||||
> Note: If you get a `Cannot start container` error mentioning SELinux
|
||||
> or permission denied, you may need to update the SELinux policies.
|
||||
> This can be done using `sudo yum upgrade selinux-policy` and then rebooting.
|
||||
$ docker run hello-world
|
||||
Unable to find image 'hello-world:latest' locally
|
||||
latest: Pulling from hello-world
|
||||
a8219747be10: Pull complete
|
||||
91c95931e552: Already exists
|
||||
hello-world:latest: The image you are pulling has been verified. Important: image verification is a tech preview feature and should not be relied on to provide security.
|
||||
Digest: sha256:aa03e5d0d5553b4c3473e89c8619cf79df368babd18681cf5daeb82aab55838d
|
||||
Status: Downloaded newer image for hello-world:latest
|
||||
Hello from Docker.
|
||||
This message shows that your installation appears to be working correctly.
|
||||
|
||||
## Granting rights to users to use Docker
|
||||
To generate this message, Docker took the following steps:
|
||||
1. The Docker client contacted the Docker daemon.
|
||||
2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
|
||||
(Assuming it was not already locally available.)
|
||||
3. The Docker daemon created a new container from that image which runs the
|
||||
executable that produces the output you are currently reading.
|
||||
4. The Docker daemon streamed that output to the Docker client, which sent it
|
||||
to your terminal.
|
||||
|
||||
The `docker` command line tool contacts the `docker` daemon process via a
|
||||
socket file `/var/run/docker.sock` owned by `root:root`. Though it's
|
||||
[recommended](https://lists.projectatomic.io/projectatomic-archives/atomic-devel/2015-January/msg00034.html)
|
||||
to use `sudo` for docker commands, if users wish to avoid it, an administrator can
|
||||
create a `docker` group, have it own `/var/run/docker.sock`, and add users to this group.
|
||||
To try something more ambitious, you can run an Ubuntu container with:
|
||||
$ docker run -it ubuntu bash
|
||||
|
||||
$ sudo groupadd docker
|
||||
$ sudo chown root:docker /var/run/docker.sock
|
||||
$ sudo usermod -a -G docker $USERNAME
|
||||
For more examples and ideas, visit:
|
||||
http://docs.docker.com/userguide/
|
||||
|
||||
## Start the docker daemon at boot
|
||||
|
||||
## Custom daemon options
|
||||
To ensure Docker starts when you boot your system, do the following:
|
||||
|
||||
$ sudo chkconfig docker on
|
||||
|
||||
If you need to add an HTTP Proxy, set a different directory or partition for the
|
||||
Docker runtime files, or make other customizations, read our Systemd article to
|
||||
learn how to [customize your Systemd Docker daemon options](/articles/systemd/).
|
||||
|
||||
## What next?
|
||||
|
||||
Continue with the [User Guide](/userguide/).
|
||||
## Uninstall
|
||||
|
||||
You can uninstall the Docker software with `yum`.
|
||||
|
||||
1. List the package you have installed.
|
||||
|
||||
$ yum list installed | grep docker
|
||||
yum list installed | grep docker
|
||||
docker-engine.x86_64 1.7.0-0.1.fc20
|
||||
@/docker-engine-1.7.0-0.1.fc20.el6.x86_64
|
||||
|
||||
2. Remove the package.
|
||||
|
||||
$ sudo yum -y remove docker-engine.x86_64
|
||||
|
||||
This command does not remove images, containers, volumes, or user-created
|
||||
configuration files on your host.
|
||||
|
||||
3. To delete all images, containers, and volumes, run the following command:
|
||||
|
||||
$ rm -rf /var/lib/docker
|
||||
|
||||
4. Locate and delete any user-created configuration files.
|
||||
|
||||
@@ -14,7 +14,7 @@ You can install Docker using Boot2Docker to run `docker` commands at your comman
|
||||
Choose this installation if you are familiar with the command-line or plan to
|
||||
contribute to the Docker project on GitHub.
|
||||
|
||||
[<img src="/engine/installation/images/kitematic.png" alt="Download Kitematic"
|
||||
[<img src="/installation/images/kitematic.png" alt="Download Kitematic"
|
||||
style="float:right;">](https://kitematic.com/download)
|
||||
|
||||
Alternatively, you may want to try <a id="inlinelink" href="https://kitematic.com/"
|
||||
@@ -355,4 +355,4 @@ at [Boot2Docker repository](https://github.com/boot2docker/boot2docker).
|
||||
Thanks to Chris Jones whose [blog](http://viget.com/extend/how-to-use-docker-on-os-x-the-missing-guide)
|
||||
inspired me to redo this page.
|
||||
|
||||
Continue with the [Docker User Guide](/userguide/).
|
||||
Continue with the [Docker User Guide](/userguide).
|
||||
|
||||
+133
-105
@@ -12,150 +12,178 @@ parent = "smn_linux"
|
||||
|
||||
Docker is supported on the following versions of RHEL:
|
||||
|
||||
- [*Red Hat Enterprise Linux 7 (64-bit)*](#red-hat-enterprise-linux-7-installation)
|
||||
- [*Red Hat Enterprise Linux 6.6 (64-bit)*](#red-hat-enterprise-linux-66-installation) or later
|
||||
- Red Hat Enterprise Linux 7
|
||||
- Red Hat Enterprise Linux 6.6 or later
|
||||
|
||||
## Kernel support
|
||||
This page instructs you to install using Docker-managed release packages and
|
||||
installation mechanisms. Using these packages ensures you get the latest release
|
||||
of Docker. If you wish to install using Red Hat-managed packages, consult your
|
||||
Red Hat release documentation for information on Red Hat's Docker support.
|
||||
|
||||
RHEL will only support Docker via the *extras* channel or EPEL package when
|
||||
running on kernels shipped by the distribution. There are kernel changes which
|
||||
will cause issues if one decides to step outside that box and run
|
||||
non-distribution kernel packages.
|
||||
## Prerequisites
|
||||
|
||||
## Red Hat Enterprise Linux 7
|
||||
Docker requires a 64-bit installation regardless of your Red Hat version. Docker
|
||||
requires that your kernel must be 3.10 at minimum. Red Hat 7 runs the 3.10
|
||||
kernel, 6.6 does not. We make an exception for Red Hat 6.6. To run Docker on
|
||||
[Red Hat-6.6](http://www.centos.org) or later, you need kernel 2.6.32-431 or
|
||||
higher.
|
||||
|
||||
### Installation
|
||||
To check your current kernel version, open a terminal and use `uname -r` to
|
||||
display your kernel version:
|
||||
|
||||
**Red Hat Enterprise Linux 7 (64 bit)** has [shipped with
|
||||
Docker](https://access.redhat.com/site/products/red-hat-enterprise-linux/docker-and-containers).
|
||||
An overview and some guidance can be found in the [Release
|
||||
Notes](https://access.redhat.com/site/documentation/en-US/Red_Hat_Enterprise_Linux/7/html/7.0_Release_Notes/chap-Red_Hat_Enterprise_Linux-7.0_Release_Notes-Linux_Containers_with_Docker_Format.html).
|
||||
$ uname -r
|
||||
3.10.0-229.el7.x86_64
|
||||
|
||||
Docker is located in the *extras* channel. To install Docker:
|
||||
Finally, is it recommended that you fully update your system. Please keep in
|
||||
mind that your system should be fully patched to fix any potential kernel bugs.
|
||||
Any reported kernel bugs may have already been fixed on the latest kernel
|
||||
packages
|
||||
|
||||
1. Enable the *extras* channel:
|
||||
|
||||
$ sudo subscription-manager repos --enable=rhel-7-server-extras-rpms
|
||||
## Install
|
||||
|
||||
2. Install Docker:
|
||||
You use the same installation procedure for all versions of Red Hat Enterprise,
|
||||
only the package you install differs. There are two packages to choose from:
|
||||
|
||||
$ sudo yum install docker
|
||||
<table>
|
||||
<tr>
|
||||
<th>Version</th>
|
||||
<th>Package name</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>6.6 and higher</td>
|
||||
<td>
|
||||
<p>
|
||||
<a href="https://get.docker.com/rpm/1.7.0/centos-6/RPMS/x86_64/docker-engine-1.7.0-1.el6.x86_64.rpm">
|
||||
https://get.docker.com/rpm/1.7.0/centos-6/RPMS/x86_64/docker-engine-1.7.0-1.el6.x86_64.rpm</a>
|
||||
<p>
|
||||
<a href="https://get.docker.com/rpm/1.7.0/centos-6/SRPMS/docker-engine-1.7.0-1.el6.src.rpm">
|
||||
https://get.docker.com/rpm/1.7.0/centos-6/SRPMS/docker-engine-1.7.0-1.el6.src.rpm</a>
|
||||
<p>
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>7.X</td>
|
||||
<td>
|
||||
<p>
|
||||
<a href="https://get.docker.com/rpm/1.7.0/centos-7/RPMS/x86_64/docker-engine-1.7.0-1.el7.centos.x86_64.rpm">
|
||||
https://get.docker.com/rpm/1.7.0/centos-7/RPMS/x86_64/docker-engine-1.7.0-1.el7.centos.x86_64.rpm</a>
|
||||
</p>
|
||||
<p>
|
||||
<a href="https://get.docker.com/rpm/1.7.0/centos-7/SRPMS/docker-engine-1.7.0-1.el7.centos.src.rpm">
|
||||
https://get.docker.com/rpm/1.7.0/centos-7/SRPMS/docker-engine-1.7.0-1.el7.centos.src.rpm</a>
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
Additional installation, configuration, and usage information,
|
||||
including a [Get Started with Docker Containers in Red Hat
|
||||
Enterprise Linux 7](https://access.redhat.com/site/articles/881893)
|
||||
guide, can be found by Red Hat customers on the [Red Hat Customer
|
||||
Portal](https://access.redhat.com/).
|
||||
This procedure depicts an installation on version 6.6. If you are installing on
|
||||
7.X, substitute that package for your installation.
|
||||
|
||||
Please continue with the [Starting the Docker daemon](#starting-the-docker-daemon).
|
||||
1. Log into your machine as a user with `sudo` or `root` privileges.
|
||||
|
||||
### Uninstallation
|
||||
2. Download the Docker RPM to the current directory.
|
||||
|
||||
$ curl -O -sSL http://get.docker.com/docker/1.7.0/rpms/centos-6/RPMS/x86_64/docker-engine-1.7.0-0.1.el6.x86_64.rpm
|
||||
|
||||
To uninstall the Docker package:
|
||||
3. Use `yum` to install the package.
|
||||
|
||||
$ sudo yum -y remove docker
|
||||
$ sudo yum localinstall --nogpgcheck docker-engine-1.7.0-0.1.el6.x86_64.rpm
|
||||
|
||||
The above command will not remove images, containers, volumes, or user created
|
||||
configuration files on your host. If you wish to delete all images, containers,
|
||||
and volumes run the following command:
|
||||
5. Start the Docker daemon.
|
||||
|
||||
$ rm -rf /var/lib/docker
|
||||
$ sudo service docker start
|
||||
|
||||
You must delete the user created configuration files manually.
|
||||
6. Verify `docker` is installed correctly.
|
||||
|
||||
## Red Hat Enterprise Linux 6.6
|
||||
$ sudo docker run hello-world
|
||||
Unable to find image 'hello-world:latest' locally
|
||||
latest: Pulling from hello-world
|
||||
a8219747be10: Pull complete
|
||||
91c95931e552: Already exists
|
||||
hello-world:latest: The image you are pulling has been verified. Important: image verification is a tech preview feature and should not be relied on to provide security.
|
||||
Digest: sha256:aa03e5d0d5553b4c3473e89c8619cf79df368babd18681cf5daeb82aab55838d
|
||||
Status: Downloaded newer image for hello-world:latest
|
||||
Hello from Docker.
|
||||
This message shows that your installation appears to be working correctly.
|
||||
|
||||
You will need **64 bit** [RHEL
|
||||
6.6](https://access.redhat.com/site/articles/3078#RHEL6) or later, with
|
||||
a RHEL 6 kernel version 2.6.32-504.16.2 or higher as this has specific kernel
|
||||
fixes to allow Docker to work. Related issues: [#9856](https://github.com/docker/docker/issues/9856).
|
||||
To generate this message, Docker took the following steps:
|
||||
1. The Docker client contacted the Docker daemon.
|
||||
2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
|
||||
(Assuming it was not already locally available.)
|
||||
3. The Docker daemon created a new container from that image which runs the
|
||||
executable that produces the output you are currently reading.
|
||||
4. The Docker daemon streamed that output to the Docker client, which sent it
|
||||
to your terminal.
|
||||
|
||||
Docker is available for **RHEL6.6** on EPEL. Please note that
|
||||
this package is part of [Extra Packages for Enterprise Linux
|
||||
(EPEL)](https://fedoraproject.org/wiki/EPEL), a community effort to
|
||||
create and maintain additional packages for the RHEL distribution.
|
||||
To try something more ambitious, you can run an Ubuntu container with:
|
||||
$ docker run -it ubuntu bash
|
||||
|
||||
### Kernel support
|
||||
For more examples and ideas, visit:
|
||||
http://docs.docker.com/userguide/
|
||||
|
||||
## Create a docker group
|
||||
|
||||
RHEL will only support Docker via the *extras* channel or EPEL package when
|
||||
running on kernels shipped by the distribution. There are things like namespace
|
||||
changes which will cause issues if one decides to step outside that box and run
|
||||
non-distro kernel packages.
|
||||
The `docker` daemon binds to a Unix socket instead of a TCP port. By default
|
||||
that Unix socket is owned by the user `root` and other users can access it with
|
||||
`sudo`. For this reason, `docker` daemon always runs as the `root` user.
|
||||
|
||||
> **Warning**:
|
||||
> Please keep your system up to date using `yum update` and rebooting
|
||||
> your system. Keeping your system updated ensures critical security
|
||||
> vulnerabilities and severe bugs (such as those found in kernel 2.6.32)
|
||||
> are fixed.
|
||||
To avoid having to use `sudo` when you use the `docker` command, create a Unix
|
||||
group called `docker` and add users to it. When the `docker` daemon starts, it
|
||||
makes the ownership of the Unix socket read/writable by the `docker` group.
|
||||
|
||||
### Installation
|
||||
>**Warning**: The `docker` group is equivalent to the `root` user; For details
|
||||
>on how this impacts security in your system, see [*Docker Daemon Attack
|
||||
>Surface*](/articles/security/#docker-daemon-attack-surface) for details.
|
||||
|
||||
Firstly, you need to install the EPEL repository. Please follow the
|
||||
[EPEL installation
|
||||
instructions](https://fedoraproject.org/wiki/EPEL#How_can_I_use_these_extra_packages.3F).
|
||||
To create the `docker` group and add your user:
|
||||
|
||||
There is a package name conflict with a system tray application
|
||||
and its executable, so the Docker RPM package was called `docker-io`.
|
||||
1. Log into your machine as a user with `sudo` or `root` privileges.
|
||||
|
||||
To proceed with `docker-io` installation, you may need to remove the
|
||||
`docker` package first.
|
||||
2. Create the `docker` group and add your user.
|
||||
|
||||
$ sudo yum -y remove docker
|
||||
`sudo usermod -aG docker your_username`
|
||||
|
||||
Next, let's install the `docker-io` package which will install Docker on our host.
|
||||
3. Log out and log back in.
|
||||
|
||||
$ sudo yum install docker-io
|
||||
This ensures your user is running with the correct permissions.
|
||||
|
||||
To update the `docker-io` package
|
||||
4. Verify your work by running `docker` without `sudo`.
|
||||
|
||||
$ sudo yum -y update docker-io
|
||||
$ docker run hello-world
|
||||
|
||||
## Start the docker daemon at boot
|
||||
|
||||
Please continue with the [Starting the Docker daemon](#starting-the-docker-daemon).
|
||||
|
||||
### Uninstallation
|
||||
|
||||
To uninstall the Docker package:
|
||||
|
||||
$ sudo yum -y remove docker-io
|
||||
|
||||
The above command will not remove images, containers, volumes, or user created
|
||||
configuration files on your host. If you wish to delete all images, containers,
|
||||
and volumes run the following command:
|
||||
|
||||
$ rm -rf /var/lib/docker
|
||||
|
||||
You must delete the user created configuration files manually.
|
||||
|
||||
## Starting the Docker daemon
|
||||
|
||||
Now that it's installed, let's start the Docker daemon.
|
||||
|
||||
$ sudo service docker start
|
||||
|
||||
If we want Docker to start at boot, we should also:
|
||||
To ensure Docker starts when you boot your system, do the following:
|
||||
|
||||
$ sudo chkconfig docker on
|
||||
|
||||
Now let's verify that Docker is working.
|
||||
|
||||
$ sudo docker run -i -t fedora /bin/bash
|
||||
|
||||
> Note: If you get a `Cannot start container` error mentioning SELinux
|
||||
> or permission denied, you may need to update the SELinux policies.
|
||||
> This can be done using `sudo yum upgrade selinux-policy` and then rebooting.
|
||||
|
||||
**Done!**
|
||||
|
||||
Continue with the [User Guide](/userguide/).
|
||||
|
||||
## Custom daemon options
|
||||
|
||||
If you need to add an HTTP Proxy, set a different directory or partition for the
|
||||
Docker runtime files, or make other customizations, read our Systemd article to
|
||||
learn how to [customize your Systemd Docker daemon options](/articles/systemd/).
|
||||
|
||||
## Issues?
|
||||
|
||||
If you have any issues - please report them directly in the
|
||||
[Red Hat Bugzilla for docker-io component](
|
||||
https://bugzilla.redhat.com/enter_bug.cgi?product=Fedora%20EPEL&component=docker-io).
|
||||
## Uninstall
|
||||
|
||||
You can uninstall the Docker software with `yum`.
|
||||
|
||||
1. List the package you have installed.
|
||||
|
||||
$ yum list installed | grep docker
|
||||
yum list installed | grep docker
|
||||
docker-engine.x86_64 1.7.0-0.1.el6
|
||||
@/docker-engine-1.7.0-0.1.el6.x86_64
|
||||
|
||||
2. Remove the package.
|
||||
|
||||
$ sudo yum -y remove docker-engine.x86_64
|
||||
|
||||
This command does not remove images, containers, volumes, or user created
|
||||
configuration files on your host.
|
||||
|
||||
3. To delete all images, containers, and volumes run the following command:
|
||||
|
||||
$ rm -rf /var/lib/docker
|
||||
|
||||
4. Locate and delete any user-created configuration files.
|
||||
@@ -8,7 +8,7 @@ parent = "smn_linux"
|
||||
+++
|
||||
<![end-metadata]-->
|
||||
|
||||
#Ubuntu
|
||||
# Ubuntu
|
||||
|
||||
Docker is supported on these Ubuntu operating systems:
|
||||
|
||||
|
||||
@@ -53,7 +53,9 @@ is developed, you can launch only Linux containers from your Windows machine.
|
||||
|
||||
## Running Docker
|
||||
|
||||
{{ include "no-remote-sudo.md" }}
|
||||
> **Note:** if you are using a remote Docker daemon, such as Boot2Docker,
|
||||
> then _do not_ type the `sudo` before the `docker` commands shown in the
|
||||
> documentation's examples.
|
||||
|
||||
**Boot2Docker Start** will automatically start a shell with environment variables
|
||||
correctly set so you can start using Docker right away:
|
||||
|
||||
+3
-1
@@ -36,7 +36,9 @@ Windows*](../installation/windows/#windows) installation guides. The small Linux
|
||||
distribution boot2docker can be run inside virtual machines on these two
|
||||
operating systems.
|
||||
|
||||
{{ include "no-remote-sudo.md" }}
|
||||
> **Note:** if you are using a remote Docker daemon, such as Boot2Docker,
|
||||
> then _do not_ type the `sudo` before the `docker` commands shown in the
|
||||
> documentation's examples.
|
||||
|
||||
### How do containers compare to virtual machines?
|
||||
|
||||
|
||||
+1
-3
@@ -1,12 +1,10 @@
|
||||
<!--[metadata]>
|
||||
+++
|
||||
draft = true
|
||||
title = "Get started with Docker"
|
||||
title = "About Docker"
|
||||
description = "Introduction to Docker."
|
||||
keywords = ["docker, introduction, documentation, about, technology, understanding, Dockerfile"]
|
||||
[menu.main]
|
||||
parent = "mn_use_docker"
|
||||
weight = 1
|
||||
+++
|
||||
<![end-metadata]-->
|
||||
|
||||
|
||||
-229
@@ -1,229 +0,0 @@
|
||||
site_name: Docker Documentation
|
||||
#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
|
||||
|
||||
dev_addr: '0.0.0.0:8000'
|
||||
|
||||
repo_url: https://github.com/docker/docker/
|
||||
|
||||
docs_dir: sources
|
||||
|
||||
include_search: true
|
||||
|
||||
use_absolute_urls: true
|
||||
|
||||
# theme: docker
|
||||
theme_dir: ./theme/mkdocs/
|
||||
theme_center_lead: false
|
||||
|
||||
copyright: Copyright © 2014-2015, Docker, Inc.
|
||||
google_analytics: ['UA-6096819-11', 'docker.io']
|
||||
|
||||
pages:
|
||||
|
||||
# Introduction:
|
||||
- ['index.md', 'About', 'Docker']
|
||||
- ['introduction/understanding-docker.md', 'About', 'Understanding Docker']
|
||||
- ['release-notes.md', 'About', 'Release notes']
|
||||
- ['reference/glossary.md', 'About', 'Glossary']
|
||||
- ['introduction/index.md', '**HIDDEN**']
|
||||
|
||||
|
||||
# Installation:
|
||||
- ['installation/index.md', '**HIDDEN**']
|
||||
- ['installation/ubuntulinux.md', 'Installation', 'Ubuntu']
|
||||
- ['installation/mac.md', 'Installation', 'Mac OS X']
|
||||
- ['kitematic/index.md', 'Installation', 'Kitematic on OS X']
|
||||
- ['installation/windows.md', 'Installation', 'Microsoft Windows']
|
||||
- ['installation/testing-windows-docker-client.md', 'Installation', 'Building and testing the Windows Docker client']
|
||||
- ['installation/amazon.md', 'Installation', 'Amazon EC2']
|
||||
- ['installation/archlinux.md', 'Installation', 'Arch Linux']
|
||||
- ['installation/binaries.md', 'Installation', 'Binaries']
|
||||
- ['installation/centos.md', 'Installation', 'CentOS']
|
||||
- ['installation/cruxlinux.md', 'Installation', 'CRUX Linux']
|
||||
- ['installation/debian.md', 'Installation', 'Debian']
|
||||
- ['installation/fedora.md', 'Installation', 'Fedora']
|
||||
- ['installation/frugalware.md', 'Installation', 'FrugalWare']
|
||||
- ['installation/google.md', 'Installation', 'Google Cloud Platform']
|
||||
- ['installation/gentoolinux.md', 'Installation', 'Gentoo']
|
||||
- ['installation/softlayer.md', 'Installation', 'IBM Softlayer']
|
||||
- ['installation/joyent.md', 'Installation', 'Joyent Compute Service']
|
||||
- ['installation/azure.md', 'Installation', 'Microsoft Azure']
|
||||
- ['installation/rackspace.md', 'Installation', 'Rackspace Cloud']
|
||||
- ['installation/rhel.md', 'Installation', 'Red Hat Enterprise Linux']
|
||||
- ['installation/oracle.md', 'Installation', 'Oracle Linux']
|
||||
- ['installation/SUSE.md', 'Installation', 'SUSE']
|
||||
- ['compose/install.md', 'Installation', 'Docker Compose']
|
||||
|
||||
# User Guide:
|
||||
- ['userguide/index.md', 'User Guide', 'The Docker user guide' ]
|
||||
- ['userguide/dockerhub.md', 'User Guide', 'Getting started with Docker Hub' ]
|
||||
- ['userguide/dockerizing.md', 'User Guide', 'Dockerizing applications' ]
|
||||
- ['userguide/usingdocker.md', 'User Guide', 'Working with containers' ]
|
||||
- ['userguide/dockerimages.md', 'User Guide', 'Working with Docker images' ]
|
||||
- ['userguide/dockerlinks.md', 'User Guide', 'Linking containers together' ]
|
||||
- ['userguide/dockervolumes.md', 'User Guide', 'Managing data in containers' ]
|
||||
- ['userguide/labels-custom-metadata.md', 'User Guide', 'Apply custom metadata' ]
|
||||
- ['userguide/dockerrepos.md', 'User Guide', 'Working with Docker Hub' ]
|
||||
- ['userguide/level1.md', '**HIDDEN**' ]
|
||||
- ['userguide/level2.md', '**HIDDEN**' ]
|
||||
- ['compose/index.md', 'User Guide', 'Docker Compose' ]
|
||||
- ['compose/production.md', 'User Guide', ' ▪ Use Compose in production' ]
|
||||
- ['compose/extends.md', 'User Guide', ' ▪ Extend Compose services' ]
|
||||
- ['machine/index.md', 'User Guide', 'Docker Machine' ]
|
||||
- ['swarm/index.md', 'User Guide', 'Docker Swarm' ]
|
||||
- ['kitematic/userguide.md', 'User Guide', 'Kitematic']
|
||||
|
||||
# Docker Hub docs:
|
||||
- ['docker-hub/index.md', 'Docker Hub', 'Docker Hub' ]
|
||||
- ['docker-hub/accounts.md', 'Docker Hub', 'Accounts']
|
||||
- ['docker-hub/userguide.md', 'Docker Hub', 'User Guide']
|
||||
- ['docker-hub/repos.md', 'Docker Hub', 'Your Repositories']
|
||||
- ['docker-hub/builds.md', 'Docker Hub', 'Automated Builds']
|
||||
- ['docker-hub/official_repos.md', 'Docker Hub', 'Official Repositories']
|
||||
|
||||
# Docker Hub Enterprise:
|
||||
- ['docker-hub-enterprise/index.md', 'Docker Hub Enterprise', 'Overview' ]
|
||||
- ['docker-hub-enterprise/quick-start.md', 'Docker Hub Enterprise', 'Quick Start: Basic Workflow' ]
|
||||
- ['docker-hub-enterprise/userguide.md', 'Docker Hub Enterprise', 'User Guide' ]
|
||||
- ['docker-hub-enterprise/adminguide.md', 'Docker Hub Enterprise', 'Admin Guide' ]
|
||||
- ['docker-hub-enterprise/install.md', 'Docker Hub Enterprise', ' Installation' ]
|
||||
- ['docker-hub-enterprise/configuration.md', 'Docker Hub Enterprise', ' Configuration options' ]
|
||||
- ['docker-hub-enterprise/support.md', 'Docker Hub Enterprise', 'Support' ]
|
||||
- ['docker-hub-enterprise/release-notes.md', 'Docker Hub Enterprise', 'Release notes' ]
|
||||
|
||||
# Examples:
|
||||
- ['examples/index.md', '**HIDDEN**']
|
||||
- ['examples/nodejs_web_app.md', 'Examples', 'Dockerizing a Node.js web application']
|
||||
- ['examples/mongodb.md', 'Examples', 'Dockerizing MongoDB']
|
||||
- ['examples/running_redis_service.md', 'Examples', 'Dockerizing a Redis service']
|
||||
- ['examples/postgresql_service.md', 'Examples', 'Dockerizing a PostgreSQL service']
|
||||
- ['examples/running_riak_service.md', 'Examples', 'Dockerizing a Riak service']
|
||||
- ['examples/running_ssh_service.md', 'Examples', 'Dockerizing an SSH service']
|
||||
- ['examples/couchdb_data_volumes.md', 'Examples', 'Dockerizing a CouchDB service']
|
||||
- ['examples/apt-cacher-ng.md', 'Examples', 'Dockerizing an Apt-Cacher-ng service']
|
||||
- ['compose/django.md', 'Examples', 'Getting started with Compose and Django']
|
||||
- ['compose/rails.md', 'Examples', 'Getting started with Compose and Rails']
|
||||
- ['compose/wordpress.md', 'Examples', 'Getting started with Compose and Wordpress']
|
||||
- ['kitematic/minecraft-server.md', 'Examples', 'Kitematic: Minecraft server']
|
||||
- ['kitematic/nginx-web-server.md', 'Examples', 'Kitematic: Ngnix web server']
|
||||
- ['kitematic/rethinkdb-dev-database.md', 'Examples', 'Kitematic: RethinkDB development database']
|
||||
|
||||
# Articles
|
||||
- ['articles/index.md', '**HIDDEN**']
|
||||
- ['articles/basics.md', 'Articles', 'Docker basics']
|
||||
- ['articles/networking.md', 'Articles', 'Advanced networking']
|
||||
- ['articles/security.md', 'Articles', 'Security']
|
||||
- ['articles/https.md', 'Articles', 'Running Docker with HTTPS']
|
||||
- ['articles/registry_mirror.md', 'Articles', 'Run a local registry mirror']
|
||||
- ['articles/host_integration.md', 'Articles', 'Automatically starting containers']
|
||||
- ['articles/baseimages.md', 'Articles', 'Creating a base image']
|
||||
- ['articles/dockerfile_best-practices.md', 'Articles', 'Best practices for writing Dockerfiles']
|
||||
- ['articles/certificates.md', 'Articles', 'Using certificates for repository client verification']
|
||||
- ['articles/using_supervisord.md', 'Articles', 'Using Supervisor']
|
||||
- ['articles/configuring.md', 'Articles', 'Configuring Docker']
|
||||
- ['articles/cfengine_process_management.md', 'Articles', 'Process management with CFEngine']
|
||||
- ['articles/puppet.md', 'Articles', 'Using Puppet']
|
||||
- ['articles/chef.md', 'Articles', 'Using Chef']
|
||||
- ['articles/dsc.md', 'Articles', 'Using PowerShell DSC']
|
||||
- ['articles/ambassador_pattern_linking.md', 'Articles', 'Cross-Host linking using ambassador containers']
|
||||
- ['articles/runmetrics.md', 'Articles', 'Runtime metrics']
|
||||
- ['articles/b2d_volume_resize.md', 'Articles', 'Increasing a Boot2Docker volume']
|
||||
- ['articles/systemd.md', 'Articles', 'Controlling and configuring Docker using Systemd']
|
||||
|
||||
# Reference
|
||||
- ['reference/index.md', '**HIDDEN**']
|
||||
- ['reference/commandline/index.md', '**HIDDEN**']
|
||||
- ['reference/commandline/cli.md', 'Reference', 'Docker command line']
|
||||
- ['reference/builder.md', 'Reference', 'Dockerfile']
|
||||
- ['faq.md', 'Reference', 'FAQ']
|
||||
- ['reference/run.md', 'Reference', 'Run reference']
|
||||
- ['reference/logging/journald.md', '**HIDDEN**']
|
||||
- ['compose/cli.md', 'Reference', 'Compose command line']
|
||||
- ['compose/yml.md', 'Reference', 'Compose yml']
|
||||
- ['compose/env.md', 'Reference', 'Compose ENV variables']
|
||||
- ['compose/completion.md', 'Reference', 'Compose commandline completion']
|
||||
- ['swarm/discovery.md', 'Reference', 'Swarm discovery']
|
||||
- ['swarm/scheduler/strategy.md', 'Reference', 'Swarm strategies']
|
||||
- ['swarm/scheduler/filter.md', 'Reference', 'Swarm filters']
|
||||
- ['swarm/API.md', 'Reference', 'Swarm API']
|
||||
- ['reference/api/index.md', '**HIDDEN**']
|
||||
- ['registry/index.md', 'Reference', 'Docker Registry 2.0']
|
||||
- ['registry/deploying.md', 'Reference', ' ▪ Deploy a registry' ]
|
||||
- ['registry/configuration.md', 'Reference', ' ▪ Configure a registry' ]
|
||||
- ['registry/storagedrivers.md', 'Reference', ' ▪ Storage driver model' ]
|
||||
- ['registry/notifications.md', 'Reference', ' ▪ Work with notifications' ]
|
||||
- ['registry/spec/api.md', 'Reference', ' ▪ Registry Service API v2' ]
|
||||
- ['registry/spec/json.md', 'Reference', ' ▪ JSON format' ]
|
||||
- ['registry/spec/auth/token.md', 'Reference', ' ▪ Authenticate via central service' ]
|
||||
- ['reference/api/hub_registry_spec.md', 'Reference', 'Docker Hub and Registry 1.0']
|
||||
- ['reference/api/registry_api.md', 'Reference', ' ▪ Docker Registry API v1']
|
||||
- ['reference/api/registry_api_client_libraries.md', 'Reference', ' ▪ Docker Registry 1.0 API client libraries']
|
||||
#- ['reference/image-spec-v1.md', 'Reference', 'Docker Image Specification v1.0.0']
|
||||
- ['reference/api/docker-io_api.md', 'Reference', 'Docker Hub API']
|
||||
#- ['reference/image-spec-v1.md', 'Reference', 'Docker Image Specification v1.0.0']
|
||||
- ['reference/api/docker_remote_api.md', 'Reference', 'Docker Remote API']
|
||||
- ['reference/api/docker_remote_api_v1.19.md', 'Reference', 'Docker Remote API v1.19']
|
||||
- ['reference/api/docker_remote_api_v1.18.md', 'Reference', 'Docker Remote API v1.18']
|
||||
- ['reference/api/docker_remote_api_v1.17.md', 'Reference', 'Docker Remote API v1.17']
|
||||
- ['reference/api/docker_remote_api_v1.16.md', 'Reference', 'Docker Remote API v1.16']
|
||||
- ['reference/api/docker_remote_api_v1.15.md', '**HIDDEN**']
|
||||
- ['reference/api/docker_remote_api_v1.14.md', '**HIDDEN**']
|
||||
- ['reference/api/docker_remote_api_v1.13.md', '**HIDDEN**']
|
||||
- ['reference/api/docker_remote_api_v1.12.md', '**HIDDEN**']
|
||||
- ['reference/api/docker_remote_api_v1.11.md', '**HIDDEN**']
|
||||
- ['reference/api/docker_remote_api_v1.10.md', '**HIDDEN**']
|
||||
- ['reference/api/docker_remote_api_v1.9.md', '**HIDDEN**']
|
||||
- ['reference/api/docker_remote_api_v1.8.md', '**HIDDEN**']
|
||||
- ['reference/api/docker_remote_api_v1.7.md', '**HIDDEN**']
|
||||
- ['reference/api/docker_remote_api_v1.6.md', '**HIDDEN**']
|
||||
- ['reference/api/docker_remote_api_v1.5.md', '**HIDDEN**']
|
||||
- ['reference/api/docker_remote_api_v1.4.md', '**HIDDEN**']
|
||||
- ['reference/api/docker_remote_api_v1.3.md', '**HIDDEN**']
|
||||
- ['reference/api/docker_remote_api_v1.2.md', '**HIDDEN**']
|
||||
- ['reference/api/docker_remote_api_v1.1.md', '**HIDDEN**']
|
||||
- ['reference/api/docker_remote_api_v1.0.md', '**HIDDEN**']
|
||||
- ['reference/api/remote_api_client_libraries.md', 'Reference', 'Docker Remote API client libraries']
|
||||
- ['reference/api/docker_io_accounts_api.md', 'Reference', 'Docker Hub accounts API']
|
||||
- ['kitematic/faq.md', 'Reference', 'Kitematic: FAQ']
|
||||
- ['kitematic/known-issues.md', 'Reference', 'Kitematic: Known issues']
|
||||
|
||||
# Hidden registry files
|
||||
- ['registry/storage-drivers/azure.md', '**HIDDEN**' ]
|
||||
- ['registry/storage-drivers/filesystem.md', '**HIDDEN**' ]
|
||||
- ['registry/storage-drivers/inmemory.md', '**HIDDEN**' ]
|
||||
- ['registry/storage-drivers/s3.md', '**HIDDEN**' ]
|
||||
|
||||
- ['jsearch.md', '**HIDDEN**']
|
||||
|
||||
# - ['static_files/README.md', 'static_files', 'README']
|
||||
- ['terms/index.md', '**HIDDEN**']
|
||||
- ['terms/layer.md', '**HIDDEN**']
|
||||
- ['terms/index.md', '**HIDDEN**']
|
||||
- ['terms/registry.md', '**HIDDEN**']
|
||||
- ['terms/container.md', '**HIDDEN**']
|
||||
- ['terms/repository.md', '**HIDDEN**']
|
||||
- ['terms/filesystem.md', '**HIDDEN**']
|
||||
- ['terms/image.md', '**HIDDEN**']
|
||||
|
||||
|
||||
# Project:
|
||||
- ['project/index.md', '**HIDDEN**']
|
||||
- ['project/who-written-for.md', 'Contributor', 'README first']
|
||||
- ['project/software-required.md', 'Contributor', 'Get required software for Linux or OS X']
|
||||
- ['project/software-req-win.md', 'Contributor', 'Get required software for Windows']
|
||||
- ['project/set-up-git.md', 'Contributor', 'Configure Git for contributing']
|
||||
- ['project/set-up-dev-env.md', 'Contributor', 'Work with a development container']
|
||||
- ['project/test-and-docs.md', 'Contributor', 'Run tests and test documentation']
|
||||
- ['project/make-a-contribution.md', 'Contributor', 'Understand contribution workflow']
|
||||
- ['project/find-an-issue.md', 'Contributor', 'Find an issue']
|
||||
- ['project/work-issue.md', 'Contributor', 'Work on an issue']
|
||||
- ['project/create-pr.md', 'Contributor', 'Create a pull request']
|
||||
- ['project/review-pr.md', 'Contributor', 'Participate in the PR review']
|
||||
- ['project/advanced-contributing.md', 'Contributor', 'Advanced contributing']
|
||||
- ['project/get-help.md', 'Contributor', 'Where to get help']
|
||||
- ['project/coding-style.md', 'Contributor', 'Coding style guide']
|
||||
- ['project/doc-style.md', 'Contributor', 'Documentation style guide']
|
||||
|
||||
@@ -5,6 +5,7 @@ description = "Explains workflows for refactor and design proposals"
|
||||
keywords = ["contribute, project, design, refactor, proposal"]
|
||||
[menu.main]
|
||||
parent = "smn_contribute"
|
||||
weight=6
|
||||
+++
|
||||
<![end-metadata]-->
|
||||
|
||||
|
||||
@@ -4,7 +4,8 @@ title = "Coding style checklist"
|
||||
description = "List of guidelines for coding Docker contributions"
|
||||
keywords = ["change, commit, squash, request, pull request, test, unit test, integration tests, Go, gofmt, LGTM"]
|
||||
[menu.main]
|
||||
parent = "mn_opensource"
|
||||
parent = "smn_contribute"
|
||||
weight=7
|
||||
+++
|
||||
<![end-metadata]-->
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ description = "Basic workflow for Docker contributions"
|
||||
keywords = ["contribute, pull request, review, workflow, beginner, squash, commit"]
|
||||
[menu.main]
|
||||
parent = "smn_contribute"
|
||||
weight=4
|
||||
+++
|
||||
<![end-metadata]-->
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ description = "Style guide for Docker documentation describing standards and con
|
||||
keywords = ["style, guide, docker, documentation"]
|
||||
[menu.main]
|
||||
parent = "mn_opensource"
|
||||
weight=100
|
||||
+++
|
||||
<![end-metadata]-->
|
||||
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
<!--[metadata]>
|
||||
+++
|
||||
title = "Make a project contribution"
|
||||
title = "Find and claim an issue"
|
||||
description = "Basic workflow for Docker contributions"
|
||||
keywords = ["contribute, pull request, review, workflow, beginner, expert, squash, commit"]
|
||||
keywords = ["contribute, issue, review, workflow, beginner, expert, squash, commit"]
|
||||
[menu.main]
|
||||
parent = "smn_contribute"
|
||||
weight=2
|
||||
+++
|
||||
<![end-metadata]-->
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ description = "Basic workflow for Docker contributions"
|
||||
keywords = ["contribute, pull request, review, workflow, beginner, squash, commit"]
|
||||
[menu.main]
|
||||
parent = "smn_contribute"
|
||||
weight=5
|
||||
+++
|
||||
<![end-metadata]-->
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ description = "How to use Docker's development environment"
|
||||
keywords = ["development, inception, container, image Dockerfile, dependencies, Go, artifacts"]
|
||||
[menu.main]
|
||||
parent = "smn_develop"
|
||||
weight=5
|
||||
+++
|
||||
<![end-metadata]-->
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ description = "Describes how to set up your local machine and repository"
|
||||
keywords = ["GitHub account, repository, clone, fork, branch, upstream, Git, Go, make "]
|
||||
[menu.main]
|
||||
parent = "smn_develop"
|
||||
weight=4
|
||||
+++
|
||||
<![end-metadata]-->
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ description = "How to set up a server to test Docker Windows client"
|
||||
keywords = ["development, inception, container, image Dockerfile, dependencies, Go, artifacts, windows"]
|
||||
[menu.main]
|
||||
parent = "smn_develop"
|
||||
weight=3
|
||||
+++
|
||||
<![end-metadata]-->
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ description = "Describes the software required to contribute to Docker"
|
||||
keywords = ["GitHub account, repository, Docker, Git, Go, make, "]
|
||||
[menu.main]
|
||||
parent = "smn_develop"
|
||||
weight=2
|
||||
+++
|
||||
<![end-metadata]-->
|
||||
|
||||
|
||||
@@ -4,7 +4,8 @@ title = "Run tests and test documentation"
|
||||
description = "Describes Docker's testing infrastructure"
|
||||
keywords = ["make test, make docs, Go tests, gofmt, contributing, running tests"]
|
||||
[menu.main]
|
||||
parent = "smn_contribute"
|
||||
parent = "smn_develop"
|
||||
weight=6
|
||||
+++
|
||||
<![end-metadata]-->
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ description = "Basic workflow for Docker contributions"
|
||||
keywords = ["contribute, pull request, review, workflow, beginner, squash, commit"]
|
||||
[menu.main]
|
||||
parent = "smn_contribute"
|
||||
weight=3
|
||||
+++
|
||||
<![end-metadata]-->
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<!--[metadata]>
|
||||
+++
|
||||
draft = true
|
||||
title = "Remote API v1.10"
|
||||
description = "API Documentation for Docker"
|
||||
keywords = ["API, Docker, rcli, REST, documentation"]
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<!--[metadata]>
|
||||
+++
|
||||
draft = true
|
||||
title = "Remote API v1.11"
|
||||
description = "API Documentation for Docker"
|
||||
keywords = ["API, Docker, rcli, REST, documentation"]
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<!--[metadata]>
|
||||
+++
|
||||
draft = true
|
||||
title = "Remote API v1.12"
|
||||
description = "API Documentation for Docker"
|
||||
keywords = ["API, Docker, rcli, REST, documentation"]
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<!--[metadata]>
|
||||
+++
|
||||
draft = true
|
||||
title = "Remote API v1.13"
|
||||
description = "API Documentation for Docker"
|
||||
keywords = ["API, Docker, rcli, REST, documentation"]
|
||||
|
||||
@@ -5,6 +5,7 @@ description = "API Documentation for Docker"
|
||||
keywords = ["API, Docker, rcli, REST, documentation"]
|
||||
[menu.main]
|
||||
parent = "smn_remoteapi"
|
||||
weight = 7
|
||||
+++
|
||||
<![end-metadata]-->
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ description = "API Documentation for Docker"
|
||||
keywords = ["API, Docker, rcli, REST, documentation"]
|
||||
[menu.main]
|
||||
parent = "smn_remoteapi"
|
||||
weight = 6
|
||||
+++
|
||||
<![end-metadata]-->
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ description = "API Documentation for Docker"
|
||||
keywords = ["API, Docker, rcli, REST, documentation"]
|
||||
[menu.main]
|
||||
parent = "smn_remoteapi"
|
||||
weight = 5
|
||||
+++
|
||||
<![end-metadata]-->
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ description = "API Documentation for Docker"
|
||||
keywords = ["API, Docker, rcli, REST, documentation"]
|
||||
[menu.main]
|
||||
parent = "smn_remoteapi"
|
||||
weight = 4
|
||||
+++
|
||||
<![end-metadata]-->
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ description = "API Documentation for Docker"
|
||||
keywords = ["API, Docker, rcli, REST, documentation"]
|
||||
[menu.main]
|
||||
parent = "smn_remoteapi"
|
||||
weight = 3
|
||||
+++
|
||||
<![end-metadata]-->
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ description = "API Documentation for Docker"
|
||||
keywords = ["API, Docker, rcli, REST, documentation"]
|
||||
[menu.main]
|
||||
parent = "smn_remoteapi"
|
||||
weight = 2
|
||||
+++
|
||||
<![end-metadata]-->
|
||||
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
<!--[metadata]>
|
||||
+++
|
||||
title = "Registry documentation"
|
||||
title = "The Docker Hub and the Registry v1"
|
||||
description = "Documentation for docker Registry and Registry API"
|
||||
keywords = ["docker, registry, api, hub"]
|
||||
[menu.main]
|
||||
parent="smn_registry_ref"
|
||||
parent="smn_hub_ref"
|
||||
+++
|
||||
<![end-metadata]-->
|
||||
|
||||
# The Docker Hub and the Registry 1.0 spec
|
||||
# The Docker Hub and the Registry v1
|
||||
|
||||
## The three roles
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<!--[metadata]>
|
||||
+++
|
||||
title = "Registry API"
|
||||
draft = true
|
||||
title = "Registry v1 API"
|
||||
description = "API Documentation for Docker Registry"
|
||||
keywords = ["API, Docker, index, registry, REST, documentation"]
|
||||
[menu.main]
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<!--[metadata]>
|
||||
+++
|
||||
draft = true
|
||||
title = "Registry API v1 client libraries"
|
||||
description = "Various client libraries available to use with the Docker registry API"
|
||||
keywords = ["API, Docker, index, registry, REST, documentation, clients, C#, Erlang, Go, Groovy, Java, JavaScript, Perl, PHP, Python, Ruby, Rust, Scala"]
|
||||
|
||||
@@ -10,7 +10,9 @@ parent = "mn_reference"
|
||||
|
||||
# Docker Command Line
|
||||
|
||||
{{ include "no-remote-sudo.md" }}
|
||||
> **Note:** if you are using a remote Docker daemon, such as Boot2Docker,
|
||||
> then _do not_ type the `sudo` before the `docker` commands shown in the
|
||||
> documentation's examples.
|
||||
|
||||
To list available commands, either run `docker` with no parameters
|
||||
or execute `docker help`:
|
||||
|
||||
@@ -1,357 +0,0 @@
|
||||
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
|
||||
|
||||
# Configuring DHE
|
||||
|
||||
## Overview
|
||||
|
||||
This page will help you properly configure Docker Hub Enterprise (DHE) so it can
|
||||
run in your environment.
|
||||
|
||||
Start with DHE loaded in your browser and click the "Settings" tab to view
|
||||
configuration options. You'll see options for configuring:
|
||||
|
||||
* Domains and ports
|
||||
* Security settings
|
||||
* Storage settings
|
||||
* Authentication settings
|
||||
* Your DHE license
|
||||
|
||||
## Domains and Ports
|
||||
|
||||

|
||||
|
||||
* *Domain Name*: **required** defaults to an empty string, the fully qualified domain name assigned to the DHE host.
|
||||
* *Load Balancer HTTP Port*: defaults to 80, used as the entry point for the image storage service. To see load balancer status, you can query
|
||||
http://<dhe-host>/load_balancer_status.
|
||||
* *Load Balancer HTTPS Port*: defaults to 443, used as the secure entry point
|
||||
for the image storage service.
|
||||
* *HTTP_PROXY*: defaults to an empty string, proxy server for HTTP requests.
|
||||
* *HTTPS_PROXY*: defaults to an empty string, proxy server for HTTPS requests.
|
||||
* *NO_PROXY*: defaults to an empty string, proxy bypass for HTTP and HTTPS requests.
|
||||
|
||||
|
||||
> **Note**: If you need DHE to re-generate a self-signed certificate at some
|
||||
> point, you'll need to first delete `/usr/local/etc/dhe/ssl/server.pem`, and
|
||||
> then restart the DHE containers, either by changing and saving the "Domain Name",
|
||||
> or using `bash -c "$(docker run dockerhubenterprise/manager restart)"`.
|
||||
|
||||
|
||||
## Security
|
||||
|
||||

|
||||
|
||||
* *SSL Certificate*: Used to enter the hash (string) from the SSL Certificate.
|
||||
This cert must be accompanied by its private key, entered below.
|
||||
* *Private Key*: The hash from the private key associated with the provided
|
||||
SSL Certificate (as a standard x509 key pair).
|
||||
|
||||
In order to run, DHE requires encrypted communications via HTTPS/SSL between (a) the DHE registry and your Docker Engine(s), and (b) between your web browser and the DHE admin server. There are a few options for setting this up:
|
||||
|
||||
1. You can use the self-signed certificate DHE generates by default.
|
||||
2. You can generate your own certificates using a public service or your enterprise's infrastructure. See the [Generating SSL certificates](#generating-ssl-certificates) section for the options available.
|
||||
|
||||
If you are generating your own certificates, you can install them by following the instructions for
|
||||
[Adding your own registry certificates to DHE](#adding-your-own-registry-certificates-to-dhe).
|
||||
|
||||
On the other hand, if you choose to use the DHE-generated certificates, or the
|
||||
certificates you generate yourself are not trusted by your client Docker hosts,
|
||||
you will need to do one of the following:
|
||||
|
||||
* [Install a registry certificate on all of your client Docker daemons](#installing-registry-certificates-on-client-docker-daemons),
|
||||
|
||||
* Set your [client Docker daemons to run with an unconfirmed connection to the registry](#if-you-cant-install-the-certificates).
|
||||
|
||||
### Generating SSL certificates
|
||||
|
||||
There are three basic approaches to generating certificates:
|
||||
|
||||
1. Most enterprises will have private key infrastructure (PKI) in place to
|
||||
generate keys. Consult with your security team or whomever manages your private
|
||||
key infrastructure. If you have this resource available, Docker recommends you
|
||||
use it.
|
||||
|
||||
2. If your enterprise can't provide keys, you can use a public Certificate
|
||||
Authority (CA) like "InstantSSL.com" or "RapidSSL.com" to generate a
|
||||
certificate. If your certificates are generated using a globally trusted
|
||||
Certificate Authority, you won't need to install them on all of your
|
||||
client Docker daemons.
|
||||
|
||||
3. Use the self-signed registry certificate generated by DHE, and install it
|
||||
onto the client Docker daemon hosts as shown below.
|
||||
|
||||
### Adding your own Registry certificates to DHE
|
||||
|
||||
Whichever method you use to generate certificates, once you have them
|
||||
you can set up your DHE server to use them by navigating to the "Settings" page,
|
||||
going to "Security," and putting the SSL Certificate text (including all
|
||||
intermediate Certificates, starting with the host) into the
|
||||
"SSL Certificate" edit box, and the previously generated Private key into
|
||||
the "SSL Private Key" edit box.
|
||||
|
||||
Click the "Save" button, and then wait for the DHE Admin site to restart and
|
||||
reload. It should now be using the new certificate.
|
||||
|
||||
Once the "Security" page has reloaded, it will show `#` hashes instead of the
|
||||
certificate text you pasted in.
|
||||
|
||||
If your certificate is signed by a chain of Certificate Authorities that are
|
||||
already trusted by your Docker daemon servers, you can skip the "Installing
|
||||
registry certificates" step below.
|
||||
|
||||
### Installing Registry certificates on client Docker daemons
|
||||
|
||||
If your certificates do not have a trusted Certificate Authority, you will need
|
||||
to install them on each client Docker daemon host.
|
||||
|
||||
The procedure for installing the DHE certificates on each Linux distribution has
|
||||
slightly different steps, as shown below.
|
||||
|
||||
You can test this certificate using `curl`:
|
||||
|
||||
```
|
||||
$ curl https://dhe.yourdomain.com/v2/
|
||||
curl: (60) SSL certificate problem: self signed certificate
|
||||
More details here: http://curl.haxx.se/docs/sslcerts.html
|
||||
|
||||
curl performs SSL certificate verification by default, using a "bundle"
|
||||
of Certificate Authority (CA) public keys (CA certs). If the default
|
||||
bundle file isn't adequate, you can specify an alternate file
|
||||
using the --cacert option.
|
||||
If this HTTPS server uses a certificate signed by a CA represented in
|
||||
the bundle, the certificate verification probably failed due to a
|
||||
problem with the certificate (it might be expired, or the name might
|
||||
not match the domain name in the URL).
|
||||
If you'd like to turn off curl's verification of the certificate, use
|
||||
the -k (or --insecure) option.
|
||||
|
||||
$ curl --cacert /usr/local/etc/dhe/ssl/server.pem https://dhe.yourdomain.com/v2/
|
||||
{"errors":[{"code":"UNAUTHORIZED","message":"access to the requested resource is not authorized","detail":null}]}
|
||||
```
|
||||
|
||||
Continue by following the steps corresponding to your chosen OS.
|
||||
|
||||
#### Ubuntu/Debian
|
||||
|
||||
```
|
||||
$ export DOMAIN_NAME=dhe.yourdomain.com
|
||||
$ 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.
|
||||
$ sudo service docker restart
|
||||
docker stop/waiting
|
||||
docker start/running, process 29291
|
||||
```
|
||||
|
||||
#### RHEL
|
||||
|
||||
```
|
||||
$ export DOMAIN_NAME=dhe.yourdomain.com
|
||||
$ 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
|
||||
|
||||
Install the CA cert (or the auto-generated cert) by adding the following to
|
||||
your `/var/lib/boot2docker/bootsync.sh`:
|
||||
|
||||
```
|
||||
#!/bin/sh
|
||||
|
||||
cat /var/lib/boot2docker/server.pem >> /etc/ssl/certs/ca-certificates.crt
|
||||
```
|
||||
|
||||
|
||||
Then get the certificate from the new DHE server using:
|
||||
|
||||
```
|
||||
$ openssl s_client -connect dhe.yourdomain.com:443 -showcerts </dev/null 2>/dev/null | openssl x509 -outform PEM | sudo tee -a /var/lib/boot2docker/server.pem
|
||||
```
|
||||
|
||||
If your certificate chain is complicated, you may want to use the changes in
|
||||
[Pull request 807](https://github.com/boot2docker/boot2docker/pull/807/files)
|
||||
|
||||
Now you can either reboot your Boot2Docker virtual machine, or run the following to
|
||||
install the server certificate, and then restart the Docker daemon.
|
||||
|
||||
```
|
||||
$ sudo chmod 755 /var/lib/boot2docker/bootsync.sh
|
||||
$ sudo /var/lib/boot2docker/bootsync.sh
|
||||
$ sudo /etc/init.d/docker restart`.
|
||||
```
|
||||
|
||||
### If you can't install the certificates
|
||||
|
||||
If for some reason you can't install the certificate chain on a client Docker host,
|
||||
or your certificates do not have a global CA, you can configure your Docker daemon to run in "insecure" mode. This is done by adding an extra flag,
|
||||
`--insecure-registry host-ip|domain-name`, to your client Docker daemon startup flags.
|
||||
You'll need to restart the Docker daemon for the change to take effect.
|
||||
|
||||
This flag means that the communications between your Docker client and the DHE
|
||||
Registry server are still encrypted, but the client Docker daemon is not
|
||||
confirming that the Registry connection is not being hijacked or diverted.
|
||||
|
||||
> **Note**: If you enter a "Domain Name" into the "Security" settings, it needs
|
||||
> to be DNS resolvable on any client Docker daemons that are running in
|
||||
> "insecure-registry" mode.
|
||||
|
||||
To set the flag, follow the directions below for your operating system.
|
||||
|
||||
#### Ubuntu
|
||||
|
||||
On Ubuntu 14.04 LTS, you customize the Docker daemon configuration with the
|
||||
`/etc/defaults/docker` file.
|
||||
|
||||
Open or create the `/etc/defaults/docker` file, and add the
|
||||
`--insecure-registry` flag to the `DOCKER_OPTS` setting (which may need to be
|
||||
added or uncommented) as follows:
|
||||
|
||||
```
|
||||
DOCKER_OPTS="--insecure-registry dhe.yourdomain.com"
|
||||
```
|
||||
|
||||
Then restart the Docker daemon with `sudo service docker restart`.
|
||||
|
||||
#### RHEL
|
||||
|
||||
On RHEL, you customize the Docker daemon configuration with the
|
||||
`/etc/sysconfig/docker` file.
|
||||
|
||||
Open or create the `/etc/sysconfig/docker` file, and add the
|
||||
`--insecure-registry` flag to the `OPTIONS` setting (which may need to be
|
||||
added or uncommented) as follows:
|
||||
|
||||
```
|
||||
OPTIONS="--insecure-registry dhe.yourdomain.com"
|
||||
```
|
||||
|
||||
Then restart the Docker daemon with `sudo service docker restart`.
|
||||
|
||||
### Boot2Docker
|
||||
|
||||
On Boot2Docker, you customize the Docker daemon configuration with the
|
||||
`/var/lib/boot2docker/profile` file.
|
||||
|
||||
Open or create the `/var/lib/boot2docker/profile` file, and add an `EXTRA_ARGS`
|
||||
setting as follows:
|
||||
|
||||
```
|
||||
EXTRA_ARGS="--insecure-registry dhe.yourdomain.com"
|
||||
```
|
||||
|
||||
Then restart the Docker daemon with `sudo /etc/init.d/docker restart`.
|
||||
|
||||
## Image Storage Configuration
|
||||
|
||||
DHE offers multiple methods for image storage, which are defined using specific
|
||||
storage drivers. Image storage can be local, remote, or on a cloud service such
|
||||
as S3. Storage drivers can be added or customized via the DHE storage driver
|
||||
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](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`.
|
||||
|
||||
> **Note:**
|
||||
> Saving changes you've made to settings will restart the Docker Hub Enterprise
|
||||
> instance. The restart may cause a brief interruption for users of the image
|
||||
> storage system.
|
||||
|
||||
## Authentication
|
||||
|
||||
The "Authentication" settings tab lets DHE administrators control access
|
||||
to the DHE web admin tool and to the DHE Registry.
|
||||
|
||||
The current authentication methods are `None`, `Basic` and `LDAP`.
|
||||
|
||||
> **Note**: if you have issues logging into the DHE admin web interface after changing the authentication
|
||||
> settings, you may need to use the [emergency access to the DHE admin web interface](./adminguide.md#Emergency-access-to-the-dhe-admin-web-interface).
|
||||
|
||||
### No authentication
|
||||
|
||||
No authentication means that everyone that can access your DHE web administration
|
||||
site. This is not recommended for any use other than testing.
|
||||
|
||||
|
||||
### Basic authentication
|
||||
|
||||
The `Basic` authentication setting allows the admin to provide username/password pairs local to DHE.
|
||||
Any user who can successfully authenticate can use DHE to push and pull Docker images.
|
||||
You can optionally filter the list of users to a subset of just those users with access to the DHE
|
||||
admin web interface.
|
||||
|
||||

|
||||
|
||||
* A button to add one user, or to upload a CSV file containing username,
|
||||
password pairs
|
||||
* A DHE website Administrator Filter, allowing you to either
|
||||
* * *Allow all authenticated users*: to log into the DHE admin web interface, or
|
||||
* * *Whitelist usernames*: which allows you to restrict access to the web interface to a listed set of users.
|
||||
|
||||
### LDAP authentication
|
||||
|
||||
Using LDAP authentication allows you to integrate your DHE registry into your
|
||||
organization's existing user and authentication database.
|
||||
|
||||
As this involves existing infrastructure external to DHE and Docker, you will need to
|
||||
gather the details required to configure DHE for your organization's particular LDAP
|
||||
implementation.
|
||||
|
||||
You can test that you have the necessary LDAP server information by using it from
|
||||
inside a Docker container running on the same server as your DHE:
|
||||
|
||||
> **Note**: if the LDAP server is configured to use *StartTLS*, then you need to add `-Z` to the
|
||||
> `ldapsearch` command examples below.
|
||||
|
||||
```
|
||||
docker run --rm -it svendowideit/ldapsearch -h <LDAP Server hostname> -b <User Base DN> -D <Search User DN> -w <Search User Password>
|
||||
```
|
||||
|
||||
or if the LDAP server is set up to allow anonymous access (which means your *Search User DN* and *Search User Password* settings can remain empty):
|
||||
|
||||
```
|
||||
docker run --rm -it svendowideit/ldapsearch -h <LDAP Server hostname> -b <User Base DN> -x
|
||||
```
|
||||
|
||||
The result of these queries should be a (very) long list - if you get an authentication error,
|
||||
then the details you have been given are not sufficient.
|
||||
|
||||
The *User Login Attribute* key setting must match the field used in the LDAP server
|
||||
for the user's login-name. On OpenLDAP, it's generally `uid`, and on Microsoft Active Directory
|
||||
servers, it's `sAMAccountName`. The `ldapsearch` output above should allow you to
|
||||
confirm which setting you need.
|
||||
|
||||

|
||||
|
||||
* *Use StartTLS*: defaults to unchecked, check to enable StartTLS
|
||||
* *LDAP Server URL*: **required** defaults to null, LDAP server URL (e.g., - ldap://example.com)
|
||||
* *User Base DN*: **required** defaults to null, user base DN in the form (e.g., - dc=example,dc=com)
|
||||
* *User Login Attribute*: **required** defaults to null, user login attribute (e.g., - uid or sAMAccountName)
|
||||
* *Search User DN*: **required** defaults to null, search user DN (e.g., - domain\username)
|
||||
* *Search User Password*: **required** defaults to null, search user password
|
||||
* A *DHE Registry User filter*: allowing you to either
|
||||
* * *Allow all authenticated users* to push or pull any images, or
|
||||
* * *Filter LDAP search results*: which allows you to restrict DHE registry pull and push to users matching the LDAP filter,
|
||||
* * *Whitelist usernames*: which allows you to restrict DHE registry pull and push to the listed set of users.
|
||||
* A *DHE website Administrator filter*, allowing you to either
|
||||
* * *Allow all authenticated users*: to log into the DHE admin web interface, or
|
||||
* * *Filter LDAP search results*: which allows you to restrict DHE admin web access to users matching the LDAP filter,
|
||||
* * *Whitelist usernames*: which allows you to restrict access to the web interface to the listed set of users.
|
||||
|
||||
|
||||
## Next Steps
|
||||
|
||||
For information on getting support for DHE, take a look at the
|
||||
[Support information](./support.md).
|
||||
|
||||
@@ -1,331 +0,0 @@
|
||||
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
|
||||
|
||||
|
||||
# Docker Hub Enterprise Quick Start: Basic User Workflow
|
||||
|
||||
## 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.
|
||||
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
|
||||
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
|
||||
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
|
||||
working from, be it a laptop, a VM, or a cloud provider.
|
||||
|
||||
The guide will walk you through the following steps:
|
||||
|
||||
1. Pulling the official Jenkins image from the public Docker Hub
|
||||
2. Customizing the Jenkins image to suit your needs
|
||||
3. Pushing the customized image to DHE
|
||||
4. Pulling the customized image from DHE
|
||||
4. Launching a container from the custom image
|
||||
5. Using the new Jenkins container
|
||||
|
||||
You should be able to complete this guide in about thirty minutes.
|
||||
|
||||
> **Note:** This guide assumes you have installed a working instance of DHE
|
||||
> reachable at dhe.yourdomain.com. If you need help installing and configuring
|
||||
> DHE, please consult the
|
||||
[installation instructions](./install.md).
|
||||
|
||||
|
||||
## Pulling the official Jenkins image
|
||||
|
||||
> **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](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
|
||||
Docker Hub. From the CLI of a machine running the Docker Engine on your network, use
|
||||
the
|
||||
[`docker pull`](https://docs.docker.com/reference/commandline/cli/#pull)
|
||||
command to pull the public Jenkins image.
|
||||
|
||||
$ docker pull jenkins
|
||||
|
||||
> **Note:** This guide assumes you can run Docker commands from a machine where
|
||||
> you are a member of the `docker` group, or have root privileges. Otherwise, you may
|
||||
> need to add `sudo` to the example commands below.
|
||||
|
||||
Docker will start the process of pulling the image from the Hub. Once it has completed, the Jenkins image should be visible in the output of a [`docker images`](https://docs.docker.com/reference/commandline/cli/#images) command, which lists your available images:
|
||||
|
||||
$ docker images
|
||||
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
|
||||
jenkins latest 1a7cc22b0ee9 6 days ago 662 MB
|
||||
|
||||
> **Note:** Because the `pull` command did not specify any tags, it will pull
|
||||
> the latest version of the public Jenkins image. If your enterprise environment
|
||||
> requires you to use a specific version, add the tag for the version you need
|
||||
> (e.g., `jenkins:1.565`).
|
||||
|
||||
## Customizing the Jenkins image
|
||||
|
||||
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
|
||||
disabling HTTP access and forcing it to use HTTPS.
|
||||
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
|
||||
> customization is necessary to run Jenkins in your environment.
|
||||
|
||||
### Creating a `build` context
|
||||
|
||||
In order to add the new plugin and configure HTTPS access to the custom Jenkins
|
||||
image, you need to:
|
||||
|
||||
1. Create text file that defines the new plugin
|
||||
2. Create copies of the private key and certificate
|
||||
|
||||
All of the above files need to be in the same directory as the Dockerfile you
|
||||
will create in the next step.
|
||||
|
||||
1. Create a build directory called `build`, and change to that new directory:
|
||||
|
||||
$ mkdir build && cd build
|
||||
|
||||
In this directory, create a new file called `plugins` and add the following
|
||||
line:
|
||||
|
||||
role-strategy:2.2.0
|
||||
|
||||
(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`.
|
||||
|
||||
> **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
|
||||
> 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.
|
||||
|
||||
### Creating a Dockerfile
|
||||
|
||||
In the same directory as the `plugins` file and the private key and certificate,
|
||||
create a new [`Dockerfile`](https://docs.docker.com/reference/builder/) with the
|
||||
following contents:
|
||||
|
||||
FROM jenkins
|
||||
|
||||
#New plugins must be placed in the plugins file
|
||||
COPY plugins /usr/share/jenkins/plugins
|
||||
|
||||
#The plugins.sh script will install new plugins
|
||||
RUN /usr/local/bin/plugins.sh /usr/share/jenkins/plugins
|
||||
|
||||
#Copy private key and cert to image
|
||||
COPY https.pem /var/lib/jenkins/cert
|
||||
COPY https.key /var/lib/jenkins/pk
|
||||
|
||||
#Configure HTTP off and HTTPS on, using port 1973
|
||||
ENV JENKINS_OPTS --httpPort=-1 --httpsPort=1973 --httpsCertificate=/var/lib/jenkins/cert --httpsPrivateKey=/var/lib/jenkins/pk
|
||||
|
||||
The first `COPY` instruction in the above will copy the `plugin` file created
|
||||
earlier into the `/usr/share/jenkins` directory within the custom image you are
|
||||
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
|
||||
into the required directories within the new image.
|
||||
|
||||
The `ENV` instruction creates an environment variable called `JENKINS_OPT` in
|
||||
the image you are about to create. This environment variable will be present in
|
||||
any containers launched form the image and contains the required settings to
|
||||
tell Jenkins to disable HTTP and operate over HTTPS.
|
||||
|
||||
> **Note:** You can specify any valid port number as part of the `JENKINS_OPT`
|
||||
> environment variable declared above. The value `1973` used in the example is
|
||||
> arbitrary.
|
||||
|
||||
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
|
||||
the image being built.
|
||||
|
||||
### Building your custom image
|
||||
|
||||
Now that the `Dockerfile`, the `plugins` file, and the files required for HTTPS
|
||||
operation are created in your current working directory, you can build your
|
||||
custom image using the
|
||||
[`docker build` command](https://docs.docker.com/reference/commandline/cli/#build):
|
||||
|
||||
docker build -t dhe.yourdomain.com/ci-infrastructure/jnkns-img .
|
||||
|
||||
> **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".
|
||||
|
||||
This command will build a new Docker image called `jnkns-img` which is based on
|
||||
the public Jenkins image you pulled earlier, but contains all of your
|
||||
customization.
|
||||
|
||||
Please note the use of the `-t` flag in the `docker build` command above. The
|
||||
`-t` flag lets you tag an image so it can be pushed to a custom repository. In
|
||||
the example above, the new image is tagged so it can be pushed to the
|
||||
`ci-infrastructure` Repository within the `dhe.yourdomain.com` registry (your
|
||||
local DHE instance). This will be important when you need to `push` the
|
||||
customized image to DHE later.
|
||||
|
||||
A `docker images` command will now show the custom image alongside the Jenkins
|
||||
image pulled earlier:
|
||||
|
||||
$ sudo docker images
|
||||
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
|
||||
dhe.yourdomain.com/ci-infrastructure/jnkns-img latest fc0ab3008d40 2 minutes ago 674.5 MB
|
||||
jenkins latest 1a7cc22b0ee9 6 days ago 662 MB
|
||||
|
||||
## Pushing to Docker Hub Enterprise
|
||||
|
||||
> **Note**: If your DHE instance has authentication enabled, you will need to
|
||||
> use your command line to `docker login <dhe-hostname>` (e.g., `docker login
|
||||
> dhe.yourdomain.com`).
|
||||
>
|
||||
> Failures due to unauthenticated `docker push` and `docker pull` commands will
|
||||
> look like :
|
||||
>
|
||||
> $ docker pull dhe.yourdomain.com/hello-world
|
||||
> Pulling repository dhe.yourdomain.com/hello-world
|
||||
> FATA[0001] Error: image hello-world:latest not found
|
||||
>
|
||||
> $ docker push dhe.yourdomain.com/hello-world
|
||||
> The push refers to a repository [dhe.yourdomain.com/hello-world] (len: 1)
|
||||
> e45a5af57b00: Image push failed
|
||||
> FATA[0001] Error pushing to registry: token auth attempt for registry
|
||||
> https://dhe.yourdomain.com/v2/:
|
||||
> https://dhe.yourdomain.com/auth/v2/token/
|
||||
> ?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
|
||||
[`docker push`command](https://docs.docker.com/reference/commandline/cli/#push):
|
||||
|
||||
$ docker push dhe.yourdomain.com/ci-infrastructure/jnkns-img
|
||||
511136ea3c5a: Image successfully pushed
|
||||
848d84b4b2ab: Image successfully pushed
|
||||
71d9d77ae89e: Image already exists
|
||||
<truncated ouput...>
|
||||
492ed3875e3e: Image successfully pushed
|
||||
fc0ab3008d40: Image successfully pushed
|
||||
|
||||
You can view the traffic throughput while the custom image is being pushed from
|
||||
the `System Health` tab in DHE:
|
||||
|
||||

|
||||
|
||||
Once the image is successfully pushed, it can be downloaded, or pulled, by any
|
||||
Docker host that has access to DHE.
|
||||
|
||||
## Pulling from Docker Hub Enterprise
|
||||
To pull the `jnkns-img` image from DHE, run the
|
||||
[`docker pull`](https://docs.docker.com/reference/commandline/cli/#pull)
|
||||
command from any Docker Host that has access to your DHE instance:
|
||||
|
||||
$ docker pull dhe.yourdomain.com/ci-infrastructure/jnkns-img
|
||||
latest: Pulling from dhe.yourdomain.com/ci-infrastructure/jnkns-img
|
||||
511136ea3c5a: Pull complete
|
||||
848d84b4b2ab: Pull complete
|
||||
71d9d77ae89e: Pull complete
|
||||
<truncated ouput...>
|
||||
492ed3875e3e: Pull complete
|
||||
fc0ab3008d40: Pull complete
|
||||
dhe.yourdomain.com/ci-infrastructure/jnkns-img:latest: The image you are pulling has been verified. Important: image verification is a tech preview feature and should not be relied on to provide security.
|
||||
Status: Downloaded newer image for dhe.yourdomain.com/ci-infrastructure/jnkns-img:latest
|
||||
|
||||
You can view the traffic throughput while the custom image is being pulled from
|
||||
the `System Health` tab in DHE:
|
||||
|
||||

|
||||
|
||||
Now that the `jnkns-img` image has been pulled locally from DHE, you can view it
|
||||
in the output of the `docker images` command:
|
||||
|
||||
$ docker images
|
||||
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
|
||||
dhe.yourdomain.com/ci-infrastructure/jnkns-img latest fc0ab3008d40 8 minutes ago 674.5 MB
|
||||
|
||||
## Launching a custom Jenkins container
|
||||
|
||||
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):
|
||||
|
||||
|
||||
$ docker run -p 1973:1973 --name jenkins01 dhe.yourdomain.com/ci-infrastructure/jnkns-img
|
||||
/usr/share/jenkins/ref/init.groovy.d/tcp-slave-angent-port.groovy
|
||||
/usr/share/jenkins/ref/init.groovy.d/tcp-slave-angent-port.groovy -> init.groovy.d/tcp-slave-angent-port.groovy
|
||||
copy init.groovy.d/tcp-slave-angent-port.groovy to JENKINS_HOME
|
||||
/usr/share/jenkins/ref/plugins/role-strategy.hpi
|
||||
/usr/share/jenkins/ref/plugins/role-strategy.hpi -> plugins/role-strategy.hpi
|
||||
copy plugins/role-strategy.hpi to JENKINS_HOME
|
||||
/usr/share/jenkins/ref/plugins/dockerhub.hpi
|
||||
/usr/share/jenkins/ref/plugins/dockerhub.hpi -> plugins/dockerhub.hpi
|
||||
copy plugins/dockerhub.hpi to JENKINS_HOME
|
||||
<truncated output...>
|
||||
INFO: Jenkins is fully up and running
|
||||
|
||||
> **Note:** The `docker run` command above maps port 1973 in the container
|
||||
> through to port 1973 on the host. This is the HTTPS port you specified in the
|
||||
> Dockerfile earlier. If you specified a different HTTPS port in your
|
||||
> Dockerfile, you will need to substitute this with the correct port numbers for
|
||||
> your environment.
|
||||
|
||||
You can view the newly launched a container, called `jenkins01`, using the
|
||||
[`docker ps` command](https://docs.docker.com/reference/commandline/cli/#ps):
|
||||
|
||||
$ docker ps
|
||||
CONTAINER ID IMAGE COMMAND CREATED STATUS ...PORTS NAMES
|
||||
2e5d2f068504 dhe.yourdomain.com/ci-infrastructure/jnkns-img:latest "/usr/local/bin/jenk About a minute ago Up About a minute 50000/tcp, 0.0.0.0:1973->1973/tcp jenkins01
|
||||
|
||||
|
||||
## Accessing the new Jenkins container
|
||||
|
||||
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`.)
|
||||
|
||||
> **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
|
||||
> not trusted. You may wish to add the certificate to the trusted store in order
|
||||
> to prevent further warnings in the future.
|
||||
|
||||

|
||||
|
||||
From within the Jenkins Web UI, navigate to `Manage Jenkins` (on the left-hand
|
||||
pane) > `Manage Plugins` > `Installed`. The `Role-based Authorization Strategy`
|
||||
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",
|
||||
showing that Jenkins is not available on its default port 8080 over HTTP.
|
||||
|
||||
This demonstration shows your Jenkins image has been configured correctly for
|
||||
HTTPS access, your new plugin was added and is ready for use, and HTTP access
|
||||
has been disabled. At this point, any member of your team can use `docker pull`
|
||||
to access the image from your DHE instance, allowing them to access a
|
||||
configured, secured Jenkins instance that can run on any infrastructure.
|
||||
|
||||
## Next Steps
|
||||
|
||||
For more information on using DHE, take a look at the
|
||||
[User's Guide](./userguide.md).
|
||||
@@ -1,241 +0,0 @@
|
||||
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
|
||||
|
||||
# Release Notes
|
||||
|
||||
## Docker Hub Enterprise
|
||||
|
||||
### DHE 1.0.1
|
||||
(11 May 2015)
|
||||
|
||||
- Addresses compatibility issue with 1.6.1 CS Docker Engine
|
||||
|
||||
### DHE 1.0.0
|
||||
(23 Apr 2015)
|
||||
|
||||
- First release
|
||||
|
||||
## Commercially Supported Docker Engine
|
||||
|
||||
### CS Docker Engine 1.6.2-cs5
|
||||
(21 May 2015)
|
||||
|
||||
For customers running Docker Engine on [supported versions of RedHat Enterprise
|
||||
Linux](https://www.docker.com/enterprise/support/) with [SELinux
|
||||
enabled](https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/
|
||||
6/html/Security-Enhanced_Linux/sect-Security-Enhanced_Linux-Working_with_SELinux
|
||||
-Enabling_and_Disabling_SELinux.html), the `docker build` and `docker run`
|
||||
commands will not have DNS host name resolution and bind-mounted volumes may
|
||||
not be accessible.
|
||||
As a result, customers with SELinux will be unable to use hostname-based network
|
||||
access in either `docker build` or `docker run`, nor will they be able to
|
||||
`docker run` containers
|
||||
that use `--volume` or `-v` bind-mounts (with an incorrect SELinux label) in
|
||||
their environment. By installing Docker
|
||||
Engine 1.6.2-cs5, customers can use Docker as intended on RHEL with SELinux enabled.
|
||||
|
||||
For example, you see will failures like:
|
||||
|
||||
```
|
||||
[root@dhe ~]# docker -v
|
||||
Docker version 1.6.0-cs2, build b8dd430
|
||||
[root@dhe ~]# ping dhe.home.org.au
|
||||
PING dhe.home.org.au (10.10.10.104) 56(84) bytes of data.
|
||||
64 bytes from dhe.home.gateway (10.10.10.104): icmp_seq=1 ttl=64 time=0.663 ms
|
||||
^C
|
||||
--- dhe.home.org.au ping statistics ---
|
||||
2 packets transmitted, 2 received, 0% packet loss, time 1001ms
|
||||
rtt min/avg/max/mdev = 0.078/0.370/0.663/0.293 ms
|
||||
[root@dhe ~]# docker run --rm -it debian ping dhe.home.org.au
|
||||
ping: unknown host
|
||||
[root@dhe ~]# docker run --rm -it debian cat /etc/resolv.conf
|
||||
cat: /etc/resolv.conf: Permission denied
|
||||
[root@dhe ~]# docker run --rm -it debian apt-get update
|
||||
Err http://httpredir.debian.org jessie InRelease
|
||||
|
||||
Err http://security.debian.org jessie/updates InRelease
|
||||
|
||||
Err http://httpredir.debian.org jessie-updates InRelease
|
||||
|
||||
Err http://security.debian.org jessie/updates Release.gpg
|
||||
Could not resolve 'security.debian.org'
|
||||
Err http://httpredir.debian.org jessie Release.gpg
|
||||
Could not resolve 'httpredir.debian.org'
|
||||
Err http://httpredir.debian.org jessie-updates Release.gpg
|
||||
Could not resolve 'httpredir.debian.org'
|
||||
[output truncated]
|
||||
|
||||
```
|
||||
|
||||
or when running a `docker build`:
|
||||
|
||||
```
|
||||
[root@dhe ~]# docker build .
|
||||
Sending build context to Docker daemon 11.26 kB
|
||||
Sending build context to Docker daemon
|
||||
Step 0 : FROM fedora
|
||||
---> e26efd418c48
|
||||
Step 1 : RUN yum install httpd
|
||||
---> Running in cf274900ea35
|
||||
|
||||
One of the configured repositories failed (Fedora 21 - x86_64),
|
||||
and yum doesn't have enough cached data to continue. At this point the only
|
||||
safe thing yum can do is fail. There are a few ways to work "fix" this:
|
||||
|
||||
[output truncated]
|
||||
```
|
||||
|
||||
|
||||
**Affected Versions**: All previous versions of Docker Engine when SELinux
|
||||
is enabled.
|
||||
|
||||
Docker **highly recommends** that all customers running previous versions of
|
||||
Docker Engine update to this release.
|
||||
|
||||
#### **How to workaround this issue**
|
||||
|
||||
Customers who choose not to install this update have two options. The
|
||||
first option is to disable SELinux. This is *not recommended* for production
|
||||
systems where SELinux is typically required.
|
||||
|
||||
The second option is to pass the following parameter in to `docker run`.
|
||||
|
||||
--security-opt=label:type:docker_t
|
||||
|
||||
This parameter cannot be passed to the `docker build` command.
|
||||
|
||||
#### **Upgrade notes**
|
||||
|
||||
When upgrading, make sure you stop DHE first, perform the Engine upgrade, and
|
||||
then restart DHE.
|
||||
|
||||
If you are running with SELinux enabled, previous Docker Engine releases allowed
|
||||
you to bind-mount additional volumes or files inside the container as follows:
|
||||
|
||||
$ docker run -it -v /home/user/foo.txt:/foobar.txt:ro <imagename>
|
||||
|
||||
In the 1.6.2-cs5 release, you must ensure additional bind-mounts have the correct
|
||||
SELinux context. For example, if you want to mount `foobar.txt` as read-only
|
||||
into the container, do the following to create and test your bind-mount:
|
||||
|
||||
1. Add the `z` option to the bind mount when you specify `docker run`.
|
||||
|
||||
$ docker run -it -v /home/user/foo.txt:/foobar.txt:ro,z <imagename>
|
||||
|
||||
2. Exec into your new container.
|
||||
|
||||
For example, if your container is `bashful_curie`, open a shell on the
|
||||
container:
|
||||
|
||||
$ docker exec -it bashful_curie bash
|
||||
|
||||
3. Use `cat` to check the permissions on the mounted file.
|
||||
|
||||
$ cat /foobar.txt
|
||||
the contents of foobar appear
|
||||
|
||||
If you see the file's contents, your mount succeeded. If you receive a
|
||||
`Permission denied` message and/or the `/var/log/audit/audit.log` file on
|
||||
your Docker host contains an AVC Denial message, the mount did not succeed.
|
||||
|
||||
type=AVC msg=audit(1432145409.197:7570): avc: denied { read } for pid=21167 comm="cat" name="foobar.txt" dev="xvda2" ino=17704136 scontext=system_u:system_r:svirt_lxc_net_t:s0:c909,c965 tcontext=unconfined_u:object_r:user_home_t:s0 tclass=file
|
||||
|
||||
Recheck your command line to make sure you passed in the `z` option.
|
||||
|
||||
|
||||
### CS Docker Engine 1.6.2-cs4
|
||||
(13 May 2015)
|
||||
|
||||
Fix mount regression for `/sys`.
|
||||
|
||||
### CS Docker Engine 1.6.1-cs3
|
||||
(11 May 2015)
|
||||
|
||||
Docker Engine version 1.6.1 has been released to address several vulnerabilities
|
||||
and is immediately available for all supported platforms. Users are advised to
|
||||
upgrade existing installations of the Docker Engine and use 1.6.1 for new installations.
|
||||
|
||||
It should be noted that each of the vulnerabilities allowing privilege escalation
|
||||
may only be exploited by a malicious Dockerfile or image. Users are advised to
|
||||
run their own images and/or images built by trusted parties, such as those in
|
||||
the official images library.
|
||||
|
||||
Please send any questions to security@docker.com.
|
||||
|
||||
|
||||
#### **[CVE-2015-3629](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2015-3629) Symlink traversal on container respawn allows local privilege escalation**
|
||||
|
||||
Libcontainer version 1.6.0 introduced changes which facilitated a mount namespace
|
||||
breakout upon respawn of a container. This allowed malicious images to write
|
||||
files to the host system and escape containerization.
|
||||
|
||||
Libcontainer and Docker Engine 1.6.1 have been released to address this
|
||||
vulnerability. Users running untrusted images are encouraged to upgrade Docker Engine.
|
||||
|
||||
Discovered by Tõnis Tiigi.
|
||||
|
||||
|
||||
#### **[CVE-2015-3627](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2015-3627) Insecure opening of file-descriptor 1 leading to privilege escalation**
|
||||
|
||||
The file-descriptor passed by libcontainer to the pid-1 process of a container
|
||||
has been found to be opened prior to performing the chroot, allowing insecure
|
||||
open and symlink traversal. This allows malicious container images to trigger
|
||||
a local privilege escalation.
|
||||
|
||||
Libcontainer and Docker Engine 1.6.1 have been released to address this
|
||||
vulnerability. Users running untrusted images are encouraged to upgrade
|
||||
Docker Engine.
|
||||
|
||||
Discovered by Tõnis Tiigi.
|
||||
|
||||
#### **[CVE-2015-3630](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2015-3630) Read/write proc paths allow host modification & information disclosure**
|
||||
|
||||
Several paths underneath /proc were writable from containers, allowing global
|
||||
system manipulation and configuration. These paths included `/proc/asound`,
|
||||
`/proc/timer_stats`, `/proc/latency_stats`, and `/proc/fs`.
|
||||
|
||||
By allowing writes to `/proc/fs`, it has been noted that CIFS volumes could be
|
||||
forced into a protocol downgrade attack by a root user operating inside of a
|
||||
container. Machines having loaded the timer_stats module were vulnerable to
|
||||
having this mechanism enabled and consumed by a container.
|
||||
|
||||
We are releasing Docker Engine 1.6.1 to address this vulnerability. All
|
||||
versions up to 1.6.1 are believed vulnerable. Users running untrusted
|
||||
images are encouraged to upgrade.
|
||||
|
||||
Discovered by Eric Windisch of the Docker Security Team.
|
||||
|
||||
#### **[CVE-2015-3631](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2015-3631) Volume mounts allow LSM profile escalation**
|
||||
|
||||
By allowing volumes to override files of `/proc` within a mount namespace, a user
|
||||
could specify arbitrary policies for Linux Security Modules, including setting
|
||||
an unconfined policy underneath AppArmor, or a `docker_t` policy for processes
|
||||
managed by SELinux. In all versions of Docker up until 1.6.1, it is possible for
|
||||
malicious images to configure volume mounts such that files of proc may be overridden.
|
||||
|
||||
We are releasing Docker Engine 1.6.1 to address this vulnerability. All versions
|
||||
up to 1.6.1 are believed vulnerable. Users running untrusted images are encouraged
|
||||
to upgrade.
|
||||
|
||||
Discovered by Eric Windisch of the Docker Security Team.
|
||||
|
||||
#### **AppArmor policy improvements**
|
||||
|
||||
The 1.6.1 release also marks preventative additions to the AppArmor policy.
|
||||
Recently, several CVEs against the kernel have been reported whereby mount
|
||||
namespaces could be circumvented through the use of the sys_mount syscall from
|
||||
inside of an unprivileged Docker container. In all reported cases, the
|
||||
AppArmor policy included in libcontainer and shipped with Docker has been
|
||||
sufficient to deflect these attacks. However, we have deemed it prudent to
|
||||
proactively tighten the policy further by outright denying the use of the
|
||||
`sys_mount` syscall.
|
||||
|
||||
Because this addition is preventative, no CVE-ID is requested.
|
||||
|
||||
### CS Docker Engine 1.6.0-cs2
|
||||
(23 Apr 2015)
|
||||
|
||||
- First release, please see the [Docker Engine 1.6.0 Release notes](/release-notes/)
|
||||
for more details.
|
||||
Executable
+20
@@ -0,0 +1,20 @@
|
||||
#!/bin/bash -e
|
||||
|
||||
|
||||
# Sed to process GitHub Markdown
|
||||
# 1-2 Remove comment code from metadata block
|
||||
#
|
||||
for i in ls -l /docs/content/*
|
||||
do # Line breaks are important
|
||||
if [ -d $i ] # Spaces are important
|
||||
then
|
||||
y=${i##*/}
|
||||
find $i -type f -name "*.md" -exec sed -i.old \
|
||||
-e '/^<!.*metadata]>/g' \
|
||||
-e '/^<!.*end-metadata.*>/g' {} \;
|
||||
fi
|
||||
done
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -15,7 +15,9 @@ parent = "smn_applied"
|
||||
Docker allows you to run applications inside containers. Running an
|
||||
application inside a container takes a single command: `docker run`.
|
||||
|
||||
{{ include "no-remote-sudo.md" }}
|
||||
> **Note:** if you are using a remote Docker daemon, such as Boot2Docker,
|
||||
> then _do not_ type the `sudo` before the `docker` commands shown in the
|
||||
> documentation's examples.
|
||||
|
||||
## Hello world
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
<!--[metadata]>
|
||||
+++
|
||||
draft = true
|
||||
title = "The Docker user guide"
|
||||
description = "The Docker user guide home page"
|
||||
keywords = ["docker, introduction, documentation, about, technology, docker.io, user, guide, user's, manual, platform, framework, virtualization, home, intro"]
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
<!--[metadata]>
|
||||
+++
|
||||
draft = true
|
||||
title = "Docker images test"
|
||||
description = "How to work with Docker images."
|
||||
keywords = ["documentation, docs, the docker guide, docker guide, docker, docker platform, virtualization framework, docker.io, Docker images, Docker image, image management, Docker repos, Docker repositories, docker, docker tag, docker tags, Docker Hub, collaboration"]
|
||||
[menu.main]
|
||||
parent = "identifier"
|
||||
+++
|
||||
<![end-metadata]-->
|
||||
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
<!--[metadata]>
|
||||
+++
|
||||
draft = true
|
||||
title = "Docker images test"
|
||||
description = "How to work with Docker images."
|
||||
keywords = ["documentation, docs, the docker guide, docker guide, docker, docker platform, virtualization framework, docker.io, Docker images, Docker image, image management, Docker repos, Docker repositories, docker, docker tag, docker tags, Docker Hub, collaboration"]
|
||||
[menu.main]
|
||||
parent = "identifier"
|
||||
+++
|
||||
<![end-metadata]-->
|
||||
|
||||
|
||||
@@ -5,9 +5,9 @@ Docker Engine.
|
||||
|
||||
This page is intended for people who want to develop their own Docker plugin.
|
||||
If you just want to learn about or use Docker plugins, look
|
||||
[here](/userguide/plugins).
|
||||
[here](/experimental/plugins.md).
|
||||
|
||||
This is an experimental feature. For information on installing and using experimental features, see [the experimental feature overview](experimental.md).
|
||||
This is an experimental feature. For information on installing and using experimental features, see [the experimental feature overview](README.md).
|
||||
|
||||
## What plugins are
|
||||
|
||||
|
||||
@@ -3,12 +3,12 @@
|
||||
You can extend the capabilities of the Docker Engine by loading third-party
|
||||
plugins.
|
||||
|
||||
This is an experimental feature. For information on installing and using experimental features, see [the experimental feature overview](experimental.md).
|
||||
This is an experimental feature. For information on installing and using experimental features, see [the experimental feature overview](README.md).
|
||||
|
||||
## Types of plugins
|
||||
|
||||
Plugins extend Docker's functionality. They come in specific types. For
|
||||
example, a [volume plugin](/experimental/plugins_volume) might enable Docker
|
||||
example, a [volume plugin](/experimental/plugins_volume.md) might enable Docker
|
||||
volumes to persist across multiple Docker hosts.
|
||||
|
||||
Currently Docker supports volume plugins. In the future it will support
|
||||
@@ -35,7 +35,7 @@ of the plugin for help. The Docker team may not be able to assist you.
|
||||
## Writing a plugin
|
||||
|
||||
If you are interested in writing a plugin for Docker, or seeing how they work
|
||||
under the hood, see the [docker plugins reference](/experimental/plugin_api).
|
||||
under the hood, see the [docker plugins reference](/experimental/plugin_api.md).
|
||||
|
||||
# Related GitHub PRs and issues
|
||||
|
||||
|
||||
@@ -2,10 +2,10 @@
|
||||
|
||||
Docker volume plugins enable Docker deployments to be integrated with external
|
||||
storage systems, such as Amazon EBS, and enable data volumes to persist beyond
|
||||
the lifetime of a single Docker host. See the [plugin documentation](/experimental/plugins)
|
||||
the lifetime of a single Docker host. See the [plugin documentation](/experimental/plugins.md)
|
||||
for more information.
|
||||
|
||||
This is an experimental feature. For information on installing and using experimental features, see [the experimental feature overview](experimental.md).
|
||||
This is an experimental feature. For information on installing and using experimental features, see [the experimental feature overview](README.md).
|
||||
|
||||
# Command-line changes
|
||||
|
||||
|
||||
+14
-6
@@ -29,9 +29,10 @@ import (
|
||||
|
||||
// A Graph is a store for versioned filesystem images and the relationship between them.
|
||||
type Graph struct {
|
||||
Root string
|
||||
idIndex *truncindex.TruncIndex
|
||||
driver graphdriver.Driver
|
||||
Root string
|
||||
idIndex *truncindex.TruncIndex
|
||||
driver graphdriver.Driver
|
||||
imageMutex imageMutex // protect images in driver.
|
||||
}
|
||||
|
||||
// NewGraph instantiates a new graph at the given root path in the filesystem.
|
||||
@@ -145,6 +146,15 @@ func (graph *Graph) Create(layerData archive.ArchiveReader, containerID, contain
|
||||
|
||||
// Register imports a pre-existing image into the graph.
|
||||
func (graph *Graph) Register(img *image.Image, layerData archive.ArchiveReader) (err error) {
|
||||
if err := image.ValidateID(img.ID); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// We need this entire operation to be atomic within the engine. Note that
|
||||
// this doesn't mean Register is fully safe yet.
|
||||
graph.imageMutex.Lock(img.ID)
|
||||
defer graph.imageMutex.Unlock(img.ID)
|
||||
|
||||
defer func() {
|
||||
// If any error occurs, remove the new dir from the driver.
|
||||
// Don't check for errors since the dir might not have been created.
|
||||
@@ -153,9 +163,7 @@ func (graph *Graph) Register(img *image.Image, layerData archive.ArchiveReader)
|
||||
graph.driver.Remove(img.ID)
|
||||
}
|
||||
}()
|
||||
if err := image.ValidateID(img.ID); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// (This is a convenience to save time. Race conditions are taken care of by os.Rename)
|
||||
if graph.Exists(img.ID) {
|
||||
return fmt.Errorf("Image %s already exists", img.ID)
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
package graph
|
||||
|
||||
import "sync"
|
||||
|
||||
// imageMutex provides a lock per image id to protect shared resources in the
|
||||
// graph. This is only used with registration but should be used when
|
||||
// manipulating the layer store.
|
||||
type imageMutex struct {
|
||||
mus map[string]*sync.Mutex // mutexes by image id.
|
||||
mu sync.Mutex // protects lock map
|
||||
|
||||
// NOTE(stevvooe): The map above will grow to the size of all images ever
|
||||
// registered during a daemon run. To free these resources, we must
|
||||
// deallocate after unlock. Doing this safely is non-trivial in the face
|
||||
// of a very minor leak.
|
||||
}
|
||||
|
||||
// Lock the provided id.
|
||||
func (im *imageMutex) Lock(id string) {
|
||||
im.getImageLock(id).Lock()
|
||||
}
|
||||
|
||||
// Unlock the provided id.
|
||||
func (im *imageMutex) Unlock(id string) {
|
||||
im.getImageLock(id).Unlock()
|
||||
}
|
||||
|
||||
// getImageLock returns the mutex for the given id. This method will never
|
||||
// return nil.
|
||||
func (im *imageMutex) getImageLock(id string) *sync.Mutex {
|
||||
im.mu.Lock()
|
||||
defer im.mu.Unlock()
|
||||
|
||||
if im.mus == nil { // lazy
|
||||
im.mus = make(map[string]*sync.Mutex)
|
||||
}
|
||||
|
||||
mu, ok := im.mus[id]
|
||||
if !ok {
|
||||
mu = new(sync.Mutex)
|
||||
im.mus[id] = mu
|
||||
}
|
||||
|
||||
return mu
|
||||
}
|
||||
+3
-3
@@ -55,9 +55,9 @@ 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 b116b5c0d20ee4021297fa92b7db4429a622c044
|
||||
clone git github.com/vishvananda/netns 5478c060110032f972e86a1f844fdb9a2f008f2c
|
||||
clone git github.com/vishvananda/netlink 8eb64238879fed52fd51c5b30ad20b928fb4c36c
|
||||
clone git github.com/docker/libnetwork 3daf67270570c1e07e3e3184d46a10f0c5d66f87
|
||||
clone git github.com/vishvananda/netns 493029407eeb434d0c2d44e02ea072ff2488d322
|
||||
clone git github.com/vishvananda/netlink 20397a138846e4d6590e01783ed023ed7e1c38a6
|
||||
|
||||
# get distribution packages
|
||||
clone git github.com/docker/distribution b9eeb328080d367dbde850ec6e94f1e4ac2b5efe
|
||||
|
||||
@@ -2,6 +2,7 @@ package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"net/http"
|
||||
"os/exec"
|
||||
"strings"
|
||||
"time"
|
||||
@@ -77,3 +78,24 @@ func (s *DockerSuite) TestGetContainersAttachWebsocket(c *check.C) {
|
||||
c.Fatal("Expected output on websocket to match input")
|
||||
}
|
||||
}
|
||||
|
||||
// regression gh14320
|
||||
func (s *DockerSuite) TestPostContainersAttachContainerNotFound(c *check.C) {
|
||||
status, body, err := sockRequest("POST", "/containers/doesnotexist/attach", nil)
|
||||
c.Assert(status, check.Equals, http.StatusNotFound)
|
||||
c.Assert(err, check.IsNil)
|
||||
expected := "no such id: doesnotexist\n"
|
||||
if !strings.Contains(string(body), expected) {
|
||||
c.Fatalf("Expected response body to contain %q", expected)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestGetContainersWsAttachContainerNotFound(c *check.C) {
|
||||
status, body, err := sockRequest("GET", "/containers/doesnotexist/attach/ws", nil)
|
||||
c.Assert(status, check.Equals, http.StatusNotFound)
|
||||
c.Assert(err, check.IsNil)
|
||||
expected := "no such id: doesnotexist\n"
|
||||
if !strings.Contains(string(body), expected) {
|
||||
c.Fatalf("Expected response body to contain %q", expected)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -998,6 +998,30 @@ func (s *DockerSuite) TestContainerApiVerifyHeader(c *check.C) {
|
||||
body.Close()
|
||||
}
|
||||
|
||||
//Issue 14230. daemon should return 500 for invalid port syntax
|
||||
func (s *DockerSuite) TestContainerApiInvalidPortSyntax(c *check.C) {
|
||||
config := `{
|
||||
"Image": "busybox",
|
||||
"HostConfig": {
|
||||
"PortBindings": {
|
||||
"19039;1230": [
|
||||
{}
|
||||
]
|
||||
}
|
||||
}
|
||||
}`
|
||||
|
||||
res, body, err := sockRequestRaw("POST", "/containers/create", strings.NewReader(config), "application/json")
|
||||
c.Assert(res.StatusCode, check.Equals, http.StatusInternalServerError)
|
||||
c.Assert(err, check.IsNil)
|
||||
|
||||
b, err := readBody(body)
|
||||
if err != nil {
|
||||
c.Fatal(err)
|
||||
}
|
||||
c.Assert(strings.Contains(string(b[:]), "Invalid port"), check.Equals, true)
|
||||
}
|
||||
|
||||
// Issue 7941 - test to make sure a "null" in JSON is just ignored.
|
||||
// W/o this fix a null in JSON would be parsed into a string var as "null"
|
||||
func (s *DockerSuite) TestContainerApiPostCreateNull(c *check.C) {
|
||||
@@ -1501,3 +1525,48 @@ func (s *DockerSuite) TestPostContainerStop(c *check.C) {
|
||||
c.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
// #14170
|
||||
func (s *DockerSuite) TestPostContainersCreateWithStringOrSliceEntrypoint(c *check.C) {
|
||||
config := struct {
|
||||
Image string
|
||||
Entrypoint string
|
||||
Cmd []string
|
||||
}{"busybox", "echo", []string{"hello", "world"}}
|
||||
_, _, err := sockRequest("POST", "/containers/create?name=echotest", config)
|
||||
c.Assert(err, check.IsNil)
|
||||
out, _ := dockerCmd(c, "start", "-a", "echotest")
|
||||
c.Assert(strings.TrimSpace(out), check.Equals, "hello world")
|
||||
|
||||
config2 := struct {
|
||||
Image string
|
||||
Entrypoint []string
|
||||
Cmd []string
|
||||
}{"busybox", []string{"echo"}, []string{"hello", "world"}}
|
||||
_, _, err = sockRequest("POST", "/containers/create?name=echotest2", config2)
|
||||
c.Assert(err, check.IsNil)
|
||||
out, _ = dockerCmd(c, "start", "-a", "echotest2")
|
||||
c.Assert(strings.TrimSpace(out), check.Equals, "hello world")
|
||||
}
|
||||
|
||||
// #14170
|
||||
func (s *DockerSuite) TestPostContainersCreateWithStringOrSliceCmd(c *check.C) {
|
||||
config := struct {
|
||||
Image string
|
||||
Entrypoint string
|
||||
Cmd string
|
||||
}{"busybox", "echo", "hello world"}
|
||||
_, _, err := sockRequest("POST", "/containers/create?name=echotest", config)
|
||||
c.Assert(err, check.IsNil)
|
||||
out, _ := dockerCmd(c, "start", "-a", "echotest")
|
||||
c.Assert(strings.TrimSpace(out), check.Equals, "hello world")
|
||||
|
||||
config2 := struct {
|
||||
Image string
|
||||
Cmd []string
|
||||
}{"busybox", []string{"echo", "hello", "world"}}
|
||||
_, _, err = sockRequest("POST", "/containers/create?name=echotest2", config2)
|
||||
c.Assert(err, check.IsNil)
|
||||
out, _ = dockerCmd(c, "start", "-a", "echotest2")
|
||||
c.Assert(strings.TrimSpace(out), check.Equals, "hello world")
|
||||
}
|
||||
|
||||
@@ -3,6 +3,8 @@ package main
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os/exec"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/docker/docker/api/types"
|
||||
@@ -33,3 +35,41 @@ func (s *DockerSuite) TestCliStatsNoStreamGetCpu(c *check.C) {
|
||||
c.Fatalf("docker stats with no-stream get cpu usage failed: was %v", cpuPercent)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestApiNetworkStats(c *check.C) {
|
||||
// Run container for 30 secs
|
||||
out, _ := dockerCmd(c, "run", "-d", "busybox", "top")
|
||||
id := strings.TrimSpace(out)
|
||||
err := waitRun(id)
|
||||
c.Assert(err, check.IsNil)
|
||||
|
||||
// Retrieve the container address
|
||||
contIP := findContainerIP(c, id)
|
||||
numPings := 10
|
||||
|
||||
// Get the container networking stats before and after pinging the container
|
||||
nwStatsPre := getNetworkStats(c, id)
|
||||
_, err = exec.Command("ping", contIP, "-c", strconv.Itoa(numPings)).Output()
|
||||
c.Assert(err, check.IsNil)
|
||||
nwStatsPost := getNetworkStats(c, id)
|
||||
|
||||
// Verify the stats contain at least the expected number of packets (account for ARP)
|
||||
expRxPkts := 1 + nwStatsPre.RxPackets + uint64(numPings)
|
||||
expTxPkts := 1 + nwStatsPre.TxPackets + uint64(numPings)
|
||||
c.Assert(nwStatsPost.TxPackets >= expTxPkts, check.Equals, true,
|
||||
check.Commentf("Reported less TxPackets than expected. Expected >= %d. Found %d", expTxPkts, nwStatsPost.TxPackets))
|
||||
c.Assert(nwStatsPost.RxPackets >= expRxPkts, check.Equals, true,
|
||||
check.Commentf("Reported less Txbytes than expected. Expected >= %d. Found %d", expRxPkts, nwStatsPost.RxPackets))
|
||||
}
|
||||
|
||||
func getNetworkStats(c *check.C, id string) types.Network {
|
||||
var st *types.Stats
|
||||
|
||||
_, body, err := sockRequestRaw("GET", fmt.Sprintf("/containers/%s/stats?stream=false", id), nil, "")
|
||||
c.Assert(err, check.IsNil)
|
||||
|
||||
err = json.NewDecoder(body).Decode(&st)
|
||||
c.Assert(err, check.IsNil)
|
||||
|
||||
return st.Network
|
||||
}
|
||||
|
||||
@@ -3,15 +3,18 @@ package main
|
||||
import (
|
||||
"net/http"
|
||||
"net/http/httputil"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/docker/docker/api"
|
||||
"github.com/go-check/check"
|
||||
)
|
||||
|
||||
func (s *DockerSuite) TestApiOptionsRoute(c *check.C) {
|
||||
status, _, err := sockRequest("OPTIONS", "/", nil)
|
||||
c.Assert(status, check.Equals, http.StatusOK)
|
||||
c.Assert(err, check.IsNil)
|
||||
c.Assert(status, check.Equals, http.StatusOK)
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestApiGetEnabledCors(c *check.C) {
|
||||
@@ -26,7 +29,7 @@ func (s *DockerSuite) TestApiGetEnabledCors(c *check.C) {
|
||||
//c.Assert(res.Header.Get("Access-Control-Allow-Headers"), check.Equals, "Origin, X-Requested-With, Content-Type, Accept, X-Registry-Auth")
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestVersionStatusCode(c *check.C) {
|
||||
func (s *DockerSuite) TestApiVersionStatusCode(c *check.C) {
|
||||
conn, err := sockConn(time.Duration(10 * time.Second))
|
||||
c.Assert(err, check.IsNil)
|
||||
|
||||
@@ -40,3 +43,31 @@ func (s *DockerSuite) TestVersionStatusCode(c *check.C) {
|
||||
res, err := client.Do(req)
|
||||
c.Assert(res.StatusCode, check.Equals, http.StatusBadRequest)
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestApiClientVersionNewerThanServer(c *check.C) {
|
||||
v := strings.Split(string(api.Version), ".")
|
||||
vMinInt, err := strconv.Atoi(v[1])
|
||||
c.Assert(err, check.IsNil)
|
||||
vMinInt++
|
||||
v[1] = strconv.Itoa(vMinInt)
|
||||
version := strings.Join(v, ".")
|
||||
|
||||
status, body, err := sockRequest("GET", "/v"+version+"/version", nil)
|
||||
c.Assert(err, check.IsNil)
|
||||
c.Assert(status, check.Equals, http.StatusBadRequest)
|
||||
c.Assert(len(string(body)), check.Not(check.Equals), 0) // Expected not empty body
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestApiClientVersionOldNotSupported(c *check.C) {
|
||||
v := strings.Split(string(api.MinVersion), ".")
|
||||
vMinInt, err := strconv.Atoi(v[1])
|
||||
c.Assert(err, check.IsNil)
|
||||
vMinInt--
|
||||
v[1] = strconv.Itoa(vMinInt)
|
||||
version := strings.Join(v, ".")
|
||||
|
||||
status, body, err := sockRequest("GET", "/v"+version+"/version", nil)
|
||||
c.Assert(err, check.IsNil)
|
||||
c.Assert(status, check.Equals, http.StatusBadRequest)
|
||||
c.Assert(len(string(body)), check.Not(check.Equals), 0) // Expected not empty body
|
||||
}
|
||||
|
||||
@@ -1207,7 +1207,12 @@ func (s *DockerDaemonSuite) TestRunContainerWithBridgeNone(c *check.C) {
|
||||
out, err := s.d.Cmd("run", "--rm", "busybox", "ip", "l")
|
||||
c.Assert(err, check.IsNil, check.Commentf("Output: %s", out))
|
||||
c.Assert(strings.Contains(out, "eth0"), check.Equals, false,
|
||||
check.Commentf("There shouldn't be eth0 in container when network is disabled: %s", out))
|
||||
check.Commentf("There shouldn't be eth0 in container in default(bridge) mode when bridge network is disabled: %s", out))
|
||||
|
||||
out, err = s.d.Cmd("run", "--rm", "--net=host", "busybox", "ip", "l")
|
||||
c.Assert(err, check.IsNil, check.Commentf("Output: %s", out))
|
||||
c.Assert(strings.Contains(out, "eth0"), check.Equals, true,
|
||||
check.Commentf("There should be eth0 in container when --net=host when bridge network is disabled: %s", out))
|
||||
}
|
||||
|
||||
func (s *DockerDaemonSuite) TestDaemonRestartWithContainerRunning(t *check.C) {
|
||||
|
||||
@@ -444,7 +444,6 @@ func (s *DockerSuite) TestInspectExecID(c *check.C) {
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestLinksPingLinkedContainersOnRename(c *check.C) {
|
||||
|
||||
var out string
|
||||
out, _ = dockerCmd(c, "run", "-d", "--name", "container1", "busybox", "top")
|
||||
idA := strings.TrimSpace(out)
|
||||
@@ -609,7 +608,6 @@ func (s *DockerSuite) TestRunMutableNetworkFiles(c *check.C) {
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestExecWithUser(c *check.C) {
|
||||
|
||||
runCmd := exec.Command(dockerBinary, "run", "-d", "--name", "parent", "busybox", "top")
|
||||
if out, _, err := runCommandWithOutput(runCmd); err != nil {
|
||||
c.Fatal(out, err)
|
||||
@@ -634,3 +632,22 @@ func (s *DockerSuite) TestExecWithUser(c *check.C) {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestExecWithImageUser(c *check.C) {
|
||||
name := "testbuilduser"
|
||||
_, err := buildImage(name,
|
||||
`FROM busybox
|
||||
RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
|
||||
USER dockerio`,
|
||||
true)
|
||||
if err != nil {
|
||||
c.Fatalf("Could not build image %s: %v", name, err)
|
||||
}
|
||||
|
||||
dockerCmd(c, "run", "-d", "--name", "dockerioexec", name, "top")
|
||||
|
||||
out, _ := dockerCmd(c, "exec", "dockerioexec", "whoami")
|
||||
if !strings.Contains(out, "dockerio") {
|
||||
c.Fatalf("exec with user by id expected dockerio user got %s", out)
|
||||
}
|
||||
}
|
||||
|
||||
+3
-3
@@ -154,9 +154,9 @@ func NewSession(client *http.Client, authConfig *cliconfig.AuthConfig, endpoint
|
||||
}
|
||||
}
|
||||
|
||||
if endpoint.Version == APIVersion1 {
|
||||
client.Transport = AuthTransport(client.Transport, authConfig, alwaysSetBasicAuth)
|
||||
}
|
||||
// Annotate the transport unconditionally so that v2 can
|
||||
// properly fallback on v1 when an image is not found.
|
||||
client.Transport = AuthTransport(client.Transport, authConfig, alwaysSetBasicAuth)
|
||||
|
||||
jar, err := cookiejar.New(nil)
|
||||
if err != nil {
|
||||
|
||||
+10
-2
@@ -32,7 +32,11 @@ func (e *Entrypoint) UnmarshalJSON(b []byte) error {
|
||||
|
||||
p := make([]string, 0, 1)
|
||||
if err := json.Unmarshal(b, &p); err != nil {
|
||||
p = append(p, string(b))
|
||||
var s string
|
||||
if err := json.Unmarshal(b, &s); err != nil {
|
||||
return err
|
||||
}
|
||||
p = append(p, s)
|
||||
}
|
||||
e.parts = p
|
||||
return nil
|
||||
@@ -79,7 +83,11 @@ func (e *Command) UnmarshalJSON(b []byte) error {
|
||||
|
||||
p := make([]string, 0, 1)
|
||||
if err := json.Unmarshal(b, &p); err != nil {
|
||||
p = append(p, string(b))
|
||||
var s string
|
||||
if err := json.Unmarshal(b, &s); err != nil {
|
||||
return err
|
||||
}
|
||||
p = append(p, s)
|
||||
}
|
||||
e.parts = p
|
||||
return nil
|
||||
|
||||
@@ -2,6 +2,7 @@ package runconfig
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"strings"
|
||||
@@ -299,3 +300,83 @@ func TestDecodeContainerConfig(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestEntrypointUnmarshalString(t *testing.T) {
|
||||
var e *Entrypoint
|
||||
echo, err := json.Marshal("echo")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := json.Unmarshal(echo, &e); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
slice := e.Slice()
|
||||
if len(slice) != 1 {
|
||||
t.Fatalf("expected 1 element after unmarshal: %q", slice)
|
||||
}
|
||||
|
||||
if slice[0] != "echo" {
|
||||
t.Fatalf("expected `echo`, got: %q", slice[0])
|
||||
}
|
||||
}
|
||||
|
||||
func TestEntrypointUnmarshalSlice(t *testing.T) {
|
||||
var e *Entrypoint
|
||||
echo, err := json.Marshal([]string{"echo"})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := json.Unmarshal(echo, &e); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
slice := e.Slice()
|
||||
if len(slice) != 1 {
|
||||
t.Fatalf("expected 1 element after unmarshal: %q", slice)
|
||||
}
|
||||
|
||||
if slice[0] != "echo" {
|
||||
t.Fatalf("expected `echo`, got: %q", slice[0])
|
||||
}
|
||||
}
|
||||
|
||||
func TestCommandUnmarshalSlice(t *testing.T) {
|
||||
var e *Command
|
||||
echo, err := json.Marshal([]string{"echo"})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := json.Unmarshal(echo, &e); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
slice := e.Slice()
|
||||
if len(slice) != 1 {
|
||||
t.Fatalf("expected 1 element after unmarshal: %q", slice)
|
||||
}
|
||||
|
||||
if slice[0] != "echo" {
|
||||
t.Fatalf("expected `echo`, got: %q", slice[0])
|
||||
}
|
||||
}
|
||||
|
||||
func TestCommandUnmarshalString(t *testing.T) {
|
||||
var e *Command
|
||||
echo, err := json.Marshal("echo")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := json.Unmarshal(echo, &e); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
slice := e.Slice()
|
||||
if len(slice) != 1 {
|
||||
t.Fatalf("expected 1 element after unmarshal: %q", slice)
|
||||
}
|
||||
|
||||
if slice[0] != "echo" {
|
||||
t.Fatalf("expected `echo`, got: %q", slice[0])
|
||||
}
|
||||
}
|
||||
|
||||
+8
-3
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"ImportPath": "github.com/docker/libnetwork",
|
||||
"GoVersion": "go1.4.1",
|
||||
"GoVersion": "go1.4.2",
|
||||
"Packages": [
|
||||
"./..."
|
||||
],
|
||||
@@ -55,6 +55,11 @@
|
||||
"Comment": "v1.4.1-3479-ga9172f5",
|
||||
"Rev": "a9172f572e13086859c652e2d581950e910d63d4"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/docker/libcontainer/netlink",
|
||||
"Comment": "v1.4.0-495-g3e66118",
|
||||
"Rev": "3e661186ba24f259d3860f067df052c7f6904bee"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/docker/libcontainer/user",
|
||||
"Comment": "v1.4.0-495-g3e66118",
|
||||
@@ -75,11 +80,11 @@
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/vishvananda/netlink",
|
||||
"Rev": "8eb64238879fed52fd51c5b30ad20b928fb4c36c"
|
||||
"Rev": "20397a138846e4d6590e01783ed023ed7e1c38a6"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/vishvananda/netns",
|
||||
"Rev": "5478c060110032f972e86a1f844fdb9a2f008f2c"
|
||||
"Rev": "493029407eeb434d0c2d44e02ea072ff2488d322"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -2,12 +2,14 @@ package bridge
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"os/exec"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
bri "github.com/docker/libcontainer/netlink"
|
||||
"github.com/docker/libnetwork/driverapi"
|
||||
"github.com/docker/libnetwork/ipallocator"
|
||||
"github.com/docker/libnetwork/iptables"
|
||||
@@ -397,6 +399,20 @@ func (d *driver) DeleteNetwork(nid types.UUID) error {
|
||||
return err
|
||||
}
|
||||
|
||||
func addToBridge(ifaceName, bridgeName string) error {
|
||||
iface, err := net.InterfaceByName(ifaceName)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not find interface %s: %v", ifaceName, err)
|
||||
}
|
||||
|
||||
master, err := net.InterfaceByName(bridgeName)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not find bridge %s: %v", bridgeName, err)
|
||||
}
|
||||
|
||||
return bri.AddToBridge(iface, master)
|
||||
}
|
||||
|
||||
func (d *driver) CreateEndpoint(nid, eid types.UUID, epInfo driverapi.EndpointInfo, epOptions map[string]interface{}) error {
|
||||
var (
|
||||
ipv6Addr *net.IPNet
|
||||
@@ -461,27 +477,27 @@ func (d *driver) CreateEndpoint(nid, eid types.UUID, epInfo driverapi.EndpointIn
|
||||
}()
|
||||
|
||||
// Generate a name for what will be the host side pipe interface
|
||||
name1, err := generateIfaceName()
|
||||
hostIfName, err := generateIfaceName()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Generate a name for what will be the sandbox side pipe interface
|
||||
name2, err := generateIfaceName()
|
||||
containerIfName, err := generateIfaceName()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Generate and add the interface pipe host <-> sandbox
|
||||
veth := &netlink.Veth{
|
||||
LinkAttrs: netlink.LinkAttrs{Name: name1, TxQLen: 0},
|
||||
PeerName: name2}
|
||||
LinkAttrs: netlink.LinkAttrs{Name: hostIfName, TxQLen: 0},
|
||||
PeerName: containerIfName}
|
||||
if err = netlink.LinkAdd(veth); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Get the host side pipe interface handler
|
||||
host, err := netlink.LinkByName(name1)
|
||||
host, err := netlink.LinkByName(hostIfName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -492,7 +508,7 @@ func (d *driver) CreateEndpoint(nid, eid types.UUID, epInfo driverapi.EndpointIn
|
||||
}()
|
||||
|
||||
// Get the sandbox side pipe interface handler
|
||||
sbox, err := netlink.LinkByName(name2)
|
||||
sbox, err := netlink.LinkByName(containerIfName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -515,9 +531,8 @@ func (d *driver) CreateEndpoint(nid, eid types.UUID, epInfo driverapi.EndpointIn
|
||||
}
|
||||
|
||||
// Attach host side pipe interface into the bridge
|
||||
if err = netlink.LinkSetMaster(host,
|
||||
&netlink.Bridge{LinkAttrs: netlink.LinkAttrs{Name: config.BridgeName}}); err != nil {
|
||||
return err
|
||||
if err = addToBridge(hostIfName, config.BridgeName); err != nil {
|
||||
return fmt.Errorf("adding interface %s to bridge %s failed: %v", hostIfName, config.BridgeName, err)
|
||||
}
|
||||
|
||||
if !config.EnableUserlandProxy {
|
||||
@@ -534,14 +549,24 @@ func (d *driver) CreateEndpoint(nid, eid types.UUID, epInfo driverapi.EndpointIn
|
||||
}
|
||||
ipv4Addr := &net.IPNet{IP: ip4, Mask: n.bridge.bridgeIPv4.Mask}
|
||||
|
||||
// Down the interface before configuring mac address.
|
||||
if err := netlink.LinkSetDown(sbox); err != nil {
|
||||
return fmt.Errorf("could not set link down for container interface %s: %v", containerIfName, err)
|
||||
}
|
||||
|
||||
// Set the sbox's MAC. If specified, use the one configured by user, otherwise generate one based on IP.
|
||||
mac := electMacAddress(epConfig, ip4)
|
||||
err = netlink.LinkSetHardwareAddr(sbox, mac)
|
||||
if err != nil {
|
||||
return err
|
||||
return fmt.Errorf("could not set mac address for container interface %s: %v", containerIfName, err)
|
||||
}
|
||||
endpoint.macAddress = mac
|
||||
|
||||
// Up the host interface after finishing all netlink configuration
|
||||
if err := netlink.LinkSetUp(host); err != nil {
|
||||
return fmt.Errorf("could not set link up for host interface %s: %v", hostIfName, err)
|
||||
}
|
||||
|
||||
// v6 address for the sandbox side pipe interface
|
||||
ipv6Addr = &net.IPNet{}
|
||||
if config.EnableIPv6 {
|
||||
@@ -571,7 +596,7 @@ func (d *driver) CreateEndpoint(nid, eid types.UUID, epInfo driverapi.EndpointIn
|
||||
|
||||
// Create the sandbox side pipe interface
|
||||
intf := &sandbox.Interface{}
|
||||
intf.SrcName = name2
|
||||
intf.SrcName = containerIfName
|
||||
intf.DstName = containerVethPrefix
|
||||
intf.Address = ipv4Addr
|
||||
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
package bridge
|
||||
|
||||
import (
|
||||
log "github.com/Sirupsen/logrus"
|
||||
"github.com/docker/docker/pkg/parsers/kernel"
|
||||
"github.com/docker/libnetwork/netutils"
|
||||
bri "github.com/docker/libcontainer/netlink"
|
||||
"github.com/vishvananda/netlink"
|
||||
)
|
||||
|
||||
// SetupDevice create a new bridge interface/
|
||||
func setupDevice(config *NetworkConfiguration, i *bridgeInterface) error {
|
||||
var setMac bool
|
||||
|
||||
// We only attempt to create the bridge when the requested device name is
|
||||
// the default one.
|
||||
if config.BridgeName != DefaultBridgeName && !config.AllowNonDefaultBridge {
|
||||
@@ -26,12 +27,10 @@ func setupDevice(config *NetworkConfiguration, i *bridgeInterface) error {
|
||||
// was not supported before that.
|
||||
kv, err := kernel.GetKernelVersion()
|
||||
if err == nil && (kv.Kernel >= 3 && kv.Major >= 3) {
|
||||
i.Link.Attrs().HardwareAddr = netutils.GenerateRandomMAC()
|
||||
log.Debugf("Setting bridge mac address to %s", i.Link.Attrs().HardwareAddr)
|
||||
setMac = true
|
||||
}
|
||||
|
||||
// Call out to netlink to create the device.
|
||||
return netlink.LinkAdd(i.Link)
|
||||
return bri.CreateBridge(config.BridgeName, setMac)
|
||||
}
|
||||
|
||||
// SetupDeviceUp ups the given bridge interface.
|
||||
|
||||
@@ -40,7 +40,11 @@ func (d *driver) EndpointOperInfo(nid, eid types.UUID) (map[string]interface{},
|
||||
|
||||
// Join method is invoked when a Sandbox is attached to an endpoint.
|
||||
func (d *driver) Join(nid, eid types.UUID, sboxKey string, jinfo driverapi.JoinInfo, options map[string]interface{}) error {
|
||||
return (jinfo.SetHostsPath("/etc/hosts"))
|
||||
if err := jinfo.SetHostsPath("/etc/hosts"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return jinfo.SetResolvConfPath("/etc/resolv.conf")
|
||||
}
|
||||
|
||||
// Leave method is invoked when a Sandbox detaches from an endpoint.
|
||||
|
||||
@@ -2,6 +2,7 @@ package libnetwork
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path"
|
||||
@@ -45,6 +46,9 @@ type Endpoint interface {
|
||||
|
||||
// Delete and detaches this endpoint from the network.
|
||||
Delete() error
|
||||
|
||||
// Retrieve the interfaces' statistics from the sandbox
|
||||
Statistics() (map[string]*sandbox.InterfaceStatistics, error)
|
||||
}
|
||||
|
||||
// EndpointOption is a option setter function type used to pass varios options to Network
|
||||
@@ -402,6 +406,33 @@ func (ep *endpoint) Delete() error {
|
||||
return err
|
||||
}
|
||||
|
||||
func (ep *endpoint) Statistics() (map[string]*sandbox.InterfaceStatistics, error) {
|
||||
m := make(map[string]*sandbox.InterfaceStatistics)
|
||||
|
||||
ep.Lock()
|
||||
n := ep.network
|
||||
skey := ep.container.data.SandboxKey
|
||||
ep.Unlock()
|
||||
|
||||
n.Lock()
|
||||
c := n.ctrlr
|
||||
n.Unlock()
|
||||
|
||||
sbox := c.sandboxGet(skey)
|
||||
if sbox == nil {
|
||||
return m, nil
|
||||
}
|
||||
|
||||
var err error
|
||||
for _, i := range sbox.Interfaces() {
|
||||
if m[i.DstName], err = i.Statistics(); err != nil {
|
||||
return m, err
|
||||
}
|
||||
}
|
||||
|
||||
return m, nil
|
||||
}
|
||||
|
||||
func (ep *endpoint) buildHostsFiles() error {
|
||||
var extraContent []etchosts.Record
|
||||
|
||||
@@ -567,9 +598,19 @@ func (ep *endpoint) updateDNS(resolvConf []byte) error {
|
||||
return os.Rename(tmpResolvFile.Name(), container.config.resolvConfPath)
|
||||
}
|
||||
|
||||
func copyFile(src, dst string) error {
|
||||
sBytes, err := ioutil.ReadFile(src)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return ioutil.WriteFile(dst, sBytes, 0644)
|
||||
}
|
||||
|
||||
func (ep *endpoint) setupDNS() error {
|
||||
ep.Lock()
|
||||
container := ep.container
|
||||
joinInfo := ep.joinInfo
|
||||
ep.Unlock()
|
||||
|
||||
if container == nil {
|
||||
@@ -586,6 +627,14 @@ func (ep *endpoint) setupDNS() error {
|
||||
return err
|
||||
}
|
||||
|
||||
if joinInfo.resolvConfPath != "" {
|
||||
if err := copyFile(joinInfo.resolvConfPath, container.config.resolvConfPath); err != nil {
|
||||
return fmt.Errorf("could not copy source resolv.conf file %s to %s: %v", joinInfo.resolvConfPath, container.config.resolvConfPath, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
resolvConf, err := resolvconf.Get()
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@@ -817,6 +817,15 @@ func TestEndpointJoin(t *testing.T) {
|
||||
t.Fatalf("Expected an non-empty sandbox key for a joined endpoint. Instead found a empty sandbox key")
|
||||
}
|
||||
|
||||
// Attempt retrieval of endpoint interfaces statistics
|
||||
stats, err := ep.Statistics()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, ok := stats["eth0"]; !ok {
|
||||
t.Fatalf("Did not find eth0 statistics")
|
||||
}
|
||||
|
||||
checkSandbox(t, info)
|
||||
}
|
||||
|
||||
@@ -1119,6 +1128,74 @@ func TestEnableIPv6(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestResolvConfHost(t *testing.T) {
|
||||
if !netutils.IsRunningInContainer() {
|
||||
defer netutils.SetupTestNetNS(t)()
|
||||
}
|
||||
|
||||
tmpResolvConf := []byte("search localhost.net\nnameserver 127.0.0.1\nnameserver 2001:4860:4860::8888")
|
||||
|
||||
//take a copy of resolv.conf for restoring after test completes
|
||||
resolvConfSystem, err := ioutil.ReadFile("/etc/resolv.conf")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
//cleanup
|
||||
defer func() {
|
||||
if err := ioutil.WriteFile("/etc/resolv.conf", resolvConfSystem, 0644); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}()
|
||||
|
||||
n, err := createTestNetwork("host", "testnetwork", options.Generic{}, options.Generic{})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
ep1, err := n.CreateEndpoint("ep1", nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if err := ioutil.WriteFile("/etc/resolv.conf", tmpResolvConf, 0644); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
resolvConfPath := "/tmp/libnetwork_test/resolv.conf"
|
||||
defer os.Remove(resolvConfPath)
|
||||
|
||||
_, err = ep1.Join(containerID,
|
||||
libnetwork.JoinOptionResolvConfPath(resolvConfPath))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer func() {
|
||||
err = ep1.Leave(containerID)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}()
|
||||
|
||||
finfo, err := os.Stat(resolvConfPath)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
fmode := (os.FileMode)(0644)
|
||||
if finfo.Mode() != fmode {
|
||||
t.Fatalf("Expected file mode %s, got %s", fmode.String(), finfo.Mode().String())
|
||||
}
|
||||
|
||||
content, err := ioutil.ReadFile(resolvConfPath)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if !bytes.Equal(content, tmpResolvConf) {
|
||||
t.Fatalf("Expected %s, Got %s", string(tmpResolvConf), string(content))
|
||||
}
|
||||
}
|
||||
|
||||
func TestResolvConf(t *testing.T) {
|
||||
if !netutils.IsRunningInContainer() {
|
||||
defer netutils.SetupTestNetNS(t)()
|
||||
|
||||
@@ -276,6 +276,7 @@ func (n *networkNamespace) AddInterface(i *Interface) error {
|
||||
n.Lock()
|
||||
i.DstName = fmt.Sprintf("%s%d", i.DstName, n.nextIfIndex)
|
||||
n.nextIfIndex++
|
||||
path := n.path
|
||||
n.Unlock()
|
||||
|
||||
runtime.LockOSThread()
|
||||
@@ -287,9 +288,9 @@ func (n *networkNamespace) AddInterface(i *Interface) error {
|
||||
}
|
||||
defer origns.Close()
|
||||
|
||||
f, err := os.OpenFile(n.path, os.O_RDONLY, 0)
|
||||
f, err := os.OpenFile(path, os.O_RDONLY, 0)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed get network namespace %q: %v", n.path, err)
|
||||
return fmt.Errorf("failed get network namespace %q: %v", path, err)
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
@@ -325,6 +326,8 @@ func (n *networkNamespace) AddInterface(i *Interface) error {
|
||||
return err
|
||||
}
|
||||
|
||||
i.sandboxKey = path
|
||||
|
||||
n.Lock()
|
||||
n.sinfo.Interfaces = append(n.sinfo.Interfaces, i)
|
||||
n.Unlock()
|
||||
|
||||
@@ -1,9 +1,15 @@
|
||||
package sandbox
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
"os/exec"
|
||||
"regexp"
|
||||
"runtime"
|
||||
|
||||
"github.com/docker/libnetwork/types"
|
||||
"github.com/vishvananda/netns"
|
||||
)
|
||||
|
||||
// Sandbox represents a network sandbox, identified by a specific key. It
|
||||
@@ -74,6 +80,9 @@ type Interface struct {
|
||||
|
||||
// IPv6 address for the interface.
|
||||
AddressIPv6 *net.IPNet
|
||||
|
||||
// Parent sandbox's key
|
||||
sandboxKey string
|
||||
}
|
||||
|
||||
// GetCopy returns a copy of this Interface structure
|
||||
@@ -157,3 +166,95 @@ func (s *Info) Equal(o *Info) bool {
|
||||
return true
|
||||
|
||||
}
|
||||
|
||||
func nsInvoke(path string, inNsfunc func(callerFD int) error) error {
|
||||
runtime.LockOSThread()
|
||||
defer runtime.UnlockOSThread()
|
||||
|
||||
origns, err := netns.Get()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer origns.Close()
|
||||
|
||||
f, err := os.OpenFile(path, os.O_RDONLY, 0)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed get network namespace %q: %v", path, err)
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
nsFD := f.Fd()
|
||||
|
||||
if err = netns.Set(netns.NsHandle(nsFD)); err != nil {
|
||||
return err
|
||||
}
|
||||
defer netns.Set(origns)
|
||||
|
||||
// Invoked after the namespace switch.
|
||||
return inNsfunc(int(origns))
|
||||
}
|
||||
|
||||
// Statistics returns the statistics for this interface
|
||||
func (i *Interface) Statistics() (*InterfaceStatistics, error) {
|
||||
|
||||
s := &InterfaceStatistics{}
|
||||
|
||||
err := nsInvoke(i.sandboxKey, func(callerFD int) error {
|
||||
// For some reason ioutil.ReadFile(netStatsFile) reads the file in
|
||||
// the default netns when this code is invoked from docker.
|
||||
// Executing "cat <netStatsFile>" works as expected.
|
||||
data, err := exec.Command("cat", netStatsFile).Output()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to open %s: %v", netStatsFile, err)
|
||||
}
|
||||
return scanInterfaceStats(string(data), i.DstName, s)
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
err = fmt.Errorf("failed to retrieve the statistics for %s in netns %s: %v", i.DstName, i.sandboxKey, err)
|
||||
}
|
||||
|
||||
return s, err
|
||||
}
|
||||
|
||||
// InterfaceStatistics represents the interface's statistics
|
||||
type InterfaceStatistics struct {
|
||||
RxBytes uint64
|
||||
RxPackets uint64
|
||||
RxErrors uint64
|
||||
RxDropped uint64
|
||||
TxBytes uint64
|
||||
TxPackets uint64
|
||||
TxErrors uint64
|
||||
TxDropped uint64
|
||||
}
|
||||
|
||||
func (is *InterfaceStatistics) String() string {
|
||||
return fmt.Sprintf("\nRxBytes: %d, RxPackets: %d, RxErrors: %d, RxDropped: %d, TxBytes: %d, TxPackets: %d, TxErrors: %d, TxDropped: %d",
|
||||
is.RxBytes, is.RxPackets, is.RxErrors, is.RxDropped, is.TxBytes, is.TxPackets, is.TxErrors, is.TxDropped)
|
||||
}
|
||||
|
||||
// In older kernels (like the one in Centos 6.6 distro) sysctl does not have netns support. Therefore
|
||||
// we cannot gather the statistics from /sys/class/net/<dev>/statistics/<counter> files. Per-netns stats
|
||||
// are naturally found in /proc/net/dev in kernels which support netns (ifconfig relyes on that).
|
||||
const (
|
||||
netStatsFile = "/proc/net/dev"
|
||||
base = "[ ]*%s:([ ]+[0-9]+){16}"
|
||||
)
|
||||
|
||||
func scanInterfaceStats(data, ifName string, i *InterfaceStatistics) error {
|
||||
var (
|
||||
bktStr string
|
||||
bkt uint64
|
||||
)
|
||||
|
||||
regex := fmt.Sprintf(base, ifName)
|
||||
re := regexp.MustCompile(regex)
|
||||
line := re.FindString(data)
|
||||
|
||||
_, err := fmt.Sscanf(line, "%s %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d",
|
||||
&bktStr, &i.RxBytes, &i.RxPackets, &i.RxErrors, &i.RxDropped, &bkt, &bkt, &bkt,
|
||||
&bkt, &i.TxBytes, &i.TxPackets, &i.TxErrors, &i.TxDropped, &bkt, &bkt, &bkt, &bkt)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -157,3 +157,29 @@ func verifyCleanup(t *testing.T, s Sandbox, wait bool) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestScanStatistics(t *testing.T) {
|
||||
data :=
|
||||
"Inter-| Receive | Transmit\n" +
|
||||
" face |bytes packets errs drop fifo frame compressed multicast|bytes packets errs drop fifo colls carrier compressed\n" +
|
||||
" eth0: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n" +
|
||||
" wlan0: 7787685 11141 0 0 0 0 0 0 1681390 7220 0 0 0 0 0 0\n" +
|
||||
" lo: 783782 1853 0 0 0 0 0 0 783782 1853 0 0 0 0 0 0\n" +
|
||||
"lxcbr0: 0 0 0 0 0 0 0 0 9006 61 0 0 0 0 0 0\n"
|
||||
|
||||
i := &InterfaceStatistics{}
|
||||
|
||||
if err := scanInterfaceStats(data, "wlan0", i); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if i.TxBytes != 1681390 || i.TxPackets != 7220 || i.RxBytes != 7787685 || i.RxPackets != 11141 {
|
||||
t.Fatalf("Error scanning the statistics")
|
||||
}
|
||||
|
||||
if err := scanInterfaceStats(data, "lxcbr0", i); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if i.TxBytes != 9006 || i.TxPackets != 61 || i.RxBytes != 0 || i.RxPackets != 0 {
|
||||
t.Fatalf("Error scanning the statistics")
|
||||
}
|
||||
}
|
||||
|
||||
+7
-1
@@ -43,13 +43,19 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
mybridge := &netlink.Bridge{netlink.LinkAttrs{Name: "foo"}}
|
||||
la := netlink.NewLinkAttrs()
|
||||
la.Name = "foo"
|
||||
mybridge := &netlink.Bridge{la}}
|
||||
_ := netlink.LinkAdd(mybridge)
|
||||
eth1, _ := netlink.LinkByName("eth1")
|
||||
netlink.LinkSetMaster(eth1, mybridge)
|
||||
}
|
||||
|
||||
```
|
||||
Note `NewLinkAttrs` constructor, it sets default values in structure. For now
|
||||
it sets only `TxQLen` to `-1`, so kernel will set default by itself. If you're
|
||||
using simple initialization(`LinkAttrs{Name: "foo"}`) `TxQLen` will be set to
|
||||
`0` unless you specify it like `LinkAttrs{Name: "foo", TxQLen: 1000}`.
|
||||
|
||||
Add a new ip address to loopback:
|
||||
|
||||
|
||||
+2
-2
@@ -14,8 +14,8 @@ type Addr struct {
|
||||
}
|
||||
|
||||
// String returns $ip/$netmask $label
|
||||
func (addr Addr) String() string {
|
||||
return fmt.Sprintf("%s %s", addr.IPNet, addr.Label)
|
||||
func (a Addr) String() string {
|
||||
return fmt.Sprintf("%s %s", a.IPNet, a.Label)
|
||||
}
|
||||
|
||||
// ParseAddr parses the string representation of an address in the
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user