Compare commits
29 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| f0df35096d | |||
| f485f66943 | |||
| 746c553574 | |||
| 2945ba4f7a | |||
| 032e485e1c | |||
| 88de81ff21 | |||
| 706ca7985b | |||
| e0d47b1c0b | |||
| 54b529feae | |||
| c88e6432ec | |||
| f291a49ba5 | |||
| 78fcd905c6 | |||
| 12e2f94eba | |||
| 00755d7dba | |||
| 8264f5be8d | |||
| 9780f41efe | |||
| 4fbdf3f362 | |||
| 1ff45aac40 | |||
| bb03b9d3c2 | |||
| ed71df1b9f | |||
| ee20fa1ec4 | |||
| ffe40dc6b6 | |||
| 7ab2d19a1e | |||
| 4630fe0075 | |||
| fbbf1be52d | |||
| 3de2cc6efd | |||
| 234036d105 | |||
| 0c442dc179 | |||
| 6b48c78672 |
@ -97,7 +97,8 @@ func runAttach(dockerCli command.Cli, opts *attachOptions) error {
|
||||
}
|
||||
|
||||
if opts.proxy && !c.Config.Tty {
|
||||
sigc := ForwardAllSignals(ctx, dockerCli, opts.container)
|
||||
sigc := notfiyAllSignals()
|
||||
go ForwardAllSignals(ctx, dockerCli, opts.container, sigc)
|
||||
defer signal.StopCatch(sigc)
|
||||
}
|
||||
|
||||
|
||||
@ -32,6 +32,7 @@ type fakeClient struct {
|
||||
containerExportFunc func(string) (io.ReadCloser, error)
|
||||
containerExecResizeFunc func(id string, options types.ResizeOptions) error
|
||||
containerRemoveFunc func(ctx context.Context, container string, options types.ContainerRemoveOptions) error
|
||||
containerKillFunc func(ctx context.Context, container, signal string) error
|
||||
Version string
|
||||
}
|
||||
|
||||
@ -154,3 +155,10 @@ func (f *fakeClient) ContainerExecResize(_ context.Context, id string, options t
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *fakeClient) ContainerKill(ctx context.Context, container, signal string) error {
|
||||
if f.containerKillFunc != nil {
|
||||
return f.containerKillFunc(ctx, container, signal)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -131,7 +131,8 @@ func runContainer(dockerCli command.Cli, opts *runOptions, copts *containerOptio
|
||||
return runStartContainerErr(err)
|
||||
}
|
||||
if opts.sigProxy {
|
||||
sigc := ForwardAllSignals(ctx, dockerCli, createResponse.ID)
|
||||
sigc := notfiyAllSignals()
|
||||
go ForwardAllSignals(ctx, dockerCli, createResponse.ID, sigc)
|
||||
defer signal.StopCatch(sigc)
|
||||
}
|
||||
|
||||
|
||||
61
cli/command/container/signals.go
Normal file
@ -0,0 +1,61 @@
|
||||
package container
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
gosignal "os/signal"
|
||||
|
||||
"github.com/docker/cli/cli/command"
|
||||
"github.com/docker/docker/pkg/signal"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// ForwardAllSignals forwards signals to the container
|
||||
//
|
||||
// The channel you pass in must already be setup to receive any signals you want to forward.
|
||||
func ForwardAllSignals(ctx context.Context, cli command.Cli, cid string, sigc <-chan os.Signal) {
|
||||
var (
|
||||
s os.Signal
|
||||
ok bool
|
||||
)
|
||||
for {
|
||||
select {
|
||||
case s, ok = <-sigc:
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
case <-ctx.Done():
|
||||
return
|
||||
}
|
||||
|
||||
if s == signal.SIGCHLD || s == signal.SIGPIPE {
|
||||
continue
|
||||
}
|
||||
|
||||
// In go1.14+, the go runtime issues SIGURG as an interrupt to support pre-emptable system calls on Linux.
|
||||
// Since we can't forward that along we'll check that here.
|
||||
if isRuntimeSig(s) {
|
||||
continue
|
||||
}
|
||||
var sig string
|
||||
for sigStr, sigN := range signal.SignalMap {
|
||||
if sigN == s {
|
||||
sig = sigStr
|
||||
break
|
||||
}
|
||||
}
|
||||
if sig == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
if err := cli.Client().ContainerKill(ctx, cid, sig); err != nil {
|
||||
logrus.Debugf("Error sending signal: %s", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func notfiyAllSignals() chan os.Signal {
|
||||
sigc := make(chan os.Signal, 128)
|
||||
gosignal.Notify(sigc)
|
||||
return sigc
|
||||
}
|
||||
48
cli/command/container/signals_test.go
Normal file
@ -0,0 +1,48 @@
|
||||
package container
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/docker/cli/internal/test"
|
||||
"github.com/docker/docker/pkg/signal"
|
||||
)
|
||||
|
||||
func TestForwardSignals(t *testing.T) {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
called := make(chan struct{})
|
||||
client := &fakeClient{containerKillFunc: func(ctx context.Context, container, signal string) error {
|
||||
close(called)
|
||||
return nil
|
||||
}}
|
||||
|
||||
cli := test.NewFakeCli(client)
|
||||
sigc := make(chan os.Signal)
|
||||
defer close(sigc)
|
||||
|
||||
go ForwardAllSignals(ctx, cli, t.Name(), sigc)
|
||||
|
||||
timer := time.NewTimer(30 * time.Second)
|
||||
defer timer.Stop()
|
||||
|
||||
select {
|
||||
case <-timer.C:
|
||||
t.Fatal("timeout waiting to send signal")
|
||||
case sigc <- signal.SignalMap["TERM"]:
|
||||
}
|
||||
if !timer.Stop() {
|
||||
<-timer.C
|
||||
}
|
||||
timer.Reset(30 * time.Second)
|
||||
|
||||
select {
|
||||
case <-called:
|
||||
case <-timer.C:
|
||||
t.Fatal("timeout waiting for signal to be processed")
|
||||
}
|
||||
|
||||
}
|
||||
13
cli/command/container/signals_unix.go
Normal file
@ -0,0 +1,13 @@
|
||||
// +build !windows
|
||||
|
||||
package container
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
func isRuntimeSig(s os.Signal) bool {
|
||||
return s == unix.SIGURG
|
||||
}
|
||||
59
cli/command/container/signals_unix_test.go
Normal file
@ -0,0 +1,59 @@
|
||||
// +build !windows
|
||||
|
||||
package container
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"syscall"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/docker/cli/internal/test"
|
||||
"golang.org/x/sys/unix"
|
||||
"gotest.tools/v3/assert"
|
||||
)
|
||||
|
||||
func TestIgnoredSignals(t *testing.T) {
|
||||
ignoredSignals := []syscall.Signal{unix.SIGPIPE, unix.SIGCHLD, unix.SIGURG}
|
||||
|
||||
for _, s := range ignoredSignals {
|
||||
t.Run(unix.SignalName(s), func(t *testing.T) {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
var called bool
|
||||
client := &fakeClient{containerKillFunc: func(ctx context.Context, container, signal string) error {
|
||||
called = true
|
||||
return nil
|
||||
}}
|
||||
|
||||
cli := test.NewFakeCli(client)
|
||||
sigc := make(chan os.Signal)
|
||||
defer close(sigc)
|
||||
|
||||
done := make(chan struct{})
|
||||
go func() {
|
||||
ForwardAllSignals(ctx, cli, t.Name(), sigc)
|
||||
close(done)
|
||||
}()
|
||||
|
||||
timer := time.NewTimer(30 * time.Second)
|
||||
defer timer.Stop()
|
||||
|
||||
select {
|
||||
case <-timer.C:
|
||||
t.Fatal("timeout waiting to send signal")
|
||||
case sigc <- s:
|
||||
case <-done:
|
||||
}
|
||||
|
||||
// cancel the context so ForwardAllSignals will exit after it has processed the signal we sent.
|
||||
// This is how we know the signal was actually processed and are not introducing a flakey test.
|
||||
cancel()
|
||||
<-done
|
||||
|
||||
assert.Assert(t, !called, "kill was called")
|
||||
})
|
||||
}
|
||||
}
|
||||
7
cli/command/container/signals_windows.go
Normal file
@ -0,0 +1,7 @@
|
||||
package container
|
||||
|
||||
import "os"
|
||||
|
||||
func isRuntimeSig(_ os.Signal) bool {
|
||||
return false
|
||||
}
|
||||
@ -74,7 +74,8 @@ func runStart(dockerCli command.Cli, opts *startOptions) error {
|
||||
|
||||
// We always use c.ID instead of container to maintain consistency during `docker start`
|
||||
if !c.Config.Tty {
|
||||
sigc := ForwardAllSignals(ctx, dockerCli, c.ID)
|
||||
sigc := notfiyAllSignals()
|
||||
go ForwardAllSignals(ctx, dockerCli, c.ID, sigc)
|
||||
defer signal.StopCatch(sigc)
|
||||
}
|
||||
|
||||
|
||||
@ -95,32 +95,3 @@ func MonitorTtySize(ctx context.Context, cli command.Cli, id string, isExec bool
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ForwardAllSignals forwards signals to the container
|
||||
func ForwardAllSignals(ctx context.Context, cli command.Cli, cid string) chan os.Signal {
|
||||
sigc := make(chan os.Signal, 128)
|
||||
signal.CatchAll(sigc)
|
||||
go func() {
|
||||
for s := range sigc {
|
||||
if s == signal.SIGCHLD || s == signal.SIGPIPE {
|
||||
continue
|
||||
}
|
||||
var sig string
|
||||
for sigStr, sigN := range signal.SignalMap {
|
||||
if sigN == s {
|
||||
sig = sigStr
|
||||
break
|
||||
}
|
||||
}
|
||||
if sig == "" {
|
||||
fmt.Fprintf(cli.Err(), "Unsupported signal: %v. Discarding.\n", s)
|
||||
continue
|
||||
}
|
||||
|
||||
if err := cli.Client().ContainerKill(ctx, cid, sig); err != nil {
|
||||
logrus.Debugf("Error sending signal: %s", err)
|
||||
}
|
||||
}
|
||||
}()
|
||||
return sigc
|
||||
}
|
||||
|
||||
@ -402,10 +402,7 @@ func printServerWarningsLegacy(dockerCli command.Cli, info types.Info) {
|
||||
if !info.SwapLimit {
|
||||
fmt.Fprintln(dockerCli.Err(), "WARNING: No swap limit support")
|
||||
}
|
||||
if !info.KernelMemory {
|
||||
fmt.Fprintln(dockerCli.Err(), "WARNING: No kernel memory limit support")
|
||||
}
|
||||
if !info.OomKillDisable {
|
||||
if !info.OomKillDisable && info.CgroupVersion != "2" {
|
||||
fmt.Fprintln(dockerCli.Err(), "WARNING: No oom kill disable support")
|
||||
}
|
||||
if !info.CPUCfsQuota {
|
||||
|
||||
@ -248,7 +248,6 @@ func TestPrettyPrintInfo(t *testing.T) {
|
||||
sampleInfoDaemonWarnings.Warnings = []string{
|
||||
"WARNING: No memory limit support",
|
||||
"WARNING: No swap limit support",
|
||||
"WARNING: No kernel memory limit support",
|
||||
"WARNING: No oom kill disable support",
|
||||
"WARNING: No cpu cfs quota support",
|
||||
"WARNING: No cpu cfs period support",
|
||||
|
||||
@ -1 +1 @@
|
||||
{"ID":"EKHL:QDUU:QZ7U:MKGD:VDXK:S27Q:GIPU:24B7:R7VT:DGN6:QCSF:2UBX","Containers":0,"ContainersRunning":0,"ContainersPaused":0,"ContainersStopped":0,"Images":0,"Driver":"aufs","DriverStatus":[["Root Dir","/var/lib/docker/aufs"],["Backing Filesystem","extfs"],["Dirs","0"],["Dirperm1 Supported","true"]],"Plugins":{"Volume":["local"],"Network":["bridge","host","macvlan","null","overlay"],"Authorization":null,"Log":["awslogs","fluentd","gcplogs","gelf","journald","json-file","logentries","splunk","syslog"]},"MemoryLimit":true,"SwapLimit":true,"KernelMemory":true,"KernelMemoryTCP":false,"CpuCfsPeriod":true,"CpuCfsQuota":true,"CPUShares":true,"CPUSet":true,"PidsLimit":false,"IPv4Forwarding":true,"BridgeNfIptables":true,"BridgeNfIp6tables":true,"Debug":true,"NFd":33,"OomKillDisable":true,"NGoroutines":135,"SystemTime":"2017-08-24T17:44:34.077811894Z","LoggingDriver":"json-file","CgroupDriver":"cgroupfs","NEventsListener":0,"KernelVersion":"4.4.0-87-generic","OperatingSystem":"Ubuntu 16.04.3 LTS","OSVersion":"","OSType":"linux","Architecture":"x86_64","IndexServerAddress":"https://index.docker.io/v1/","RegistryConfig":{"AllowNondistributableArtifactsCIDRs":null,"AllowNondistributableArtifactsHostnames":null,"InsecureRegistryCIDRs":["127.0.0.0/8"],"IndexConfigs":{"docker.io":{"Name":"docker.io","Mirrors":null,"Secure":true,"Official":true}},"Mirrors":null},"NCPU":2,"MemTotal":2097356800,"GenericResources":null,"DockerRootDir":"/var/lib/docker","HttpProxy":"","HttpsProxy":"","NoProxy":"","Name":"system-sample","Labels":["provider=digitalocean"],"ExperimentalBuild":false,"ServerVersion":"17.06.1-ce","Runtimes":{"runc":{"path":"docker-runc"}},"DefaultRuntime":"runc","Swarm":{"NodeID":"","NodeAddr":"","LocalNodeState":"inactive","ControlAvailable":false,"Error":"","RemoteManagers":null},"LiveRestoreEnabled":false,"Isolation":"","InitBinary":"docker-init","ContainerdCommit":{"ID":"6e23458c129b551d5c9871e5174f6b1b7f6d1170","Expected":"6e23458c129b551d5c9871e5174f6b1b7f6d1170"},"RuncCommit":{"ID":"810190ceaa507aa2727d7ae6f4790c76ec150bd2","Expected":"810190ceaa507aa2727d7ae6f4790c76ec150bd2"},"InitCommit":{"ID":"949e6fa","Expected":"949e6fa"},"SecurityOptions":["name=apparmor","name=seccomp,profile=default"],"DefaultAddressPools":[{"Base":"10.123.0.0/16","Size":24}],"Warnings":["WARNING: No memory limit support","WARNING: No swap limit support","WARNING: No kernel memory limit support","WARNING: No oom kill disable support","WARNING: No cpu cfs quota support","WARNING: No cpu cfs period support","WARNING: No cpu shares support","WARNING: No cpuset support","WARNING: IPv4 forwarding is disabled","WARNING: bridge-nf-call-iptables is disabled","WARNING: bridge-nf-call-ip6tables is disabled"],"ClientInfo":{"Debug":true,"Context":"default","Plugins":[],"Warnings":null}}
|
||||
{"ID":"EKHL:QDUU:QZ7U:MKGD:VDXK:S27Q:GIPU:24B7:R7VT:DGN6:QCSF:2UBX","Containers":0,"ContainersRunning":0,"ContainersPaused":0,"ContainersStopped":0,"Images":0,"Driver":"aufs","DriverStatus":[["Root Dir","/var/lib/docker/aufs"],["Backing Filesystem","extfs"],["Dirs","0"],["Dirperm1 Supported","true"]],"Plugins":{"Volume":["local"],"Network":["bridge","host","macvlan","null","overlay"],"Authorization":null,"Log":["awslogs","fluentd","gcplogs","gelf","journald","json-file","logentries","splunk","syslog"]},"MemoryLimit":true,"SwapLimit":true,"KernelMemory":true,"KernelMemoryTCP":false,"CpuCfsPeriod":true,"CpuCfsQuota":true,"CPUShares":true,"CPUSet":true,"PidsLimit":false,"IPv4Forwarding":true,"BridgeNfIptables":true,"BridgeNfIp6tables":true,"Debug":true,"NFd":33,"OomKillDisable":true,"NGoroutines":135,"SystemTime":"2017-08-24T17:44:34.077811894Z","LoggingDriver":"json-file","CgroupDriver":"cgroupfs","NEventsListener":0,"KernelVersion":"4.4.0-87-generic","OperatingSystem":"Ubuntu 16.04.3 LTS","OSVersion":"","OSType":"linux","Architecture":"x86_64","IndexServerAddress":"https://index.docker.io/v1/","RegistryConfig":{"AllowNondistributableArtifactsCIDRs":null,"AllowNondistributableArtifactsHostnames":null,"InsecureRegistryCIDRs":["127.0.0.0/8"],"IndexConfigs":{"docker.io":{"Name":"docker.io","Mirrors":null,"Secure":true,"Official":true}},"Mirrors":null},"NCPU":2,"MemTotal":2097356800,"GenericResources":null,"DockerRootDir":"/var/lib/docker","HttpProxy":"","HttpsProxy":"","NoProxy":"","Name":"system-sample","Labels":["provider=digitalocean"],"ExperimentalBuild":false,"ServerVersion":"17.06.1-ce","Runtimes":{"runc":{"path":"docker-runc"}},"DefaultRuntime":"runc","Swarm":{"NodeID":"","NodeAddr":"","LocalNodeState":"inactive","ControlAvailable":false,"Error":"","RemoteManagers":null},"LiveRestoreEnabled":false,"Isolation":"","InitBinary":"docker-init","ContainerdCommit":{"ID":"6e23458c129b551d5c9871e5174f6b1b7f6d1170","Expected":"6e23458c129b551d5c9871e5174f6b1b7f6d1170"},"RuncCommit":{"ID":"810190ceaa507aa2727d7ae6f4790c76ec150bd2","Expected":"810190ceaa507aa2727d7ae6f4790c76ec150bd2"},"InitCommit":{"ID":"949e6fa","Expected":"949e6fa"},"SecurityOptions":["name=apparmor","name=seccomp,profile=default"],"DefaultAddressPools":[{"Base":"10.123.0.0/16","Size":24}],"Warnings":["WARNING: No memory limit support","WARNING: No swap limit support","WARNING: No oom kill disable support","WARNING: No cpu cfs quota support","WARNING: No cpu cfs period support","WARNING: No cpu shares support","WARNING: No cpuset support","WARNING: IPv4 forwarding is disabled","WARNING: bridge-nf-call-iptables is disabled","WARNING: bridge-nf-call-ip6tables is disabled"],"ClientInfo":{"Debug":true,"Context":"default","Plugins":[],"Warnings":null}}
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
WARNING: No memory limit support
|
||||
WARNING: No swap limit support
|
||||
WARNING: No kernel memory limit support
|
||||
WARNING: No oom kill disable support
|
||||
WARNING: No cpu cfs quota support
|
||||
WARNING: No cpu cfs period support
|
||||
|
||||
@ -122,7 +122,7 @@ enabled, and use it to create a volume.
|
||||
To disable a plugin, use the `docker plugin disable` command. To completely
|
||||
remove it, use the `docker plugin remove` command. For other available
|
||||
commands and options, see the
|
||||
[command line reference](../reference/commandline/index.md).
|
||||
[command line reference](https://docs.docker.com/engine/reference/commandline/cli/).
|
||||
|
||||
|
||||
## Developing a plugin
|
||||
|
||||
@ -33,11 +33,11 @@ a `Dockerfile` and a *context*. The build's context is the set of files at a
|
||||
specified location `PATH` or `URL`. The `PATH` is a directory on your local
|
||||
filesystem. The `URL` is a Git repository location.
|
||||
|
||||
A context is processed recursively. So, a `PATH` includes any subdirectories and
|
||||
the `URL` includes the repository and its submodules. This example shows a
|
||||
build command that uses the current directory as context:
|
||||
The build context is processed recursively. So, a `PATH` includes any subdirectories
|
||||
and the `URL` includes the repository and its submodules. This example shows a
|
||||
build command that uses the current directory (`.`) as build context:
|
||||
|
||||
```bash
|
||||
```console
|
||||
$ docker build .
|
||||
|
||||
Sending build context to Docker daemon 6.51 MB
|
||||
@ -52,8 +52,9 @@ Dockerfile.
|
||||
|
||||
> **Warning**
|
||||
>
|
||||
> Do not use your root directory, `/`, as the `PATH` as it causes the build to
|
||||
> transfer the entire contents of your hard drive to the Docker daemon.
|
||||
> Do not use your root directory, `/`, as the `PATH` for your build context, as
|
||||
> it causes the build to transfer the entire contents of your hard drive to the
|
||||
> Docker daemon.
|
||||
{:.warning}
|
||||
|
||||
To use a file in the build context, the `Dockerfile` refers to the file specified
|
||||
@ -66,32 +67,37 @@ Traditionally, the `Dockerfile` is called `Dockerfile` and located in the root
|
||||
of the context. You use the `-f` flag with `docker build` to point to a Dockerfile
|
||||
anywhere in your file system.
|
||||
|
||||
```bash
|
||||
```console
|
||||
$ docker build -f /path/to/a/Dockerfile .
|
||||
```
|
||||
|
||||
You can specify a repository and tag at which to save the new image if
|
||||
the build succeeds:
|
||||
|
||||
```bash
|
||||
```console
|
||||
$ docker build -t shykes/myapp .
|
||||
```
|
||||
|
||||
To tag the image into multiple repositories after the build,
|
||||
add multiple `-t` parameters when you run the `build` command:
|
||||
|
||||
```bash
|
||||
```console
|
||||
$ docker build -t shykes/myapp:1.0.2 -t shykes/myapp:latest .
|
||||
```
|
||||
|
||||
Before the Docker daemon runs the instructions in the `Dockerfile`, it performs
|
||||
a preliminary validation of the `Dockerfile` and returns an error if the syntax is incorrect:
|
||||
|
||||
```bash
|
||||
```console
|
||||
$ docker build -t test/myapp .
|
||||
|
||||
Sending build context to Docker daemon 2.048 kB
|
||||
Error response from daemon: Unknown instruction: RUNCMD
|
||||
[+] Building 0.3s (2/2) FINISHED
|
||||
=> [internal] load build definition from Dockerfile 0.1s
|
||||
=> => transferring dockerfile: 60B 0.0s
|
||||
=> [internal] load .dockerignore 0.1s
|
||||
=> => transferring context: 2B 0.0s
|
||||
error: failed to solve: rpc error: code = Unknown desc = failed to solve with frontend dockerfile.v0: failed to create LLB definition:
|
||||
dockerfile parse error line 2: unknown instruction: RUNCMD
|
||||
```
|
||||
|
||||
The Docker daemon runs the instructions in the `Dockerfile` one-by-one,
|
||||
@ -104,38 +110,35 @@ Note that each instruction is run independently, and causes a new image
|
||||
to be created - so `RUN cd /tmp` will not have any effect on the next
|
||||
instructions.
|
||||
|
||||
Whenever possible, Docker will re-use the intermediate images (cache),
|
||||
to accelerate the `docker build` process significantly. This is indicated by
|
||||
the `Using cache` message in the console output.
|
||||
(For more information, see the [`Dockerfile` best practices guide](https://docs.docker.com/engine/userguide/eng-image/dockerfile_best-practices/):
|
||||
Whenever possible, Docker uses a build-cache to accelerate the `docker build`
|
||||
process significantly. This is indicated by the `CACHED` message in the console
|
||||
output. (For more information, see the [`Dockerfile` best practices guide](https://docs.docker.com/engine/userguide/eng-image/dockerfile_best-practices/):
|
||||
|
||||
```bash
|
||||
```console
|
||||
$ docker build -t svendowideit/ambassador .
|
||||
|
||||
Sending build context to Docker daemon 15.36 kB
|
||||
Step 1/4 : FROM alpine:3.2
|
||||
---> 31f630c65071
|
||||
Step 2/4 : MAINTAINER SvenDowideit@home.org.au
|
||||
---> Using cache
|
||||
---> 2a1c91448f5f
|
||||
Step 3/4 : RUN apk update && apk add socat && rm -r /var/cache/
|
||||
---> Using cache
|
||||
---> 21ed6e7fbb73
|
||||
Step 4/4 : CMD env | grep _TCP= | (sed 's/.*_PORT_\([0-9]*\)_TCP=tcp:\/\/\(.*\):\(.*\)/socat -t 100000000 TCP4-LISTEN:\1,fork,reuseaddr TCP4:\2:\3 \&/' && echo wait) | sh
|
||||
---> Using cache
|
||||
---> 7ea8aef582cc
|
||||
Successfully built 7ea8aef582cc
|
||||
[+] Building 0.7s (6/6) FINISHED
|
||||
=> [internal] load build definition from Dockerfile 0.1s
|
||||
=> => transferring dockerfile: 286B 0.0s
|
||||
=> [internal] load .dockerignore 0.1s
|
||||
=> => transferring context: 2B 0.0s
|
||||
=> [internal] load metadata for docker.io/library/alpine:3.2 0.4s
|
||||
=> CACHED [1/2] FROM docker.io/library/alpine:3.2@sha256:e9a2035f9d0d7ce 0.0s
|
||||
=> CACHED [2/2] RUN apk add --no-cache socat 0.0s
|
||||
=> exporting to image 0.0s
|
||||
=> => exporting layers 0.0s
|
||||
=> => writing image sha256:1affb80ca37018ac12067fa2af38cc5bcc2a8f09963de 0.0s
|
||||
=> => naming to docker.io/svendowideit/ambassador 0.0s
|
||||
```
|
||||
|
||||
Build cache is only used from images that have a local parent chain. This means
|
||||
that these images were created by previous builds or the whole chain of images
|
||||
was loaded with `docker load`. If you wish to use build cache of a specific
|
||||
image you can specify it with `--cache-from` option. Images specified with
|
||||
`--cache-from` do not need to have a parent chain and may be pulled from other
|
||||
registries.
|
||||
By default, the build cache is based on results from previous builds on the machine
|
||||
on which you are building. The `--cache-from` option also allows you to use a
|
||||
build-cache that's distributed through an image registry refer to the
|
||||
[specifying external cache sources](commandline/build.md#specifying-external-cache-sources)
|
||||
section in the `docker build` command reference.
|
||||
|
||||
When you're done with your build, you're ready to look into [*Pushing a
|
||||
repository to its registry*](https://docs.docker.com/engine/tutorials/dockerrepos/#/contributing-to-docker-hub).
|
||||
When you're done with your build, you're ready to look into [scanning your image with `docker scan`](https://docs.docker.com/engine/scan/),
|
||||
and [pushing your image to Docker Hub](https://docs.docker.com/docker-hub/repos/).
|
||||
|
||||
|
||||
## BuildKit
|
||||
@ -315,6 +318,8 @@ The following parser directives are supported:
|
||||
|
||||
## syntax
|
||||
|
||||
<a name="external-implementation-features"><!-- included for deep-links to old section --></a>
|
||||
|
||||
```dockerfile
|
||||
# syntax=[remote image reference]
|
||||
```
|
||||
@ -322,55 +327,73 @@ The following parser directives are supported:
|
||||
For example:
|
||||
|
||||
```dockerfile
|
||||
# syntax=docker/dockerfile
|
||||
# syntax=docker/dockerfile:1.0
|
||||
# syntax=docker/dockerfile:1
|
||||
# syntax=docker.io/docker/dockerfile:1
|
||||
# syntax=docker/dockerfile:1.0.0-experimental
|
||||
# syntax=example.com/user/repo:tag@sha256:abcdef...
|
||||
```
|
||||
|
||||
This feature is only enabled if the [BuildKit](#buildkit) backend is used.
|
||||
This feature is only available when using the [BuildKit](#buildkit) backend, and
|
||||
is ignored when using the classic builder backend.
|
||||
|
||||
The syntax directive defines the location of the Dockerfile builder that is used for
|
||||
building the current Dockerfile. The BuildKit backend allows to seamlessly use
|
||||
external implementations of builders that are distributed as Docker images and
|
||||
execute inside a container sandbox environment.
|
||||
The syntax directive defines the location of the Dockerfile syntax that is used
|
||||
to build the Dockerfile. The BuildKit backend allows to seamlessly use external
|
||||
implementations that are distributed as Docker images and execute inside a
|
||||
container sandbox environment.
|
||||
|
||||
Custom Dockerfile implementation allows you to:
|
||||
Custom Dockerfile implementations allows you to:
|
||||
|
||||
- Automatically get bugfixes without updating the daemon
|
||||
- Automatically get bugfixes without updating the Docker daemon
|
||||
- Make sure all users are using the same implementation to build your Dockerfile
|
||||
- Use the latest features without updating the daemon
|
||||
- Try out new experimental or third-party features
|
||||
- Use the latest features without updating the Docker daemon
|
||||
- Try out new features or third-party features before they are integrated in the Docker daemon
|
||||
- Use [alternative build definitions, or create your own](https://github.com/moby/buildkit#exploring-llb)
|
||||
|
||||
### Official releases
|
||||
|
||||
Docker distributes official versions of the images that can be used for building
|
||||
Dockerfiles under `docker/dockerfile` repository on Docker Hub. There are two
|
||||
channels where new images are released: stable and experimental.
|
||||
channels where new images are released: `stable` and `labs`.
|
||||
|
||||
Stable channel follows semantic versioning. For example:
|
||||
Stable channel follows [semantic versioning](https://semver.org). For example:
|
||||
|
||||
- `docker/dockerfile:1.0.0` - only allow immutable version `1.0.0`
|
||||
- `docker/dockerfile:1.0` - allow versions `1.0.*`
|
||||
- `docker/dockerfile:1` - allow versions `1.*.*`
|
||||
- `docker/dockerfile:latest` - latest release on stable channel
|
||||
- `docker/dockerfile:1` - kept updated with the latest `1.x.x` minor _and_ patch release
|
||||
- `docker/dockerfile:1.2` - kept updated with the latest `1.2.x` patch release,
|
||||
and stops receiving updates once version `1.3.0` is released.
|
||||
- `docker/dockerfile:1.2.1` - immutable: never updated
|
||||
|
||||
The experimental channel uses incremental versioning with the major and minor
|
||||
component from the stable channel on the time of the release. For example:
|
||||
We recommend using `docker/dockerfile:1`, which always points to the latest stable
|
||||
release of the version 1 syntax, and receives both "minor" and "patch" updates
|
||||
for the version 1 release cycle. BuildKit automatically checks for updates of the
|
||||
syntax when performing a build, making sure you are using the most current version.
|
||||
|
||||
- `docker/dockerfile:1.0.1-experimental` - only allow immutable version `1.0.1-experimental`
|
||||
- `docker/dockerfile:1.0-experimental` - latest experimental releases after `1.0`
|
||||
- `docker/dockerfile:experimental` - latest release on experimental channel
|
||||
If a specific version is used, such as `1.2` or `1.2.1`, the Dockerfile needs to
|
||||
be updated manually to continue receiving bugfixes and new features. Old versions
|
||||
of the Dockerfile remain compatible with the new versions of the builder.
|
||||
|
||||
You should choose a channel that best fits your needs. If you only want
|
||||
bugfixes, you should use `docker/dockerfile:1.0`. If you want to benefit from
|
||||
experimental features, you should use the experimental channel. If you are using
|
||||
the experimental channel, newer releases may not be backwards compatible, so it
|
||||
**labs channel**
|
||||
|
||||
The "labs" channel provides early access to Dockerfile features that are not yet
|
||||
available in the stable channel. Labs channel images are released in conjunction
|
||||
with the stable releases, and follow the same versioning with the `-labs` suffix,
|
||||
for example:
|
||||
|
||||
- `docker/dockerfile:labs` - latest release on labs channel
|
||||
- `docker/dockerfile:1-labs` - same as `dockerfile:1` in the stable channel, with labs features enabled
|
||||
- `docker/dockerfile:1.2-labs` - same as `dockerfile:1.2` in the stable channel, with labs features enabled
|
||||
- `docker/dockerfile:1.2.1-labs` - immutable: never updated. Same as `dockerfile:1.2.1` in the stable channel, with labs features enabled
|
||||
|
||||
Choose a channel that best fits your needs; if you want to benefit from
|
||||
new features, use the labs channel. Images in the labs channel provide a superset
|
||||
of the features in the stable channel; note that `stable` features in the labs
|
||||
channel images follow [semantic versioning](https://semver.org), but "labs"
|
||||
features do not, and newer releases may not be backwards compatible, so it
|
||||
is recommended to use an immutable full version variant.
|
||||
|
||||
For master builds and nightly feature releases refer to the description in
|
||||
[the source repository](https://github.com/moby/buildkit/blob/master/README.md).
|
||||
For documentation on "labs" features, master builds, and nightly feature releases,
|
||||
refer to the description in [the BuildKit source repository on GitHub](https://github.com/moby/buildkit/blob/master/README.md).
|
||||
For a full list of available images, visit the [image repository on Docker Hub](https://hub.docker.com/r/docker/dockerfile),
|
||||
and the [docker/dockerfile-upstream image repository](https://hub.docker.com/r/docker/dockerfile-upstream)
|
||||
for development builds.
|
||||
|
||||
## escape
|
||||
|
||||
@ -413,14 +436,15 @@ RUN dir c:\
|
||||
|
||||
Results in:
|
||||
|
||||
```powershell
|
||||
PS C:\John> docker build -t cmd .
|
||||
```console
|
||||
PS E:\myproject> docker build -t cmd .
|
||||
|
||||
Sending build context to Docker daemon 3.072 kB
|
||||
Step 1/2 : FROM microsoft/nanoserver
|
||||
---> 22738ff49c6d
|
||||
Step 2/2 : COPY testfile.txt c:\RUN dir c:
|
||||
GetFileAttributesEx c:RUN: The system cannot find the file specified.
|
||||
PS C:\John>
|
||||
PS E:\myproject>
|
||||
```
|
||||
|
||||
One solution to the above would be to use `/` as the target of both the `COPY`
|
||||
@ -441,8 +465,9 @@ RUN dir c:\
|
||||
|
||||
Results in:
|
||||
|
||||
```powershell
|
||||
PS C:\John> docker build -t succeeds --no-cache=true .
|
||||
```console
|
||||
PS E:\myproject> docker build -t succeeds --no-cache=true .
|
||||
|
||||
Sending build context to Docker daemon 3.072 kB
|
||||
Step 1/3 : FROM microsoft/nanoserver
|
||||
---> 22738ff49c6d
|
||||
@ -467,7 +492,7 @@ Step 3/3 : RUN dir c:\
|
||||
---> 01c7f3bef04f
|
||||
Removing intermediate container a2c157f842f5
|
||||
Successfully built 01c7f3bef04f
|
||||
PS C:\John>
|
||||
PS E:\myproject>
|
||||
```
|
||||
|
||||
## Environment replacement
|
||||
@ -910,8 +935,8 @@ the most-recently-applied value overrides any previously-set value.
|
||||
To view an image's labels, use the `docker image inspect` command. You can use
|
||||
the `--format` option to show just the labels;
|
||||
|
||||
```bash
|
||||
docker image inspect --format='{{json .Config.Labels}}' myimage
|
||||
```console
|
||||
$ docker image inspect --format='{{json .Config.Labels}}' myimage
|
||||
```
|
||||
```json
|
||||
{
|
||||
@ -938,7 +963,7 @@ easily, for example with `docker inspect`. To set a label corresponding to the
|
||||
`MAINTAINER` field you could use:
|
||||
|
||||
```dockerfile
|
||||
LABEL maintainer="SvenDowideit@home.org.au"
|
||||
LABEL org.opencontainers.image.authors="SvenDowideit@home.org.au"
|
||||
```
|
||||
|
||||
This will then be visible from `docker inspect` with the other labels.
|
||||
@ -980,8 +1005,8 @@ port on the host, so the port will not be the same for TCP and UDP.
|
||||
Regardless of the `EXPOSE` settings, you can override them at runtime by using
|
||||
the `-p` flag. For example
|
||||
|
||||
```bash
|
||||
docker run -p 80:80/tcp -p 80:80/udp ...
|
||||
```console
|
||||
$ docker run -p 80:80/tcp -p 80:80/udp ...
|
||||
```
|
||||
|
||||
To set up port redirection on the host system, see [using the -P flag](run.md#expose-incoming-ports).
|
||||
@ -1397,7 +1422,7 @@ An `ENTRYPOINT` allows you to configure a container that will run as an executab
|
||||
For example, the following starts nginx with its default content, listening
|
||||
on port 80:
|
||||
|
||||
```bash
|
||||
```console
|
||||
$ docker run -i -t --rm -p 80:80 nginx
|
||||
```
|
||||
|
||||
@ -1432,7 +1457,7 @@ CMD ["-c"]
|
||||
|
||||
When you run the container, you can see that `top` is the only process:
|
||||
|
||||
```bash
|
||||
```console
|
||||
$ docker run -it --rm --name test top -H
|
||||
|
||||
top - 08:25:00 up 7:27, 0 users, load average: 0.00, 0.01, 0.05
|
||||
@ -1447,7 +1472,7 @@ KiB Swap: 1441840 total, 0 used, 1441840 free. 1324440 cached Mem
|
||||
|
||||
To examine the result further, you can use `docker exec`:
|
||||
|
||||
```bash
|
||||
```console
|
||||
$ docker exec -it test ps aux
|
||||
|
||||
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
|
||||
@ -1519,7 +1544,7 @@ If you run this image with `docker run -it --rm -p 80:80 --name test apache`,
|
||||
you can then examine the container's processes with `docker exec`, or `docker top`,
|
||||
and then ask the script to stop Apache:
|
||||
|
||||
```bash
|
||||
```console
|
||||
$ docker exec -it test ps aux
|
||||
|
||||
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
|
||||
@ -1579,7 +1604,7 @@ ENTRYPOINT exec top -b
|
||||
|
||||
When you run this image, you'll see the single `PID 1` process:
|
||||
|
||||
```bash
|
||||
```console
|
||||
$ docker run -it --rm --name test top
|
||||
|
||||
Mem: 1704520K used, 352148K free, 0K shrd, 0K buff, 140368121167873K cached
|
||||
@ -1591,7 +1616,7 @@ Load average: 0.08 0.03 0.05 2/98 6
|
||||
|
||||
Which exits cleanly on `docker stop`:
|
||||
|
||||
```bash
|
||||
```console
|
||||
$ /usr/bin/time docker stop test
|
||||
|
||||
test
|
||||
@ -1610,7 +1635,7 @@ CMD --ignored-param1
|
||||
|
||||
You can then run it (giving it a name for the next step):
|
||||
|
||||
```bash
|
||||
```console
|
||||
$ docker run -it --name test top --ignored-param2
|
||||
|
||||
Mem: 1704184K used, 352484K free, 0K shrd, 0K buff, 140621524238337K cached
|
||||
@ -1626,7 +1651,7 @@ You can see from the output of `top` that the specified `ENTRYPOINT` is not `PID
|
||||
If you then run `docker stop test`, the container will not exit cleanly - the
|
||||
`stop` command will be forced to send a `SIGKILL` after the timeout:
|
||||
|
||||
```bash
|
||||
```console
|
||||
$ docker exec -it test ps aux
|
||||
|
||||
PID USER COMMAND
|
||||
@ -1859,9 +1884,10 @@ ARG user
|
||||
USER $user
|
||||
# ...
|
||||
```
|
||||
|
||||
A user builds this file by calling:
|
||||
|
||||
```bash
|
||||
```console
|
||||
$ docker build --build-arg user=what_user .
|
||||
```
|
||||
|
||||
@ -1900,7 +1926,7 @@ RUN echo $CONT_IMG_VER
|
||||
|
||||
Then, assume this image is built with this command:
|
||||
|
||||
```bash
|
||||
```console
|
||||
$ docker build --build-arg CONT_IMG_VER=v2.0.1 .
|
||||
```
|
||||
|
||||
@ -1922,7 +1948,7 @@ RUN echo $CONT_IMG_VER
|
||||
Unlike an `ARG` instruction, `ENV` values are always persisted in the built
|
||||
image. Consider a docker build without the `--build-arg` flag:
|
||||
|
||||
```bash
|
||||
```console
|
||||
$ docker build .
|
||||
```
|
||||
|
||||
@ -1948,10 +1974,11 @@ corresponding `ARG` instruction in the Dockerfile.
|
||||
- `NO_PROXY`
|
||||
- `no_proxy`
|
||||
|
||||
To use these, simply pass them on the command line using the flag:
|
||||
To use these, pass them on the command line using the `--build-arg` flag, for
|
||||
example:
|
||||
|
||||
```bash
|
||||
--build-arg <varname>=<value>
|
||||
```console
|
||||
$ docker build --build-arg HTTPS_PROXY=https://my-proxy.example.com .
|
||||
```
|
||||
|
||||
By default, these pre-defined variables are excluded from the output of
|
||||
@ -2298,8 +2325,9 @@ RUN c:\example\Execute-MyCmdlet -sample 'hello world'
|
||||
|
||||
Resulting in:
|
||||
|
||||
```powershell
|
||||
PS E:\docker\build\shell> docker build -t shell .
|
||||
```console
|
||||
PS E:\myproject> docker build -t shell .
|
||||
|
||||
Sending build context to Docker daemon 4.096 kB
|
||||
Step 1/5 : FROM microsoft/nanoserver
|
||||
---> 22738ff49c6d
|
||||
@ -2314,9 +2342,9 @@ Step 3/5 : RUN New-Item -ItemType Directory C:\Example
|
||||
Directory: C:\
|
||||
|
||||
|
||||
Mode LastWriteTime Length Name
|
||||
---- ------------- ------ ----
|
||||
d----- 10/28/2016 11:26 AM Example
|
||||
Mode LastWriteTime Length Name
|
||||
---- ------------- ------ ----
|
||||
d----- 10/28/2016 11:26 AM Example
|
||||
|
||||
|
||||
---> 3f2fbf1395d9
|
||||
@ -2330,7 +2358,7 @@ hello world
|
||||
---> 8e559e9bf424
|
||||
Removing intermediate container be6d8e63fe75
|
||||
Successfully built 8e559e9bf424
|
||||
PS E:\docker\build\shell>
|
||||
PS E:\myproject>
|
||||
```
|
||||
|
||||
The `SHELL` instruction could also be used to modify the way in which
|
||||
@ -2340,61 +2368,10 @@ environment variable expansion semantics could be modified.
|
||||
The `SHELL` instruction can also be used on Linux should an alternate shell be
|
||||
required such as `zsh`, `csh`, `tcsh` and others.
|
||||
|
||||
## External implementation features
|
||||
|
||||
This feature is only available when using the [BuildKit](#buildkit) backend.
|
||||
|
||||
Docker build supports experimental features like cache mounts, build secrets and
|
||||
ssh forwarding that are enabled by using an external implementation of the
|
||||
builder with a syntax directive. To learn about these features,
|
||||
[refer to the documentation in BuildKit repository](https://github.com/moby/buildkit/blob/master/frontend/dockerfile/docs/experimental.md).
|
||||
|
||||
## Dockerfile examples
|
||||
|
||||
Below you can see some examples of Dockerfile syntax.
|
||||
For examples of Dockerfiles, refer to:
|
||||
|
||||
```dockerfile
|
||||
# Nginx
|
||||
#
|
||||
# VERSION 0.0.1
|
||||
|
||||
FROM ubuntu
|
||||
LABEL Description="This image is used to start the foobar executable" Vendor="ACME Products" Version="1.0"
|
||||
RUN apt-get update && apt-get install -y inotify-tools nginx apache2 openssh-server
|
||||
```
|
||||
|
||||
```dockerfile
|
||||
# Firefox over VNC
|
||||
#
|
||||
# VERSION 0.3
|
||||
|
||||
FROM ubuntu
|
||||
|
||||
# Install vnc, xvfb in order to create a 'fake' display and firefox
|
||||
RUN apt-get update && apt-get install -y x11vnc xvfb firefox
|
||||
RUN mkdir ~/.vnc
|
||||
# Setup a password
|
||||
RUN x11vnc -storepasswd 1234 ~/.vnc/passwd
|
||||
# Autostart firefox (might not be the best way, but it does the trick)
|
||||
RUN bash -c 'echo "firefox" >> /.bashrc'
|
||||
|
||||
EXPOSE 5900
|
||||
CMD ["x11vnc", "-forever", "-usepw", "-create"]
|
||||
```
|
||||
|
||||
```dockerfile
|
||||
# Multiple images example
|
||||
#
|
||||
# VERSION 0.1
|
||||
|
||||
FROM ubuntu
|
||||
RUN echo foo > bar
|
||||
# Will output something like ===> 907ad6c2736f
|
||||
|
||||
FROM ubuntu
|
||||
RUN echo moo > oink
|
||||
# Will output something like ===> 695d7793cbe4
|
||||
|
||||
# You'll now have two images, 907ad6c2736f with /bar, and 695d7793cbe4 with
|
||||
# /oink.
|
||||
```
|
||||
- The ["build images" section](https://docs.docker.com/develop/develop-images/dockerfile_best-practices/)
|
||||
- The ["get started](https://docs.docker.com/get-started/)
|
||||
- The [language-specific getting started guides](https://docs.docker.com/language/)
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
---
|
||||
title: "Use the Docker command line"
|
||||
description: "Docker's CLI command description and usage"
|
||||
keywords: "Docker, Docker documentation, CLI, command line"
|
||||
keywords: "Docker, Docker documentation, CLI, command line, config.json, CLI configuration file"
|
||||
redirect_from:
|
||||
- /go/experimental/
|
||||
- /engine/reference/commandline/engine/
|
||||
@ -62,30 +62,22 @@ the [installation](https://docs.docker.com/install/) instructions for your opera
|
||||
|
||||
## Environment variables
|
||||
|
||||
For easy reference, the following list of environment variables are supported
|
||||
by the `docker` command line:
|
||||
The following list of environment variables are supported by the `docker` command
|
||||
line:
|
||||
|
||||
* `DOCKER_API_VERSION` The API version to use (e.g. `1.19`)
|
||||
* `DOCKER_CONFIG` The location of your client configuration files.
|
||||
* `DOCKER_HOST` Daemon socket to connect to.
|
||||
* `DOCKER_STACK_ORCHESTRATOR` Configure the default orchestrator to use when using `docker stack` management commands.
|
||||
* `DOCKER_CONTENT_TRUST` When set Docker uses notary to sign and verify images.
|
||||
Equates to `--disable-content-trust=false` for build, create, pull, push, run.
|
||||
* `DOCKER_CONTENT_TRUST_SERVER` The URL of the Notary server to use. This defaults
|
||||
to the same URL as the registry.
|
||||
* `DOCKER_HIDE_LEGACY_COMMANDS` When set, Docker hides "legacy" top-level commands (such as `docker rm`, and
|
||||
`docker pull`) in `docker help` output, and only `Management commands` per object-type (e.g., `docker container`) are
|
||||
printed. This may become the default in a future release, at which point this environment-variable is removed.
|
||||
* `DOCKER_CONTEXT` Specify the context to use (overrides DOCKER_HOST env var and default context set with "docker context use")
|
||||
* `DOCKER_DEFAULT_PLATFORM` Specify the default platform for the commands that take the `--platform` flag.
|
||||
|
||||
#### Shared Environment variables
|
||||
|
||||
These environment variables can be used both with the `docker` command line and
|
||||
`dockerd` command line:
|
||||
|
||||
* `DOCKER_CERT_PATH` The location of your authentication keys.
|
||||
* `DOCKER_TLS_VERIFY` When set Docker uses TLS and verifies the remote.
|
||||
| Variable | Description |
|
||||
|:------------------------------|:--------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| `DOCKER_API_VERSION` | Override the negotiated API version to use for debugging (e.g. `1.19`) |
|
||||
| `DOCKER_CERT_PATH` | Location of your authentication keys. This variable is used both by the `docker` CLI and the [`dockerd` daemon](dockerd.md) |
|
||||
| `DOCKER_CONFIG` | The location of your client configuration files. |
|
||||
| `DOCKER_CONTENT_TRUST_SERVER` | The URL of the Notary server to use. Defaults to the same URL as the registry. |
|
||||
| `DOCKER_CONTENT_TRUST` | When set Docker uses notary to sign and verify images. Equates to `--disable-content-trust=false` for build, create, pull, push, run. |
|
||||
| `DOCKER_CONTEXT` | Name of the `docker context` to use (overrides `DOCKER_HOST` env var and default context set with `docker context use`) |
|
||||
| `DOCKER_DEFAULT_PLATFORM` | Default platform for commands that take the `--platform` flag. |
|
||||
| `DOCKER_HIDE_LEGACY_COMMANDS` | When set, Docker hides "legacy" top-level commands (such as `docker rm`, and `docker pull`) in `docker help` output, and only `Management commands` per object-type (e.g., `docker container`) are printed. This may become the default in a future release, at which point this environment-variable is removed. |
|
||||
| `DOCKER_HOST` | Daemon socket to connect to. |
|
||||
| `DOCKER_STACK_ORCHESTRATOR` | Configure the default orchestrator to use when using `docker stack` management commands. |
|
||||
| `DOCKER_TLS_VERIFY` | When set Docker uses TLS and verifies the remote. This variable is used both by the `docker` CLI and the [`dockerd` daemon](dockerd.md) |
|
||||
|
||||
Because Docker is developed using Go, you can also use any environment
|
||||
variables used by the Go runtime. In particular, you may find these useful:
|
||||
@ -98,7 +90,7 @@ These Go environment variables are case-insensitive. See the
|
||||
[Go specification](http://golang.org/pkg/net/http/) for details on these
|
||||
variables.
|
||||
|
||||
### Configuration files
|
||||
## Configuration files
|
||||
|
||||
By default, the Docker command line stores its configuration files in a
|
||||
directory called `.docker` within your `$HOME` directory.
|
||||
@ -124,7 +116,7 @@ specified, then the `--config` option overrides the `DOCKER_CONFIG` environment
|
||||
variable. The example below overrides the `docker ps` command using a
|
||||
`config.json` file located in the `~/testconfigs/` directory.
|
||||
|
||||
```bash
|
||||
```console
|
||||
$ docker --config ~/testconfigs/ ps
|
||||
```
|
||||
|
||||
@ -133,79 +125,56 @@ configuration, you can set the `DOCKER_CONFIG` environment variable in your
|
||||
shell (e.g. `~/.profile` or `~/.bashrc`). The example below sets the new
|
||||
directory to be `HOME/newdir/.docker`.
|
||||
|
||||
```bash
|
||||
echo export DOCKER_CONFIG=$HOME/newdir/.docker > ~/.profile
|
||||
```console
|
||||
$ echo export DOCKER_CONFIG=$HOME/newdir/.docker > ~/.profile
|
||||
```
|
||||
|
||||
### `config.json` properties
|
||||
## Docker CLI configuration file (`config.json`) properties
|
||||
|
||||
The `config.json` file stores a JSON encoding of several properties:
|
||||
<a name="configjson-properties"><!-- included for deep-links to old section --></a>
|
||||
|
||||
Use the Docker CLI configuration to customize settings for the `docker` CLI. The
|
||||
configuration file uses JSON formatting, and properties:
|
||||
|
||||
By default, configuration file is stored in `~/.docker/config.json`. Refer to the
|
||||
[change the `.docker` directory](#change-the-docker-directory) section to use a
|
||||
different location.
|
||||
|
||||
> **Warning**
|
||||
>
|
||||
> The configuration file and other files inside the `~/.docker` configuration
|
||||
> directory may contain sensitive information, such as authentication information
|
||||
> for proxies or, depending on your credential store, credentials for your image
|
||||
> registries. Review your configuration file's content before sharing with others,
|
||||
> and prevent committing the file to version control.
|
||||
|
||||
### Customize the default output format for commands
|
||||
|
||||
These fields allow you to customize the default output format for some commands
|
||||
if no `--format` flag is provided.
|
||||
|
||||
| Property | Description |
|
||||
|:-----------------------|:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| `configFormat` | Custom default format for `docker config ls` output. Refer to the [**format the output** section in the `docker config ls` documentation](config_ls.md#format-the-output) for a list of supported formatting directives. |
|
||||
| `imagesFormat` | Custom default format for `docker images` / `docker image ls` output. Refer to the [**format the output** section in the `docker images` documentation](images.md#format-the-output) for a list of supported formatting directives. |
|
||||
| `nodesFormat` | Custom default format for `docker node ls` output. Refer to the [**formatting** section in the `docker node ls` documentation](node_ls.md#formatting) for a list of supported formatting directives. |
|
||||
| `pluginsFormat` | Custom default format for `docker plugin ls` output. Refer to the [**formatting** section in the `docker plugin ls` documentation](plugin_ls.md#formatting) for a list of supported formatting directives. |
|
||||
| `psFormat` | Custom default format for `docker ps` / `docker container ps` output. Refer to the [**formatting** section in the `docker ps` documentation](ps.md#formatting) for a list of supported formatting directives. |
|
||||
| `secretFormat` | Custom default format for `docker secret ls` output. Refer to the [**format the output** section in the `docker secret ls` documentation](secret_ls.md#format-the-output) for a list of supported formatting directives. |
|
||||
| `serviceInspectFormat` | Custom default format for `docker service inspect` output. Refer to the [**formatting** section in the `docker service inspect` documentation](service_inspect.md#formatting) for a list of supported formatting directives. |
|
||||
| `servicesFormat` | Custom default format for `docker service ls` output. Refer to the [**formatting** section in the `docker service ls` documentation](service_ls.md#formatting) for a list of supported formatting directives. |
|
||||
| `statsFormat` | Custom default format for `docker stats` output. Refer to the [**formatting** section in the `docker stats` documentation](stats.md#formatting) for a list of supported formatting directives. |
|
||||
|
||||
|
||||
### Custom HTTP headers
|
||||
|
||||
The property `HttpHeaders` specifies a set of headers to include in all messages
|
||||
sent from the Docker client to the daemon. Docker does not try to interpret or
|
||||
understand these header; it simply puts them into the messages. Docker does
|
||||
understand these headers; it simply puts them into the messages. Docker does
|
||||
not allow these headers to change any headers it sets for itself.
|
||||
|
||||
The property `psFormat` specifies the default format for `docker ps` output.
|
||||
When the `--format` flag is not provided with the `docker ps` command,
|
||||
Docker's client uses this property. If this property is not set, the client
|
||||
falls back to the default table format. For a list of supported formatting
|
||||
directives, see the
|
||||
[**Formatting** section in the `docker ps` documentation](ps.md)
|
||||
|
||||
The property `imagesFormat` specifies the default format for `docker images` output.
|
||||
When the `--format` flag is not provided with the `docker images` command,
|
||||
Docker's client uses this property. If this property is not set, the client
|
||||
falls back to the default table format. For a list of supported formatting
|
||||
directives, see the [**Formatting** section in the `docker images` documentation](images.md)
|
||||
|
||||
The property `pluginsFormat` specifies the default format for `docker plugin ls` output.
|
||||
When the `--format` flag is not provided with the `docker plugin ls` command,
|
||||
Docker's client uses this property. If this property is not set, the client
|
||||
falls back to the default table format. For a list of supported formatting
|
||||
directives, see the [**Formatting** section in the `docker plugin ls` documentation](plugin_ls.md)
|
||||
|
||||
The property `servicesFormat` specifies the default format for `docker
|
||||
service ls` output. When the `--format` flag is not provided with the
|
||||
`docker service ls` command, Docker's client uses this property. If this
|
||||
property is not set, the client falls back to the default json format. For a
|
||||
list of supported formatting directives, see the
|
||||
[**Formatting** section in the `docker service ls` documentation](service_ls.md)
|
||||
|
||||
The property `serviceInspectFormat` specifies the default format for `docker
|
||||
service inspect` output. When the `--format` flag is not provided with the
|
||||
`docker service inspect` command, Docker's client uses this property. If this
|
||||
property is not set, the client falls back to the default json format. For a
|
||||
list of supported formatting directives, see the
|
||||
[**Formatting** section in the `docker service inspect` documentation](service_inspect.md)
|
||||
|
||||
The property `statsFormat` specifies the default format for `docker
|
||||
stats` output. When the `--format` flag is not provided with the
|
||||
`docker stats` command, Docker's client uses this property. If this
|
||||
property is not set, the client falls back to the default table
|
||||
format. For a list of supported formatting directives, see
|
||||
[**Formatting** section in the `docker stats` documentation](stats.md)
|
||||
|
||||
The property `secretFormat` specifies the default format for `docker
|
||||
secret ls` output. When the `--format` flag is not provided with the
|
||||
`docker secret ls` command, Docker's client uses this property. If this
|
||||
property is not set, the client falls back to the default table
|
||||
format. For a list of supported formatting directives, see
|
||||
[**Formatting** section in the `docker secret ls` documentation](secret_ls.md)
|
||||
|
||||
|
||||
The property `nodesFormat` specifies the default format for `docker node ls` output.
|
||||
When the `--format` flag is not provided with the `docker node ls` command,
|
||||
Docker's client uses the value of `nodesFormat`. If the value of `nodesFormat` is not set,
|
||||
the client uses the default table format. For a list of supported formatting
|
||||
directives, see the [**Formatting** section in the `docker node ls` documentation](node_ls.md)
|
||||
|
||||
The property `configFormat` specifies the default format for `docker
|
||||
config ls` output. When the `--format` flag is not provided with the
|
||||
`docker config ls` command, Docker's client uses this property. If this
|
||||
property is not set, the client falls back to the default table
|
||||
format. For a list of supported formatting directives, see
|
||||
[**Formatting** section in the `docker config ls` documentation](config_ls.md)
|
||||
### Credential store options
|
||||
|
||||
The property `credsStore` specifies an external binary to serve as the default
|
||||
credential store. When this property is set, `docker login` will attempt to
|
||||
@ -221,11 +190,17 @@ credentials for specific registries. If this property is set, the binary
|
||||
for a specific registry. For more information, see the
|
||||
[**Credential helpers** section in the `docker login` documentation](login.md#credential-helpers)
|
||||
|
||||
|
||||
### Orchestrator options for docker stacks
|
||||
|
||||
The property `stackOrchestrator` specifies the default orchestrator to use when
|
||||
running `docker stack` management commands. Valid values are `"swarm"`,
|
||||
`"kubernetes"`, and `"all"`. This property can be overridden with the
|
||||
`DOCKER_STACK_ORCHESTRATOR` environment variable, or the `--orchestrator` flag.
|
||||
|
||||
|
||||
### Automatic proxy configuration for containers
|
||||
|
||||
The property `proxies` specifies proxy environment variables to be automatically
|
||||
set on containers, and set as `--build-arg` on containers used during `docker build`.
|
||||
A `"default"` set of proxies can be configured, and will be used for any docker
|
||||
@ -233,15 +208,26 @@ daemon that the client connects to, or a configuration per host (docker daemon),
|
||||
for example, "https://docker-daemon1.example.com". The following properties can
|
||||
be set for each environment:
|
||||
|
||||
* `httpProxy` (sets the value of `HTTP_PROXY` and `http_proxy`)
|
||||
* `httpsProxy` (sets the value of `HTTPS_PROXY` and `https_proxy`)
|
||||
* `ftpProxy` (sets the value of `FTP_PROXY` and `ftp_proxy`)
|
||||
* `noProxy` (sets the value of `NO_PROXY` and `no_proxy`)
|
||||
| Property | Description |
|
||||
|:---------------|:--------------------------------------------------------------------------------------------------------|
|
||||
| `httpProxy` | Default value of `HTTP_PROXY` and `http_proxy` for containers, and as `--build-arg` on `docker build` |
|
||||
| `httpsProxy` | Default value of `HTTPS_PROXY` and `https_proxy` for containers, and as `--build-arg` on `docker build` |
|
||||
| `ftpProxy` | Default value of `FTP_PROXY` and `ftp_proxy` for containers, and as `--build-arg` on `docker build` |
|
||||
| `noProxy` | Default value of `NO_PROXY` and `no_proxy` for containers, and as `--build-arg` on `docker build` |
|
||||
|
||||
> **Warning**: Proxy settings may contain sensitive information (for example,
|
||||
> if the proxy requires authentication). Environment variables are stored as
|
||||
> plain text in the container's configuration, and as such can be inspected
|
||||
> through the remote API or committed to an image when using `docker commit`.
|
||||
These settings are used to configure proxy settings for containers only, and not
|
||||
used as proxy settings for the `docker` CLI or the `dockerd` daemon. Refer to the
|
||||
[environment variables](#environment-variables) and [HTTP/HTTPS proxy](https://docs.docker.com/config/daemon/systemd/#httphttps-proxy)
|
||||
sections for configuring proxy settings for the cli and daemon.
|
||||
|
||||
> **Warning**
|
||||
>
|
||||
> Proxy settings may contain sensitive information (for example, if the proxy
|
||||
> requires authentication). Environment variables are stored as plain text in
|
||||
> the container's configuration, and as such can be inspected through the remote
|
||||
> API or committed to an image when using `docker commit`.
|
||||
|
||||
### Default key-sequence to detach from containers
|
||||
|
||||
Once attached to a container, users detach from it and leave it running using
|
||||
the using `CTRL-p CTRL-q` key sequence. This detach key sequence is customizable
|
||||
@ -261,11 +247,17 @@ Users can override your custom or the default key sequence on a per-container
|
||||
basis. To do this, the user specifies the `--detach-keys` flag with the `docker
|
||||
attach`, `docker exec`, `docker run` or `docker start` command.
|
||||
|
||||
### CLI Plugin options
|
||||
|
||||
The property `plugins` contains settings specific to CLI plugins. The
|
||||
key is the plugin name, while the value is a further map of options,
|
||||
which are specific to that plugin.
|
||||
|
||||
Following is a sample `config.json` file:
|
||||
|
||||
### Sample configuration file
|
||||
|
||||
Following is a sample `config.json` file to illustrate the format used for
|
||||
various fields:
|
||||
|
||||
```json
|
||||
{% raw %}
|
||||
@ -301,14 +293,14 @@ Following is a sample `config.json` file:
|
||||
"proxies": {
|
||||
"default": {
|
||||
"httpProxy": "http://user:pass@example.com:3128",
|
||||
"httpsProxy": "http://user:pass@example.com:3128",
|
||||
"noProxy": "http://user:pass@example.com:3128",
|
||||
"httpsProxy": "https://my-proxy.example.com:3129",
|
||||
"noProxy": "intra.mycorp.example.com",
|
||||
"ftpProxy": "http://user:pass@example.com:3128"
|
||||
},
|
||||
"https://manager1.mycorp.example.com:2377": {
|
||||
"httpProxy": "http://user:pass@example.com:3128",
|
||||
"httpsProxy": "http://user:pass@example.com:3128"
|
||||
},
|
||||
"httpsProxy": "https://my-proxy.example.com:3129"
|
||||
}
|
||||
}
|
||||
}
|
||||
{% endraw %}
|
||||
@ -336,16 +328,18 @@ list of root Certificate Authorities.
|
||||
To list the help on any command just execute the command, followed by the
|
||||
`--help` option.
|
||||
|
||||
$ docker run --help
|
||||
```console
|
||||
$ docker run --help
|
||||
|
||||
Usage: docker run [OPTIONS] IMAGE [COMMAND] [ARG...]
|
||||
Usage: docker run [OPTIONS] IMAGE [COMMAND] [ARG...]
|
||||
|
||||
Run a command in a new container
|
||||
Run a command in a new container
|
||||
|
||||
Options:
|
||||
--add-host value Add a custom host-to-IP mapping (host:ip) (default [])
|
||||
-a, --attach value Attach to STDIN, STDOUT or STDERR (default [])
|
||||
...
|
||||
Options:
|
||||
--add-host value Add a custom host-to-IP mapping (host:ip) (default [])
|
||||
-a, --attach value Attach to STDIN, STDOUT or STDERR (default [])
|
||||
<...>
|
||||
```
|
||||
|
||||
### Option types
|
||||
|
||||
@ -366,7 +360,7 @@ container **will** run in "detached" mode, in the background.
|
||||
Options which default to `true` (e.g., `docker build --rm=true`) can only be
|
||||
set to the non-default value by explicitly setting them to `false`:
|
||||
|
||||
```bash
|
||||
```console
|
||||
$ docker build --rm=false .
|
||||
```
|
||||
|
||||
@ -375,7 +369,7 @@ $ docker build --rm=false .
|
||||
You can specify options like `-a=[]` multiple times in a single command line,
|
||||
for example in these commands:
|
||||
|
||||
```bash
|
||||
```console
|
||||
$ docker run -a stdin -a stdout -i -t ubuntu /bin/bash
|
||||
|
||||
$ docker run -a stdin -a stdout -a stderr ubuntu /bin/ls
|
||||
@ -384,7 +378,7 @@ $ docker run -a stdin -a stdout -a stderr ubuntu /bin/ls
|
||||
Sometimes, multiple options can call for a more complex value string as for
|
||||
`-v`:
|
||||
|
||||
```bash
|
||||
```console
|
||||
$ docker run -v /host:/container example/mysql
|
||||
```
|
||||
|
||||
|
||||
35
docs/reference/commandline/config.md
Normal file
@ -0,0 +1,35 @@
|
||||
---
|
||||
title: "config"
|
||||
description: "The config command description and usage"
|
||||
keywords: "config"
|
||||
---
|
||||
|
||||
# config
|
||||
|
||||
```markdown
|
||||
Usage: docker config COMMAND
|
||||
|
||||
Manage Docker configs
|
||||
|
||||
Options:
|
||||
--help Print usage
|
||||
|
||||
Commands:
|
||||
create Create a config from a file or STDIN
|
||||
inspect Display detailed information on one or more configs
|
||||
ls List configs
|
||||
rm Remove one or more configs
|
||||
|
||||
Run 'docker config COMMAND --help' for more information on a command.
|
||||
```
|
||||
|
||||
## Description
|
||||
|
||||
Manage configs.
|
||||
|
||||
## Related commands
|
||||
|
||||
* [config create](config_create.md)
|
||||
* [config inspect](config_inspect.md)
|
||||
* [config list](config_ls.md)
|
||||
* [config rm](config_rm.md)
|
||||
99
docs/reference/commandline/config_create.md
Normal file
@ -0,0 +1,99 @@
|
||||
---
|
||||
title: "config create"
|
||||
description: "The config create command description and usage"
|
||||
keywords: ["config, create"]
|
||||
---
|
||||
|
||||
# config create
|
||||
|
||||
```Markdown
|
||||
Usage: docker config create [OPTIONS] CONFIG [file|-]
|
||||
|
||||
Create a config from a file or STDIN as content
|
||||
|
||||
Options:
|
||||
-l, --label list Config labels
|
||||
--template-driver string Template driver
|
||||
```
|
||||
|
||||
## Description
|
||||
|
||||
Creates a config using standard input or from a file for the config content.
|
||||
|
||||
For detailed information about using configs, refer to [store configuration data using Docker Configs](https://docs.docker.com/engine/swarm/configs/).
|
||||
|
||||
> **Note**
|
||||
>
|
||||
> This is a cluster management command, and must be executed on a swarm
|
||||
> manager node. To learn about managers and workers, refer to the
|
||||
> [Swarm mode section](https://docs.docker.com/engine/swarm/) in the
|
||||
> documentation.
|
||||
|
||||
## Examples
|
||||
|
||||
### Create a config
|
||||
|
||||
```bash
|
||||
$ printf <config> | docker config create my_config -
|
||||
|
||||
onakdyv307se2tl7nl20anokv
|
||||
|
||||
$ docker config ls
|
||||
|
||||
ID NAME CREATED UPDATED
|
||||
onakdyv307se2tl7nl20anokv my_config 6 seconds ago 6 seconds ago
|
||||
```
|
||||
|
||||
### Create a config with a file
|
||||
|
||||
```bash
|
||||
$ docker config create my_config ./config.json
|
||||
|
||||
dg426haahpi5ezmkkj5kyl3sn
|
||||
|
||||
$ docker config ls
|
||||
|
||||
ID NAME CREATED UPDATED
|
||||
dg426haahpi5ezmkkj5kyl3sn my_config 7 seconds ago 7 seconds ago
|
||||
```
|
||||
|
||||
### Create a config with labels
|
||||
|
||||
```bash
|
||||
$ docker config create \
|
||||
--label env=dev \
|
||||
--label rev=20170324 \
|
||||
my_config ./config.json
|
||||
|
||||
eo7jnzguqgtpdah3cm5srfb97
|
||||
```
|
||||
|
||||
```bash
|
||||
$ docker config inspect my_config
|
||||
|
||||
[
|
||||
{
|
||||
"ID": "eo7jnzguqgtpdah3cm5srfb97",
|
||||
"Version": {
|
||||
"Index": 17
|
||||
},
|
||||
"CreatedAt": "2017-03-24T08:15:09.735271783Z",
|
||||
"UpdatedAt": "2017-03-24T08:15:09.735271783Z",
|
||||
"Spec": {
|
||||
"Name": "my_config",
|
||||
"Labels": {
|
||||
"env": "dev",
|
||||
"rev": "20170324"
|
||||
},
|
||||
"Data": "aGVsbG8K"
|
||||
}
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
|
||||
## Related commands
|
||||
|
||||
* [config inspect](config_inspect.md)
|
||||
* [config ls](config_ls.md)
|
||||
* [config rm](config_rm.md)
|
||||
97
docs/reference/commandline/config_inspect.md
Normal file
@ -0,0 +1,97 @@
|
||||
---
|
||||
title: "config inspect"
|
||||
description: "The config inspect command description and usage"
|
||||
keywords: ["config, inspect"]
|
||||
---
|
||||
|
||||
# config inspect
|
||||
|
||||
```Markdown
|
||||
Usage: docker config inspect [OPTIONS] CONFIG [CONFIG...]
|
||||
|
||||
Display detailed information on one or more configs
|
||||
|
||||
Options:
|
||||
-f, --format string Format the output using the given Go template
|
||||
--help Print usage
|
||||
```
|
||||
|
||||
## Description
|
||||
|
||||
Inspects the specified config.
|
||||
|
||||
By default, this renders all results in a JSON array. If a format is specified,
|
||||
the given template will be executed for each result.
|
||||
|
||||
Go's [text/template](http://golang.org/pkg/text/template/) package
|
||||
describes all the details of the format.
|
||||
|
||||
For detailed information about using configs, refer to [store configuration data using Docker Configs](https://docs.docker.com/engine/swarm/configs/).
|
||||
|
||||
> **Note**
|
||||
>
|
||||
> This is a cluster management command, and must be executed on a swarm
|
||||
> manager node. To learn about managers and workers, refer to the
|
||||
> [Swarm mode section](https://docs.docker.com/engine/swarm/) in the
|
||||
> documentation.
|
||||
|
||||
## Examples
|
||||
|
||||
### Inspect a config by name or ID
|
||||
|
||||
You can inspect a config, either by its *name*, or *ID*
|
||||
|
||||
For example, given the following config:
|
||||
|
||||
```bash
|
||||
$ docker config ls
|
||||
|
||||
ID NAME CREATED UPDATED
|
||||
eo7jnzguqgtpdah3cm5srfb97 my_config 3 minutes ago 3 minutes ago
|
||||
```
|
||||
|
||||
```bash
|
||||
$ docker config inspect config.json
|
||||
```
|
||||
|
||||
The output is in JSON format, for example:
|
||||
|
||||
```json
|
||||
[
|
||||
{
|
||||
"ID": "eo7jnzguqgtpdah3cm5srfb97",
|
||||
"Version": {
|
||||
"Index": 17
|
||||
},
|
||||
"CreatedAt": "2017-03-24T08:15:09.735271783Z",
|
||||
"UpdatedAt": "2017-03-24T08:15:09.735271783Z",
|
||||
"Spec": {
|
||||
"Name": "my_config",
|
||||
"Labels": {
|
||||
"env": "dev",
|
||||
"rev": "20170324"
|
||||
},
|
||||
"Data": "aGVsbG8K"
|
||||
}
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
### Formatting
|
||||
|
||||
You can use the --format option to obtain specific information about a
|
||||
config. The following example command outputs the creation time of the
|
||||
config.
|
||||
|
||||
```bash
|
||||
$ docker config inspect --format='{{.CreatedAt}}' eo7jnzguqgtpdah3cm5srfb97
|
||||
|
||||
2017-03-24 08:15:09.735271783 +0000 UTC
|
||||
```
|
||||
|
||||
|
||||
## Related commands
|
||||
|
||||
* [config create](config_create.md)
|
||||
* [config ls](config_ls.md)
|
||||
* [config rm](config_rm.md)
|
||||
155
docs/reference/commandline/config_ls.md
Normal file
@ -0,0 +1,155 @@
|
||||
---
|
||||
title: "config ls"
|
||||
description: "The config ls command description and usage"
|
||||
keywords: ["config, ls"]
|
||||
---
|
||||
|
||||
# config ls
|
||||
|
||||
```Markdown
|
||||
Usage: docker config ls [OPTIONS]
|
||||
|
||||
List configs
|
||||
|
||||
Aliases:
|
||||
ls, list
|
||||
|
||||
Options:
|
||||
-f, --filter filter Filter output based on conditions provided
|
||||
--format string Pretty-print configs using a Go template
|
||||
--help Print usage
|
||||
-q, --quiet Only display IDs
|
||||
```
|
||||
|
||||
## Description
|
||||
|
||||
Run this command on a manager node to list the configs in the swarm.
|
||||
|
||||
For detailed information about using configs, refer to [store configuration data using Docker Configs](https://docs.docker.com/engine/swarm/configs/).
|
||||
|
||||
> **Note**
|
||||
>
|
||||
> This is a cluster management command, and must be executed on a swarm
|
||||
> manager node. To learn about managers and workers, refer to the
|
||||
> [Swarm mode section](https://docs.docker.com/engine/swarm/) in the
|
||||
> documentation.
|
||||
|
||||
## Examples
|
||||
|
||||
```bash
|
||||
$ docker config ls
|
||||
|
||||
ID NAME CREATED UPDATED
|
||||
6697bflskwj1998km1gnnjr38 q5s5570vtvnimefos1fyeo2u2 6 weeks ago 6 weeks ago
|
||||
9u9hk4br2ej0wgngkga6rp4hq my_config 5 weeks ago 5 weeks ago
|
||||
mem02h8n73mybpgqjf0kfi1n0 test_config 3 seconds ago 3 seconds ago
|
||||
```
|
||||
|
||||
### Filtering
|
||||
|
||||
The filtering flag (`-f` or `--filter`) format is a `key=value` pair. If there is more
|
||||
than one filter, then pass multiple flags (e.g., `--filter "foo=bar" --filter "bif=baz"`)
|
||||
|
||||
The currently supported filters are:
|
||||
|
||||
- [id](#id) (config's ID)
|
||||
- [label](#label) (`label=<key>` or `label=<key>=<value>`)
|
||||
- [name](#name) (config's name)
|
||||
|
||||
#### id
|
||||
|
||||
The `id` filter matches all or prefix of a config's id.
|
||||
|
||||
```bash
|
||||
$ docker config ls -f "id=6697bflskwj1998km1gnnjr38"
|
||||
|
||||
ID NAME CREATED UPDATED
|
||||
6697bflskwj1998km1gnnjr38 q5s5570vtvnimefos1fyeo2u2 6 weeks ago 6 weeks ago
|
||||
```
|
||||
|
||||
#### label
|
||||
|
||||
The `label` filter matches configs based on the presence of a `label` alone or
|
||||
a `label` and a value.
|
||||
|
||||
The following filter matches all configs with a `project` label regardless of
|
||||
its value:
|
||||
|
||||
```bash
|
||||
$ docker config ls --filter label=project
|
||||
|
||||
ID NAME CREATED UPDATED
|
||||
mem02h8n73mybpgqjf0kfi1n0 test_config About an hour ago About an hour ago
|
||||
```
|
||||
|
||||
The following filter matches only services with the `project` label with the
|
||||
`project-a` value.
|
||||
|
||||
```bash
|
||||
$ docker service ls --filter label=project=test
|
||||
|
||||
ID NAME CREATED UPDATED
|
||||
mem02h8n73mybpgqjf0kfi1n0 test_config About an hour ago About an hour ago
|
||||
```
|
||||
|
||||
#### name
|
||||
|
||||
The `name` filter matches on all or prefix of a config's name.
|
||||
|
||||
The following filter matches config with a name containing a prefix of `test`.
|
||||
|
||||
```bash
|
||||
$ docker config ls --filter name=test_config
|
||||
|
||||
ID NAME CREATED UPDATED
|
||||
mem02h8n73mybpgqjf0kfi1n0 test_config About an hour ago About an hour ago
|
||||
```
|
||||
|
||||
### Format the output
|
||||
|
||||
The formatting option (`--format`) pretty prints configs output
|
||||
using a Go template.
|
||||
|
||||
Valid placeholders for the Go template are listed below:
|
||||
|
||||
| Placeholder | Description |
|
||||
| ------------ | ------------------------------------------------------------------------------------ |
|
||||
| `.ID` | Config ID |
|
||||
| `.Name` | Config name |
|
||||
| `.CreatedAt` | Time when the config was created |
|
||||
| `.UpdatedAt` | Time when the config was updated |
|
||||
| `.Labels` | All labels assigned to the config |
|
||||
| `.Label` | Value of a specific label for this config. For example `{{.Label "my-label"}}` |
|
||||
|
||||
When using the `--format` option, the `config ls` command will either
|
||||
output the data exactly as the template declares or, when using the
|
||||
`table` directive, will include column headers as well.
|
||||
|
||||
The following example uses a template without headers and outputs the
|
||||
`ID` and `Name` entries separated by a colon (`:`) for all images:
|
||||
|
||||
```bash
|
||||
$ docker config ls --format "{{.ID}}: {{.Name}}"
|
||||
|
||||
77af4d6b9913: config-1
|
||||
b6fa739cedf5: config-2
|
||||
78a85c484f71: config-3
|
||||
```
|
||||
|
||||
To list all configs with their name and created date in a table format you
|
||||
can use:
|
||||
|
||||
```bash
|
||||
$ docker config ls --format "table {{.ID}}\t{{.Name}}\t{{.CreatedAt}}"
|
||||
|
||||
ID NAME CREATED
|
||||
77af4d6b9913 config-1 5 minutes ago
|
||||
b6fa739cedf5 config-2 3 hours ago
|
||||
78a85c484f71 config-3 10 days ago
|
||||
```
|
||||
|
||||
## Related commands
|
||||
|
||||
* [config create](config_create.md)
|
||||
* [config inspect](config_inspect.md)
|
||||
* [config rm](config_rm.md)
|
||||
53
docs/reference/commandline/config_rm.md
Normal file
@ -0,0 +1,53 @@
|
||||
---
|
||||
title: "config rm"
|
||||
description: "The config rm command description and usage"
|
||||
keywords: ["config, rm"]
|
||||
---
|
||||
|
||||
# config rm
|
||||
|
||||
```Markdown
|
||||
Usage: docker config rm CONFIG [CONFIG...]
|
||||
|
||||
Remove one or more configs
|
||||
|
||||
Aliases:
|
||||
rm, remove
|
||||
|
||||
Options:
|
||||
--help Print usage
|
||||
```
|
||||
|
||||
## Description
|
||||
|
||||
Removes the specified configs from the swarm.
|
||||
|
||||
For detailed information about using configs, refer to [store configuration data using Docker Configs](https://docs.docker.com/engine/swarm/configs/).
|
||||
|
||||
> **Note**
|
||||
>
|
||||
> This is a cluster management command, and must be executed on a swarm
|
||||
> manager node. To learn about managers and workers, refer to the
|
||||
> [Swarm mode section](https://docs.docker.com/engine/swarm/) in the
|
||||
> documentation.
|
||||
|
||||
## Examples
|
||||
|
||||
This example removes a config:
|
||||
|
||||
```bash
|
||||
$ docker config rm my_config
|
||||
sapth4csdo5b6wz2p5uimh5xg
|
||||
```
|
||||
|
||||
> **Warning**
|
||||
>
|
||||
> Unlike `docker rm`, this command does not ask for confirmation before removing
|
||||
> a config.
|
||||
|
||||
|
||||
## Related commands
|
||||
|
||||
* [config create](config_create.md)
|
||||
* [config inspect](config_inspect.md)
|
||||
* [config ls](config_ls.md)
|
||||
@ -1203,8 +1203,8 @@ command line or Docker's Engine API are allowed or denied by the plugin.
|
||||
If you have multiple plugins installed, each plugin, in order, must
|
||||
allow the request for it to complete.
|
||||
|
||||
For information about how to create an authorization plugin, see [authorization
|
||||
plugin](../../extend/plugins_authorization.md) section in the Docker extend section of this documentation.
|
||||
For information about how to create an authorization plugin, refer to the
|
||||
[authorization plugin](../../extend/plugins_authorization.md) section.
|
||||
|
||||
|
||||
### Daemon user namespace options
|
||||
@ -1232,10 +1232,16 @@ Docker supports softlinks for the Docker data directory (`/var/lib/docker`) and
|
||||
for `/var/lib/docker/tmp`. The `DOCKER_TMPDIR` and the data directory can be
|
||||
set like this:
|
||||
|
||||
DOCKER_TMPDIR=/mnt/disk2/tmp /usr/local/bin/dockerd -D -g /var/lib/docker -H unix:// > /var/lib/docker-machine/docker.log 2>&1
|
||||
# or
|
||||
export DOCKER_TMPDIR=/mnt/disk2/tmp
|
||||
/usr/local/bin/dockerd -D -g /var/lib/docker -H unix:// > /var/lib/docker-machine/docker.log 2>&1
|
||||
```console
|
||||
$ DOCKER_TMPDIR=/mnt/disk2/tmp /usr/local/bin/dockerd -D -g /var/lib/docker -H unix:// > /var/lib/docker-machine/docker.log 2>&1
|
||||
```
|
||||
|
||||
or
|
||||
|
||||
```console
|
||||
$ export DOCKER_TMPDIR=/mnt/disk2/tmp
|
||||
$ /usr/local/bin/dockerd -D -g /var/lib/docker -H unix:// > /var/lib/docker-machine/docker.log 2>&1
|
||||
````
|
||||
|
||||
#### Default cgroup parent
|
||||
|
||||
@ -1400,6 +1406,10 @@ This is a full example of the allowed configuration options on Linux:
|
||||
"log-driver": "json-file",
|
||||
"log-level": "",
|
||||
"log-opts": {
|
||||
"cache-disabled": "false",
|
||||
"cache-max-file": "5",
|
||||
"cache-max-size": "20m",
|
||||
"cache-compress": "true",
|
||||
"env": "os,customer",
|
||||
"labels": "somelabel",
|
||||
"max-file": "5",
|
||||
@ -1560,7 +1570,9 @@ previously configured cluster configurations.
|
||||
|
||||
### Run multiple daemons
|
||||
|
||||
> **Note:** Running multiple daemons on a single host is considered as "experimental". The user should be aware of
|
||||
> **Note:**
|
||||
>
|
||||
> Running multiple daemons on a single host is considered as "experimental". The user should be aware of
|
||||
> unsolved problems. This solution may not work properly in some cases. Solutions are currently under development
|
||||
> and will be delivered in the near future.
|
||||
|
||||
@ -1612,7 +1624,7 @@ The `--tls*` options enable use of specific certificates for individual daemons.
|
||||
|
||||
Example script for a separate “bootstrap” instance of the Docker daemon without network:
|
||||
|
||||
```bash
|
||||
```console
|
||||
$ sudo dockerd \
|
||||
-H unix:///var/run/docker-bootstrap.sock \
|
||||
-p /var/run/docker-bootstrap.pid \
|
||||
|
||||
@ -160,7 +160,7 @@ Digest can also be used in the `FROM` of a Dockerfile, for example:
|
||||
|
||||
```dockerfile
|
||||
FROM ubuntu@sha256:45b23dee08af5e43a7fea6c4cf9c25ccf269ee113168c19722f87876677c5cb2
|
||||
LABEL maintainer="some maintainer <maintainer@example.com>"
|
||||
LABEL org.opencontainers.image.authors="some maintainer <maintainer@example.com>"
|
||||
```
|
||||
|
||||
> **Note**
|
||||
|
||||
@ -19,7 +19,9 @@ Options:
|
||||
## Description
|
||||
|
||||
The main process inside the container will receive `SIGTERM`, and after a grace
|
||||
period, `SIGKILL`.
|
||||
period, `SIGKILL`. The first signal can be changed with the `STOPSIGNAL`
|
||||
instruction in the container's Dockerfile, or the `--stop-signal` option to
|
||||
`docker run`.
|
||||
|
||||
## Examples
|
||||
|
||||
|
||||
@ -587,7 +587,7 @@ $ docker inspect -f "{{ .State.StartedAt }}" my-container
|
||||
|
||||
Combining `--restart` (restart policy) with the `--rm` (clean up) flag results
|
||||
in an error. On container restart, attached clients are disconnected. See the
|
||||
examples on using the [`--rm` (clean up)](#clean-up-rm) flag later in this page.
|
||||
examples on using the [`--rm` (clean up)](#clean-up---rm) flag later in this page.
|
||||
|
||||
### Examples
|
||||
|
||||
|
||||
@ -39,12 +39,5 @@ Checkpoint and restore support for Containers.
|
||||
Metrics (Prometheus) output for basic container, image, and daemon operations.
|
||||
|
||||
* [External graphdriver plugins](../docs/extend/plugins_graphdriver.md)
|
||||
* [Ipvlan Network Drivers](vlan-networks.md)
|
||||
* [Checkpoint & Restore](checkpoint-restore.md)
|
||||
* [Docker build with --squash argument](../docs/reference/commandline/build.md#squash-an-images-layers---squash-experimental)
|
||||
|
||||
## How to comment on an experimental feature
|
||||
|
||||
Each feature's documentation includes a list of proposal pull requests or PRs associated with the feature. If you want to comment on or suggest a change to a feature, please add it to the existing feature PR.
|
||||
|
||||
Issues or problems with a feature? Inquire for help on the `#docker` IRC channel or on the [Docker Google group](https://groups.google.com/forum/#!forum/docker-user).
|
||||
|
||||
|
Before Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 43 KiB |
|
Before Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 39 KiB |
|
Before Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 53 KiB |
|
Before Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 48 KiB |
|
Before Width: | Height: | Size: 38 KiB |
|
Before Width: | Height: | Size: 108 KiB |
@ -1,632 +0,0 @@
|
||||
# Ipvlan Network Driver
|
||||
|
||||
### Getting Started
|
||||
|
||||
The Ipvlan driver is currently in experimental mode in order to incubate Docker
|
||||
users use cases and vet the implementation to ensure a hardened, production ready
|
||||
driver in a future release. Libnetwork now gives users total control over both
|
||||
IPv4 and IPv6 addressing. The VLAN driver builds on top of that in giving
|
||||
operators complete control of layer 2 VLAN tagging and even Ipvlan L3 routing
|
||||
for users interested in underlay network integration. For overlay deployments
|
||||
that abstract away physical constraints see the
|
||||
[multi-host overlay](https://docs.docker.com/network/network-tutorial-overlay/)
|
||||
driver.
|
||||
|
||||
Ipvlan is a new twist on the tried and true network virtualization technique.
|
||||
The Linux implementations are extremely lightweight because rather than using
|
||||
the traditional Linux bridge for isolation, they are simply associated to a Linux
|
||||
Ethernet interface or sub-interface to enforce separation between networks and
|
||||
connectivity to the physical network.
|
||||
|
||||
Ipvlan offers a number of unique features and plenty of room for further
|
||||
innovations with the various modes. Two high level advantages of these approaches
|
||||
are, the positive performance implications of bypassing the Linux bridge and the
|
||||
simplicity of having fewer moving parts. Removing the bridge that traditionally
|
||||
resides in between the Docker host NIC and container interface leaves a simple
|
||||
setup consisting of container interfaces, attached directly to the Docker host
|
||||
interface. This result is easy access for external facing services as there is
|
||||
no need for port mappings in these scenarios.
|
||||
|
||||
### Pre-Requisites
|
||||
|
||||
- The examples on this page are all single host and require using Docker
|
||||
experimental features to be enabled.
|
||||
- All of the examples can be performed on a single host running Docker. Any
|
||||
example using a sub-interface like `eth0.10` can be replaced with `eth0` or
|
||||
any other valid parent interface on the Docker host. Sub-interfaces with a `.`
|
||||
are created on the fly. `-o parent` interfaces can also be left out of the
|
||||
`docker network create` all together and the driver will create a `dummy`
|
||||
interface that will enable local host connectivity to perform the examples.
|
||||
- Kernel requirements:
|
||||
- To check your current kernel version, use `uname -r`
|
||||
- Ipvlan Linux kernel v4.2+ (support for earlier kernels exists but is buggy)
|
||||
|
||||
### Ipvlan L2 Mode Example Usage
|
||||
|
||||
An example of the ipvlan `L2` mode topology is shown in the following image.
|
||||
The driver is specified with `-d driver_name` option. In this case `-d ipvlan`.
|
||||
|
||||

|
||||
|
||||
The parent interface in the next example `-o parent=eth0` is configured as follows:
|
||||
|
||||
```bash
|
||||
$ ip addr show eth0
|
||||
3: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
|
||||
inet 192.168.1.250/24 brd 192.168.1.255 scope global eth0
|
||||
```
|
||||
|
||||
Use the network from the host's interface as the `--subnet` in the
|
||||
`docker network create`. The container will be attached to the same network as
|
||||
the host interface as set via the `-o parent=` option.
|
||||
|
||||
Create the ipvlan network and run a container attaching to it:
|
||||
|
||||
```bash
|
||||
# Ipvlan (-o ipvlan_mode= Defaults to L2 mode if not specified)
|
||||
$ docker network create -d ipvlan \
|
||||
--subnet=192.168.1.0/24 \
|
||||
--gateway=192.168.1.1 \
|
||||
-o ipvlan_mode=l2 \
|
||||
-o parent=eth0 db_net
|
||||
|
||||
# Start a container on the db_net network
|
||||
$ docker run --net=db_net -it --rm alpine /bin/sh
|
||||
|
||||
# NOTE: the containers can NOT ping the underlying host interfaces as
|
||||
# they are intentionally filtered by Linux for additional isolation.
|
||||
```
|
||||
|
||||
The default mode for Ipvlan is `l2`. If `-o ipvlan_mode=` are left unspecified,
|
||||
the default mode will be used. Similarly, if the `--gateway` is left empty, the
|
||||
first usable address on the network will be set as the gateway. For example, if
|
||||
the subnet provided in the network create is `--subnet=192.168.1.0/24` then the
|
||||
gateway the container receives is `192.168.1.1`.
|
||||
|
||||
To help understand how this mode interacts with other hosts, the following
|
||||
figure shows the same layer 2 segment between two Docker hosts that applies to
|
||||
and Ipvlan L2 mode.
|
||||
|
||||

|
||||
|
||||
The following will create the exact same network as the network `db_net` created
|
||||
prior, with the driver defaults for `--gateway=192.168.1.1` and `-o ipvlan_mode=l2`.
|
||||
|
||||
```bash
|
||||
# Ipvlan (-o ipvlan_mode= Defaults to L2 mode if not specified)
|
||||
$ docker network create -d ipvlan \
|
||||
--subnet=192.168.1.0/24 \
|
||||
-o parent=eth0 db_net_ipv
|
||||
|
||||
# Start a container with an explicit name in daemon mode
|
||||
$ docker run --net=db_net_ipv --name=ipv1 -itd alpine /bin/sh
|
||||
|
||||
# Start a second container and ping using the container name
|
||||
# to see the docker included name resolution functionality
|
||||
$ docker run --net=db_net_ipv --name=ipv2 -it --rm alpine /bin/sh
|
||||
$ ping -c 4 ipv1
|
||||
|
||||
# NOTE: the containers can NOT ping the underlying host interfaces as
|
||||
# they are intentionally filtered by Linux for additional isolation.
|
||||
```
|
||||
|
||||
The drivers also support the `--internal` flag that will completely isolate
|
||||
containers on a network from any communications external to that network. Since
|
||||
network isolation is tightly coupled to the network's parent interface the result
|
||||
of leaving the `-o parent=` option off of a `docker network create` is the exact
|
||||
same as the `--internal` option. If the parent interface is not specified or the
|
||||
`--internal` flag is used, a netlink type `dummy` parent interface is created
|
||||
for the user and used as the parent interface effectively isolating the network
|
||||
completely.
|
||||
|
||||
The following two `docker network create` examples result in identical networks
|
||||
that you can attach container to:
|
||||
|
||||
```bash
|
||||
# Empty '-o parent=' creates an isolated network
|
||||
$ docker network create -d ipvlan \
|
||||
--subnet=192.168.10.0/24 isolated1
|
||||
|
||||
# Explicit '--internal' flag is the same:
|
||||
$ docker network create -d ipvlan \
|
||||
--subnet=192.168.11.0/24 --internal isolated2
|
||||
|
||||
# Even the '--subnet=' can be left empty and the default
|
||||
# IPAM subnet of 172.18.0.0/16 will be assigned
|
||||
$ docker network create -d ipvlan isolated3
|
||||
|
||||
$ docker run --net=isolated1 --name=cid1 -it --rm alpine /bin/sh
|
||||
$ docker run --net=isolated2 --name=cid2 -it --rm alpine /bin/sh
|
||||
$ docker run --net=isolated3 --name=cid3 -it --rm alpine /bin/sh
|
||||
|
||||
# To attach to any use `docker exec` and start a shell
|
||||
$ docker exec -it cid1 /bin/sh
|
||||
$ docker exec -it cid2 /bin/sh
|
||||
$ docker exec -it cid3 /bin/sh
|
||||
```
|
||||
|
||||
### Ipvlan 802.1q Trunk L2 Mode Example Usage
|
||||
|
||||
Architecturally, Ipvlan L2 mode trunking is the same as Macvlan with regard to
|
||||
gateways and L2 path isolation. There are nuances that can be advantageous for
|
||||
CAM table pressure in ToR switches, one MAC per port and MAC exhaustion on a
|
||||
host's parent NIC to name a few. The 802.1q trunk scenario looks the same. Both
|
||||
modes adhere to tagging standards and have seamless integration with the physical
|
||||
network for underlay integration and hardware vendor plugin integrations.
|
||||
|
||||
Hosts on the same VLAN are typically on the same subnet and almost always are
|
||||
grouped together based on their security policy. In most scenarios, a multi-tier
|
||||
application is tiered into different subnets because the security profile of each
|
||||
process requires some form of isolation. For example, hosting your credit card
|
||||
processing on the same virtual network as the frontend webserver would be a
|
||||
regulatory compliance issue, along with circumventing the long standing best
|
||||
practice of layered defense in depth architectures. VLANs or the equivocal VNI
|
||||
(Virtual Network Identifier) when using the Overlay driver, are the first step
|
||||
in isolating tenant traffic.
|
||||
|
||||

|
||||
|
||||
The Linux sub-interface tagged with a vlan can either already exist or will be
|
||||
created when you call a `docker network create`. `docker network rm` will delete
|
||||
the sub-interface. Parent interfaces such as `eth0` are not deleted, only
|
||||
sub-interfaces with a netlink parent index > 0.
|
||||
|
||||
For the driver to add/delete the vlan sub-interfaces the format needs to be
|
||||
`interface_name.vlan_tag`. Other sub-interface naming can be used as the
|
||||
specified parent, but the link will not be deleted automatically when
|
||||
`docker network rm` is invoked.
|
||||
|
||||
The option to use either existing parent vlan sub-interfaces or let Docker manage
|
||||
them enables the user to either completely manage the Linux interfaces and
|
||||
networking or let Docker create and delete the Vlan parent sub-interfaces
|
||||
(netlink `ip link`) with no effort from the user.
|
||||
|
||||
For example: use `eth0.10` to denote a sub-interface of `eth0` tagged with the
|
||||
vlan id of `10`. The equivalent `ip link` command would be
|
||||
`ip link add link eth0 name eth0.10 type vlan id 10`.
|
||||
|
||||
The example creates the vlan tagged networks and then start two containers to
|
||||
test connectivity between containers. Different Vlans cannot ping one another
|
||||
without a router routing between the two networks. The default namespace is not
|
||||
reachable per ipvlan design in order to isolate container namespaces from the
|
||||
underlying host.
|
||||
|
||||
**Vlan ID 20**
|
||||
|
||||
In the first network tagged and isolated by the Docker host, `eth0.20` is the
|
||||
parent interface tagged with vlan id `20` specified with `-o parent=eth0.20`.
|
||||
Other naming formats can be used, but the links need to be added and deleted
|
||||
manually using `ip link` or Linux configuration files. As long as the `-o parent`
|
||||
exists anything can be used if compliant with Linux netlink.
|
||||
|
||||
```bash
|
||||
# now add networks and hosts as you would normally by attaching to the master (sub)interface that is tagged
|
||||
$ docker network create -d ipvlan \
|
||||
--subnet=192.168.20.0/24 \
|
||||
--gateway=192.168.20.1 \
|
||||
-o parent=eth0.20 ipvlan20
|
||||
|
||||
# in two separate terminals, start a Docker container and the containers can now ping one another.
|
||||
$ docker run --net=ipvlan20 -it --name ivlan_test1 --rm alpine /bin/sh
|
||||
$ docker run --net=ipvlan20 -it --name ivlan_test2 --rm alpine /bin/sh
|
||||
```
|
||||
|
||||
**Vlan ID 30**
|
||||
|
||||
In the second network, tagged and isolated by the Docker host, `eth0.30` is the
|
||||
parent interface tagged with vlan id `30` specified with `-o parent=eth0.30`. The
|
||||
`ipvlan_mode=` defaults to l2 mode `ipvlan_mode=l2`. It can also be explicitly
|
||||
set with the same result as shown in the next example.
|
||||
|
||||
```bash
|
||||
# now add networks and hosts as you would normally by attaching to the master (sub)interface that is tagged.
|
||||
$ docker network create -d ipvlan \
|
||||
--subnet=192.168.30.0/24 \
|
||||
--gateway=192.168.30.1 \
|
||||
-o parent=eth0.30 \
|
||||
-o ipvlan_mode=l2 ipvlan30
|
||||
|
||||
# in two separate terminals, start a Docker container and the containers can now ping one another.
|
||||
$ docker run --net=ipvlan30 -it --name ivlan_test3 --rm alpine /bin/sh
|
||||
$ docker run --net=ipvlan30 -it --name ivlan_test4 --rm alpine /bin/sh
|
||||
```
|
||||
|
||||
The gateway is set inside of the container as the default gateway. That gateway
|
||||
would typically be an external router on the network.
|
||||
|
||||
```bash
|
||||
$$ ip route
|
||||
default via 192.168.30.1 dev eth0
|
||||
192.168.30.0/24 dev eth0 src 192.168.30.2
|
||||
```
|
||||
|
||||
Example: Multi-Subnet Ipvlan L2 Mode starting two containers on the same subnet
|
||||
and pinging one another. In order for the `192.168.114.0/24` to reach
|
||||
`192.168.116.0/24` it requires an external router in L2 mode. L3 mode can route
|
||||
between subnets that share a common `-o parent=`.
|
||||
|
||||
Secondary addresses on network routers are common as an address space becomes
|
||||
exhausted to add another secondary to an L3 vlan interface or commonly referred
|
||||
to as a "switched virtual interface" (SVI).
|
||||
|
||||
```bash
|
||||
$ docker network create -d ipvlan \
|
||||
--subnet=192.168.114.0/24 --subnet=192.168.116.0/24 \
|
||||
--gateway=192.168.114.254 --gateway=192.168.116.254 \
|
||||
-o parent=eth0.114 \
|
||||
-o ipvlan_mode=l2 ipvlan114
|
||||
|
||||
$ docker run --net=ipvlan114 --ip=192.168.114.10 -it --rm alpine /bin/sh
|
||||
$ docker run --net=ipvlan114 --ip=192.168.114.11 -it --rm alpine /bin/sh
|
||||
```
|
||||
|
||||
A key takeaway is, operators have the ability to map their physical network into
|
||||
their virtual network for integrating containers into their environment with no
|
||||
operational overhauls required. NetOps simply drops an 802.1q trunk into the
|
||||
Docker host. That virtual link would be the `-o parent=` passed in the network
|
||||
creation. For untagged (non-VLAN) links, it is as simple as `-o parent=eth0` or
|
||||
for 802.1q trunks with VLAN IDs each network gets mapped to the corresponding
|
||||
VLAN/Subnet from the network.
|
||||
|
||||
An example being, NetOps provides VLAN ID and the associated subnets for VLANs
|
||||
being passed on the Ethernet link to the Docker host server. Those values are
|
||||
simply plugged into the `docker network create` commands when provisioning the
|
||||
Docker networks. These are persistent configurations that are applied every time
|
||||
the Docker engine starts which alleviates having to manage often complex
|
||||
configuration files. The network interfaces can also be managed manually by
|
||||
being pre-created and docker networking will never modify them, simply use them
|
||||
as parent interfaces. Example mappings from NetOps to Docker network commands
|
||||
are as follows:
|
||||
|
||||
- VLAN: 10, Subnet: 172.16.80.0/24, Gateway: 172.16.80.1
|
||||
- `--subnet=172.16.80.0/24 --gateway=172.16.80.1 -o parent=eth0.10`
|
||||
- VLAN: 20, IP subnet: 172.16.50.0/22, Gateway: 172.16.50.1
|
||||
- `--subnet=172.16.50.0/22 --gateway=172.16.50.1 -o parent=eth0.20 `
|
||||
- VLAN: 30, Subnet: 10.1.100.0/16, Gateway: 10.1.100.1
|
||||
- `--subnet=10.1.100.0/16 --gateway=10.1.100.1 -o parent=eth0.30`
|
||||
|
||||
### IPVlan L3 Mode Example
|
||||
|
||||
IPVlan will require routes to be distributed to each endpoint. The driver only
|
||||
builds the Ipvlan L3 mode port and attaches the container to the interface. Route
|
||||
distribution throughout a cluster is beyond the initial implementation of this
|
||||
single host scoped driver. In L3 mode, the Docker host is very similar to a
|
||||
router starting new networks in the container. They are on networks that the
|
||||
upstream network will not know about without route distribution. For those
|
||||
curious how Ipvlan L3 will fit into container networking see the following
|
||||
examples.
|
||||
|
||||

|
||||
|
||||
Ipvlan L3 mode drops all broadcast and multicast traffic. This reason alone
|
||||
makes Ipvlan L3 mode a prime candidate for those looking for massive scale and
|
||||
predictable network integrations. It is predictable and in turn will lead to
|
||||
greater uptimes because there is no bridging involved. Bridging loops have been
|
||||
responsible for high profile outages that can be hard to pinpoint depending on
|
||||
the size of the failure domain. This is due to the cascading nature of BPDUs
|
||||
(Bridge Port Data Units) that are flooded throughout a broadcast domain (VLAN)
|
||||
to find and block topology loops. Eliminating bridging domains, or at the least,
|
||||
keeping them isolated to a pair of ToRs (top of rack switches) will reduce hard
|
||||
to troubleshoot bridging instabilities. Ipvlan L2 modes is well suited for
|
||||
isolated VLANs only trunked into a pair of ToRs that can provide a loop-free
|
||||
non-blocking fabric. The next step further is to route at the edge via Ipvlan L3
|
||||
mode that reduces a failure domain to a local host only.
|
||||
|
||||
- L3 mode needs to be on a separate subnet as the default namespace since it
|
||||
requires a netlink route in the default namespace pointing to the Ipvlan parent
|
||||
interface.
|
||||
- The parent interface used in this example is `eth0` and it is on the subnet
|
||||
`192.168.1.0/24`. Notice the `docker network` is **not** on the same subnet
|
||||
as `eth0`.
|
||||
- Unlike ipvlan l2 modes, different subnets/networks can ping one another as
|
||||
long as they share the same parent interface `-o parent=`.
|
||||
|
||||
```bash
|
||||
$$ ip a show eth0
|
||||
3: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
|
||||
link/ether 00:50:56:39:45:2e brd ff:ff:ff:ff:ff:ff
|
||||
inet 192.168.1.250/24 brd 192.168.1.255 scope global eth0
|
||||
```
|
||||
|
||||
- A traditional gateway doesn't mean much to an L3 mode Ipvlan interface since
|
||||
there is no broadcast traffic allowed. Because of that, the container default
|
||||
gateway simply points to the containers `eth0` device. See below for CLI output
|
||||
of `ip route` or `ip -6 route` from inside an L3 container for details.
|
||||
|
||||
The mode ` -o ipvlan_mode=l3` must be explicitly specified since the default
|
||||
ipvlan mode is `l2`.
|
||||
|
||||
The following example does not specify a parent interface. The network drivers
|
||||
will create a dummy type link for the user rather than rejecting the network
|
||||
creation and isolating containers from only communicating with one another.
|
||||
|
||||
```bash
|
||||
# Create the Ipvlan L3 network
|
||||
$ docker network create -d ipvlan \
|
||||
--subnet=192.168.214.0/24 \
|
||||
--subnet=10.1.214.0/24 \
|
||||
-o ipvlan_mode=l3 ipnet210
|
||||
|
||||
# Test 192.168.214.0/24 connectivity
|
||||
$ docker run --net=ipnet210 --ip=192.168.214.10 -itd alpine /bin/sh
|
||||
$ docker run --net=ipnet210 --ip=10.1.214.10 -itd alpine /bin/sh
|
||||
|
||||
# Test L3 connectivity from 10.1.214.0/24 to 192.168.212.0/24
|
||||
$ docker run --net=ipnet210 --ip=192.168.214.9 -it --rm alpine ping -c 2 10.1.214.10
|
||||
|
||||
# Test L3 connectivity from 192.168.212.0/24 to 10.1.214.0/24
|
||||
$ docker run --net=ipnet210 --ip=10.1.214.9 -it --rm alpine ping -c 2 192.168.214.10
|
||||
|
||||
```
|
||||
|
||||
> **Note**
|
||||
>
|
||||
> Notice that there is no `--gateway=` option in the network create. The field
|
||||
> is ignored if one is specified `l3` mode. Take a look at the container routing
|
||||
> table from inside of the container:
|
||||
>
|
||||
> ```bash
|
||||
> # Inside an L3 mode container
|
||||
> $$ ip route
|
||||
> default dev eth0
|
||||
> 192.168.214.0/24 dev eth0 src 192.168.214.10
|
||||
> ```
|
||||
|
||||
In order to ping the containers from a remote Docker host or the container be
|
||||
able to ping a remote host, the remote host or the physical network in between
|
||||
need to have a route pointing to the host IP address of the container's Docker
|
||||
host eth interface. More on this as we evolve the Ipvlan `L3` story.
|
||||
|
||||
### Dual Stack IPv4 IPv6 Ipvlan L2 Mode
|
||||
|
||||
- Not only does Libnetwork give you complete control over IPv4 addressing, but
|
||||
it also gives you total control over IPv6 addressing as well as feature parity
|
||||
between the two address families.
|
||||
|
||||
- The next example will start with IPv6 only. Start two containers on the same
|
||||
VLAN `139` and ping one another. Since the IPv4 subnet is not specified, the
|
||||
default IPAM will provision a default IPv4 subnet. That subnet is isolated
|
||||
unless the upstream network is explicitly routing it on VLAN `139`.
|
||||
|
||||
```bash
|
||||
# Create a v6 network
|
||||
$ docker network create -d ipvlan \
|
||||
--subnet=2001:db8:abc2::/64 --gateway=2001:db8:abc2::22 \
|
||||
-o parent=eth0.139 v6ipvlan139
|
||||
|
||||
# Start a container on the network
|
||||
$ docker run --net=v6ipvlan139 -it --rm alpine /bin/sh
|
||||
```
|
||||
|
||||
View the container eth0 interface and v6 routing table:
|
||||
|
||||
```bash
|
||||
# Inside the IPv6 container
|
||||
$$ ip a show eth0
|
||||
75: eth0@if55: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN group default
|
||||
link/ether 00:50:56:2b:29:40 brd ff:ff:ff:ff:ff:ff
|
||||
inet 172.18.0.2/16 scope global eth0
|
||||
valid_lft forever preferred_lft forever
|
||||
inet6 2001:db8:abc4::250:56ff:fe2b:2940/64 scope link
|
||||
valid_lft forever preferred_lft forever
|
||||
inet6 2001:db8:abc2::1/64 scope link nodad
|
||||
valid_lft forever preferred_lft forever
|
||||
|
||||
$$ ip -6 route
|
||||
2001:db8:abc4::/64 dev eth0 proto kernel metric 256
|
||||
2001:db8:abc2::/64 dev eth0 proto kernel metric 256
|
||||
default via 2001:db8:abc2::22 dev eth0 metric 1024
|
||||
```
|
||||
|
||||
Start a second container and ping the first container's v6 address.
|
||||
|
||||
```bash
|
||||
# Test L2 connectivity over IPv6
|
||||
$ docker run --net=v6ipvlan139 -it --rm alpine /bin/sh
|
||||
|
||||
# Inside the second IPv6 container
|
||||
$$ ip a show eth0
|
||||
75: eth0@if55: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN group default
|
||||
link/ether 00:50:56:2b:29:40 brd ff:ff:ff:ff:ff:ff
|
||||
inet 172.18.0.3/16 scope global eth0
|
||||
valid_lft forever preferred_lft forever
|
||||
inet6 2001:db8:abc4::250:56ff:fe2b:2940/64 scope link tentative dadfailed
|
||||
valid_lft forever preferred_lft forever
|
||||
inet6 2001:db8:abc2::2/64 scope link nodad
|
||||
valid_lft forever preferred_lft forever
|
||||
|
||||
$$ ping6 2001:db8:abc2::1
|
||||
PING 2001:db8:abc2::1 (2001:db8:abc2::1): 56 data bytes
|
||||
64 bytes from 2001:db8:abc2::1%eth0: icmp_seq=0 ttl=64 time=0.044 ms
|
||||
64 bytes from 2001:db8:abc2::1%eth0: icmp_seq=1 ttl=64 time=0.058 ms
|
||||
|
||||
2 packets transmitted, 2 packets received, 0% packet loss
|
||||
round-trip min/avg/max/stddev = 0.044/0.051/0.058/0.000 ms
|
||||
```
|
||||
|
||||
The next example with setup a dual stack IPv4/IPv6 network with an example
|
||||
VLAN ID of `140`.
|
||||
|
||||
Next create a network with two IPv4 subnets and one IPv6 subnets, all of which
|
||||
have explicit gateways:
|
||||
|
||||
```bash
|
||||
$ docker network create -d ipvlan \
|
||||
--subnet=192.168.140.0/24 --subnet=192.168.142.0/24 \
|
||||
--gateway=192.168.140.1 --gateway=192.168.142.1 \
|
||||
--subnet=2001:db8:abc9::/64 --gateway=2001:db8:abc9::22 \
|
||||
-o parent=eth0.140 \
|
||||
-o ipvlan_mode=l2 ipvlan140
|
||||
```
|
||||
|
||||
Start a container and view eth0 and both v4 & v6 routing tables:
|
||||
|
||||
```bash
|
||||
$ docker run --net=ipvlan140 --ip6=2001:db8:abc2::51 -it --rm alpine /bin/sh
|
||||
|
||||
$ ip a show eth0
|
||||
78: eth0@if77: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN group default
|
||||
link/ether 00:50:56:2b:29:40 brd ff:ff:ff:ff:ff:ff
|
||||
inet 192.168.140.2/24 scope global eth0
|
||||
valid_lft forever preferred_lft forever
|
||||
inet6 2001:db8:abc4::250:56ff:fe2b:2940/64 scope link
|
||||
valid_lft forever preferred_lft forever
|
||||
inet6 2001:db8:abc9::1/64 scope link nodad
|
||||
valid_lft forever preferred_lft forever
|
||||
|
||||
$$ ip route
|
||||
default via 192.168.140.1 dev eth0
|
||||
192.168.140.0/24 dev eth0 proto kernel scope link src 192.168.140.2
|
||||
|
||||
$$ ip -6 route
|
||||
2001:db8:abc4::/64 dev eth0 proto kernel metric 256
|
||||
2001:db8:abc9::/64 dev eth0 proto kernel metric 256
|
||||
default via 2001:db8:abc9::22 dev eth0 metric 1024
|
||||
```
|
||||
|
||||
Start a second container with a specific `--ip4` address and ping the first host
|
||||
using IPv4 packets:
|
||||
|
||||
```bash
|
||||
$ docker run --net=ipvlan140 --ip=192.168.140.10 -it --rm alpine /bin/sh
|
||||
```
|
||||
|
||||
> **Note**
|
||||
>
|
||||
> Different subnets on the same parent interface in Ipvlan `L2` mode cannot ping
|
||||
> one another. That requires a router to proxy-arp the requests with a secondary
|
||||
> subnet. However, Ipvlan `L3` will route the unicast traffic between disparate
|
||||
> subnets as long as they share the same `-o parent` parent link.
|
||||
|
||||
### Dual Stack IPv4 IPv6 Ipvlan L3 Mode
|
||||
|
||||
**Example:** IpVlan L3 Mode Dual Stack IPv4/IPv6, Multi-Subnet w/ 802.1q Vlan Tag:118
|
||||
|
||||
As in all of the examples, a tagged VLAN interface does not have to be used. The
|
||||
sub-interfaces can be swapped with `eth0`, `eth1`, `bond0` or any other valid
|
||||
interface on the host other then the `lo` loopback.
|
||||
|
||||
The primary difference you will see is that L3 mode does not create a default
|
||||
route with a next-hop but rather sets a default route pointing to `dev eth` only
|
||||
since ARP/Broadcasts/Multicast are all filtered by Linux as per the design. Since
|
||||
the parent interface is essentially acting as a router, the parent interface IP
|
||||
and subnet needs to be different from the container networks. That is the opposite
|
||||
of bridge and L2 modes, which need to be on the same subnet (broadcast domain)
|
||||
in order to forward broadcast and multicast packets.
|
||||
|
||||
```bash
|
||||
# Create an IPv6+IPv4 Dual Stack Ipvlan L3 network
|
||||
# Gateways for both v4 and v6 are set to a dev e.g. 'default dev eth0'
|
||||
$ docker network create -d ipvlan \
|
||||
--subnet=192.168.110.0/24 \
|
||||
--subnet=192.168.112.0/24 \
|
||||
--subnet=2001:db8:abc6::/64 \
|
||||
-o parent=eth0 \
|
||||
-o ipvlan_mode=l3 ipnet110
|
||||
|
||||
|
||||
# Start a few of containers on the network (ipnet110)
|
||||
# in separate terminals and check connectivity
|
||||
$ docker run --net=ipnet110 -it --rm alpine /bin/sh
|
||||
# Start a second container specifying the v6 address
|
||||
$ docker run --net=ipnet110 --ip6=2001:db8:abc6::10 -it --rm alpine /bin/sh
|
||||
# Start a third specifying the IPv4 address
|
||||
$ docker run --net=ipnet110 --ip=192.168.112.30 -it --rm alpine /bin/sh
|
||||
# Start a 4th specifying both the IPv4 and IPv6 addresses
|
||||
$ docker run --net=ipnet110 --ip6=2001:db8:abc6::50 --ip=192.168.112.50 -it --rm alpine /bin/sh
|
||||
```
|
||||
|
||||
Interface and routing table outputs are as follows:
|
||||
|
||||
```bash
|
||||
$$ ip a show eth0
|
||||
63: eth0@if59: <BROADCAST,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN group default
|
||||
link/ether 00:50:56:2b:29:40 brd ff:ff:ff:ff:ff:ff
|
||||
inet 192.168.112.2/24 scope global eth0
|
||||
valid_lft forever preferred_lft forever
|
||||
inet6 2001:db8:abc4::250:56ff:fe2b:2940/64 scope link
|
||||
valid_lft forever preferred_lft forever
|
||||
inet6 2001:db8:abc6::10/64 scope link nodad
|
||||
valid_lft forever preferred_lft forever
|
||||
|
||||
# Note the default route is simply the eth device because ARPs are filtered.
|
||||
$$ ip route
|
||||
default dev eth0 scope link
|
||||
192.168.112.0/24 dev eth0 proto kernel scope link src 192.168.112.2
|
||||
|
||||
$$ ip -6 route
|
||||
2001:db8:abc4::/64 dev eth0 proto kernel metric 256
|
||||
2001:db8:abc6::/64 dev eth0 proto kernel metric 256
|
||||
default dev eth0 metric 1024
|
||||
```
|
||||
|
||||
> *Note*
|
||||
>
|
||||
> There may be a bug when specifying `--ip6=` addresses when you delete a
|
||||
> container with a specified v6 address and then start a new container with the
|
||||
> same v6 address it throws the following like the address isn't properly being
|
||||
> released to the v6 pool. It will fail to unmount the container and be left dead.
|
||||
|
||||
```console
|
||||
docker: Error response from daemon: Address already in use.
|
||||
```
|
||||
|
||||
### Manually Creating 802.1q Links
|
||||
|
||||
**Vlan ID 40**
|
||||
|
||||
If a user does not want the driver to create the vlan sub-interface it simply
|
||||
needs to exist prior to the `docker network create`. If you have sub-interface
|
||||
naming that is not `interface.vlan_id` it is honored in the `-o parent=` option
|
||||
again as long as the interface exists and is up.
|
||||
|
||||
Links, when manually created, can be named anything as long as they exist when
|
||||
the network is created. Manually created links do not get deleted regardless of
|
||||
the name when the network is deleted with `docker network rm`.
|
||||
|
||||
```bash
|
||||
# create a new sub-interface tied to dot1q vlan 40
|
||||
$ ip link add link eth0 name eth0.40 type vlan id 40
|
||||
|
||||
# enable the new sub-interface
|
||||
$ ip link set eth0.40 up
|
||||
|
||||
# now add networks and hosts as you would normally by attaching to the master (sub)interface that is tagged
|
||||
$ docker network create -d ipvlan \
|
||||
--subnet=192.168.40.0/24 \
|
||||
--gateway=192.168.40.1 \
|
||||
-o parent=eth0.40 ipvlan40
|
||||
|
||||
# in two separate terminals, start a Docker container and the containers can now ping one another.
|
||||
$ docker run --net=ipvlan40 -it --name ivlan_test5 --rm alpine /bin/sh
|
||||
$ docker run --net=ipvlan40 -it --name ivlan_test6 --rm alpine /bin/sh
|
||||
```
|
||||
|
||||
**Example:** Vlan sub-interface manually created with any name:
|
||||
|
||||
```bash
|
||||
# create a new sub interface tied to dot1q vlan 40
|
||||
$ ip link add link eth0 name foo type vlan id 40
|
||||
|
||||
# enable the new sub-interface
|
||||
$ ip link set foo up
|
||||
|
||||
# now add networks and hosts as you would normally by attaching to the master (sub)interface that is tagged
|
||||
$ docker network create -d ipvlan \
|
||||
--subnet=192.168.40.0/24 --gateway=192.168.40.1 \
|
||||
-o parent=foo ipvlan40
|
||||
|
||||
# in two separate terminals, start a Docker container and the containers can now ping one another.
|
||||
$ docker run --net=ipvlan40 -it --name ivlan_test5 --rm alpine /bin/sh
|
||||
$ docker run --net=ipvlan40 -it --name ivlan_test6 --rm alpine /bin/sh
|
||||
```
|
||||
|
||||
Manually created links can be cleaned up with:
|
||||
|
||||
```bash
|
||||
$ ip link del foo
|
||||
```
|
||||
|
||||
As with all of the Libnetwork drivers, they can be mixed and matched, even as
|
||||
far as running 3rd party ecosystem drivers in parallel for maximum flexibility
|
||||
to the Docker user.
|
||||
@ -438,8 +438,12 @@ A Dockerfile is similar to a Makefile.
|
||||
* `NO_PROXY`
|
||||
* `no_proxy`
|
||||
|
||||
To use these, simply pass them on the command line using the `--build-arg
|
||||
<varname>=<value>` flag.
|
||||
To use these, pass them on the command line using `--build-arg` flag, for
|
||||
example:
|
||||
|
||||
```
|
||||
$ docker build --build-arg HTTPS_PROXY=https://my-proxy.example.com .
|
||||
```
|
||||
|
||||
**ONBUILD**
|
||||
-- `ONBUILD [INSTRUCTION]`
|
||||
|
||||
@ -111,7 +111,7 @@ pull the above image by digest, run the following command:
|
||||
Digest can also be used in the `FROM` of a Dockerfile, for example:
|
||||
|
||||
FROM ubuntu@sha256:45b23dee08af5e43a7fea6c4cf9c25ccf269ee113168c19722f87876677c5cb2
|
||||
LABEL maintainer="some maintainer <maintainer@example.com>"
|
||||
LABEL org.opencontainers.image.authors="some maintainer <maintainer@example.com>"
|
||||
|
||||
> **Note**: Using this feature "pins" an image to a specific version in time.
|
||||
> Docker will therefore not pull updated versions of an image, which may include
|
||||
|
||||