mirror of
https://github.com/clearlinux/docker.git
synced 2026-08-20 20:56:42 +00:00
Compare commits
2 Commits
v1.7.0
..
v1.7.0-rc1
| Author | SHA1 | Date | |
|---|---|---|---|
| 395ccedc9b | |||
| 22a6d71919 |
@@ -30,8 +30,5 @@ docs/_build
|
||||
docs/_static
|
||||
docs/_templates
|
||||
docs/changed-files
|
||||
# generated by man/man/md2man-all.sh
|
||||
man/man1
|
||||
man/man5
|
||||
pyenv
|
||||
vendor/pkg/
|
||||
|
||||
+3
-1
@@ -4,6 +4,8 @@
|
||||
|
||||
#### Runtime
|
||||
+ Experimental feature: support for out-of-process volume plugins
|
||||
+ Experimental feature: support for out-of-process network plugins
|
||||
* Logging: syslog logging driver is available
|
||||
* The userland proxy can be disabled in favor of hairpin NAT using the daemon’s `--userland-proxy=false` flag
|
||||
* The `exec` command supports the `-u|--user` flag to specify the new process owner
|
||||
+ Default gateway for containers can be specified daemon-wide using the `--default-gateway` and `--default-gateway-v6` flags
|
||||
@@ -15,7 +17,7 @@
|
||||
|
||||
#### Quality
|
||||
* Networking stack was entirely rewritten as part of the libnetwork effort
|
||||
* Engine internals refactoring
|
||||
* Engine internals refactoring (shout out to the contributors?)
|
||||
* Volumes code was entirely rewritten to support the plugins effort
|
||||
+ Sending SIGUSR1 to a daemon will dump all goroutines stacks without exiting
|
||||
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@ Want to hack on Docker? Awesome! We have a contributor's guide that explains
|
||||
[setting up a Docker development environment and the contribution
|
||||
process](https://docs.docker.com/project/who-written-for/).
|
||||
|
||||

|
||||

|
||||
|
||||
This page contains information about reporting issues as well as some tips and
|
||||
guidelines useful to experienced open source contributors. Finally, make sure
|
||||
|
||||
@@ -22,6 +22,11 @@ DOCKER_ENVS := \
|
||||
BIND_DIR := $(if $(BINDDIR),$(BINDDIR),$(if $(DOCKER_HOST),,bundles))
|
||||
DOCKER_MOUNT := $(if $(BIND_DIR),-v "$(CURDIR)/$(BIND_DIR):/go/src/github.com/docker/docker/$(BIND_DIR)")
|
||||
|
||||
# to allow `make DOCSDIR=docs docs-shell` (to create a bind mount in docs)
|
||||
DOCS_MOUNT := $(if $(DOCSDIR),-v $(CURDIR)/$(DOCSDIR):/$(DOCSDIR))
|
||||
|
||||
# to allow `make DOCSPORT=9000 docs`
|
||||
DOCSPORT := 8000
|
||||
|
||||
GIT_BRANCH := $(shell git rev-parse --abbrev-ref HEAD 2>/dev/null)
|
||||
DOCKER_IMAGE := docker-dev$(if $(GIT_BRANCH),:$(GIT_BRANCH))
|
||||
@@ -45,6 +50,19 @@ binary: build
|
||||
cross: build
|
||||
$(DOCKER_RUN_DOCKER) hack/make.sh binary cross
|
||||
|
||||
docs: docs-build
|
||||
$(DOCKER_RUN_DOCS) -p $(if $(DOCSPORT),$(DOCSPORT):)8000 "$(DOCKER_DOCS_IMAGE)" mkdocs serve
|
||||
|
||||
docs-shell: docs-build
|
||||
$(DOCKER_RUN_DOCS) -p $(if $(DOCSPORT),$(DOCSPORT):)8000 "$(DOCKER_DOCS_IMAGE)" bash
|
||||
|
||||
docs-release: docs-build
|
||||
$(DOCKER_RUN_DOCS) -e OPTIONS -e BUILD_ROOT -e DISTRIBUTION_ID \
|
||||
-v $(CURDIR)/docs/awsconfig:/docs/awsconfig \
|
||||
"$(DOCKER_DOCS_IMAGE)" ./release.sh
|
||||
|
||||
docs-test: docs-build
|
||||
$(DOCKER_RUN_DOCS) "$(DOCKER_DOCS_IMAGE)" ./test.sh
|
||||
|
||||
test: build
|
||||
$(DOCKER_RUN_DOCKER) hack/make.sh binary cross test-unit test-integration-cli test-docker-py
|
||||
@@ -67,5 +85,13 @@ shell: build
|
||||
build: bundles
|
||||
docker build -t "$(DOCKER_IMAGE)" .
|
||||
|
||||
docs-build:
|
||||
cp ./VERSION docs/VERSION
|
||||
echo "$(GIT_BRANCH)" > docs/GIT_BRANCH
|
||||
# echo "$(AWS_S3_BUCKET)" > docs/AWS_S3_BUCKET
|
||||
echo "$(GITCOMMIT)" > docs/GITCOMMIT
|
||||
docker pull docs/base
|
||||
docker build -t "$(DOCKER_DOCS_IMAGE)" docs
|
||||
|
||||
bundles:
|
||||
mkdir bundles
|
||||
|
||||
@@ -18,7 +18,7 @@ It benefits directly from the experience accumulated over several years
|
||||
of large-scale operation and support of hundreds of thousands of
|
||||
applications and databases.
|
||||
|
||||

|
||||

|
||||
|
||||
## Security Disclosure
|
||||
|
||||
@@ -30,7 +30,7 @@ security@docker.com and not by creating a github issue.
|
||||
|
||||
A common method for distributing applications and sandboxing their
|
||||
execution is to use virtual machines, or VMs. Typical VM formats are
|
||||
VMware's vmdk, Oracle Virtualbox's vdi, and Amazon EC2's ami. In theory
|
||||
VMWare's vmdk, Oracle Virtualbox's vdi, and Amazon EC2's ami. In theory
|
||||
these formats should allow every developer to automatically package
|
||||
their application into a "machine" for easy distribution and deployment.
|
||||
In practice, that almost never happens, for a few reasons:
|
||||
@@ -180,7 +180,7 @@ Contributing to Docker
|
||||
======================
|
||||
|
||||
[](https://godoc.org/github.com/docker/docker)
|
||||
[](https://jenkins.dockerproject.org/job/Docker%20Master/)
|
||||
[](https://jenkins.dockerproject.com/job/Docker%20Master/)
|
||||
|
||||
Want to hack on Docker? Awesome! We have [instructions to help you get
|
||||
started contributing code or documentation.](https://docs.docker.com/project/who-written-for/).
|
||||
@@ -192,12 +192,12 @@ Getting the development builds
|
||||
==============================
|
||||
|
||||
Want to run Docker from a master build? You can download
|
||||
master builds at [master.dockerproject.org](https://master.dockerproject.org).
|
||||
master builds at [master.dockerproject.com](https://master.dockerproject.com).
|
||||
They are updated with each commit merged into the master branch.
|
||||
|
||||
Don't know how to use that super cool new feature in the master build? Check
|
||||
out the master docs at
|
||||
[docs.master.dockerproject.org](http://docs.master.dockerproject.org).
|
||||
[docs.master.dockerproject.com](http://docs.master.dockerproject.com).
|
||||
|
||||
How the project is run
|
||||
======================
|
||||
|
||||
+9
-9
@@ -7,6 +7,7 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"strings"
|
||||
@@ -96,7 +97,7 @@ func (cli *DockerCli) Cmd(args ...string) error {
|
||||
if len(args) > 0 {
|
||||
method, exists := cli.getMethod(args[0])
|
||||
if !exists {
|
||||
return fmt.Errorf("docker: '%s' is not a docker command.\nSee 'docker --help'.", args[0])
|
||||
return fmt.Errorf("docker: '%s' is not a docker command. See 'docker --help'.", args[0])
|
||||
}
|
||||
return method(args[1:]...)
|
||||
}
|
||||
@@ -116,19 +117,18 @@ func (cli *DockerCli) Subcmd(name, signature, description string, exitOnError bo
|
||||
errorHandling = flag.ContinueOnError
|
||||
}
|
||||
flags := flag.NewFlagSet(name, errorHandling)
|
||||
if signature != "" {
|
||||
signature = " " + signature
|
||||
}
|
||||
flags.Usage = func() {
|
||||
flags.ShortUsage()
|
||||
flags.PrintDefaults()
|
||||
}
|
||||
flags.ShortUsage = func() {
|
||||
options := ""
|
||||
if signature != "" {
|
||||
signature = " " + signature
|
||||
}
|
||||
if flags.FlagCountUndeprecated() > 0 {
|
||||
options = " [OPTIONS]"
|
||||
}
|
||||
fmt.Fprintf(flags.Out(), "\nUsage: docker %s%s%s\n\n%s\n", name, options, signature, description)
|
||||
fmt.Fprintf(cli.out, "\nUsage: docker %s%s%s\n\n%s\n\n", name, options, signature, description)
|
||||
flags.SetOutput(cli.out)
|
||||
flags.PrintDefaults()
|
||||
os.Exit(0)
|
||||
}
|
||||
return flags
|
||||
}
|
||||
|
||||
@@ -145,7 +145,6 @@ func (cli *DockerCli) CmdCreate(args ...string) error {
|
||||
config, hostConfig, cmd, err := runconfig.Parse(cmd, args)
|
||||
if err != nil {
|
||||
cmd.ReportError(err.Error(), true)
|
||||
os.Exit(1)
|
||||
}
|
||||
if config.Image == "" {
|
||||
cmd.Usage()
|
||||
|
||||
+17
-12
@@ -5,7 +5,6 @@ import (
|
||||
"fmt"
|
||||
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/pkg/ioutils"
|
||||
flag "github.com/docker/docker/pkg/mflag"
|
||||
"github.com/docker/docker/pkg/units"
|
||||
)
|
||||
@@ -16,7 +15,7 @@ import (
|
||||
func (cli *DockerCli) CmdInfo(args ...string) error {
|
||||
cmd := cli.Subcmd("info", "", "Display system-wide information", true)
|
||||
cmd.Require(flag.Exact, 0)
|
||||
cmd.ParseFlags(args, true)
|
||||
cmd.ParseFlags(args, false)
|
||||
|
||||
rdr, _, err := cli.call("GET", "/info", nil, nil)
|
||||
if err != nil {
|
||||
@@ -30,20 +29,20 @@ func (cli *DockerCli) CmdInfo(args ...string) error {
|
||||
|
||||
fmt.Fprintf(cli.out, "Containers: %d\n", info.Containers)
|
||||
fmt.Fprintf(cli.out, "Images: %d\n", info.Images)
|
||||
ioutils.FprintfIfNotEmpty(cli.out, "Storage Driver: %s\n", info.Driver)
|
||||
fmt.Fprintf(cli.out, "Storage Driver: %s\n", info.Driver)
|
||||
if info.DriverStatus != nil {
|
||||
for _, pair := range info.DriverStatus {
|
||||
fmt.Fprintf(cli.out, " %s: %s\n", pair[0], pair[1])
|
||||
}
|
||||
}
|
||||
ioutils.FprintfIfNotEmpty(cli.out, "Execution Driver: %s\n", info.ExecutionDriver)
|
||||
ioutils.FprintfIfNotEmpty(cli.out, "Logging Driver: %s\n", info.LoggingDriver)
|
||||
ioutils.FprintfIfNotEmpty(cli.out, "Kernel Version: %s\n", info.KernelVersion)
|
||||
ioutils.FprintfIfNotEmpty(cli.out, "Operating System: %s\n", info.OperatingSystem)
|
||||
fmt.Fprintf(cli.out, "Execution Driver: %s\n", info.ExecutionDriver)
|
||||
fmt.Fprintf(cli.out, "Logging Driver: %s\n", info.LoggingDriver)
|
||||
fmt.Fprintf(cli.out, "Kernel Version: %s\n", info.KernelVersion)
|
||||
fmt.Fprintf(cli.out, "Operating System: %s\n", info.OperatingSystem)
|
||||
fmt.Fprintf(cli.out, "CPUs: %d\n", info.NCPU)
|
||||
fmt.Fprintf(cli.out, "Total Memory: %s\n", units.BytesSize(float64(info.MemTotal)))
|
||||
ioutils.FprintfIfNotEmpty(cli.out, "Name: %s\n", info.Name)
|
||||
ioutils.FprintfIfNotEmpty(cli.out, "ID: %s\n", info.ID)
|
||||
fmt.Fprintf(cli.out, "Name: %s\n", info.Name)
|
||||
fmt.Fprintf(cli.out, "ID: %s\n", info.ID)
|
||||
|
||||
if info.Debug {
|
||||
fmt.Fprintf(cli.out, "Debug mode (server): %v\n", info.Debug)
|
||||
@@ -56,9 +55,15 @@ func (cli *DockerCli) CmdInfo(args ...string) error {
|
||||
fmt.Fprintf(cli.out, "Docker Root Dir: %s\n", info.DockerRootDir)
|
||||
}
|
||||
|
||||
ioutils.FprintfIfNotEmpty(cli.out, "Http Proxy: %s\n", info.HttpProxy)
|
||||
ioutils.FprintfIfNotEmpty(cli.out, "Https Proxy: %s\n", info.HttpsProxy)
|
||||
ioutils.FprintfIfNotEmpty(cli.out, "No Proxy: %s\n", info.NoProxy)
|
||||
if info.HttpProxy != "" {
|
||||
fmt.Fprintf(cli.out, "Http Proxy: %s\n", info.HttpProxy)
|
||||
}
|
||||
if info.HttpsProxy != "" {
|
||||
fmt.Fprintf(cli.out, "Https Proxy: %s\n", info.HttpsProxy)
|
||||
}
|
||||
if info.NoProxy != "" {
|
||||
fmt.Fprintf(cli.out, "No Proxy: %s\n", info.NoProxy)
|
||||
}
|
||||
|
||||
if info.IndexServerAddress != "" {
|
||||
u := cli.configFile.AuthConfigs[info.IndexServerAddress].Username
|
||||
|
||||
@@ -16,7 +16,7 @@ func (cli *DockerCli) CmdLogout(args ...string) error {
|
||||
cmd := cli.Subcmd("logout", "[SERVER]", "Log out from a Docker registry, if no server is\nspecified \""+registry.IndexServerAddress()+"\" is the default.", true)
|
||||
cmd.Require(flag.Max, 1)
|
||||
|
||||
cmd.ParseFlags(args, true)
|
||||
cmd.ParseFlags(args, false)
|
||||
serverAddress := registry.IndexServerAddress()
|
||||
if len(cmd.Args()) > 0 {
|
||||
serverAddress = cmd.Arg(0)
|
||||
|
||||
+1
-1
@@ -12,7 +12,7 @@ import (
|
||||
func (cli *DockerCli) CmdPause(args ...string) error {
|
||||
cmd := cli.Subcmd("pause", "CONTAINER [CONTAINER...]", "Pause all processes within a container", true)
|
||||
cmd.Require(flag.Min, 1)
|
||||
cmd.ParseFlags(args, true)
|
||||
cmd.ParseFlags(args, false)
|
||||
|
||||
var errNames []string
|
||||
for _, name := range cmd.Args() {
|
||||
|
||||
@@ -57,7 +57,6 @@ func (cli *DockerCli) CmdRun(args ...string) error {
|
||||
// just in case the Parse does not exit
|
||||
if err != nil {
|
||||
cmd.ReportError(err.Error(), true)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if len(hostConfig.Dns) > 0 {
|
||||
|
||||
+8
-4
@@ -46,6 +46,7 @@ func (s *containerStats) Collect(cli *DockerCli, streamStats bool) {
|
||||
var (
|
||||
previousCPU uint64
|
||||
previousSystem uint64
|
||||
start = true
|
||||
dec = json.NewDecoder(stream)
|
||||
u = make(chan error, 1)
|
||||
)
|
||||
@@ -60,9 +61,10 @@ func (s *containerStats) Collect(cli *DockerCli, streamStats bool) {
|
||||
memPercent = float64(v.MemoryStats.Usage) / float64(v.MemoryStats.Limit) * 100.0
|
||||
cpuPercent = 0.0
|
||||
)
|
||||
previousCPU = v.PreCpuStats.CpuUsage.TotalUsage
|
||||
previousSystem = v.PreCpuStats.SystemUsage
|
||||
cpuPercent = calculateCPUPercent(previousCPU, previousSystem, v)
|
||||
if !start {
|
||||
cpuPercent = calculateCPUPercent(previousCPU, previousSystem, v)
|
||||
}
|
||||
start = false
|
||||
s.mu.Lock()
|
||||
s.CPUPercentage = cpuPercent
|
||||
s.Memory = float64(v.MemoryStats.Usage)
|
||||
@@ -71,6 +73,8 @@ func (s *containerStats) Collect(cli *DockerCli, streamStats bool) {
|
||||
s.NetworkRx = float64(v.Network.RxBytes)
|
||||
s.NetworkTx = float64(v.Network.TxBytes)
|
||||
s.mu.Unlock()
|
||||
previousCPU = v.CpuStats.CpuUsage.TotalUsage
|
||||
previousSystem = v.CpuStats.SystemUsage
|
||||
u <- nil
|
||||
if !streamStats {
|
||||
return
|
||||
@@ -147,7 +151,7 @@ func (cli *DockerCli) CmdStats(args ...string) error {
|
||||
}
|
||||
// do a quick pause so that any failed connections for containers that do not exist are able to be
|
||||
// evicted before we display the initial or default values.
|
||||
time.Sleep(1500 * time.Millisecond)
|
||||
time.Sleep(500 * time.Millisecond)
|
||||
var errs []string
|
||||
for _, c := range cStats {
|
||||
c.mu.Lock()
|
||||
|
||||
@@ -12,7 +12,7 @@ import (
|
||||
func (cli *DockerCli) CmdUnpause(args ...string) error {
|
||||
cmd := cli.Subcmd("unpause", "CONTAINER [CONTAINER...]", "Unpause all processes within a container", true)
|
||||
cmd.Require(flag.Min, 1)
|
||||
cmd.ParseFlags(args, true)
|
||||
cmd.ParseFlags(args, false)
|
||||
|
||||
var errNames []string
|
||||
for _, name := range cmd.Args() {
|
||||
|
||||
@@ -9,7 +9,6 @@ import (
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/autogen/dockerversion"
|
||||
flag "github.com/docker/docker/pkg/mflag"
|
||||
"github.com/docker/docker/utils"
|
||||
)
|
||||
|
||||
// CmdVersion shows Docker version information.
|
||||
@@ -21,7 +20,7 @@ func (cli *DockerCli) CmdVersion(args ...string) error {
|
||||
cmd := cli.Subcmd("version", "", "Show the Docker version information.", true)
|
||||
cmd.Require(flag.Exact, 0)
|
||||
|
||||
cmd.ParseFlags(args, true)
|
||||
cmd.ParseFlags(args, false)
|
||||
|
||||
if dockerversion.VERSION != "" {
|
||||
fmt.Fprintf(cli.out, "Client version: %s\n", dockerversion.VERSION)
|
||||
@@ -32,9 +31,6 @@ func (cli *DockerCli) CmdVersion(args ...string) error {
|
||||
fmt.Fprintf(cli.out, "Git commit (client): %s\n", dockerversion.GITCOMMIT)
|
||||
}
|
||||
fmt.Fprintf(cli.out, "OS/Arch (client): %s/%s\n", runtime.GOOS, runtime.GOARCH)
|
||||
if utils.ExperimentalBuild() {
|
||||
fmt.Fprintf(cli.out, "Experimental (client): true\n")
|
||||
}
|
||||
|
||||
stream, _, err := cli.call("GET", "/version", nil, nil)
|
||||
if err != nil {
|
||||
@@ -54,8 +50,6 @@ func (cli *DockerCli) CmdVersion(args ...string) error {
|
||||
fmt.Fprintf(cli.out, "Go version (server): %s\n", v.GoVersion)
|
||||
fmt.Fprintf(cli.out, "Git commit (server): %s\n", v.GitCommit)
|
||||
fmt.Fprintf(cli.out, "OS/Arch (server): %s/%s\n", v.Os, v.Arch)
|
||||
if v.Experimental {
|
||||
fmt.Fprintf(cli.out, "Experimental (server): true\n")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -11,15 +11,6 @@ func boolValue(r *http.Request, k string) bool {
|
||||
return !(s == "" || s == "0" || s == "no" || s == "false" || s == "none")
|
||||
}
|
||||
|
||||
// boolValueOrDefault returns the default bool passed if the query param is
|
||||
// missing, otherwise it's just a proxy to boolValue above
|
||||
func boolValueOrDefault(r *http.Request, k string, d bool) bool {
|
||||
if _, ok := r.Form[k]; !ok {
|
||||
return d
|
||||
}
|
||||
return boolValue(r, k)
|
||||
}
|
||||
|
||||
func int64ValueOrZero(r *http.Request, k string) int64 {
|
||||
val, err := strconv.ParseInt(r.FormValue(k), 10, 64)
|
||||
if err != nil {
|
||||
|
||||
@@ -33,21 +33,6 @@ func TestBoolValue(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestBoolValueOrDefault(t *testing.T) {
|
||||
r, _ := http.NewRequest("GET", "", nil)
|
||||
if !boolValueOrDefault(r, "queryparam", true) {
|
||||
t.Fatal("Expected to get true default value, got false")
|
||||
}
|
||||
|
||||
v := url.Values{}
|
||||
v.Set("param", "")
|
||||
r, _ = http.NewRequest("GET", "", nil)
|
||||
r.Form = v
|
||||
if boolValueOrDefault(r, "param", true) {
|
||||
t.Fatal("Expected not to get true")
|
||||
}
|
||||
}
|
||||
|
||||
func TestInt64ValueOrZero(t *testing.T) {
|
||||
cases := map[string]int64{
|
||||
"": 0,
|
||||
|
||||
+44
-56
@@ -36,6 +36,7 @@ import (
|
||||
"github.com/docker/docker/pkg/version"
|
||||
"github.com/docker/docker/runconfig"
|
||||
"github.com/docker/docker/utils"
|
||||
"github.com/docker/libnetwork/portallocator"
|
||||
)
|
||||
|
||||
type ServerConfig struct {
|
||||
@@ -96,17 +97,15 @@ func (s *Server) ServeApi(protoAddrs []string) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
s.servers = append(s.servers, srv...)
|
||||
s.servers = append(s.servers, srv)
|
||||
|
||||
for _, s := range srv {
|
||||
logrus.Infof("Listening for HTTP on %s (%s)", protoAddrParts[0], protoAddrParts[1])
|
||||
go func(s serverCloser) {
|
||||
if err := s.Serve(); err != nil && strings.Contains(err.Error(), "use of closed network connection") {
|
||||
err = nil
|
||||
}
|
||||
chErrors <- err
|
||||
}(s)
|
||||
}
|
||||
go func(proto, addr string) {
|
||||
logrus.Infof("Listening for HTTP on %s (%s)", proto, addr)
|
||||
if err := srv.Serve(); err != nil && strings.Contains(err.Error(), "use of closed network connection") {
|
||||
err = nil
|
||||
}
|
||||
chErrors <- err
|
||||
}(protoAddrParts[0], protoAddrParts[1])
|
||||
}
|
||||
|
||||
for i := 0; i < len(protoAddrs); i++ {
|
||||
@@ -253,11 +252,6 @@ func (s *Server) getVersion(version version.Version, w http.ResponseWriter, r *h
|
||||
Os: runtime.GOOS,
|
||||
Arch: runtime.GOARCH,
|
||||
}
|
||||
|
||||
if version.GreaterThanOrEqualTo("1.19") {
|
||||
v.Experimental = utils.ExperimentalBuild()
|
||||
}
|
||||
|
||||
if kernelVersion, err := kernel.GetKernelVersion(); err == nil {
|
||||
v.KernelVersion = kernelVersion.String()
|
||||
}
|
||||
@@ -277,20 +271,14 @@ func (s *Server) postContainersKill(version version.Version, w http.ResponseWrit
|
||||
name := vars["name"]
|
||||
|
||||
// If we have a signal, look at it. Otherwise, do nothing
|
||||
if sigStr := r.Form.Get("signal"); sigStr != "" {
|
||||
if sigStr := vars["signal"]; sigStr != "" {
|
||||
// Check if we passed the signal as a number:
|
||||
// The largest legal signal is 31, so let's parse on 5 bits
|
||||
sigN, err := strconv.ParseUint(sigStr, 10, 5)
|
||||
sig, err := strconv.ParseUint(sigStr, 10, 5)
|
||||
if err != nil {
|
||||
// The signal is not a number, treat it as a string (either like
|
||||
// "KILL" or like "SIGKILL")
|
||||
syscallSig, ok := signal.SignalMap[strings.TrimPrefix(sigStr, "SIG")]
|
||||
if !ok {
|
||||
return fmt.Errorf("Invalid signal: %s", sigStr)
|
||||
}
|
||||
sig = uint64(syscallSig)
|
||||
} else {
|
||||
sig = sigN
|
||||
sig = uint64(signal.SignalMap[strings.TrimPrefix(sigStr, "SIG")])
|
||||
}
|
||||
|
||||
if sig == 0 {
|
||||
@@ -398,7 +386,6 @@ func (s *Server) getEvents(version version.Version, w http.ResponseWriter, r *ht
|
||||
}
|
||||
until = u
|
||||
}
|
||||
|
||||
timer := time.NewTimer(0)
|
||||
timer.Stop()
|
||||
if until > 0 {
|
||||
@@ -457,9 +444,6 @@ func (s *Server) getEvents(version version.Version, w http.ResponseWriter, r *ht
|
||||
}
|
||||
|
||||
current, l := es.Subscribe()
|
||||
if since == -1 {
|
||||
current = nil
|
||||
}
|
||||
defer es.Evict(l)
|
||||
for _, ev := range current {
|
||||
if ev.Time < since {
|
||||
@@ -469,12 +453,6 @@ func (s *Server) getEvents(version version.Version, w http.ResponseWriter, r *ht
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
var closeNotify <-chan bool
|
||||
if closeNotifier, ok := w.(http.CloseNotifier); ok {
|
||||
closeNotify = closeNotifier.CloseNotify()
|
||||
}
|
||||
|
||||
for {
|
||||
select {
|
||||
case ev := <-l:
|
||||
@@ -487,9 +465,6 @@ func (s *Server) getEvents(version version.Version, w http.ResponseWriter, r *ht
|
||||
}
|
||||
case <-timer.C:
|
||||
return nil
|
||||
case <-closeNotify:
|
||||
logrus.Debug("Client disconnected, stop sending events")
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -575,16 +550,7 @@ func (s *Server) getContainersStats(version version.Version, w http.ResponseWrit
|
||||
return fmt.Errorf("Missing parameter")
|
||||
}
|
||||
|
||||
stream := boolValueOrDefault(r, "stream", true)
|
||||
var out io.Writer
|
||||
if !stream {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
out = w
|
||||
} else {
|
||||
out = ioutils.NewWriteFlusher(w)
|
||||
}
|
||||
|
||||
return s.daemon.ContainerStats(vars["name"], stream, out)
|
||||
return s.daemon.ContainerStats(vars["name"], boolValue(r, "stream"), ioutils.NewWriteFlusher(w))
|
||||
}
|
||||
|
||||
func (s *Server) getContainersLogs(version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||
@@ -668,6 +634,10 @@ func (s *Server) postCommit(version version.Version, w http.ResponseWriter, r *h
|
||||
return err
|
||||
}
|
||||
|
||||
if c == nil {
|
||||
c = &runconfig.Config{}
|
||||
}
|
||||
|
||||
containerCommitConfig := &daemon.ContainerCommitConfig{
|
||||
Pause: pause,
|
||||
Repo: r.Form.Get("repo"),
|
||||
@@ -903,7 +873,6 @@ func (s *Server) postContainersCreate(version version.Version, w http.ResponseWr
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
adjustCpuShares(version, hostConfig)
|
||||
|
||||
containerId, warnings, err := s.daemon.ContainerCreate(name, config, hostConfig)
|
||||
if err != nil {
|
||||
@@ -1164,14 +1133,6 @@ func (s *Server) getContainersByName(version version.Version, w http.ResponseWri
|
||||
return fmt.Errorf("Missing parameter")
|
||||
}
|
||||
|
||||
if version.LessThan("1.19") {
|
||||
containerJSONRaw, err := s.daemon.ContainerInspectRaw(vars["name"])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return writeJSON(w, http.StatusOK, containerJSONRaw)
|
||||
}
|
||||
|
||||
containerJSON, err := s.daemon.ContainerInspect(vars["name"])
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -1585,3 +1546,30 @@ func createRouter(s *Server) *mux.Router {
|
||||
|
||||
return r
|
||||
}
|
||||
|
||||
func allocateDaemonPort(addr string) error {
|
||||
host, port, err := net.SplitHostPort(addr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
intPort, err := strconv.Atoi(port)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var hostIPs []net.IP
|
||||
if parsedIP := net.ParseIP(host); parsedIP != nil {
|
||||
hostIPs = append(hostIPs, parsedIP)
|
||||
} else if hostIPs, err = net.LookupIP(host); err != nil {
|
||||
return fmt.Errorf("failed to lookup %s address in host specification", host)
|
||||
}
|
||||
|
||||
pa := portallocator.Get()
|
||||
for _, hostIP := range hostIPs {
|
||||
if _, err := pa.RequestPort(hostIP, "tcp", intPort); err != nil {
|
||||
return fmt.Errorf("failed to allocate daemon listening port %d (err: %v)", intPort, err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
+29
-73
@@ -6,65 +6,63 @@ import (
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
"github.com/docker/docker/daemon"
|
||||
"github.com/docker/docker/pkg/sockets"
|
||||
"github.com/docker/docker/pkg/systemd"
|
||||
"github.com/docker/docker/pkg/version"
|
||||
"github.com/docker/docker/runconfig"
|
||||
"github.com/docker/libnetwork/portallocator"
|
||||
)
|
||||
|
||||
const (
|
||||
// See http://git.kernel.org/cgit/linux/kernel/git/tip/tip.git/tree/kernel/sched/sched.h?id=8cd9234c64c584432f6992fe944ca9e46ca8ea76#n269
|
||||
linuxMinCpuShares = 2
|
||||
linuxMaxCpuShares = 262144
|
||||
)
|
||||
|
||||
// newServer sets up the required serverClosers and does protocol specific checking.
|
||||
func (s *Server) newServer(proto, addr string) ([]serverCloser, error) {
|
||||
// newServer sets up the required serverCloser and does protocol specific checking.
|
||||
func (s *Server) newServer(proto, addr string) (serverCloser, error) {
|
||||
var (
|
||||
err error
|
||||
ls []net.Listener
|
||||
l net.Listener
|
||||
)
|
||||
switch proto {
|
||||
case "fd":
|
||||
ls, err = systemd.ListenFD(addr)
|
||||
ls, err := systemd.ListenFD(addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
chErrors := make(chan error, len(ls))
|
||||
// We don't want to start serving on these sockets until the
|
||||
// daemon is initialized and installed. Otherwise required handlers
|
||||
// won't be ready.
|
||||
<-s.start
|
||||
// Since ListenFD will return one or more sockets we have
|
||||
// to create a go func to spawn off multiple serves
|
||||
for i := range ls {
|
||||
listener := ls[i]
|
||||
go func() {
|
||||
httpSrv := http.Server{Handler: s.router}
|
||||
chErrors <- httpSrv.Serve(listener)
|
||||
}()
|
||||
}
|
||||
for i := 0; i < len(ls); i++ {
|
||||
if err := <-chErrors; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return nil, nil
|
||||
case "tcp":
|
||||
l, err := s.initTcpSocket(addr)
|
||||
l, err = s.initTcpSocket(addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ls = append(ls, l)
|
||||
case "unix":
|
||||
l, err := sockets.NewUnixSocket(addr, s.cfg.SocketGroup, s.start)
|
||||
if err != nil {
|
||||
if l, err = sockets.NewUnixSocket(addr, s.cfg.SocketGroup, s.start); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ls = append(ls, l)
|
||||
default:
|
||||
return nil, fmt.Errorf("Invalid protocol format: %q", proto)
|
||||
}
|
||||
var res []serverCloser
|
||||
for _, l := range ls {
|
||||
res = append(res, &HttpServer{
|
||||
&http.Server{
|
||||
Addr: addr,
|
||||
Handler: s.router,
|
||||
},
|
||||
l,
|
||||
})
|
||||
}
|
||||
return res, nil
|
||||
return &HttpServer{
|
||||
&http.Server{
|
||||
Addr: addr,
|
||||
Handler: s.router,
|
||||
},
|
||||
l,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *Server) AcceptConnections(d *daemon.Daemon) {
|
||||
@@ -78,45 +76,3 @@ func (s *Server) AcceptConnections(d *daemon.Daemon) {
|
||||
close(s.start)
|
||||
}
|
||||
}
|
||||
|
||||
func allocateDaemonPort(addr string) error {
|
||||
host, port, err := net.SplitHostPort(addr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
intPort, err := strconv.Atoi(port)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var hostIPs []net.IP
|
||||
if parsedIP := net.ParseIP(host); parsedIP != nil {
|
||||
hostIPs = append(hostIPs, parsedIP)
|
||||
} else if hostIPs, err = net.LookupIP(host); err != nil {
|
||||
return fmt.Errorf("failed to lookup %s address in host specification", host)
|
||||
}
|
||||
|
||||
pa := portallocator.Get()
|
||||
for _, hostIP := range hostIPs {
|
||||
if _, err := pa.RequestPort(hostIP, "tcp", intPort); err != nil {
|
||||
return fmt.Errorf("failed to allocate daemon listening port %d (err: %v)", intPort, err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func adjustCpuShares(version version.Version, hostConfig *runconfig.HostConfig) {
|
||||
if version.LessThan("1.19") {
|
||||
if hostConfig.CpuShares > 0 {
|
||||
// Handle unsupported CpuShares
|
||||
if hostConfig.CpuShares < linuxMinCpuShares {
|
||||
logrus.Warnf("Changing requested CpuShares of %d to minimum allowed of %d", hostConfig.CpuShares, linuxMinCpuShares)
|
||||
hostConfig.CpuShares = linuxMinCpuShares
|
||||
} else if hostConfig.CpuShares > linuxMaxCpuShares {
|
||||
logrus.Warnf("Changing requested CpuShares of %d to maximum allowed of %d", hostConfig.CpuShares, linuxMaxCpuShares)
|
||||
hostConfig.CpuShares = linuxMaxCpuShares
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,68 +0,0 @@
|
||||
// +build linux
|
||||
|
||||
package server
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/docker/docker/pkg/version"
|
||||
"github.com/docker/docker/runconfig"
|
||||
)
|
||||
|
||||
func TestAdjustCpuSharesOldApi(t *testing.T) {
|
||||
apiVersion := version.Version("1.18")
|
||||
hostConfig := &runconfig.HostConfig{
|
||||
CpuShares: linuxMinCpuShares - 1,
|
||||
}
|
||||
adjustCpuShares(apiVersion, hostConfig)
|
||||
if hostConfig.CpuShares != linuxMinCpuShares {
|
||||
t.Errorf("Expected CpuShares to be %d", linuxMinCpuShares)
|
||||
}
|
||||
|
||||
hostConfig.CpuShares = linuxMaxCpuShares + 1
|
||||
adjustCpuShares(apiVersion, hostConfig)
|
||||
if hostConfig.CpuShares != linuxMaxCpuShares {
|
||||
t.Errorf("Expected CpuShares to be %d", linuxMaxCpuShares)
|
||||
}
|
||||
|
||||
hostConfig.CpuShares = 0
|
||||
adjustCpuShares(apiVersion, hostConfig)
|
||||
if hostConfig.CpuShares != 0 {
|
||||
t.Error("Expected CpuShares to be unchanged")
|
||||
}
|
||||
|
||||
hostConfig.CpuShares = 1024
|
||||
adjustCpuShares(apiVersion, hostConfig)
|
||||
if hostConfig.CpuShares != 1024 {
|
||||
t.Error("Expected CpuShares to be unchanged")
|
||||
}
|
||||
}
|
||||
|
||||
func TestAdjustCpuSharesNoAdjustment(t *testing.T) {
|
||||
apiVersion := version.Version("1.19")
|
||||
hostConfig := &runconfig.HostConfig{
|
||||
CpuShares: linuxMinCpuShares - 1,
|
||||
}
|
||||
adjustCpuShares(apiVersion, hostConfig)
|
||||
if hostConfig.CpuShares != linuxMinCpuShares-1 {
|
||||
t.Errorf("Expected CpuShares to be %d", linuxMinCpuShares-1)
|
||||
}
|
||||
|
||||
hostConfig.CpuShares = linuxMaxCpuShares + 1
|
||||
adjustCpuShares(apiVersion, hostConfig)
|
||||
if hostConfig.CpuShares != linuxMaxCpuShares+1 {
|
||||
t.Errorf("Expected CpuShares to be %d", linuxMaxCpuShares+1)
|
||||
}
|
||||
|
||||
hostConfig.CpuShares = 0
|
||||
adjustCpuShares(apiVersion, hostConfig)
|
||||
if hostConfig.CpuShares != 0 {
|
||||
t.Error("Expected CpuShares to be unchanged")
|
||||
}
|
||||
|
||||
hostConfig.CpuShares = 1024
|
||||
adjustCpuShares(apiVersion, hostConfig)
|
||||
if hostConfig.CpuShares != 1024 {
|
||||
t.Error("Expected CpuShares to be unchanged")
|
||||
}
|
||||
}
|
||||
@@ -11,7 +11,7 @@ import (
|
||||
)
|
||||
|
||||
// NewServer sets up the required Server and does protocol specific checking.
|
||||
func (s *Server) newServer(proto, addr string) (serverCloser, error) {
|
||||
func (s *Server) newServer(proto, addr string) (Server, error) {
|
||||
var (
|
||||
err error
|
||||
l net.Listener
|
||||
@@ -22,7 +22,6 @@ func (s *Server) newServer(proto, addr string) (serverCloser, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
default:
|
||||
return nil, errors.New("Invalid protocol format. Windows only supports tcp.")
|
||||
}
|
||||
@@ -44,10 +43,3 @@ func (s *Server) AcceptConnections(d *daemon.Daemon) {
|
||||
close(s.start)
|
||||
}
|
||||
}
|
||||
|
||||
func allocateDaemonPort(addr string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func adjustCpuShares(version version.Version, hostConfig *runconfig.HostConfig) {
|
||||
}
|
||||
|
||||
@@ -81,7 +81,6 @@ type Network struct {
|
||||
type Stats struct {
|
||||
Read time.Time `json:"read"`
|
||||
Network Network `json:"network,omitempty"`
|
||||
PreCpuStats CpuStats `json:"precpu_stats,omitempty"`
|
||||
CpuStats CpuStats `json:"cpu_stats,omitempty"`
|
||||
MemoryStats MemoryStats `json:"memory_stats,omitempty"`
|
||||
BlkioStats BlkioStats `json:"blkio_stats,omitempty"`
|
||||
|
||||
+14
-35
@@ -94,23 +94,23 @@ type ImageInspect struct {
|
||||
|
||||
// GET "/containers/json"
|
||||
type Port struct {
|
||||
IP string `json:",omitempty"`
|
||||
IP string
|
||||
PrivatePort int
|
||||
PublicPort int `json:",omitempty"`
|
||||
PublicPort int
|
||||
Type string
|
||||
}
|
||||
|
||||
type Container struct {
|
||||
ID string `json:"Id"`
|
||||
Names []string
|
||||
Image string
|
||||
Command string
|
||||
Created int
|
||||
Ports []Port
|
||||
SizeRw int `json:",omitempty"`
|
||||
SizeRootFs int `json:",omitempty"`
|
||||
Labels map[string]string
|
||||
Status string
|
||||
ID string `json:"Id"`
|
||||
Names []string `json:",omitempty"`
|
||||
Image string `json:",omitempty"`
|
||||
Command string `json:",omitempty"`
|
||||
Created int `json:",omitempty"`
|
||||
Ports []Port `json:",omitempty"`
|
||||
SizeRw int `json:",omitempty"`
|
||||
SizeRootFs int `json:",omitempty"`
|
||||
Labels map[string]string `json:",omitempty"`
|
||||
Status string `json:",omitempty"`
|
||||
}
|
||||
|
||||
// POST "/containers/"+containerID+"/copy"
|
||||
@@ -132,7 +132,6 @@ type Version struct {
|
||||
Os string
|
||||
Arch string
|
||||
KernelVersion string `json:",omitempty"`
|
||||
Experimental bool `json:",omitempty"`
|
||||
}
|
||||
|
||||
// GET "/info"
|
||||
@@ -195,11 +194,12 @@ type ContainerState struct {
|
||||
}
|
||||
|
||||
// GET "/containers/{name:.*}/json"
|
||||
type ContainerJSONBase struct {
|
||||
type ContainerJSON struct {
|
||||
Id string
|
||||
Created time.Time
|
||||
Path string
|
||||
Args []string
|
||||
Config *runconfig.Config
|
||||
State *ContainerState
|
||||
Image string
|
||||
NetworkSettings *network.Settings
|
||||
@@ -219,24 +219,3 @@ type ContainerJSONBase struct {
|
||||
ExecIDs []string
|
||||
HostConfig *runconfig.HostConfig
|
||||
}
|
||||
|
||||
type ContainerJSON struct {
|
||||
*ContainerJSONBase
|
||||
Config *runconfig.Config
|
||||
}
|
||||
|
||||
// backcompatibility struct along with ContainerConfig
|
||||
type ContainerJSONRaw struct {
|
||||
*ContainerJSONBase
|
||||
Config *ContainerConfig
|
||||
}
|
||||
|
||||
type ContainerConfig struct {
|
||||
*runconfig.Config
|
||||
|
||||
// backward compatibility, they now live in HostConfig
|
||||
Memory int64
|
||||
MemorySwap int64
|
||||
CpuShares int64
|
||||
Cpuset string
|
||||
}
|
||||
|
||||
@@ -221,10 +221,6 @@ func Commit(d *daemon.Daemon, name string, c *daemon.ContainerCommitConfig) (str
|
||||
return "", err
|
||||
}
|
||||
|
||||
if c.Config == nil {
|
||||
c.Config = &runconfig.Config{}
|
||||
}
|
||||
|
||||
newConfig, err := BuildFromConfig(d, c.Config, c.Changes)
|
||||
if err != nil {
|
||||
return "", err
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
#
|
||||
# THIS FILE IS AUTOGENERATED; SEE "contrib/builder/rpm/generate.sh"!
|
||||
#
|
||||
|
||||
FROM fedora:22
|
||||
|
||||
RUN yum install -y @development-tools fedora-packager
|
||||
RUN yum install -y btrfs-progs-devel device-mapper-devel glibc-static libselinux-devel sqlite-devel tar
|
||||
|
||||
ENV GO_VERSION 1.4.2
|
||||
RUN curl -fSL "https://storage.googleapis.com/golang/go${GO_VERSION}.linux-amd64.tar.gz" | tar xzC /usr/local
|
||||
ENV PATH $PATH:/usr/local/go/bin
|
||||
|
||||
ENV AUTO_GOPATH 1
|
||||
ENV DOCKER_BUILDTAGS selinux
|
||||
@@ -212,12 +212,11 @@ _docker_docker() {
|
||||
--selinux-enabled
|
||||
--tls
|
||||
--tlsverify
|
||||
--userland-proxy=false
|
||||
--version -v
|
||||
"
|
||||
|
||||
case "$prev" in
|
||||
--exec-root|--graph|-g)
|
||||
--graph|-g)
|
||||
_filedir -d
|
||||
return
|
||||
;;
|
||||
@@ -268,25 +267,22 @@ _docker_attach() {
|
||||
|
||||
_docker_build() {
|
||||
case "$prev" in
|
||||
--cgroup-parent|--cpuset-cpus|--cpuset-mems|--cpu-shares|-c|--cpu-period|--cpu-quota|--memory|-m|--memory-swap)
|
||||
--tag|-t)
|
||||
__docker_image_repos_and_tags
|
||||
return
|
||||
;;
|
||||
--file|-f)
|
||||
_filedir
|
||||
return
|
||||
;;
|
||||
--tag|-t)
|
||||
__docker_image_repos_and_tags
|
||||
return
|
||||
;;
|
||||
esac
|
||||
|
||||
case "$cur" in
|
||||
-*)
|
||||
COMPREPLY=( $( compgen -W "--cgroup-parent --cpuset-cpus --cpuset-mems --cpu-shares -c --cpu-period --cpu-quota --file -f --force-rm --help --memory -m --memory-swap --no-cache --pull --quiet -q --rm --tag -t" -- "$cur" ) )
|
||||
COMPREPLY=( $( compgen -W "--cpu-shares -c --cpuset-cpus --cpu-quota --file -f --force-rm --help --memory -m --memory-swap --no-cache --pull --quiet -q --rm --tag -t" -- "$cur" ) )
|
||||
;;
|
||||
*)
|
||||
local counter="$(__docker_pos_first_nonflag '--cgroup-parent|--cpuset-cpus|--cpuset-mems|--cpu-shares|-c|--cpu-period|--cpu-quota|--file|-f|--memory|-m|--memory-swap|--tag|-t')"
|
||||
local counter="$(__docker_pos_first_nonflag '--tag|-t')"
|
||||
if [ $cword -eq $counter ]; then
|
||||
_filedir -d
|
||||
fi
|
||||
@@ -409,12 +405,6 @@ _docker_events() {
|
||||
}
|
||||
|
||||
_docker_exec() {
|
||||
case "$prev" in
|
||||
--user|-u)
|
||||
return
|
||||
;;
|
||||
esac
|
||||
|
||||
case "$cur" in
|
||||
-*)
|
||||
COMPREPLY=( $( compgen -W "--detach -d --help --interactive -i -t --tty -u --user" -- "$cur" ) )
|
||||
@@ -596,7 +586,7 @@ _docker_logout() {
|
||||
|
||||
_docker_logs() {
|
||||
case "$prev" in
|
||||
--since|--tail)
|
||||
--tail)
|
||||
return
|
||||
;;
|
||||
esac
|
||||
@@ -781,16 +771,15 @@ _docker_rmi() {
|
||||
_docker_run() {
|
||||
local options_with_args="
|
||||
--add-host
|
||||
--blkio-weight
|
||||
--attach -a
|
||||
--cap-add
|
||||
--cap-drop
|
||||
--cgroup-parent
|
||||
--cidfile
|
||||
--cpuset
|
||||
--cpu-shares -c
|
||||
--cpu-period
|
||||
--cpu-quota
|
||||
--cpu-shares -c
|
||||
--device
|
||||
--dns
|
||||
--dns-search
|
||||
@@ -816,7 +805,6 @@ _docker_run() {
|
||||
--security-opt
|
||||
--user -u
|
||||
--ulimit
|
||||
--uts
|
||||
--volumes-from
|
||||
--volume -v
|
||||
--workdir -w
|
||||
@@ -1168,8 +1156,6 @@ _docker() {
|
||||
--api-cors-header
|
||||
--bip
|
||||
--bridge -b
|
||||
--default-gateway
|
||||
--default-gateway-v6
|
||||
--default-ulimit
|
||||
--dns
|
||||
--dns-search
|
||||
@@ -1217,9 +1203,6 @@ _docker() {
|
||||
;;
|
||||
-*)
|
||||
;;
|
||||
=)
|
||||
(( counter++ ))
|
||||
;;
|
||||
*)
|
||||
command="${words[$counter]}"
|
||||
cpos=$counter
|
||||
|
||||
@@ -7,6 +7,7 @@ DOCKER_LOGFILE=${DOCKER_LOGFILE:-/var/log/${SVCNAME}.log}
|
||||
DOCKER_PIDFILE=${DOCKER_PIDFILE:-/run/${SVCNAME}.pid}
|
||||
DOCKER_BINARY=${DOCKER_BINARY:-/usr/bin/docker}
|
||||
DOCKER_OPTS=${DOCKER_OPTS:-}
|
||||
UNSHARE_BINARY=${UNSHARE_BINARY:-/usr/bin/unshare}
|
||||
|
||||
start() {
|
||||
checkpath -f -m 0644 -o root:docker "$DOCKER_LOGFILE"
|
||||
@@ -16,11 +17,12 @@ start() {
|
||||
|
||||
ebegin "Starting docker daemon"
|
||||
start-stop-daemon --start --background \
|
||||
--exec "$DOCKER_BINARY" \
|
||||
--exec "$UNSHARE_BINARY" \
|
||||
--pidfile "$DOCKER_PIDFILE" \
|
||||
--stdout "$DOCKER_LOGFILE" \
|
||||
--stderr "$DOCKER_LOGFILE" \
|
||||
-- -d -p "$DOCKER_PIDFILE" \
|
||||
-- --mount \
|
||||
-- "$DOCKER_BINARY" -d -p "$DOCKER_PIDFILE" \
|
||||
$DOCKER_OPTS
|
||||
eend $?
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[Unit]
|
||||
Description=Docker Application Container Engine
|
||||
Documentation=https://docs.docker.com
|
||||
Documentation=http://docs.docker.com
|
||||
After=network.target docker.socket
|
||||
Requires=docker.socket
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@ DOCKER_SSD_PIDFILE=/var/run/$BASE-ssd.pid
|
||||
DOCKER_LOGFILE=/var/log/$BASE.log
|
||||
DOCKER_OPTS=
|
||||
DOCKER_DESC="Docker"
|
||||
UNSHARE=${UNSHARE:-/usr/bin/unshare}
|
||||
|
||||
# Get lsb functions
|
||||
. /lib/lsb/init-functions
|
||||
@@ -99,11 +100,11 @@ case "$1" in
|
||||
log_begin_msg "Starting $DOCKER_DESC: $BASE"
|
||||
start-stop-daemon --start --background \
|
||||
--no-close \
|
||||
--exec "$DOCKER" \
|
||||
--exec "$UNSHARE" \
|
||||
--pidfile "$DOCKER_SSD_PIDFILE" \
|
||||
--make-pidfile \
|
||||
-- \
|
||||
-d -p "$DOCKER_PIDFILE" \
|
||||
-- --mount \
|
||||
-- "$DOCKER" -d -p "$DOCKER_PIDFILE" \
|
||||
$DOCKER_OPTS \
|
||||
>> "$DOCKER_LOGFILE" 2>&1
|
||||
log_end_msg $?
|
||||
|
||||
@@ -39,7 +39,7 @@ script
|
||||
if [ -f /etc/default/$UPSTART_JOB ]; then
|
||||
. /etc/default/$UPSTART_JOB
|
||||
fi
|
||||
exec "$DOCKER" -d $DOCKER_OPTS
|
||||
exec unshare -m -- "$DOCKER" -d $DOCKER_OPTS
|
||||
end script
|
||||
|
||||
# Don't emit "started" event until docker.sock is ready.
|
||||
|
||||
@@ -80,7 +80,7 @@ sudo mkdir -m 755 dev
|
||||
# effectively: febootstrap-minimize --keep-zoneinfo --keep-rpmdb --keep-services "$target"
|
||||
# locales
|
||||
sudo rm -rf usr/{{lib,share}/locale,{lib,lib64}/gconv,bin/localedef,sbin/build-locale-archive}
|
||||
# docs and man pages
|
||||
# docs
|
||||
sudo rm -rf usr/share/{man,doc,info,gnome/help}
|
||||
# cracklib
|
||||
sudo rm -rf usr/share/cracklib
|
||||
|
||||
@@ -10,7 +10,7 @@ shift
|
||||
# effectively: febootstrap-minimize --keep-zoneinfo --keep-rpmdb --keep-services "$target"
|
||||
# locales
|
||||
rm -rf usr/{{lib,share}/locale,{lib,lib64}/gconv,bin/localedef,sbin/build-locale-archive}
|
||||
# docs and man pages
|
||||
# docs
|
||||
rm -rf usr/share/{man,doc,info,gnome/help}
|
||||
# cracklib
|
||||
rm -rf usr/share/cracklib
|
||||
|
||||
+38
-5
@@ -1,6 +1,8 @@
|
||||
package daemon
|
||||
|
||||
import (
|
||||
"net"
|
||||
|
||||
"github.com/docker/docker/opts"
|
||||
flag "github.com/docker/docker/pkg/mflag"
|
||||
"github.com/docker/docker/runconfig"
|
||||
@@ -14,7 +16,9 @@ const (
|
||||
// CommonConfig defines the configuration of a docker daemon which are
|
||||
// common across platforms.
|
||||
type CommonConfig struct {
|
||||
AutoRestart bool
|
||||
AutoRestart bool
|
||||
// Bridge holds bridge network specific configuration.
|
||||
Bridge bridgeConfig
|
||||
Context map[string][]string
|
||||
CorsHeaders string
|
||||
DisableNetwork bool
|
||||
@@ -22,10 +26,8 @@ type CommonConfig struct {
|
||||
DnsSearch []string
|
||||
EnableCors bool
|
||||
ExecDriver string
|
||||
ExecOptions []string
|
||||
ExecRoot string
|
||||
GraphDriver string
|
||||
GraphOptions []string
|
||||
Labels []string
|
||||
LogConfig runconfig.LogConfig
|
||||
Mtu int
|
||||
@@ -34,26 +36,57 @@ type CommonConfig struct {
|
||||
TrustKeyPath string
|
||||
}
|
||||
|
||||
// bridgeConfig stores all the bridge driver specific
|
||||
// configuration.
|
||||
type bridgeConfig struct {
|
||||
EnableIPv6 bool
|
||||
EnableIPTables bool
|
||||
EnableIPForward bool
|
||||
EnableIPMasq bool
|
||||
EnableUserlandProxy bool
|
||||
DefaultIP net.IP
|
||||
Iface string
|
||||
IP string
|
||||
FixedCIDR string
|
||||
FixedCIDRv6 string
|
||||
DefaultGatewayIPv4 string
|
||||
DefaultGatewayIPv6 string
|
||||
InterContainerCommunication bool
|
||||
}
|
||||
|
||||
// InstallCommonFlags adds command-line options to the top-level flag parser for
|
||||
// the current process.
|
||||
// Subsequent calls to `flag.Parse` will populate config with values parsed
|
||||
// from the command-line.
|
||||
|
||||
func (config *Config) InstallCommonFlags() {
|
||||
opts.ListVar(&config.GraphOptions, []string{"-storage-opt"}, "Set storage driver options")
|
||||
opts.ListVar(&config.ExecOptions, []string{"-exec-opt"}, "Set exec driver options")
|
||||
flag.StringVar(&config.Pidfile, []string{"p", "-pidfile"}, defaultPidFile, "Path to use for daemon PID file")
|
||||
flag.StringVar(&config.Root, []string{"g", "-graph"}, defaultGraph, "Root of the Docker runtime")
|
||||
flag.StringVar(&config.ExecRoot, []string{"-exec-root"}, "/var/run/docker", "Root of the Docker execdriver")
|
||||
flag.BoolVar(&config.AutoRestart, []string{"#r", "#-restart"}, true, "--restart on the daemon has been deprecated in favor of --restart policies on docker run")
|
||||
flag.BoolVar(&config.Bridge.EnableIPTables, []string{"#iptables", "-iptables"}, true, "Enable addition of iptables rules")
|
||||
flag.BoolVar(&config.Bridge.EnableIPForward, []string{"#ip-forward", "-ip-forward"}, true, "Enable net.ipv4.ip_forward")
|
||||
flag.BoolVar(&config.Bridge.EnableIPMasq, []string{"-ip-masq"}, true, "Enable IP masquerading")
|
||||
flag.BoolVar(&config.Bridge.EnableIPv6, []string{"-ipv6"}, false, "Enable IPv6 networking")
|
||||
flag.StringVar(&config.Bridge.IP, []string{"#bip", "-bip"}, "", "Specify network bridge IP")
|
||||
flag.StringVar(&config.Bridge.Iface, []string{"b", "-bridge"}, "", "Attach containers to a network bridge")
|
||||
flag.StringVar(&config.Bridge.FixedCIDR, []string{"-fixed-cidr"}, "", "IPv4 subnet for fixed IPs")
|
||||
flag.StringVar(&config.Bridge.FixedCIDRv6, []string{"-fixed-cidr-v6"}, "", "IPv6 subnet for fixed IPs")
|
||||
flag.StringVar(&config.Bridge.DefaultGatewayIPv4, []string{"-default-gateway"}, "", "Container default gateway IPv4 address")
|
||||
flag.StringVar(&config.Bridge.DefaultGatewayIPv6, []string{"-default-gateway-v6"}, "", "Container default gateway IPv6 address")
|
||||
flag.BoolVar(&config.Bridge.InterContainerCommunication, []string{"#icc", "-icc"}, true, "Enable inter-container communication")
|
||||
flag.StringVar(&config.GraphDriver, []string{"s", "-storage-driver"}, "", "Storage driver to use")
|
||||
flag.StringVar(&config.ExecDriver, []string{"e", "-exec-driver"}, defaultExec, "Exec driver to use")
|
||||
flag.IntVar(&config.Mtu, []string{"#mtu", "-mtu"}, 0, "Set the containers network MTU")
|
||||
flag.BoolVar(&config.EnableCors, []string{"#api-enable-cors", "#-api-enable-cors"}, false, "Enable CORS headers in the remote API, this is deprecated by --api-cors-header")
|
||||
flag.StringVar(&config.CorsHeaders, []string{"-api-cors-header"}, "", "Set CORS headers in the remote API")
|
||||
opts.IPVar(&config.Bridge.DefaultIP, []string{"#ip", "-ip"}, "0.0.0.0", "Default IP when binding container ports")
|
||||
// FIXME: why the inconsistency between "hosts" and "sockets"?
|
||||
opts.IPListVar(&config.Dns, []string{"#dns", "-dns"}, "DNS server to use")
|
||||
opts.DnsSearchListVar(&config.DnsSearch, []string{"-dns-search"}, "DNS search domains to use")
|
||||
opts.LabelListVar(&config.Labels, []string{"-label"}, "Set key=value labels to the daemon")
|
||||
flag.StringVar(&config.LogConfig.Type, []string{"-log-driver"}, "json-file", "Default driver for container logs")
|
||||
opts.LogOptsVar(config.LogConfig.Config, []string{"-log-opt"}, "Set log driver options")
|
||||
flag.BoolVar(&config.Bridge.EnableUserlandProxy, []string{"-userland-proxy"}, true, "Use userland proxy for loopback traffic")
|
||||
|
||||
}
|
||||
|
||||
+4
-36
@@ -1,8 +1,6 @@
|
||||
package daemon
|
||||
|
||||
import (
|
||||
"net"
|
||||
|
||||
"github.com/docker/docker/opts"
|
||||
flag "github.com/docker/docker/pkg/mflag"
|
||||
"github.com/docker/docker/pkg/ulimit"
|
||||
@@ -21,32 +19,13 @@ type Config struct {
|
||||
CommonConfig
|
||||
|
||||
// Fields below here are platform specific.
|
||||
|
||||
// Bridge holds bridge network specific configuration.
|
||||
Bridge bridgeConfig
|
||||
EnableSelinuxSupport bool
|
||||
ExecOptions []string
|
||||
GraphOptions []string
|
||||
SocketGroup string
|
||||
Ulimits map[string]*ulimit.Ulimit
|
||||
}
|
||||
|
||||
// bridgeConfig stores all the bridge driver specific
|
||||
// configuration.
|
||||
type bridgeConfig struct {
|
||||
EnableIPv6 bool
|
||||
EnableIPTables bool
|
||||
EnableIPForward bool
|
||||
EnableIPMasq bool
|
||||
EnableUserlandProxy bool
|
||||
DefaultIP net.IP
|
||||
Iface string
|
||||
IP string
|
||||
FixedCIDR string
|
||||
FixedCIDRv6 string
|
||||
DefaultGatewayIPv4 net.IP
|
||||
DefaultGatewayIPv6 net.IP
|
||||
InterContainerCommunication bool
|
||||
}
|
||||
|
||||
// InstallFlags adds command-line options to the top-level flag parser for
|
||||
// the current process.
|
||||
// Subsequent calls to `flag.Parse` will populate config with values parsed
|
||||
@@ -56,21 +35,10 @@ func (config *Config) InstallFlags() {
|
||||
config.InstallCommonFlags()
|
||||
|
||||
// Then platform-specific install flags
|
||||
opts.ListVar(&config.GraphOptions, []string{"-storage-opt"}, "Set storage driver options")
|
||||
opts.ListVar(&config.ExecOptions, []string{"-exec-opt"}, "Set exec driver options")
|
||||
flag.BoolVar(&config.EnableSelinuxSupport, []string{"-selinux-enabled"}, false, "Enable selinux support")
|
||||
flag.StringVar(&config.SocketGroup, []string{"G", "-group"}, "docker", "Group for the unix socket")
|
||||
config.Ulimits = make(map[string]*ulimit.Ulimit)
|
||||
opts.UlimitMapVar(config.Ulimits, []string{"-default-ulimit"}, "Set default ulimits for containers")
|
||||
flag.BoolVar(&config.Bridge.EnableIPTables, []string{"#iptables", "-iptables"}, true, "Enable addition of iptables rules")
|
||||
flag.BoolVar(&config.Bridge.EnableIPForward, []string{"#ip-forward", "-ip-forward"}, true, "Enable net.ipv4.ip_forward")
|
||||
flag.BoolVar(&config.Bridge.EnableIPMasq, []string{"-ip-masq"}, true, "Enable IP masquerading")
|
||||
flag.BoolVar(&config.Bridge.EnableIPv6, []string{"-ipv6"}, false, "Enable IPv6 networking")
|
||||
flag.StringVar(&config.Bridge.IP, []string{"#bip", "-bip"}, "", "Specify network bridge IP")
|
||||
flag.StringVar(&config.Bridge.Iface, []string{"b", "-bridge"}, "", "Attach containers to a network bridge")
|
||||
flag.StringVar(&config.Bridge.FixedCIDR, []string{"-fixed-cidr"}, "", "IPv4 subnet for fixed IPs")
|
||||
flag.StringVar(&config.Bridge.FixedCIDRv6, []string{"-fixed-cidr-v6"}, "", "IPv6 subnet for fixed IPs")
|
||||
opts.IPVar(&config.Bridge.DefaultGatewayIPv4, []string{"-default-gateway"}, "", "Container default gateway IPv4 address")
|
||||
opts.IPVar(&config.Bridge.DefaultGatewayIPv6, []string{"-default-gateway-v6"}, "", "Container default gateway IPv6 address")
|
||||
flag.BoolVar(&config.Bridge.InterContainerCommunication, []string{"#icc", "-icc"}, true, "Enable inter-container communication")
|
||||
opts.IPVar(&config.Bridge.DefaultIP, []string{"#ip", "-ip"}, "0.0.0.0", "Default IP when binding container ports")
|
||||
flag.BoolVar(&config.Bridge.EnableUserlandProxy, []string{"-userland-proxy"}, true, "Use userland proxy for loopback traffic")
|
||||
}
|
||||
|
||||
+1
-13
@@ -73,10 +73,7 @@ type CommonContainer struct {
|
||||
MountLabel, ProcessLabel string
|
||||
RestartCount int
|
||||
UpdateDns bool
|
||||
|
||||
MountPoints map[string]*mountPoint
|
||||
Volumes map[string]string // Deprecated since 1.7, kept for backwards compatibility
|
||||
VolumesRW map[string]bool // Deprecated since 1.7, kept for backwards compatibility
|
||||
MountPoints map[string]*mountPoint
|
||||
|
||||
hostConfig *runconfig.HostConfig
|
||||
command *execdriver.Command
|
||||
@@ -1057,15 +1054,6 @@ func (container *Container) networkMounts() []execdriver.Mount {
|
||||
return mounts
|
||||
}
|
||||
|
||||
func (container *Container) addBindMountPoint(name, source, destination string, rw bool) {
|
||||
container.MountPoints[destination] = &mountPoint{
|
||||
Name: name,
|
||||
Source: source,
|
||||
Destination: destination,
|
||||
RW: rw,
|
||||
}
|
||||
}
|
||||
|
||||
func (container *Container) addLocalMountPoint(name, destination string, rw bool) {
|
||||
container.MountPoints[destination] = &mountPoint{
|
||||
Name: name,
|
||||
|
||||
@@ -183,7 +183,7 @@ func getDevicesFromPath(deviceMapping runconfig.DeviceMapping) (devs []*configs.
|
||||
|
||||
func populateCommand(c *Container, env []string) error {
|
||||
var en *execdriver.Network
|
||||
if !c.Config.NetworkDisabled {
|
||||
if !c.daemon.config.DisableNetwork {
|
||||
en = &execdriver.Network{
|
||||
NamespacePath: c.NetworkSettings.SandboxKey,
|
||||
}
|
||||
@@ -227,10 +227,9 @@ func populateCommand(c *Container, env []string) error {
|
||||
|
||||
userSpecifiedDevices = append(userSpecifiedDevices, devs...)
|
||||
}
|
||||
allowedDevices := append(configs.DefaultAllowedDevices, userSpecifiedDevices...)
|
||||
|
||||
allowedDevices := mergeDevices(configs.DefaultAllowedDevices, userSpecifiedDevices)
|
||||
|
||||
autoCreatedDevices := mergeDevices(configs.DefaultAutoCreatedDevices, userSpecifiedDevices)
|
||||
autoCreatedDevices := append(configs.DefaultAutoCreatedDevices, userSpecifiedDevices...)
|
||||
|
||||
// TODO: this can be removed after lxc-conf is fully deprecated
|
||||
lxcConfig, err := mergeLxcConfIntoOptions(c.hostConfig)
|
||||
@@ -310,25 +309,6 @@ func populateCommand(c *Container, env []string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func mergeDevices(defaultDevices, userDevices []*configs.Device) []*configs.Device {
|
||||
if len(userDevices) == 0 {
|
||||
return defaultDevices
|
||||
}
|
||||
|
||||
paths := map[string]*configs.Device{}
|
||||
for _, d := range userDevices {
|
||||
paths[d.Path] = d
|
||||
}
|
||||
|
||||
var devs []*configs.Device
|
||||
for _, d := range defaultDevices {
|
||||
if _, defined := paths[d.Path]; !defined {
|
||||
devs = append(devs, d)
|
||||
}
|
||||
}
|
||||
return append(devs, userDevices...)
|
||||
}
|
||||
|
||||
// GetSize, return real size, virtual size
|
||||
func (container *Container) GetSize() (int64, int64) {
|
||||
var (
|
||||
@@ -513,23 +493,13 @@ func (container *Container) buildPortMapInfo(n libnetwork.Network, ep libnetwork
|
||||
networkSettings.MacAddress = mac.(net.HardwareAddr).String()
|
||||
}
|
||||
|
||||
networkSettings.Ports = nat.PortMap{}
|
||||
|
||||
if expData, ok := driverInfo[netlabel.ExposedPorts]; ok {
|
||||
if exposedPorts, ok := expData.([]types.TransportPort); ok {
|
||||
for _, tp := range exposedPorts {
|
||||
natPort := nat.NewPort(tp.Proto.String(), strconv.Itoa(int(tp.Port)))
|
||||
networkSettings.Ports[natPort] = nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mapData, ok := driverInfo[netlabel.PortMap]
|
||||
if !ok {
|
||||
return networkSettings, nil
|
||||
}
|
||||
|
||||
if portMapping, ok := mapData.([]types.PortBinding); ok {
|
||||
networkSettings.Ports = nat.PortMap{}
|
||||
for _, pp := range portMapping {
|
||||
natPort := nat.NewPort(pp.Proto.String(), strconv.Itoa(int(pp.Port)))
|
||||
natBndg := nat.PortBinding{HostIp: pp.HostIP.String(), HostPort: strconv.Itoa(int(pp.HostPort))}
|
||||
@@ -943,12 +913,6 @@ func (container *Container) ReleaseNetwork() {
|
||||
return
|
||||
}
|
||||
|
||||
// If the container is not attached to any network do not try
|
||||
// to release network and generate spurious error messages.
|
||||
if container.NetworkSettings.NetworkID == "" {
|
||||
return
|
||||
}
|
||||
|
||||
n, err := container.daemon.netController.NetworkByID(container.NetworkSettings.NetworkID)
|
||||
if err != nil {
|
||||
logrus.Errorf("error locating network id %s: %v", container.NetworkSettings.NetworkID, err)
|
||||
|
||||
@@ -15,10 +15,6 @@ import (
|
||||
)
|
||||
|
||||
func (daemon *Daemon) ContainerCreate(name string, config *runconfig.Config, hostConfig *runconfig.HostConfig) (string, []string, error) {
|
||||
if config == nil {
|
||||
return "", nil, fmt.Errorf("Config cannot be empty in order to create a container")
|
||||
}
|
||||
|
||||
warnings, err := daemon.verifyHostConfig(hostConfig)
|
||||
if err != nil {
|
||||
return "", warnings, err
|
||||
|
||||
+39
-87
@@ -1,7 +1,6 @@
|
||||
package daemon
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
@@ -49,9 +48,10 @@ import (
|
||||
"github.com/docker/docker/utils"
|
||||
volumedrivers "github.com/docker/docker/volume/drivers"
|
||||
"github.com/docker/docker/volume/local"
|
||||
"github.com/docker/libcontainer/netlink"
|
||||
)
|
||||
|
||||
const defaultVolumesPathName = "volumes"
|
||||
|
||||
var (
|
||||
validContainerNameChars = `[a-zA-Z0-9][a-zA-Z0-9_.-]`
|
||||
validContainerNamePattern = regexp.MustCompile(`^/?` + validContainerNameChars + `+$`)
|
||||
@@ -158,7 +158,12 @@ func (daemon *Daemon) containerRoot(id string) string {
|
||||
// This is typically done at startup.
|
||||
func (daemon *Daemon) load(id string) (*Container, error) {
|
||||
container := &Container{
|
||||
CommonContainer: daemon.newBaseContainer(id),
|
||||
CommonContainer: CommonContainer{
|
||||
State: NewState(),
|
||||
root: daemon.containerRoot(id),
|
||||
MountPoints: make(map[string]*mountPoint),
|
||||
execCommands: newExecStore(),
|
||||
},
|
||||
}
|
||||
|
||||
if err := container.FromDisk(); err != nil {
|
||||
@@ -208,7 +213,7 @@ func (daemon *Daemon) register(container *Container, updateSuffixarray bool) err
|
||||
// we'll waste time if we update it for every container
|
||||
daemon.idIndex.Add(container.ID)
|
||||
|
||||
if err := daemon.verifyVolumesInfo(container); err != nil {
|
||||
if err := daemon.verifyOldVolumesInfo(container); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -521,21 +526,25 @@ func (daemon *Daemon) newContainer(name string, config *runconfig.Config, imgID
|
||||
daemon.generateHostname(id, config)
|
||||
entrypoint, args := daemon.getEntrypointAndArgs(config.Entrypoint, config.Cmd)
|
||||
|
||||
base := daemon.newBaseContainer(id)
|
||||
base.Created = time.Now().UTC()
|
||||
base.Path = entrypoint
|
||||
base.Args = args //FIXME: de-duplicate from config
|
||||
base.Config = config
|
||||
base.hostConfig = &runconfig.HostConfig{}
|
||||
base.ImageID = imgID
|
||||
base.NetworkSettings = &network.Settings{}
|
||||
base.Name = name
|
||||
base.Driver = daemon.driver.String()
|
||||
base.ExecDriver = daemon.execDriver.Name()
|
||||
|
||||
container := &Container{
|
||||
CommonContainer: base,
|
||||
CommonContainer: CommonContainer{
|
||||
ID: id, // FIXME: we should generate the ID here instead of receiving it as an argument
|
||||
Created: time.Now().UTC(),
|
||||
Path: entrypoint,
|
||||
Args: args, //FIXME: de-duplicate from config
|
||||
Config: config,
|
||||
hostConfig: &runconfig.HostConfig{},
|
||||
ImageID: imgID,
|
||||
NetworkSettings: &network.Settings{},
|
||||
Name: name,
|
||||
Driver: daemon.driver.String(),
|
||||
ExecDriver: daemon.execDriver.Name(),
|
||||
State: NewState(),
|
||||
execCommands: newExecStore(),
|
||||
MountPoints: map[string]*mountPoint{},
|
||||
},
|
||||
}
|
||||
container.root = daemon.containerRoot(container.ID)
|
||||
|
||||
return container, err
|
||||
}
|
||||
@@ -674,8 +683,6 @@ func NewDaemon(config *Config, registryService *registry.Service) (daemon *Daemo
|
||||
if config.Bridge.Iface != "" && config.Bridge.IP != "" {
|
||||
return nil, fmt.Errorf("You specified -b & --bip, mutually exclusive options. Please specify only one.")
|
||||
}
|
||||
setDefaultMtu(config)
|
||||
|
||||
if !config.Bridge.EnableIPTables && !config.Bridge.InterContainerCommunication {
|
||||
return nil, fmt.Errorf("You specified --iptables=false with --icc=false. ICC uses iptables to function. Please set --icc or --iptables to true.")
|
||||
}
|
||||
@@ -785,7 +792,7 @@ func NewDaemon(config *Config, registryService *registry.Service) (daemon *Daemo
|
||||
return nil, err
|
||||
}
|
||||
|
||||
volumesDriver, err := local.New(config.Root)
|
||||
volumesDriver, err := local.New(filepath.Join(config.Root, defaultVolumesPathName))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -956,14 +963,6 @@ func initNetworkController(config *Config) (libnetwork.NetworkController, error)
|
||||
netOption["FixedCIDRv6"] = fCIDRv6
|
||||
}
|
||||
|
||||
if config.Bridge.DefaultGatewayIPv4 != nil {
|
||||
netOption["DefaultGatewayIPv4"] = config.Bridge.DefaultGatewayIPv4
|
||||
}
|
||||
|
||||
if config.Bridge.DefaultGatewayIPv6 != nil {
|
||||
netOption["DefaultGatewayIPv6"] = config.Bridge.DefaultGatewayIPv6
|
||||
}
|
||||
|
||||
// --ip processing
|
||||
if config.Bridge.DefaultIP != nil {
|
||||
netOption["DefaultBindingIP"] = config.Bridge.DefaultIP
|
||||
@@ -983,6 +982,16 @@ func initNetworkController(config *Config) (libnetwork.NetworkController, error)
|
||||
}
|
||||
|
||||
func (daemon *Daemon) Shutdown() error {
|
||||
if daemon.containerGraph != nil {
|
||||
if err := daemon.containerGraph.Close(); err != nil {
|
||||
logrus.Errorf("Error during container graph.Close(): %v", err)
|
||||
}
|
||||
}
|
||||
if daemon.driver != nil {
|
||||
if err := daemon.driver.Cleanup(); err != nil {
|
||||
logrus.Errorf("Error during graph storage driver.Cleanup(): %v", err)
|
||||
}
|
||||
}
|
||||
if daemon.containers != nil {
|
||||
group := sync.WaitGroup{}
|
||||
logrus.Debug("starting clean shutdown of all containers...")
|
||||
@@ -994,9 +1003,8 @@ func (daemon *Daemon) Shutdown() error {
|
||||
|
||||
go func() {
|
||||
defer group.Done()
|
||||
// If container failed to exit in 10 seconds of SIGTERM, then using the force
|
||||
if err := c.Stop(10); err != nil {
|
||||
logrus.Errorf("Stop container %s with error: %v", c.ID, err)
|
||||
if err := c.KillSig(15); err != nil {
|
||||
logrus.Debugf("kill 15 error for %s - %s", c.ID, err)
|
||||
}
|
||||
c.WaitStop(-1 * time.Second)
|
||||
logrus.Debugf("container stopped %s", c.ID)
|
||||
@@ -1004,23 +1012,6 @@ func (daemon *Daemon) Shutdown() error {
|
||||
}
|
||||
}
|
||||
group.Wait()
|
||||
|
||||
// trigger libnetwork GC only if it's initialized
|
||||
if daemon.netController != nil {
|
||||
daemon.netController.GC()
|
||||
}
|
||||
}
|
||||
|
||||
if daemon.containerGraph != nil {
|
||||
if err := daemon.containerGraph.Close(); err != nil {
|
||||
logrus.Errorf("Error during container graph.Close(): %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
if daemon.driver != nil {
|
||||
if err := daemon.driver.Cleanup(); err != nil {
|
||||
logrus.Errorf("Error during graph storage driver.Cleanup(): %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -1254,42 +1245,3 @@ func (daemon *Daemon) setHostConfig(container *Container, hostConfig *runconfig.
|
||||
container.toDisk()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (daemon *Daemon) newBaseContainer(id string) CommonContainer {
|
||||
return CommonContainer{
|
||||
ID: id,
|
||||
State: NewState(),
|
||||
MountPoints: make(map[string]*mountPoint),
|
||||
Volumes: make(map[string]string),
|
||||
VolumesRW: make(map[string]bool),
|
||||
execCommands: newExecStore(),
|
||||
root: daemon.containerRoot(id),
|
||||
}
|
||||
}
|
||||
|
||||
func setDefaultMtu(config *Config) {
|
||||
// do nothing if the config does not have the default 0 value.
|
||||
if config.Mtu != 0 {
|
||||
return
|
||||
}
|
||||
config.Mtu = defaultNetworkMtu
|
||||
if routeMtu, err := getDefaultRouteMtu(); err == nil {
|
||||
config.Mtu = routeMtu
|
||||
}
|
||||
}
|
||||
|
||||
var errNoDefaultRoute = errors.New("no default route was found")
|
||||
|
||||
// getDefaultRouteMtu returns the MTU for the default route's interface.
|
||||
func getDefaultRouteMtu() (int, error) {
|
||||
routes, err := netlink.NetworkGetRoutes()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
for _, r := range routes {
|
||||
if r.Default {
|
||||
return r.Iface.MTU, nil
|
||||
}
|
||||
}
|
||||
return 0, errNoDefaultRoute
|
||||
}
|
||||
|
||||
+30
-339
@@ -12,8 +12,6 @@ import (
|
||||
"github.com/docker/docker/pkg/stringid"
|
||||
"github.com/docker/docker/pkg/truncindex"
|
||||
"github.com/docker/docker/volume"
|
||||
"github.com/docker/docker/volume/drivers"
|
||||
"github.com/docker/docker/volume/local"
|
||||
)
|
||||
|
||||
//
|
||||
@@ -129,311 +127,14 @@ func TestLoadWithVolume(t *testing.T) {
|
||||
}
|
||||
defer os.RemoveAll(tmp)
|
||||
|
||||
containerId := "d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e"
|
||||
containerPath := filepath.Join(tmp, containerId)
|
||||
if err := os.MkdirAll(containerPath, 0755); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
hostVolumeId := stringid.GenerateRandomID()
|
||||
vfsPath := filepath.Join(tmp, "vfs", "dir", hostVolumeId)
|
||||
volumePath := filepath.Join(tmp, "volumes", hostVolumeId)
|
||||
|
||||
if err := os.MkdirAll(vfsPath, 0755); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := os.MkdirAll(volumePath, 0755); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
content := filepath.Join(vfsPath, "helo")
|
||||
if err := ioutil.WriteFile(content, []byte("HELO"), 0644); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
config := `{"State":{"Running":true,"Paused":false,"Restarting":false,"OOMKilled":false,"Dead":false,"Pid":2464,"ExitCode":0,
|
||||
"Error":"","StartedAt":"2015-05-26T16:48:53.869308965Z","FinishedAt":"0001-01-01T00:00:00Z"},
|
||||
"ID":"d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e","Created":"2015-05-26T16:48:53.7987917Z","Path":"top",
|
||||
"Args":[],"Config":{"Hostname":"d59df5276e7b","Domainname":"","User":"","Memory":0,"MemorySwap":0,"CpuShares":0,"Cpuset":"",
|
||||
"AttachStdin":false,"AttachStdout":false,"AttachStderr":false,"PortSpecs":null,"ExposedPorts":null,"Tty":true,"OpenStdin":true,
|
||||
"StdinOnce":false,"Env":null,"Cmd":["top"],"Image":"ubuntu:latest","Volumes":null,"WorkingDir":"","Entrypoint":null,
|
||||
"NetworkDisabled":false,"MacAddress":"","OnBuild":null,"Labels":{}},"Image":"07f8e8c5e66084bef8f848877857537ffe1c47edd01a93af27e7161672ad0e95",
|
||||
"NetworkSettings":{"IPAddress":"172.17.0.1","IPPrefixLen":16,"MacAddress":"02:42:ac:11:00:01","LinkLocalIPv6Address":"fe80::42:acff:fe11:1",
|
||||
"LinkLocalIPv6PrefixLen":64,"GlobalIPv6Address":"","GlobalIPv6PrefixLen":0,"Gateway":"172.17.42.1","IPv6Gateway":"","Bridge":"docker0","PortMapping":null,"Ports":{}},
|
||||
"ResolvConfPath":"/var/lib/docker/containers/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e/resolv.conf",
|
||||
"HostnamePath":"/var/lib/docker/containers/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e/hostname",
|
||||
"HostsPath":"/var/lib/docker/containers/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e/hosts",
|
||||
"LogPath":"/var/lib/docker/containers/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e-json.log",
|
||||
"Name":"/ubuntu","Driver":"aufs","ExecDriver":"native-0.2","MountLabel":"","ProcessLabel":"","AppArmorProfile":"","RestartCount":0,
|
||||
"UpdateDns":false,"Volumes":{"/vol1":"%s"},"VolumesRW":{"/vol1":true},"AppliedVolumesFrom":null}`
|
||||
|
||||
cfg := fmt.Sprintf(config, vfsPath)
|
||||
if err = ioutil.WriteFile(filepath.Join(containerPath, "config.json"), []byte(cfg), 0644); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
hostConfig := `{"Binds":[],"ContainerIDFile":"","LxcConf":[],"Memory":0,"MemorySwap":0,"CpuShares":0,"CpusetCpus":"",
|
||||
"Privileged":false,"PortBindings":{},"Links":null,"PublishAllPorts":false,"Dns":null,"DnsSearch":null,"ExtraHosts":null,"VolumesFrom":null,
|
||||
"Devices":[],"NetworkMode":"bridge","IpcMode":"","PidMode":"","CapAdd":null,"CapDrop":null,"RestartPolicy":{"Name":"no","MaximumRetryCount":0},
|
||||
"SecurityOpt":null,"ReadonlyRootfs":false,"Ulimits":null,"LogConfig":{"Type":"","Config":null},"CgroupParent":""}`
|
||||
if err = ioutil.WriteFile(filepath.Join(containerPath, "hostconfig.json"), []byte(hostConfig), 0644); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
daemon, err := initDaemonForVolumesTest(tmp)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer volumedrivers.Unregister(volume.DefaultDriverName)
|
||||
|
||||
c, err := daemon.load(containerId)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
err = daemon.verifyVolumesInfo(c)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if len(c.MountPoints) != 1 {
|
||||
t.Fatalf("Expected 1 volume mounted, was 0\n")
|
||||
}
|
||||
|
||||
m := c.MountPoints["/vol1"]
|
||||
if m.Name != hostVolumeId {
|
||||
t.Fatalf("Expected mount name to be %s, was %s\n", hostVolumeId, m.Name)
|
||||
}
|
||||
|
||||
if m.Destination != "/vol1" {
|
||||
t.Fatalf("Expected mount destination /vol1, was %s\n", m.Destination)
|
||||
}
|
||||
|
||||
if !m.RW {
|
||||
t.Fatalf("Expected mount point to be RW but it was not\n")
|
||||
}
|
||||
|
||||
if m.Driver != volume.DefaultDriverName {
|
||||
t.Fatalf("Expected mount driver local, was %s\n", m.Driver)
|
||||
}
|
||||
|
||||
newVolumeContent := filepath.Join(volumePath, local.VolumeDataPathName, "helo")
|
||||
b, err := ioutil.ReadFile(newVolumeContent)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if string(b) != "HELO" {
|
||||
t.Fatalf("Expected HELO, was %s\n", string(b))
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoadWithBindMount(t *testing.T) {
|
||||
tmp, err := ioutil.TempDir("", "docker-daemon-test-")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.RemoveAll(tmp)
|
||||
|
||||
containerId := "d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e"
|
||||
containerPath := filepath.Join(tmp, containerId)
|
||||
if err = os.MkdirAll(containerPath, 0755); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
config := `{"State":{"Running":true,"Paused":false,"Restarting":false,"OOMKilled":false,"Dead":false,"Pid":2464,"ExitCode":0,
|
||||
"Error":"","StartedAt":"2015-05-26T16:48:53.869308965Z","FinishedAt":"0001-01-01T00:00:00Z"},
|
||||
"ID":"d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e","Created":"2015-05-26T16:48:53.7987917Z","Path":"top",
|
||||
"Args":[],"Config":{"Hostname":"d59df5276e7b","Domainname":"","User":"","Memory":0,"MemorySwap":0,"CpuShares":0,"Cpuset":"",
|
||||
"AttachStdin":false,"AttachStdout":false,"AttachStderr":false,"PortSpecs":null,"ExposedPorts":null,"Tty":true,"OpenStdin":true,
|
||||
"StdinOnce":false,"Env":null,"Cmd":["top"],"Image":"ubuntu:latest","Volumes":null,"WorkingDir":"","Entrypoint":null,
|
||||
"NetworkDisabled":false,"MacAddress":"","OnBuild":null,"Labels":{}},"Image":"07f8e8c5e66084bef8f848877857537ffe1c47edd01a93af27e7161672ad0e95",
|
||||
"NetworkSettings":{"IPAddress":"172.17.0.1","IPPrefixLen":16,"MacAddress":"02:42:ac:11:00:01","LinkLocalIPv6Address":"fe80::42:acff:fe11:1",
|
||||
"LinkLocalIPv6PrefixLen":64,"GlobalIPv6Address":"","GlobalIPv6PrefixLen":0,"Gateway":"172.17.42.1","IPv6Gateway":"","Bridge":"docker0","PortMapping":null,"Ports":{}},
|
||||
"ResolvConfPath":"/var/lib/docker/containers/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e/resolv.conf",
|
||||
"HostnamePath":"/var/lib/docker/containers/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e/hostname",
|
||||
"HostsPath":"/var/lib/docker/containers/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e/hosts",
|
||||
"LogPath":"/var/lib/docker/containers/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e-json.log",
|
||||
"Name":"/ubuntu","Driver":"aufs","ExecDriver":"native-0.2","MountLabel":"","ProcessLabel":"","AppArmorProfile":"","RestartCount":0,
|
||||
"UpdateDns":false,"Volumes":{"/vol1": "/vol1"},"VolumesRW":{"/vol1":true},"AppliedVolumesFrom":null}`
|
||||
|
||||
if err = ioutil.WriteFile(filepath.Join(containerPath, "config.json"), []byte(config), 0644); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
hostConfig := `{"Binds":["/vol1:/vol1"],"ContainerIDFile":"","LxcConf":[],"Memory":0,"MemorySwap":0,"CpuShares":0,"CpusetCpus":"",
|
||||
"Privileged":false,"PortBindings":{},"Links":null,"PublishAllPorts":false,"Dns":null,"DnsSearch":null,"ExtraHosts":null,"VolumesFrom":null,
|
||||
"Devices":[],"NetworkMode":"bridge","IpcMode":"","PidMode":"","CapAdd":null,"CapDrop":null,"RestartPolicy":{"Name":"no","MaximumRetryCount":0},
|
||||
"SecurityOpt":null,"ReadonlyRootfs":false,"Ulimits":null,"LogConfig":{"Type":"","Config":null},"CgroupParent":""}`
|
||||
if err = ioutil.WriteFile(filepath.Join(containerPath, "hostconfig.json"), []byte(hostConfig), 0644); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
daemon, err := initDaemonForVolumesTest(tmp)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer volumedrivers.Unregister(volume.DefaultDriverName)
|
||||
|
||||
c, err := daemon.load(containerId)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
err = daemon.verifyVolumesInfo(c)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if len(c.MountPoints) != 1 {
|
||||
t.Fatalf("Expected 1 volume mounted, was 0\n")
|
||||
}
|
||||
|
||||
m := c.MountPoints["/vol1"]
|
||||
if m.Name != "" {
|
||||
t.Fatalf("Expected empty mount name, was %s\n", m.Name)
|
||||
}
|
||||
|
||||
if m.Source != "/vol1" {
|
||||
t.Fatalf("Expected mount source /vol1, was %s\n", m.Source)
|
||||
}
|
||||
|
||||
if m.Destination != "/vol1" {
|
||||
t.Fatalf("Expected mount destination /vol1, was %s\n", m.Destination)
|
||||
}
|
||||
|
||||
if !m.RW {
|
||||
t.Fatalf("Expected mount point to be RW but it was not\n")
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoadWithVolume17RC(t *testing.T) {
|
||||
tmp, err := ioutil.TempDir("", "docker-daemon-test-")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.RemoveAll(tmp)
|
||||
|
||||
containerId := "d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e"
|
||||
containerPath := filepath.Join(tmp, containerId)
|
||||
if err := os.MkdirAll(containerPath, 0755); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
hostVolumeId := "6a3c03fc4a4e588561a543cc3bdd50089e27bd11bbb0e551e19bf735e2514101"
|
||||
volumePath := filepath.Join(tmp, "volumes", hostVolumeId)
|
||||
|
||||
if err := os.MkdirAll(volumePath, 0755); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
content := filepath.Join(volumePath, "helo")
|
||||
if err := ioutil.WriteFile(content, []byte("HELO"), 0644); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
config := `{"State":{"Running":true,"Paused":false,"Restarting":false,"OOMKilled":false,"Dead":false,"Pid":2464,"ExitCode":0,
|
||||
"Error":"","StartedAt":"2015-05-26T16:48:53.869308965Z","FinishedAt":"0001-01-01T00:00:00Z"},
|
||||
"ID":"d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e","Created":"2015-05-26T16:48:53.7987917Z","Path":"top",
|
||||
"Args":[],"Config":{"Hostname":"d59df5276e7b","Domainname":"","User":"","Memory":0,"MemorySwap":0,"CpuShares":0,"Cpuset":"",
|
||||
"AttachStdin":false,"AttachStdout":false,"AttachStderr":false,"PortSpecs":null,"ExposedPorts":null,"Tty":true,"OpenStdin":true,
|
||||
"StdinOnce":false,"Env":null,"Cmd":["top"],"Image":"ubuntu:latest","Volumes":null,"WorkingDir":"","Entrypoint":null,
|
||||
"NetworkDisabled":false,"MacAddress":"","OnBuild":null,"Labels":{}},"Image":"07f8e8c5e66084bef8f848877857537ffe1c47edd01a93af27e7161672ad0e95",
|
||||
"NetworkSettings":{"IPAddress":"172.17.0.1","IPPrefixLen":16,"MacAddress":"02:42:ac:11:00:01","LinkLocalIPv6Address":"fe80::42:acff:fe11:1",
|
||||
"LinkLocalIPv6PrefixLen":64,"GlobalIPv6Address":"","GlobalIPv6PrefixLen":0,"Gateway":"172.17.42.1","IPv6Gateway":"","Bridge":"docker0","PortMapping":null,"Ports":{}},
|
||||
"ResolvConfPath":"/var/lib/docker/containers/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e/resolv.conf",
|
||||
"HostnamePath":"/var/lib/docker/containers/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e/hostname",
|
||||
"HostsPath":"/var/lib/docker/containers/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e/hosts",
|
||||
"LogPath":"/var/lib/docker/containers/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e-json.log",
|
||||
"Name":"/ubuntu","Driver":"aufs","ExecDriver":"native-0.2","MountLabel":"","ProcessLabel":"","AppArmorProfile":"","RestartCount":0,
|
||||
"UpdateDns":false,"MountPoints":{"/vol1":{"Name":"6a3c03fc4a4e588561a543cc3bdd50089e27bd11bbb0e551e19bf735e2514101","Destination":"/vol1","Driver":"local","RW":true,"Source":"","Relabel":""}},"AppliedVolumesFrom":null}`
|
||||
|
||||
if err = ioutil.WriteFile(filepath.Join(containerPath, "config.json"), []byte(config), 0644); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
hostConfig := `{"Binds":[],"ContainerIDFile":"","LxcConf":[],"Memory":0,"MemorySwap":0,"CpuShares":0,"CpusetCpus":"",
|
||||
"Privileged":false,"PortBindings":{},"Links":null,"PublishAllPorts":false,"Dns":null,"DnsSearch":null,"ExtraHosts":null,"VolumesFrom":null,
|
||||
"Devices":[],"NetworkMode":"bridge","IpcMode":"","PidMode":"","CapAdd":null,"CapDrop":null,"RestartPolicy":{"Name":"no","MaximumRetryCount":0},
|
||||
"SecurityOpt":null,"ReadonlyRootfs":false,"Ulimits":null,"LogConfig":{"Type":"","Config":null},"CgroupParent":""}`
|
||||
if err = ioutil.WriteFile(filepath.Join(containerPath, "hostconfig.json"), []byte(hostConfig), 0644); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
daemon, err := initDaemonForVolumesTest(tmp)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer volumedrivers.Unregister(volume.DefaultDriverName)
|
||||
|
||||
c, err := daemon.load(containerId)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
err = daemon.verifyVolumesInfo(c)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if len(c.MountPoints) != 1 {
|
||||
t.Fatalf("Expected 1 volume mounted, was 0\n")
|
||||
}
|
||||
|
||||
m := c.MountPoints["/vol1"]
|
||||
if m.Name != hostVolumeId {
|
||||
t.Fatalf("Expected mount name to be %s, was %s\n", hostVolumeId, m.Name)
|
||||
}
|
||||
|
||||
if m.Destination != "/vol1" {
|
||||
t.Fatalf("Expected mount destination /vol1, was %s\n", m.Destination)
|
||||
}
|
||||
|
||||
if !m.RW {
|
||||
t.Fatalf("Expected mount point to be RW but it was not\n")
|
||||
}
|
||||
|
||||
if m.Driver != volume.DefaultDriverName {
|
||||
t.Fatalf("Expected mount driver local, was %s\n", m.Driver)
|
||||
}
|
||||
|
||||
newVolumeContent := filepath.Join(volumePath, local.VolumeDataPathName, "helo")
|
||||
b, err := ioutil.ReadFile(newVolumeContent)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if string(b) != "HELO" {
|
||||
t.Fatalf("Expected HELO, was %s\n", string(b))
|
||||
}
|
||||
}
|
||||
|
||||
func TestRemoveLocalVolumesFollowingSymlinks(t *testing.T) {
|
||||
tmp, err := ioutil.TempDir("", "docker-daemon-test-")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.RemoveAll(tmp)
|
||||
|
||||
containerId := "d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e"
|
||||
containerPath := filepath.Join(tmp, containerId)
|
||||
if err := os.MkdirAll(containerPath, 0755); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
hostVolumeId := stringid.GenerateRandomID()
|
||||
vfsPath := filepath.Join(tmp, "vfs", "dir", hostVolumeId)
|
||||
volumePath := filepath.Join(tmp, "volumes", hostVolumeId)
|
||||
|
||||
if err := os.MkdirAll(vfsPath, 0755); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := os.MkdirAll(volumePath, 0755); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
content := filepath.Join(vfsPath, "helo")
|
||||
if err := ioutil.WriteFile(content, []byte("HELO"), 0644); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
volumePath := filepath.Join(tmp, "vfs", "dir", hostVolumeId)
|
||||
|
||||
config := `{"State":{"Running":true,"Paused":false,"Restarting":false,"OOMKilled":false,"Dead":false,"Pid":2464,"ExitCode":0,
|
||||
"Error":"","StartedAt":"2015-05-26T16:48:53.869308965Z","FinishedAt":"0001-01-01T00:00:00Z"},
|
||||
@@ -451,7 +152,7 @@ func TestRemoveLocalVolumesFollowingSymlinks(t *testing.T) {
|
||||
"Name":"/ubuntu","Driver":"aufs","ExecDriver":"native-0.2","MountLabel":"","ProcessLabel":"","AppArmorProfile":"","RestartCount":0,
|
||||
"UpdateDns":false,"Volumes":{"/vol1":"%s"},"VolumesRW":{"/vol1":true},"AppliedVolumesFrom":null}`
|
||||
|
||||
cfg := fmt.Sprintf(config, vfsPath)
|
||||
cfg := fmt.Sprintf(config, volumePath)
|
||||
if err = ioutil.WriteFile(filepath.Join(containerPath, "config.json"), []byte(cfg), 0644); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -464,53 +165,43 @@ func TestRemoveLocalVolumesFollowingSymlinks(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
daemon, err := initDaemonForVolumesTest(tmp)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer volumedrivers.Unregister(volume.DefaultDriverName)
|
||||
|
||||
c, err := daemon.load(containerId)
|
||||
if err != nil {
|
||||
if err = os.MkdirAll(volumePath, 0755); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
err = daemon.verifyVolumesInfo(c)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if len(c.MountPoints) != 1 {
|
||||
t.Fatalf("Expected 1 volume mounted, was 0\n")
|
||||
}
|
||||
|
||||
m := c.MountPoints["/vol1"]
|
||||
v, err := createVolume(m.Name, m.Driver)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if err := removeVolume(v); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
fi, err := os.Stat(vfsPath)
|
||||
if err == nil || !os.IsNotExist(err) {
|
||||
t.Fatalf("Expected vfs path to not exist: %v - %v\n", fi, err)
|
||||
}
|
||||
}
|
||||
|
||||
func initDaemonForVolumesTest(tmp string) (*Daemon, error) {
|
||||
daemon := &Daemon{
|
||||
repository: tmp,
|
||||
root: tmp,
|
||||
}
|
||||
|
||||
volumesDriver, err := local.New(tmp)
|
||||
c, err := daemon.load(containerId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
t.Fatal(err)
|
||||
}
|
||||
volumedrivers.Register(volumesDriver, volumesDriver.Name())
|
||||
|
||||
return daemon, nil
|
||||
err = daemon.verifyOldVolumesInfo(c)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if len(c.MountPoints) != 1 {
|
||||
t.Fatalf("Expected 1 volume mounted, was 0\n")
|
||||
}
|
||||
|
||||
m := c.MountPoints["/vol1"]
|
||||
if m.Name != hostVolumeId {
|
||||
t.Fatalf("Expected mount name to be %s, was %s\n", hostVolumeId, m.Name)
|
||||
}
|
||||
|
||||
if m.Destination != "/vol1" {
|
||||
t.Fatalf("Expected mount destination /vol1, was %s\n", m.Destination)
|
||||
}
|
||||
|
||||
if !m.RW {
|
||||
t.Fatalf("Expected mount point to be RW but it was not\n")
|
||||
}
|
||||
|
||||
if m.Driver != volume.DefaultDriverName {
|
||||
t.Fatalf("Expected mount driver local, was %s\n", m.Driver)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,6 @@ func InitContainer(c *Command) *configs.Config {
|
||||
container.Devices = c.AutoCreatedDevices
|
||||
container.Rootfs = c.Rootfs
|
||||
container.Readonlyfs = c.ReadonlyRootfs
|
||||
container.Privatefs = true
|
||||
|
||||
// check to see if we are running in ramdisk to disable pivot root
|
||||
container.NoPivotRoot = os.Getenv("DOCKER_RAMDISK") != ""
|
||||
|
||||
@@ -124,7 +124,7 @@ func (d *driver) Run(c *execdriver.Command, pipes *execdriver.Pipes, startCallba
|
||||
dataPath = d.containerDir(c.ID)
|
||||
)
|
||||
|
||||
if c.Network == nil || (c.Network.NamespacePath == "" && c.Network.ContainerID == "") {
|
||||
if c.Network.NamespacePath == "" && c.Network.ContainerID == "" {
|
||||
return execdriver.ExitStatus{ExitCode: -1}, fmt.Errorf("empty namespace path for non-container network")
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,6 @@ import (
|
||||
"github.com/docker/docker/daemon/graphdriver"
|
||||
"github.com/docker/docker/pkg/mount"
|
||||
"github.com/docker/docker/pkg/parsers"
|
||||
"github.com/docker/libcontainer/label"
|
||||
zfs "github.com/mistifyio/go-zfs"
|
||||
)
|
||||
|
||||
@@ -282,15 +281,14 @@ func (d *Driver) Remove(id string) error {
|
||||
func (d *Driver) Get(id, mountLabel string) (string, error) {
|
||||
mountpoint := d.MountPath(id)
|
||||
filesystem := d.ZfsPath(id)
|
||||
options := label.FormatMountLabel("", mountLabel)
|
||||
log.Debugf(`[zfs] mount("%s", "%s", "%s")`, filesystem, mountpoint, options)
|
||||
log.Debugf(`[zfs] mount("%s", "%s", "%s")`, filesystem, mountpoint, mountLabel)
|
||||
|
||||
// Create the target directories if they don't exist
|
||||
if err := os.MkdirAll(mountpoint, 0755); err != nil && !os.IsExist(err) {
|
||||
return "", err
|
||||
}
|
||||
|
||||
err := mount.Mount(filesystem, mountpoint, "zfs", options)
|
||||
err := mount.Mount(filesystem, mountpoint, "zfs", mountLabel)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("error creating zfs mount of %s to %s: %v", filesystem, mountpoint, err)
|
||||
}
|
||||
|
||||
@@ -63,8 +63,7 @@ func (daemon *Daemon) imgDeleteHelper(name string, list *[]types.ImageDelete, fi
|
||||
repos := daemon.Repositories().ByID()[img.ID]
|
||||
|
||||
//If delete by id, see if the id belong only to one repository
|
||||
deleteByID := repoName == ""
|
||||
if deleteByID {
|
||||
if repoName == "" {
|
||||
for _, repoAndTag := range repos {
|
||||
parsedRepo, parsedTag := parsers.ParseRepositoryTag(repoAndTag)
|
||||
if repoName == "" || repoName == parsedRepo {
|
||||
@@ -92,7 +91,7 @@ func (daemon *Daemon) imgDeleteHelper(name string, list *[]types.ImageDelete, fi
|
||||
return nil
|
||||
}
|
||||
|
||||
if len(repos) <= 1 || (len(repoAndTags) <= 1 && deleteByID) {
|
||||
if len(repos) <= 1 {
|
||||
if err := daemon.canDeleteImage(img.ID, force); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
+3
-36
@@ -25,40 +25,6 @@ func (daemon *Daemon) ContainerInspect(name string) (*types.ContainerJSON, error
|
||||
container.Lock()
|
||||
defer container.Unlock()
|
||||
|
||||
base, err := daemon.getInspectData(container)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &types.ContainerJSON{base, container.Config}, nil
|
||||
}
|
||||
|
||||
func (daemon *Daemon) ContainerInspectRaw(name string) (*types.ContainerJSONRaw, error) {
|
||||
container, err := daemon.Get(name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
container.Lock()
|
||||
defer container.Unlock()
|
||||
|
||||
base, err := daemon.getInspectData(container)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
config := &types.ContainerConfig{
|
||||
container.Config,
|
||||
container.hostConfig.Memory,
|
||||
container.hostConfig.MemorySwap,
|
||||
container.hostConfig.CpuShares,
|
||||
container.hostConfig.CpusetCpus,
|
||||
}
|
||||
|
||||
return &types.ContainerJSONRaw{base, config}, nil
|
||||
}
|
||||
|
||||
func (daemon *Daemon) getInspectData(container *Container) (*types.ContainerJSONBase, error) {
|
||||
// make a copy to play with
|
||||
hostConfig := *container.hostConfig
|
||||
|
||||
@@ -94,11 +60,12 @@ func (daemon *Daemon) getInspectData(container *Container) (*types.ContainerJSON
|
||||
volumesRW[m.Destination] = m.RW
|
||||
}
|
||||
|
||||
contJSONBase := &types.ContainerJSONBase{
|
||||
contJSON := &types.ContainerJSON{
|
||||
Id: container.ID,
|
||||
Created: container.Created,
|
||||
Path: container.Path,
|
||||
Args: container.Args,
|
||||
Config: container.Config,
|
||||
State: containerState,
|
||||
Image: container.ImageID,
|
||||
NetworkSettings: container.NetworkSettings,
|
||||
@@ -119,7 +86,7 @@ func (daemon *Daemon) getInspectData(container *Container) (*types.ContainerJSON
|
||||
HostConfig: &hostConfig,
|
||||
}
|
||||
|
||||
return contJSONBase, nil
|
||||
return contJSON, nil
|
||||
}
|
||||
|
||||
func (daemon *Daemon) ContainerExecInspect(id string) (*execConfig, error) {
|
||||
|
||||
+7
-21
@@ -2,7 +2,6 @@ package logger
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"io"
|
||||
"sync"
|
||||
"time"
|
||||
@@ -41,27 +40,14 @@ func (c *Copier) Run() {
|
||||
|
||||
func (c *Copier) copySrc(name string, src io.Reader) {
|
||||
defer c.copyJobs.Done()
|
||||
reader := bufio.NewReader(src)
|
||||
|
||||
for {
|
||||
line, err := reader.ReadBytes('\n')
|
||||
line = bytes.TrimSuffix(line, []byte{'\n'})
|
||||
|
||||
// ReadBytes can return full or partial output even when it failed.
|
||||
// e.g. it can return a full entry and EOF.
|
||||
if err == nil || len(line) > 0 {
|
||||
if logErr := c.dst.Log(&Message{ContainerID: c.cid, Line: line, Source: name, Timestamp: time.Now().UTC()}); logErr != nil {
|
||||
logrus.Errorf("Failed to log msg %q for logger %s: %s", line, c.dst.Name(), logErr)
|
||||
}
|
||||
scanner := bufio.NewScanner(src)
|
||||
for scanner.Scan() {
|
||||
if err := c.dst.Log(&Message{ContainerID: c.cid, Line: scanner.Bytes(), Source: name, Timestamp: time.Now().UTC()}); err != nil {
|
||||
logrus.Errorf("Failed to log msg %q for logger %s: %s", scanner.Bytes(), c.dst.Name(), err)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
if err != io.EOF {
|
||||
logrus.Errorf("Error scanning log stream: %s", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
}
|
||||
if err := scanner.Err(); err != nil {
|
||||
logrus.Errorf("Error scanning log stream: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,17 +3,14 @@
|
||||
package syslog
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"log/syslog"
|
||||
"net"
|
||||
"net/url"
|
||||
"os"
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
"github.com/docker/docker/daemon/logger"
|
||||
"github.com/docker/docker/pkg/urlutil"
|
||||
)
|
||||
|
||||
const name = "syslog"
|
||||
@@ -30,18 +27,7 @@ func init() {
|
||||
|
||||
func New(ctx logger.Context) (logger.Logger, error) {
|
||||
tag := ctx.ContainerID[:12]
|
||||
|
||||
proto, address, err := parseAddress(ctx.Config["syslog-address"])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
log, err := syslog.Dial(
|
||||
proto,
|
||||
address,
|
||||
syslog.LOG_DAEMON,
|
||||
path.Base(os.Args[0])+"/"+tag,
|
||||
)
|
||||
log, err := syslog.New(syslog.LOG_DAEMON, fmt.Sprintf("%s/%s", path.Base(os.Args[0]), tag))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -69,33 +55,3 @@ func (s *Syslog) Name() string {
|
||||
func (s *Syslog) GetReader() (io.Reader, error) {
|
||||
return nil, logger.ReadLogsNotSupported
|
||||
}
|
||||
|
||||
func parseAddress(address string) (string, string, error) {
|
||||
if urlutil.IsTransportURL(address) {
|
||||
url, err := url.Parse(address)
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
|
||||
// unix socket validation
|
||||
if url.Scheme == "unix" {
|
||||
if _, err := os.Stat(url.Path); err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
return url.Scheme, url.Path, nil
|
||||
}
|
||||
|
||||
// here we process tcp|udp
|
||||
host := url.Host
|
||||
if _, _, err := net.SplitHostPort(host); err != nil {
|
||||
if !strings.Contains(err.Error(), "missing port in address") {
|
||||
return "", "", err
|
||||
}
|
||||
host = host + ":514"
|
||||
}
|
||||
|
||||
return url.Scheme, host, nil
|
||||
}
|
||||
|
||||
return "", "", nil
|
||||
}
|
||||
|
||||
+6
-24
@@ -15,39 +15,21 @@ func (daemon *Daemon) ContainerStats(name string, stream bool, out io.Writer) er
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var preCpuStats types.CpuStats
|
||||
getStat := func(v interface{}) *types.Stats {
|
||||
enc := json.NewEncoder(out)
|
||||
for v := range updates {
|
||||
update := v.(*execdriver.ResourceStats)
|
||||
ss := convertToAPITypes(update.Stats)
|
||||
ss.PreCpuStats = preCpuStats
|
||||
ss.MemoryStats.Limit = uint64(update.MemoryLimit)
|
||||
ss.Read = update.Read
|
||||
ss.CpuStats.SystemUsage = update.SystemUsage
|
||||
preCpuStats = ss.CpuStats
|
||||
return ss
|
||||
}
|
||||
|
||||
enc := json.NewEncoder(out)
|
||||
|
||||
if !stream {
|
||||
// prime the cpu stats so they aren't 0 in the final output
|
||||
s := getStat(<-updates)
|
||||
|
||||
// now pull stats again with the cpu stats primed
|
||||
s = getStat(<-updates)
|
||||
err := enc.Encode(s)
|
||||
daemon.UnsubscribeToContainerStats(name, updates)
|
||||
return err
|
||||
}
|
||||
|
||||
for v := range updates {
|
||||
s := getStat(v)
|
||||
if err := enc.Encode(s); err != nil {
|
||||
if err := enc.Encode(ss); err != nil {
|
||||
// TODO: handle the specific broken pipe
|
||||
daemon.UnsubscribeToContainerStats(name, updates)
|
||||
return err
|
||||
}
|
||||
if !stream {
|
||||
break
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
+38
-92
@@ -1,17 +1,16 @@
|
||||
package daemon
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
"github.com/docker/docker/pkg/chrootarchive"
|
||||
"github.com/docker/docker/runconfig"
|
||||
"github.com/docker/docker/volume"
|
||||
"github.com/docker/docker/volume/local"
|
||||
"github.com/docker/libcontainer/label"
|
||||
)
|
||||
|
||||
@@ -53,13 +52,6 @@ func (m *mountPoint) Path() string {
|
||||
return m.Source
|
||||
}
|
||||
|
||||
// BackwardsCompatible decides whether this mount point can be
|
||||
// used in old versions of Docker or not.
|
||||
// Only bind mounts and local volumes can be used in old versions of Docker.
|
||||
func (m *mountPoint) BackwardsCompatible() bool {
|
||||
return len(m.Source) > 0 || m.Driver == volume.DefaultDriverName
|
||||
}
|
||||
|
||||
func parseBindMount(spec string, mountLabel string, config *runconfig.Config) (*mountPoint, error) {
|
||||
bind := &mountPoint{
|
||||
RW: true,
|
||||
@@ -82,7 +74,7 @@ func parseBindMount(spec string, mountLabel string, config *runconfig.Config) (*
|
||||
return nil, fmt.Errorf("Invalid volume specification: %s", spec)
|
||||
}
|
||||
|
||||
name, source, err := parseVolumeSource(arr[0])
|
||||
name, source, err := parseVolumeSource(arr[0], config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -239,99 +231,53 @@ func (daemon *Daemon) registerMountPoints(container *Container, hostConfig *runc
|
||||
mountPoints[bind.Destination] = bind
|
||||
}
|
||||
|
||||
// Keep backwards compatible structures
|
||||
bcVolumes := map[string]string{}
|
||||
bcVolumesRW := map[string]bool{}
|
||||
for _, m := range mountPoints {
|
||||
if m.BackwardsCompatible() {
|
||||
bcVolumes[m.Destination] = m.Path()
|
||||
bcVolumesRW[m.Destination] = m.RW
|
||||
}
|
||||
}
|
||||
|
||||
container.Lock()
|
||||
container.MountPoints = mountPoints
|
||||
container.Volumes = bcVolumes
|
||||
container.VolumesRW = bcVolumesRW
|
||||
container.Unlock()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// verifyVolumesInfo ports volumes configured for the containers pre docker 1.7.
|
||||
// verifyOldVolumesInfo ports volumes configured for the containers pre docker 1.7.
|
||||
// It reads the container configuration and creates valid mount points for the old volumes.
|
||||
func (daemon *Daemon) verifyVolumesInfo(container *Container) error {
|
||||
// Inspect old structures only when we're upgrading from old versions
|
||||
// to versions >= 1.7 and the MountPoints has not been populated with volumes data.
|
||||
if len(container.MountPoints) == 0 && len(container.Volumes) > 0 {
|
||||
for destination, hostPath := range container.Volumes {
|
||||
vfsPath := filepath.Join(daemon.root, "vfs", "dir")
|
||||
rw := container.VolumesRW != nil && container.VolumesRW[destination]
|
||||
|
||||
if strings.HasPrefix(hostPath, vfsPath) {
|
||||
id := filepath.Base(hostPath)
|
||||
if err := migrateVolume(id, hostPath); err != nil {
|
||||
return err
|
||||
}
|
||||
container.addLocalMountPoint(id, destination, rw)
|
||||
} else { // Bind mount
|
||||
id, source, err := parseVolumeSource(hostPath)
|
||||
// We should not find an error here coming
|
||||
// from the old configuration, but who knows.
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
container.addBindMountPoint(id, source, destination, rw)
|
||||
}
|
||||
func (daemon *Daemon) verifyOldVolumesInfo(container *Container) error {
|
||||
jsonPath, err := container.jsonPath()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
f, err := os.Open(jsonPath)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return nil
|
||||
}
|
||||
} else if len(container.MountPoints) > 0 {
|
||||
// Volumes created with a Docker version >= 1.7. We verify integrity in case of data created
|
||||
// with Docker 1.7 RC versions that put the information in
|
||||
// DOCKER_ROOT/volumes/VOLUME_ID rather than DOCKER_ROOT/volumes/VOLUME_ID/_container_data.
|
||||
l, err := getVolumeDriver(volume.DefaultDriverName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, m := range container.MountPoints {
|
||||
if m.Driver != volume.DefaultDriverName {
|
||||
continue
|
||||
}
|
||||
dataPath := l.(*local.Root).DataPath(m.Name)
|
||||
volumePath := filepath.Dir(dataPath)
|
||||
|
||||
d, err := ioutil.ReadDir(volumePath)
|
||||
if err != nil {
|
||||
// If the volume directory doesn't exist yet it will be recreated,
|
||||
// so we only return the error when there is a different issue.
|
||||
if !os.IsNotExist(err) {
|
||||
return err
|
||||
}
|
||||
// Do not check when the volume directory does not exist.
|
||||
continue
|
||||
}
|
||||
if validVolumeLayout(d) {
|
||||
continue
|
||||
}
|
||||
|
||||
if err := os.Mkdir(dataPath, 0755); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Move data inside the data directory
|
||||
for _, f := range d {
|
||||
oldp := filepath.Join(volumePath, f.Name())
|
||||
newp := filepath.Join(dataPath, f.Name())
|
||||
if err := os.Rename(oldp, newp); err != nil {
|
||||
logrus.Errorf("Unable to move %s to %s\n", oldp, newp)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return container.ToDisk()
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
type oldContVolCfg struct {
|
||||
Volumes map[string]string
|
||||
VolumesRW map[string]bool
|
||||
}
|
||||
|
||||
vols := oldContVolCfg{
|
||||
Volumes: make(map[string]string),
|
||||
VolumesRW: make(map[string]bool),
|
||||
}
|
||||
if err := json.NewDecoder(f).Decode(&vols); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for destination, hostPath := range vols.Volumes {
|
||||
vfsPath := filepath.Join(daemon.root, "vfs", "dir")
|
||||
|
||||
if strings.HasPrefix(hostPath, vfsPath) {
|
||||
id := filepath.Base(hostPath)
|
||||
|
||||
rw := vols.VolumesRW != nil && vols.VolumesRW[destination]
|
||||
container.addLocalMountPoint(id, destination, rw)
|
||||
}
|
||||
}
|
||||
|
||||
return container.ToDisk()
|
||||
}
|
||||
|
||||
func createVolume(name, driverName string) (volume.Volume, error) {
|
||||
|
||||
@@ -5,6 +5,7 @@ package daemon
|
||||
import (
|
||||
"path/filepath"
|
||||
|
||||
"github.com/docker/docker/runconfig"
|
||||
"github.com/docker/docker/volume"
|
||||
"github.com/docker/docker/volume/drivers"
|
||||
)
|
||||
@@ -16,7 +17,7 @@ func getVolumeDriver(name string) (volume.Driver, error) {
|
||||
return volumedrivers.Lookup(name)
|
||||
}
|
||||
|
||||
func parseVolumeSource(spec string) (string, string, error) {
|
||||
func parseVolumeSource(spec string, config *runconfig.Config) (string, string, error) {
|
||||
if !filepath.IsAbs(spec) {
|
||||
return spec, "", nil
|
||||
}
|
||||
|
||||
@@ -10,8 +10,6 @@ import (
|
||||
|
||||
"github.com/docker/docker/daemon/execdriver"
|
||||
"github.com/docker/docker/pkg/system"
|
||||
"github.com/docker/docker/volume"
|
||||
"github.com/docker/docker/volume/local"
|
||||
)
|
||||
|
||||
// copyOwnership copies the permissions and uid:gid of the source file
|
||||
@@ -70,50 +68,3 @@ func (m mounts) Swap(i, j int) {
|
||||
func (m mounts) parts(i int) int {
|
||||
return len(strings.Split(filepath.Clean(m[i].Destination), string(os.PathSeparator)))
|
||||
}
|
||||
|
||||
// migrateVolume links the contents of a volume created pre Docker 1.7
|
||||
// into the location expected by the local driver.
|
||||
// It creates a symlink from DOCKER_ROOT/vfs/dir/VOLUME_ID to DOCKER_ROOT/volumes/VOLUME_ID/_container_data.
|
||||
// It preserves the volume json configuration generated pre Docker 1.7 to be able to
|
||||
// downgrade from Docker 1.7 to Docker 1.6 without losing volume compatibility.
|
||||
func migrateVolume(id, vfs string) error {
|
||||
l, err := getVolumeDriver(volume.DefaultDriverName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
newDataPath := l.(*local.Root).DataPath(id)
|
||||
fi, err := os.Stat(newDataPath)
|
||||
if err != nil && !os.IsNotExist(err) {
|
||||
return err
|
||||
}
|
||||
|
||||
if fi != nil && fi.IsDir() {
|
||||
return nil
|
||||
}
|
||||
|
||||
return os.Symlink(vfs, newDataPath)
|
||||
}
|
||||
|
||||
// validVolumeLayout checks whether the volume directory layout
|
||||
// is valid to work with Docker post 1.7 or not.
|
||||
func validVolumeLayout(files []os.FileInfo) bool {
|
||||
if len(files) == 1 && files[0].Name() == local.VolumeDataPathName && files[0].IsDir() {
|
||||
return true
|
||||
}
|
||||
|
||||
if len(files) != 2 {
|
||||
return false
|
||||
}
|
||||
|
||||
for _, f := range files {
|
||||
if f.Name() == "config.json" ||
|
||||
(f.Name() == local.VolumeDataPathName && f.Mode()&os.ModeSymlink == os.ModeSymlink) {
|
||||
// Old volume configuration, we ignore it
|
||||
continue
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/docker/docker/runconfig"
|
||||
"github.com/docker/docker/volume"
|
||||
"github.com/docker/docker/volume/drivers"
|
||||
)
|
||||
@@ -14,7 +15,7 @@ func getVolumeDriver(_ string) (volume.Driver, error) {
|
||||
return volumedrivers.Lookup(volume.DefaultDriverName)
|
||||
}
|
||||
|
||||
func parseVolumeSource(spec string) (string, string, error) {
|
||||
func parseVolumeSource(spec string, _ *runconfig.Config) (string, string, error) {
|
||||
if !filepath.IsAbs(spec) {
|
||||
return "", "", fmt.Errorf("cannot bind mount volume: %s volume paths must be absolute.", spec)
|
||||
}
|
||||
|
||||
@@ -2,11 +2,7 @@
|
||||
|
||||
package daemon
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/docker/docker/daemon/execdriver"
|
||||
)
|
||||
import "github.com/docker/docker/daemon/execdriver"
|
||||
|
||||
// Not supported on Windows
|
||||
func copyOwnership(source, destination string) error {
|
||||
@@ -16,11 +12,3 @@ func copyOwnership(source, destination string) error {
|
||||
func (container *Container) setupMounts() ([]execdriver.Mount, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func migrateVolume(id, vfs string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func validVolumeLayout(files []os.FileInfo) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
+1
-6
@@ -16,7 +16,6 @@ import (
|
||||
flag "github.com/docker/docker/pkg/mflag"
|
||||
"github.com/docker/docker/pkg/reexec"
|
||||
"github.com/docker/docker/pkg/term"
|
||||
"github.com/docker/docker/utils"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -162,9 +161,5 @@ func main() {
|
||||
}
|
||||
|
||||
func showVersion() {
|
||||
if utils.ExperimentalBuild() {
|
||||
fmt.Printf("Docker version %s, build %s, experimental\n", dockerversion.VERSION, dockerversion.GITCOMMIT)
|
||||
} else {
|
||||
fmt.Printf("Docker version %s, build %s\n", dockerversion.VERSION, dockerversion.GITCOMMIT)
|
||||
}
|
||||
fmt.Printf("Docker version %s, build %s\n", dockerversion.VERSION, dockerversion.GITCOMMIT)
|
||||
}
|
||||
|
||||
@@ -1,2 +1,5 @@
|
||||
# generated by man/man/md2man-all.sh
|
||||
man1/
|
||||
man5/
|
||||
# avoid commiting the awsconfig file used for releases
|
||||
awsconfig
|
||||
|
||||
+157
-7
@@ -1,13 +1,163 @@
|
||||
FROM docs/base:hugo
|
||||
MAINTAINER Mary Anthony <mary@docker.com> (@moxiegirl)
|
||||
#
|
||||
# See the top level Makefile in https://github.com/docker/docker for usage.
|
||||
#
|
||||
FROM docs/base:latest
|
||||
MAINTAINER Sven Dowideit <SvenDowideit@docker.com> (@SvenDowideit)
|
||||
|
||||
# To get the git info for this repo
|
||||
# This section ensures we pull the correct version of each
|
||||
# sub project
|
||||
ENV COMPOSE_BRANCH release
|
||||
ENV SWARM_BRANCH v0.2.0
|
||||
ENV MACHINE_BRANCH docs
|
||||
ENV DISTRIB_BRANCH docs
|
||||
ENV KITEMATIC_BRANCH master
|
||||
|
||||
|
||||
# TODO: need the full repo source to get the git version info
|
||||
COPY . /src
|
||||
|
||||
COPY . /docs/content/
|
||||
# Reset the /docs dir so we can replace the theme meta with the new repo's git info
|
||||
# RUN git reset --hard
|
||||
|
||||
WORKDIR /docs/content
|
||||
# Then copy the desired docs into the /docs/sources/ dir
|
||||
COPY ./sources/ /docs/sources
|
||||
|
||||
RUN /docs/content/touch-up.sh
|
||||
COPY ./VERSION VERSION
|
||||
|
||||
WORKDIR /docs
|
||||
# adding the image spec will require Docker 1.5 and `docker build -f docs/Dockerfile .`
|
||||
#COPY ./image/spec/v1.md /docs/sources/reference/image-spec-v1.md
|
||||
|
||||
# TODO: don't do this - look at merging the yml file in build.sh
|
||||
COPY ./mkdocs.yml ./s3_website.json ./release.sh ./
|
||||
|
||||
#######################
|
||||
# Docker Distribution
|
||||
########################
|
||||
|
||||
#ADD https://raw.githubusercontent.com/docker/distribution/${DISTRIB_BRANCH}/docs/mkdocs.yml /docs/mkdocs-distribution.yml
|
||||
|
||||
ADD https://raw.githubusercontent.com/docker/distribution/${DISTRIB_BRANCH}/docs/images/notifications.png \
|
||||
https://raw.githubusercontent.com/docker/distribution/${DISTRIB_BRANCH}/docs/images/registry.png \
|
||||
/docs/sources/registry/images/
|
||||
|
||||
ADD https://raw.githubusercontent.com/docker/distribution/${DISTRIB_BRANCH}/docs/index.md \
|
||||
https://raw.githubusercontent.com/docker/distribution/${DISTRIB_BRANCH}/docs/deploying.md \
|
||||
https://raw.githubusercontent.com/docker/distribution/${DISTRIB_BRANCH}/docs/configuration.md \
|
||||
https://raw.githubusercontent.com/docker/distribution/${DISTRIB_BRANCH}/docs/storagedrivers.md \
|
||||
https://raw.githubusercontent.com/docker/distribution/${DISTRIB_BRANCH}/docs/notifications.md \
|
||||
/docs/sources/registry/
|
||||
|
||||
ADD https://raw.githubusercontent.com/docker/distribution/${DISTRIB_BRANCH}/docs/spec/api.md \
|
||||
https://raw.githubusercontent.com/docker/distribution/${DISTRIB_BRANCH}/docs/spec/json.md \
|
||||
/docs/sources/registry/spec/
|
||||
|
||||
ADD https://raw.githubusercontent.com/docker/distribution/${DISTRIB_BRANCH}/docs/storage-drivers/s3.md \
|
||||
https://raw.githubusercontent.com/docker/distribution/${DISTRIB_BRANCH}/docs/storage-drivers/azure.md \
|
||||
https://raw.githubusercontent.com/docker/distribution/${DISTRIB_BRANCH}/docs/storage-drivers/filesystem.md \
|
||||
https://raw.githubusercontent.com/docker/distribution/${DISTRIB_BRANCH}/docs/storage-drivers/inmemory.md \
|
||||
/docs/sources/registry/storage-drivers/
|
||||
|
||||
ADD https://raw.githubusercontent.com/docker/distribution/${DISTRIB_BRANCH}/docs/spec/auth/token.md /docs/sources/registry/spec/auth/token.md
|
||||
|
||||
RUN sed -i.old '1s;^;no_version_dropdown: true;' \
|
||||
/docs/sources/registry/*.md \
|
||||
/docs/sources/registry/spec/*.md \
|
||||
/docs/sources/registry/spec/auth/*.md \
|
||||
/docs/sources/registry/storage-drivers/*.md
|
||||
|
||||
RUN sed -i.old -e '/^<!--GITHUB/g' -e '/^IGNORES-->/g'\
|
||||
/docs/sources/registry/*.md \
|
||||
/docs/sources/registry/spec/*.md \
|
||||
/docs/sources/registry/spec/auth/*.md \
|
||||
/docs/sources/registry/storage-drivers/*.md
|
||||
|
||||
#######################
|
||||
# Docker Swarm
|
||||
#######################
|
||||
|
||||
#ADD https://raw.githubusercontent.com/docker/swarm/${SWARM_BRANCH}/docs/mkdocs.yml /docs/mkdocs-swarm.yml
|
||||
ADD https://raw.githubusercontent.com/docker/swarm/${SWARM_BRANCH}/docs/index.md /docs/sources/swarm/index.md
|
||||
|
||||
ADD https://raw.githubusercontent.com/docker/swarm/${SWARM_BRANCH}/discovery/README.md /docs/sources/swarm/discovery.md
|
||||
|
||||
ADD https://raw.githubusercontent.com/docker/swarm/${SWARM_BRANCH}/api/README.md /docs/sources/swarm/API.md
|
||||
|
||||
ADD https://raw.githubusercontent.com/docker/swarm/${SWARM_BRANCH}/scheduler/filter/README.md /docs/sources/swarm/scheduler/filter.md
|
||||
|
||||
ADD https://raw.githubusercontent.com/docker/swarm/${SWARM_BRANCH}/scheduler/strategy/README.md /docs/sources/swarm/scheduler/strategy.md
|
||||
|
||||
RUN sed -i.old '1s;^;no_version_dropdown: true;' /docs/sources/swarm/*.md /docs/sources/swarm/scheduler/*.md
|
||||
|
||||
#######################
|
||||
# Docker Machine
|
||||
#######################
|
||||
#ADD https://raw.githubusercontent.com/docker/machine/${MACHINE_BRANCH}/docs/mkdocs.yml /docs/mkdocs-machine.yml
|
||||
|
||||
ADD https://raw.githubusercontent.com/docker/machine/${MACHINE_BRANCH}/docs/index.md /docs/sources/machine/index.md
|
||||
RUN sed -i.old '1s;^;no_version_dropdown: true;' /docs/sources/machine/index.md
|
||||
|
||||
#######################
|
||||
# Docker Compose
|
||||
#######################
|
||||
|
||||
#ADD https://raw.githubusercontent.com/docker/compose/${COMPOSE_BRANCH}/docs/mkdocs.yml /docs/mkdocs-compose.yml
|
||||
|
||||
ADD https://raw.githubusercontent.com/docker/compose/${COMPOSE_BRANCH}/docs/index.md \
|
||||
https://raw.githubusercontent.com/docker/compose/${COMPOSE_BRANCH}/docs/install.md \
|
||||
https://raw.githubusercontent.com/docker/compose/${COMPOSE_BRANCH}/docs/cli.md \
|
||||
https://raw.githubusercontent.com/docker/compose/${COMPOSE_BRANCH}/docs/yml.md \
|
||||
https://raw.githubusercontent.com/docker/compose/${COMPOSE_BRANCH}/docs/env.md \
|
||||
https://raw.githubusercontent.com/docker/compose/${COMPOSE_BRANCH}/docs/completion.md \
|
||||
https://raw.githubusercontent.com/docker/compose/${COMPOSE_BRANCH}/docs/django.md \
|
||||
https://raw.githubusercontent.com/docker/compose/${COMPOSE_BRANCH}/docs/rails.md \
|
||||
https://raw.githubusercontent.com/docker/compose/${COMPOSE_BRANCH}/docs/wordpress.md \
|
||||
https://raw.githubusercontent.com/docker/compose/${COMPOSE_BRANCH}/docs/extends.md \
|
||||
https://raw.githubusercontent.com/docker/compose/${COMPOSE_BRANCH}/docs/production.md \
|
||||
/docs/sources/compose/
|
||||
|
||||
RUN sed -i.old '1s;^;no_version_dropdown: true;' /docs/sources/compose/*.md
|
||||
|
||||
#######################
|
||||
# Kitematic
|
||||
#######################
|
||||
ADD https://raw.githubusercontent.com/kitematic/kitematic/${KITEMATIC_BRANCH}/docs/faq.md \
|
||||
https://raw.githubusercontent.com/kitematic/kitematic/${KITEMATIC_BRANCH}/docs/index.md \
|
||||
https://raw.githubusercontent.com/kitematic/kitematic/${KITEMATIC_BRANCH}/docs/known-issues.md \
|
||||
https://raw.githubusercontent.com/kitematic/kitematic/${KITEMATIC_BRANCH}/docs/minecraft-server.md \
|
||||
https://raw.githubusercontent.com/kitematic/kitematic/${KITEMATIC_BRANCH}/docs/nginx-web-server.md \
|
||||
https://raw.githubusercontent.com/kitematic/kitematic/${KITEMATIC_BRANCH}/docs/rethinkdb-dev-database.md \
|
||||
https://raw.githubusercontent.com/kitematic/kitematic/${KITEMATIC_BRANCH}/docs/userguide.md \
|
||||
/docs/sources/kitematic/
|
||||
RUN sed -i.old '1s;^;no_version_dropdown: true;' /docs/sources/kitematic/*.md
|
||||
ADD https://raw.githubusercontent.com/kitematic/kitematic/${KITEMATIC_BRANCH}/docs/assets/browse-images.png \
|
||||
https://raw.githubusercontent.com/kitematic/kitematic/${KITEMATIC_BRANCH}/docs/assets/change-folder.png \
|
||||
https://raw.githubusercontent.com/kitematic/kitematic/${KITEMATIC_BRANCH}/docs/assets/cli-access-button.png \
|
||||
https://raw.githubusercontent.com/kitematic/kitematic/${KITEMATIC_BRANCH}/docs/assets/cli-redis-container.png \
|
||||
https://raw.githubusercontent.com/kitematic/kitematic/${KITEMATIC_BRANCH}/docs/assets/cli-terminal.png \
|
||||
https://raw.githubusercontent.com/kitematic/kitematic/${KITEMATIC_BRANCH}/docs/assets/containers.png \
|
||||
https://raw.githubusercontent.com/kitematic/kitematic/${KITEMATIC_BRANCH}/docs/assets/installing.png \
|
||||
https://raw.githubusercontent.com/kitematic/kitematic/${KITEMATIC_BRANCH}/docs/assets/minecraft-add-server.png \
|
||||
https://raw.githubusercontent.com/kitematic/kitematic/${KITEMATIC_BRANCH}/docs/assets/minecraft-create.png \
|
||||
https://raw.githubusercontent.com/kitematic/kitematic/${KITEMATIC_BRANCH}/docs/assets/minecraft-data-volume.png \
|
||||
https://raw.githubusercontent.com/kitematic/kitematic/${KITEMATIC_BRANCH}/docs/assets/minecraft-login.png \
|
||||
https://raw.githubusercontent.com/kitematic/kitematic/${KITEMATIC_BRANCH}/docs/assets/minecraft-map.png \
|
||||
https://raw.githubusercontent.com/kitematic/kitematic/${KITEMATIC_BRANCH}/docs/assets/minecraft-port.png \
|
||||
https://raw.githubusercontent.com/kitematic/kitematic/${KITEMATIC_BRANCH}/docs/assets/minecraft-restart.png \
|
||||
https://raw.githubusercontent.com/kitematic/kitematic/${KITEMATIC_BRANCH}/docs/assets/minecraft-server-address.png \
|
||||
https://raw.githubusercontent.com/kitematic/kitematic/${KITEMATIC_BRANCH}/docs/assets/nginx-2048-files.png \
|
||||
https://raw.githubusercontent.com/kitematic/kitematic/${KITEMATIC_BRANCH}/docs/assets/nginx-2048.png \
|
||||
https://raw.githubusercontent.com/kitematic/kitematic/${KITEMATIC_BRANCH}/docs/assets/nginx-create.png \
|
||||
https://raw.githubusercontent.com/kitematic/kitematic/${KITEMATIC_BRANCH}/docs/assets/nginx-data-folder.png \
|
||||
https://raw.githubusercontent.com/kitematic/kitematic/${KITEMATIC_BRANCH}/docs/assets/nginx-data-volume.png \
|
||||
https://raw.githubusercontent.com/kitematic/kitematic/${KITEMATIC_BRANCH}/docs/assets/nginx-hello-world.png \
|
||||
https://raw.githubusercontent.com/kitematic/kitematic/${KITEMATIC_BRANCH}/docs/assets/nginx-preview.png \
|
||||
https://raw.githubusercontent.com/kitematic/kitematic/${KITEMATIC_BRANCH}/docs/assets/nginx-serving-2048.png \
|
||||
https://raw.githubusercontent.com/kitematic/kitematic/${KITEMATIC_BRANCH}/docs/assets/rethink-container.png \
|
||||
https://raw.githubusercontent.com/kitematic/kitematic/${KITEMATIC_BRANCH}/docs/assets/rethink-create.png \
|
||||
https://raw.githubusercontent.com/kitematic/kitematic/${KITEMATIC_BRANCH}/docs/assets/rethink-ports.png \
|
||||
https://raw.githubusercontent.com/kitematic/kitematic/${KITEMATIC_BRANCH}/docs/assets/rethinkdb-preview.png \
|
||||
https://raw.githubusercontent.com/kitematic/kitematic/${KITEMATIC_BRANCH}/docs/assets/volumes-dir.png \
|
||||
/docs/sources/kitematic/assets/
|
||||
|
||||
# Then build everything together, ready for mkdocs
|
||||
RUN /docs/build.sh
|
||||
|
||||
@@ -1,55 +0,0 @@
|
||||
.PHONY: all binary build cross default docs docs-build docs-shell shell test test-unit test-integration test-integration-cli test-docker-py validate
|
||||
|
||||
# env vars passed through directly to Docker's build scripts
|
||||
# to allow things like `make DOCKER_CLIENTONLY=1 binary` easily
|
||||
# `docs/sources/contributing/devenvironment.md ` and `project/PACKAGERS.md` have some limited documentation of some of these
|
||||
DOCKER_ENVS := \
|
||||
-e BUILDFLAGS \
|
||||
-e DOCKER_CLIENTONLY \
|
||||
-e DOCKER_EXECDRIVER \
|
||||
-e DOCKER_GRAPHDRIVER \
|
||||
-e TESTDIRS \
|
||||
-e TESTFLAGS \
|
||||
-e TIMEOUT
|
||||
# note: we _cannot_ add "-e DOCKER_BUILDTAGS" here because even if it's unset in the shell, that would shadow the "ENV DOCKER_BUILDTAGS" set in our Dockerfile, which is very important for our official builds
|
||||
|
||||
# to allow `make DOCSDIR=docs docs-shell` (to create a bind mount in docs)
|
||||
DOCS_MOUNT := $(if $(DOCSDIR),-v $(CURDIR)/$(DOCSDIR):/$(DOCSDIR))
|
||||
|
||||
# to allow `make DOCSPORT=9000 docs`
|
||||
DOCSPORT := 8000
|
||||
|
||||
# Get the IP ADDRESS
|
||||
DOCKER_IP=$(shell python -c "import urlparse ; print urlparse.urlparse('$(DOCKER_HOST)').hostname or ''")
|
||||
HUGO_BASE_URL=$(shell test -z "$(DOCKER_IP)" && echo localhost || echo "$(DOCKER_IP)")
|
||||
HUGO_BIND_IP=0.0.0.0
|
||||
|
||||
GIT_BRANCH := $(shell git rev-parse --abbrev-ref HEAD 2>/dev/null)
|
||||
DOCKER_IMAGE := docker$(if $(GIT_BRANCH),:$(GIT_BRANCH))
|
||||
DOCKER_DOCS_IMAGE := docs-base$(if $(GIT_BRANCH),:$(GIT_BRANCH))
|
||||
|
||||
|
||||
DOCKER_RUN_DOCS := docker run --rm -it $(DOCS_MOUNT) -e AWS_S3_BUCKET -e NOCACHE
|
||||
|
||||
# for some docs workarounds (see below in "docs-build" target)
|
||||
GITCOMMIT := $(shell git rev-parse --short HEAD 2>/dev/null)
|
||||
|
||||
default: docs
|
||||
|
||||
docs: docs-build
|
||||
$(DOCKER_RUN_DOCS) -p $(if $(DOCSPORT),$(DOCSPORT):)8000 -e DOCKERHOST "$(DOCKER_DOCS_IMAGE)" hugo server --port=$(DOCSPORT) --baseUrl=$(HUGO_BASE_URL) --bind=$(HUGO_BIND_IP)
|
||||
|
||||
docs-draft: docs-build
|
||||
$(DOCKER_RUN_DOCS) -p $(if $(DOCSPORT),$(DOCSPORT):)8000 -e DOCKERHOST "$(DOCKER_DOCS_IMAGE)" hugo server --buildDrafts="true" --port=$(DOCSPORT) --baseUrl=$(HUGO_BASE_URL) --bind=$(HUGO_BIND_IP)
|
||||
|
||||
|
||||
docs-shell: docs-build
|
||||
$(DOCKER_RUN_DOCS) -p $(if $(DOCSPORT),$(DOCSPORT):)8000 "$(DOCKER_DOCS_IMAGE)" bash
|
||||
|
||||
|
||||
docs-build:
|
||||
# ( git remote | grep -v upstream ) || git diff --name-status upstream/release..upstream/docs ./ > ./changed-files
|
||||
# echo "$(GIT_BRANCH)" > GIT_BRANCH
|
||||
# echo "$(AWS_S3_BUCKET)" > AWS_S3_BUCKET
|
||||
# echo "$(GITCOMMIT)" > GITCOMMIT
|
||||
docker build -t "$(DOCKER_DOCS_IMAGE)" .
|
||||
+22
-15
@@ -1,12 +1,6 @@
|
||||
<!--[metadata]>
|
||||
+++
|
||||
draft = true
|
||||
+++
|
||||
<![end-metadata]-->
|
||||
|
||||
# Docker Documentation
|
||||
|
||||
The source for Docker documentation is in this directory. Our
|
||||
The source for Docker documentation is in this directory under `sources/`. Our
|
||||
documentation uses extended Markdown, as implemented by
|
||||
[MkDocs](http://mkdocs.org). The current release of the Docker documentation
|
||||
resides on [https://docs.docker.com](https://docs.docker.com).
|
||||
@@ -18,7 +12,7 @@ Docker has two primary branches for documentation:
|
||||
| Branch | Description | URL (published via commit-hook) |
|
||||
|----------|--------------------------------|------------------------------------------------------------------------------|
|
||||
| `docs` | Official release documentation | [https://docs.docker.com](https://docs.docker.com) |
|
||||
| `master` | Merged but unreleased development work | [http://docs.master.dockerproject.org](http://docs.master.dockerproject.org) |
|
||||
| `master` | Merged but unreleased development work | [http://docs.master.dockerproject.com](http://docs.master.dockerproject.com) |
|
||||
|
||||
Additions and updates to upcoming releases are made in a feature branch off of
|
||||
the `master` branch. The Docker maintainers also support a `docs` branch that
|
||||
@@ -28,7 +22,7 @@ After a release, documentation updates are continually merged into `master` as
|
||||
they occur. This work includes new documentation for forthcoming features, bug
|
||||
fixes, and other updates. Docker's CI system automatically builds and updates
|
||||
the `master` documentation after each merge and posts it to
|
||||
[http://docs.master.dockerproject.org](http://docs.master.dockerproject.org).
|
||||
[http://docs.master.dockerproject.com](http://docs.master.dockerproject.com).
|
||||
|
||||
Periodically, the Docker maintainers update `docs.docker.com` between official
|
||||
releases of Docker. They do this by cherry-picking commits from `master`,
|
||||
@@ -60,7 +54,7 @@ own.
|
||||
release. It also allows docs maintainers to easily cherry-pick your changes
|
||||
into the `docs` release branch.
|
||||
|
||||
4. Modify existing or add new `.md` files to the `docs` directory.
|
||||
4. Modify existing or add new `.md` files to the `docs/sources` directory.
|
||||
|
||||
If you add a new document (`.md`) file, you must also add it to the
|
||||
appropriate section of the `docs/mkdocs.yml` file in this repository.
|
||||
@@ -113,7 +107,7 @@ links that are referenced in the documentation—there should be none.
|
||||
## Style guide
|
||||
|
||||
If you have questions about how to write for Docker's documentation, please see
|
||||
the [style guide](project/doc-style.md). The style guide provides
|
||||
the [style guide](sources/project/doc-style.md). The style guide provides
|
||||
guidance about grammar, syntax, formatting, styling, language, or tone. If
|
||||
something isn't clear in the guide, please submit an issue to let us know or
|
||||
submit a pull request to help us improve it.
|
||||
@@ -286,11 +280,24 @@ aws cloudfront create-invalidation --profile docs.docker.com --distribution-id
|
||||
aws cloudfront create-invalidation --profile docs.docker.com --distribution-id $DISTRIBUTION_ID --invalidation-batch '{"Paths":{"Quantity":1, "Items":["/v1.1/reference/api/docker_io_oauth_api/"]},"CallerReference":"6Mar2015sventest1"}'
|
||||
```
|
||||
|
||||
### Generate the man pages
|
||||
### Generate the man pages for Mac OSX
|
||||
|
||||
For information on generating man pages (short for manual page), see [the man
|
||||
page directory](https://github.com/docker/docker/tree/master/docker) in this
|
||||
project.
|
||||
When using Docker on Mac OSX the man pages will be missing by default. You can manually generate them by following these steps:
|
||||
|
||||
1. Checkout the docker source. You must clone into your `/Users` directory because Boot2Docker can only share this path
|
||||
with the docker containers.
|
||||
|
||||
$ git clone https://github.com/docker/docker.git
|
||||
|
||||
2. Build the docker image.
|
||||
|
||||
$ cd docker/docs/man
|
||||
$ docker build -t docker/md2man .
|
||||
|
||||
3. Build the man pages.
|
||||
|
||||
$ docker run -v /Users/<path-to-git-dir>/docker/docs/man:/docs:rw -w /docs -i docker/md2man /docs/md2man-all.sh
|
||||
|
||||
4. Copy the generated man pages to `/usr/share/man`
|
||||
|
||||
$ cp -R man* /usr/share/man/
|
||||
|
||||
@@ -1,196 +0,0 @@
|
||||
<!--[metadata]>
|
||||
+++
|
||||
title = "Installation on CentOS"
|
||||
description = "Instructions for installing Docker on CentOS"
|
||||
keywords = ["Docker, Docker documentation, requirements, linux, centos, epel, docker.io, docker-io"]
|
||||
[menu.main]
|
||||
parent = "smn_linux"
|
||||
+++
|
||||
<![end-metadata]-->
|
||||
|
||||
# CentOS
|
||||
|
||||
Docker is supported on the following versions of CentOS:
|
||||
|
||||
* CentOS 7.X
|
||||
* CentOS 6.5 or higher
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
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 check your current kernel version, open a terminal and use `uname -r` to
|
||||
display your kernel version:
|
||||
|
||||
$ uname -r
|
||||
2.6.32-431.el6.x86_64
|
||||
|
||||
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
|
||||
|
||||
## Install
|
||||
|
||||
You use the same installation procedure for all versions of CentOS,
|
||||
only the package you install differs. There are two packages to choose from:
|
||||
|
||||
<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>
|
||||
|
||||
|
||||
This procedure depicts an installation on version 6.5. If you are installing on
|
||||
7.X, substitute that package for your installation.
|
||||
|
||||
1. Log into your machine as a user with `sudo` or `root` privileges.
|
||||
|
||||
2. Make sure your existing packages are up-to-date.
|
||||
|
||||
$ 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
|
||||
|
||||
4. Use `yum` to install the package.
|
||||
|
||||
$ sudo yum localinstall --nogpgcheck docker-engine-1.7.0-1.el6.x86_64.rpm
|
||||
|
||||
5. Start the Docker daemon.
|
||||
|
||||
$ sudo service docker start
|
||||
|
||||
6. Verify `docker` is installed correctly by running a test image in a container.
|
||||
|
||||
$ 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 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 try something more ambitious, you can run an Ubuntu container with:
|
||||
$ docker run -it ubuntu bash
|
||||
|
||||
For more examples and ideas, visit:
|
||||
http://docs.docker.com/userguide/
|
||||
|
||||
## Create a docker group
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
>**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 create the `docker` group and add your user:
|
||||
|
||||
1. Log into Centos as a user with `sudo` privileges.
|
||||
|
||||
2. Create the `docker` group and add your user.
|
||||
|
||||
`sudo usermod -aG docker your_username`
|
||||
|
||||
3. Log out and log back in.
|
||||
|
||||
This ensures your user is running with the correct permissions.
|
||||
|
||||
4. Verify your work by running `docker` without `sudo`.
|
||||
|
||||
$ docker run hello-world
|
||||
|
||||
## Start the docker daemon at boot
|
||||
|
||||
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/).
|
||||
|
||||
|
||||
## 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-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.
|
||||
@@ -1,232 +0,0 @@
|
||||
<!--[metadata]>
|
||||
+++
|
||||
title = "Installation on Fedora"
|
||||
description = "Instructions for installing Docker on Fedora."
|
||||
keywords = ["Docker, Docker documentation, Fedora, requirements, linux"]
|
||||
[menu.main]
|
||||
parent = "smn_linux"
|
||||
+++
|
||||
<![end-metadata]-->
|
||||
|
||||
# Fedora
|
||||
|
||||
Docker is supported on the following versions of Fedora:
|
||||
|
||||
- Fedora 20
|
||||
- Fedora 21
|
||||
- Fedora 22
|
||||
|
||||
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.
|
||||
|
||||
##Prerequisites
|
||||
|
||||
Docker requires a 64-bit installation regardless of your Fedora version. Also, your kernel must be 3.10 at minimum. To check your current kernel
|
||||
version, open a terminal and use `uname -r` to display your kernel version:
|
||||
|
||||
$ uname -r
|
||||
3.19.5-100.fc20.x86_64
|
||||
|
||||
If your kernel is at a older version, you must update it.
|
||||
|
||||
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
|
||||
|
||||
|
||||
## Install
|
||||
|
||||
You use the same installation procedure for all versions of Fedora,
|
||||
only the package you install differs. There are two packages to choose from:
|
||||
|
||||
<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>
|
||||
|
||||
|
||||
This procedure depicts an installation on version 21. If you are installing on
|
||||
20 or 22, substitute that package for your installation.
|
||||
|
||||
1. Log into your machine as a user with `sudo` or `root` privileges.
|
||||
|
||||
2. Make sure you don't have an older version of Docker installed.
|
||||
|
||||
$ yum list installed | grep docker
|
||||
|
||||
If you have an older version, remove it using the `yum -y remove <packagename>` command.
|
||||
|
||||
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
|
||||
|
||||
4. Use `yum` to install the package.
|
||||
|
||||
$ sudo yum localinstall --nogpgcheck docker-engine-1.7.0-0.1.fc21.x86_64.rpm
|
||||
|
||||
5. Start the Docker daemon.
|
||||
|
||||
$ sudo service docker start
|
||||
|
||||
6. Verify `docker` is installed correctly by running a test image in a container.
|
||||
|
||||
$ 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.
|
||||
|
||||
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 try something more ambitious, you can run an Ubuntu container with:
|
||||
$ docker run -it ubuntu bash
|
||||
|
||||
For more examples and ideas, visit:
|
||||
http://docs.docker.com/userguide/
|
||||
|
||||
## Create a docker group
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
>**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 create the `docker` group and add your user:
|
||||
|
||||
1. Log into your system as a user with `sudo` privileges.
|
||||
|
||||
2. Create the `docker` group and add your user.
|
||||
|
||||
`sudo usermod -aG docker your_username`
|
||||
|
||||
3. Log out and log back in.
|
||||
|
||||
This ensures your user is running with the correct permissions.
|
||||
|
||||
4. Verify your work by running `docker` without `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.
|
||||
|
||||
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 try something more ambitious, you can run an Ubuntu container with:
|
||||
$ docker run -it ubuntu bash
|
||||
|
||||
For more examples and ideas, visit:
|
||||
http://docs.docker.com/userguide/
|
||||
|
||||
## Start the docker daemon at boot
|
||||
|
||||
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/).
|
||||
|
||||
|
||||
## 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.
|
||||
@@ -1,189 +0,0 @@
|
||||
<!--[metadata]>
|
||||
+++
|
||||
title = "Installation on Red Hat Enterprise Linux"
|
||||
description = "Instructions for installing Docker on Red Hat Enterprise Linux."
|
||||
keywords = ["Docker, Docker documentation, requirements, linux, rhel"]
|
||||
[menu.main]
|
||||
parent = "smn_linux"
|
||||
+++
|
||||
<![end-metadata]-->
|
||||
|
||||
# Red Hat Enterprise Linux
|
||||
|
||||
Docker is supported on the following versions of RHEL:
|
||||
|
||||
- Red Hat Enterprise Linux 7
|
||||
- Red Hat Enterprise Linux 6.6 or later
|
||||
|
||||
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.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
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.
|
||||
|
||||
To check your current kernel version, open a terminal and use `uname -r` to
|
||||
display your kernel version:
|
||||
|
||||
$ uname -r
|
||||
3.10.0-229.el7.x86_64
|
||||
|
||||
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
|
||||
|
||||
|
||||
## Install
|
||||
|
||||
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:
|
||||
|
||||
<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>
|
||||
|
||||
This procedure depicts an installation on version 6.6. If you are installing on
|
||||
7.X, substitute that package for your installation.
|
||||
|
||||
1. Log into your machine as a user with `sudo` or `root` privileges.
|
||||
|
||||
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
|
||||
|
||||
3. Use `yum` to install the package.
|
||||
|
||||
$ sudo yum localinstall --nogpgcheck docker-engine-1.7.0-0.1.el6.x86_64.rpm
|
||||
|
||||
5. Start the Docker daemon.
|
||||
|
||||
$ sudo service docker start
|
||||
|
||||
6. Verify `docker` is installed correctly.
|
||||
|
||||
$ 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.
|
||||
|
||||
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 try something more ambitious, you can run an Ubuntu container with:
|
||||
$ docker run -it ubuntu bash
|
||||
|
||||
For more examples and ideas, visit:
|
||||
http://docs.docker.com/userguide/
|
||||
|
||||
## Create a docker group
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
>**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 create the `docker` group and add your user:
|
||||
|
||||
1. Log into your machine as a user with `sudo` or `root` privileges.
|
||||
|
||||
2. Create the `docker` group and add your user.
|
||||
|
||||
`sudo usermod -aG docker your_username`
|
||||
|
||||
3. Log out and log back in.
|
||||
|
||||
This ensures your user is running with the correct permissions.
|
||||
|
||||
4. Verify your work by running `docker` without `sudo`.
|
||||
|
||||
$ docker run hello-world
|
||||
|
||||
## Start the docker daemon at boot
|
||||
|
||||
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/).
|
||||
|
||||
|
||||
## 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.
|
||||
@@ -1,7 +1,7 @@
|
||||
FROM golang:1.4
|
||||
FROM golang:1.3
|
||||
RUN mkdir -p /go/src/github.com/cpuguy83
|
||||
RUN mkdir -p /go/src/github.com/cpuguy83 \
|
||||
&& git clone -b v1.0.1 https://github.com/cpuguy83/go-md2man.git /go/src/github.com/cpuguy83/go-md2man \
|
||||
&& git clone -b v1 https://github.com/cpuguy83/go-md2man.git /go/src/github.com/cpuguy83/go-md2man \
|
||||
&& cd /go/src/github.com/cpuguy83/go-md2man \
|
||||
&& go get -v ./...
|
||||
CMD ["/go/bin/go-md2man", "--help"]
|
||||
@@ -196,7 +196,7 @@ A Dockerfile is similar to a Makefile.
|
||||
ADD <src> <dest>
|
||||
|
||||
# Required for paths with whitespace
|
||||
ADD ["<src>",... "<dest>"]
|
||||
ADD ["<src>", "<dest>"]
|
||||
```
|
||||
|
||||
The **ADD** instruction copies new files, directories
|
||||
@@ -215,7 +215,7 @@ A Dockerfile is similar to a Makefile.
|
||||
COPY <src> <dest>
|
||||
|
||||
# Required for paths with whitespace
|
||||
COPY ["<src>",... "<dest>"]
|
||||
COPY ["<src>", "<dest>"]
|
||||
```
|
||||
|
||||
The **COPY** instruction copies new files from `<src>` and
|
||||
@@ -33,7 +33,6 @@ docker-create - Create a new container
|
||||
[**--link**[=*[]*]]
|
||||
[**--lxc-conf**[=*[]*]]
|
||||
[**--log-driver**[=*[]*]]
|
||||
[**--log-opt**[=*[]*]]
|
||||
[**-m**|**--memory**[=*MEMORY*]]
|
||||
[**--memory-swap**[=*MEMORY-SWAP*]]
|
||||
[**--mac-address**[=*MAC-ADDRESS*]]
|
||||
@@ -149,9 +148,6 @@ two memory nodes.
|
||||
Logging driver for container. Default is defined by daemon `--log-driver` flag.
|
||||
**Warning**: `docker logs` command works only for `json-file` logging driver.
|
||||
|
||||
**--log-opt**=[]
|
||||
Logging driver specific options.
|
||||
|
||||
**-m**, **--memory**=""
|
||||
Memory limit (format: <number><optional unit>, where unit = b, k, m or g)
|
||||
|
||||
@@ -63,12 +63,7 @@ Again the output container IDs have been shortened for the purposes of this docu
|
||||
2015-01-28T20:25:45.000000000-08:00 c21f6c22ba27: (from whenry/testimage:latest) die
|
||||
2015-01-28T20:25:46.000000000-08:00 c21f6c22ba27: (from whenry/testimage:latest) stop
|
||||
|
||||
|
||||
If you do not provide the --since option, the command returns only new and/or
|
||||
live events.
|
||||
|
||||
# HISTORY
|
||||
April 2014, Originally compiled by William Henry (whenry at redhat dot com)
|
||||
based on docker.com source material and internal work.
|
||||
June 2014, updated by Sven Dowideit <SvenDowideit@home.org.au>
|
||||
June 2015, updated by Brian Goff <cpuguy83@gmail.com>
|
||||
@@ -34,7 +34,6 @@ docker-run - Run a command in a new container
|
||||
[**--link**[=*[]*]]
|
||||
[**--lxc-conf**[=*[]*]]
|
||||
[**--log-driver**[=*[]*]]
|
||||
[**--log-opt**[=*[]*]]
|
||||
[**-m**|**--memory**[=*MEMORY*]]
|
||||
[**--memory-swap**[=*MEMORY-SWAP*]]
|
||||
[**--mac-address**[=*MAC-ADDRESS*]]
|
||||
@@ -256,9 +255,6 @@ which interface and port to use.
|
||||
Logging driver for container. Default is defined by daemon `--log-driver` flag.
|
||||
**Warning**: `docker logs` command works only for `json-file` logging driver.
|
||||
|
||||
**--log-opt**=[]
|
||||
Logging driver specific options.
|
||||
|
||||
**-m**, **--memory**=""
|
||||
Memory limit (format: <number><optional unit>, where unit = b, k, m or g)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user