2014-02-25 16:17:48 +00:00
package main
import (
2014-08-12 09:36:49 +00:00
"bufio"
2014-10-17 18:06:05 +00:00
"bytes"
2018-04-19 22:30:59 +00:00
"context"
2016-08-04 16:17:37 +00:00
"encoding/json"
2014-02-25 16:17:48 +00:00
"fmt"
2016-11-21 22:10:34 +00:00
"io"
2014-06-26 11:03:23 +00:00
"io/ioutil"
2014-09-06 01:59:31 +00:00
"net"
2014-04-18 02:53:08 +00:00
"os"
2014-02-25 16:17:48 +00:00
"os/exec"
2014-08-28 00:25:10 +00:00
"path"
2014-07-30 02:22:50 +00:00
"path/filepath"
2014-02-17 23:14:30 +00:00
"reflect"
2014-04-18 01:58:20 +00:00
"regexp"
2016-05-25 17:19:17 +00:00
"runtime"
2014-04-18 02:53:08 +00:00
"sort"
2014-09-17 01:08:30 +00:00
"strconv"
2014-02-25 16:17:48 +00:00
"strings"
2014-04-18 02:46:03 +00:00
"sync"
2019-09-09 21:06:12 +00:00
"testing"
2014-08-12 09:36:49 +00:00
"time"
2014-06-26 11:03:23 +00:00
2019-04-17 10:39:07 +00:00
"github.com/Microsoft/hcsshim/osversion"
2017-09-15 13:16:38 +00:00
"github.com/docker/docker/client"
2017-03-27 15:12:48 +00:00
"github.com/docker/docker/integration-cli/cli"
2017-03-23 17:35:22 +00:00
"github.com/docker/docker/integration-cli/cli/build"
2015-12-14 15:39:53 +00:00
"github.com/docker/docker/pkg/mount"
2016-04-08 22:25:07 +00:00
"github.com/docker/docker/pkg/stringid"
2015-09-27 11:09:27 +00:00
"github.com/docker/docker/runconfig"
2019-08-29 20:52:40 +00:00
"github.com/docker/docker/testutil"
"github.com/docker/docker/testutil/fakecontext"
2015-12-18 17:58:48 +00:00
"github.com/docker/go-connections/nat"
2015-05-06 22:39:29 +00:00
"github.com/docker/libnetwork/resolvconf"
2016-05-08 07:33:16 +00:00
"github.com/docker/libnetwork/types"
2019-04-04 13:23:19 +00:00
"gotest.tools/assert"
2018-06-11 13:32:11 +00:00
"gotest.tools/icmd"
2014-02-25 16:17:48 +00:00
)
// "test123" should be printed by docker run
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunEchoStdout ( c * testing . T ) {
2015-07-19 20:47:47 +00:00
out , _ := dockerCmd ( c , "run" , "busybox" , "echo" , "test123" )
2014-02-25 16:17:48 +00:00
if out != "test123\n" {
2015-09-01 21:37:04 +00:00
c . Fatalf ( "container should've printed 'test123', got '%s'" , out )
2014-02-25 16:17:48 +00:00
}
}
// "test" should be printed
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunEchoNamedContainer ( c * testing . T ) {
2015-07-19 20:47:47 +00:00
out , _ := dockerCmd ( c , "run" , "--name" , "testfoonamedcontainer" , "busybox" , "echo" , "test" )
2014-02-25 16:17:48 +00:00
if out != "test\n" {
2015-04-18 16:46:47 +00:00
c . Errorf ( "container should've printed 'test'" )
2014-02-25 16:17:48 +00:00
}
}
2015-09-01 21:37:04 +00:00
// docker run should not leak file descriptors. This test relies on Unix
// specific functionality and cannot run on Windows.
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunLeakyFileDescriptors ( c * testing . T ) {
2015-08-28 17:36:42 +00:00
testRequires ( c , DaemonIsLinux )
2015-07-19 20:47:47 +00:00
out , _ := dockerCmd ( c , "run" , "busybox" , "ls" , "-C" , "/proc/self/fd" )
2014-04-29 05:22:54 +00:00
// normally, we should only get 0, 1, and 2, but 3 gets created by "ls" when it does "opendir" on the "fd" directory
if out != "0 1 2 3\n" {
2015-04-18 16:46:47 +00:00
c . Errorf ( "container should've printed '0 1 2 3', not: %s" , out )
2014-04-29 05:22:54 +00:00
}
}
2015-03-11 05:09:09 +00:00
// it should be possible to lookup Google DNS
2014-02-25 16:17:48 +00:00
// this will fail when Internet access is unavailable
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunLookupGoogleDNS ( c * testing . T ) {
2015-11-25 23:38:33 +00:00
testRequires ( c , Network , NotArm )
2018-01-15 14:32:06 +00:00
if testEnv . OSType == "windows" {
2016-07-22 02:46:17 +00:00
// nslookup isn't present in Windows busybox. Is built-in. Further,
// nslookup isn't present in nanoserver. Hence just use PowerShell...
2018-01-15 14:31:02 +00:00
dockerCmd ( c , "run" , testEnv . PlatformDefaults . BaseImage , "powershell" , "Resolve-DNSName" , "google.com" )
2016-07-22 02:46:17 +00:00
} else {
2016-12-08 15:28:06 +00:00
dockerCmd ( c , "run" , "busybox" , "nslookup" , "google.com" )
2015-09-01 21:37:04 +00:00
}
2016-07-22 02:46:17 +00:00
2014-02-25 16:17:48 +00:00
}
// the exit code should be 0
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunExitCodeZero ( c * testing . T ) {
2015-07-19 20:47:47 +00:00
dockerCmd ( c , "run" , "busybox" , "true" )
2014-02-25 16:17:48 +00:00
}
// the exit code should be 1
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunExitCodeOne ( c * testing . T ) {
2015-07-27 18:13:25 +00:00
_ , exitCode , err := dockerCmdWithError ( "run" , "busybox" , "false" )
2019-04-04 13:23:19 +00:00
assert . ErrorContains ( c , err , "" )
assert . Equal ( c , exitCode , 1 )
2014-02-25 16:17:48 +00:00
}
// it should be possible to pipe in data via stdin to a process running in a container
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunStdinPipe ( c * testing . T ) {
2015-09-01 21:37:04 +00:00
// TODO Windows: This needs some work to make compatible.
2015-08-28 17:36:42 +00:00
testRequires ( c , DaemonIsLinux )
2016-12-13 20:21:51 +00:00
result := icmd . RunCmd ( icmd . Cmd {
Command : [ ] string { dockerBinary , "run" , "-i" , "-a" , "stdin" , "busybox" , "cat" } ,
Stdin : strings . NewReader ( "blahblah" ) ,
} )
result . Assert ( c , icmd . Success )
out := result . Stdout ( )
2014-02-25 16:17:48 +00:00
2015-04-06 13:21:18 +00:00
out = strings . TrimSpace ( out )
2015-07-19 20:47:47 +00:00
dockerCmd ( c , "wait" , out )
2014-02-25 16:17:48 +00:00
2015-07-19 20:47:47 +00:00
logsOut , _ := dockerCmd ( c , "logs" , out )
2014-02-25 16:17:48 +00:00
2015-04-06 13:21:18 +00:00
containerLogs := strings . TrimSpace ( logsOut )
2014-02-25 16:17:48 +00:00
if containerLogs != "blahblah" {
2015-04-18 16:46:47 +00:00
c . Errorf ( "logs didn't print the container's logs %s" , containerLogs )
2014-02-25 16:17:48 +00:00
}
2015-07-19 20:47:47 +00:00
dockerCmd ( c , "rm" , out )
2014-02-25 16:17:48 +00:00
}
// the container's ID should be printed when starting a container in detached mode
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunDetachedContainerIDPrinting ( c * testing . T ) {
2015-07-19 20:47:47 +00:00
out , _ := dockerCmd ( c , "run" , "-d" , "busybox" , "true" )
2014-02-25 16:17:48 +00:00
2015-04-06 13:21:18 +00:00
out = strings . TrimSpace ( out )
2015-07-19 20:47:47 +00:00
dockerCmd ( c , "wait" , out )
2014-02-25 16:17:48 +00:00
2015-07-19 20:47:47 +00:00
rmOut , _ := dockerCmd ( c , "rm" , out )
2014-02-25 16:17:48 +00:00
2015-04-06 13:21:18 +00:00
rmOut = strings . TrimSpace ( rmOut )
2014-02-25 16:17:48 +00:00
if rmOut != out {
2015-04-18 16:46:47 +00:00
c . Errorf ( "rm didn't print the container ID %s %s" , out , rmOut )
2014-02-25 16:17:48 +00:00
}
}
// the working directory should be set correctly
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunWorkingDirectory ( c * testing . T ) {
2015-09-01 21:37:04 +00:00
dir := "/root"
image := "busybox"
2018-01-15 14:32:06 +00:00
if testEnv . OSType == "windows" {
2016-05-24 22:13:06 +00:00
dir = ` C:/Windows `
2015-09-01 21:37:04 +00:00
}
2014-02-25 16:17:48 +00:00
2015-09-01 21:37:04 +00:00
// First with -w
out , _ := dockerCmd ( c , "run" , "-w" , dir , image , "pwd" )
2015-04-06 13:21:18 +00:00
out = strings . TrimSpace ( out )
2015-09-01 21:37:04 +00:00
if out != dir {
2015-04-18 16:46:47 +00:00
c . Errorf ( "-w failed to set working directory" )
2014-02-25 16:17:48 +00:00
}
2015-09-01 21:37:04 +00:00
// Then with --workdir
out , _ = dockerCmd ( c , "run" , "--workdir" , dir , image , "pwd" )
2015-04-06 13:21:18 +00:00
out = strings . TrimSpace ( out )
2015-09-01 21:37:04 +00:00
if out != dir {
2015-04-18 16:46:47 +00:00
c . Errorf ( "--workdir failed to set working directory" )
2014-02-25 16:17:48 +00:00
}
}
// pinging Google's DNS resolver should fail when we disable the networking
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunWithoutNetworking ( c * testing . T ) {
2015-09-01 21:37:04 +00:00
count := "-c"
image := "busybox"
2018-01-15 14:32:06 +00:00
if testEnv . OSType == "windows" {
2015-09-01 21:37:04 +00:00
count = "-n"
2018-01-15 14:31:02 +00:00
image = testEnv . PlatformDefaults . BaseImage
2015-09-01 21:37:04 +00:00
}
// First using the long form --net
out , exitCode , err := dockerCmdWithError ( "run" , "--net=none" , image , "ping" , count , "1" , "8.8.8.8" )
2014-02-25 16:17:48 +00:00
if err != nil && exitCode != 1 {
2015-04-18 16:46:47 +00:00
c . Fatal ( out , err )
2014-02-25 16:17:48 +00:00
}
if exitCode != 1 {
2015-04-18 16:46:47 +00:00
c . Errorf ( "--net=none should've disabled the network; the container shouldn't have been able to ping 8.8.8.8" )
2014-02-25 16:17:48 +00:00
}
}
2014-03-31 17:41:40 +00:00
2019-11-27 14:36:45 +00:00
// test --link use container name to link target
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunLinksContainerWithContainerName ( c * testing . T ) {
2015-09-01 21:37:04 +00:00
// TODO Windows: This test cannot run on a Windows daemon as the networking
// settings are not populated back yet on inspect.
2015-08-28 17:36:42 +00:00
testRequires ( c , DaemonIsLinux )
2015-07-19 20:47:47 +00:00
dockerCmd ( c , "run" , "-i" , "-t" , "-d" , "--name" , "parent" , "busybox" )
2016-01-28 14:19:25 +00:00
ip := inspectField ( c , "parent" , "NetworkSettings.Networks.bridge.IPAddress" )
2015-07-19 20:47:47 +00:00
out , _ := dockerCmd ( c , "run" , "--link" , "parent:test" , "busybox" , "/bin/cat" , "/etc/hosts" )
2015-01-14 07:25:58 +00:00
if ! strings . Contains ( out , ip + " test" ) {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "use a container name to link target failed" )
2015-01-14 07:25:58 +00:00
}
}
2019-11-27 14:36:45 +00:00
// test --link use container id to link target
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunLinksContainerWithContainerID ( c * testing . T ) {
2015-09-01 21:37:04 +00:00
// TODO Windows: This test cannot run on a Windows daemon as the networking
// settings are not populated back yet on inspect.
2015-08-28 17:36:42 +00:00
testRequires ( c , DaemonIsLinux )
2015-07-19 20:47:47 +00:00
cID , _ := dockerCmd ( c , "run" , "-i" , "-t" , "-d" , "busybox" )
2015-01-14 07:25:58 +00:00
cID = strings . TrimSpace ( cID )
2016-01-28 14:19:25 +00:00
ip := inspectField ( c , cID , "NetworkSettings.Networks.bridge.IPAddress" )
2015-07-19 20:47:47 +00:00
out , _ := dockerCmd ( c , "run" , "--link" , cID + ":test" , "busybox" , "/bin/cat" , "/etc/hosts" )
2015-01-14 07:25:58 +00:00
if ! strings . Contains ( out , ip + " test" ) {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "use a container id to link target failed" )
2015-01-14 07:25:58 +00:00
}
}
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestUserDefinedNetworkLinks ( c * testing . T ) {
2015-11-25 23:38:33 +00:00
testRequires ( c , DaemonIsLinux , NotUserNamespace , NotArm )
2016-01-05 19:20:47 +00:00
dockerCmd ( c , "network" , "create" , "-d" , "bridge" , "udlinkNet" )
dockerCmd ( c , "run" , "-d" , "--net=udlinkNet" , "--name=first" , "busybox" , "top" )
2019-09-09 21:05:57 +00:00
assert . Assert ( c , waitRun ( "first" ) == nil )
2016-01-05 19:20:47 +00:00
// run a container in user-defined network udlinkNet with a link for an existing container
2016-02-11 23:21:52 +00:00
// and a link for a container that doesn't exist
2016-01-05 19:20:47 +00:00
dockerCmd ( c , "run" , "-d" , "--net=udlinkNet" , "--name=second" , "--link=first:foo" ,
"--link=third:bar" , "busybox" , "top" )
2019-09-09 21:05:57 +00:00
assert . Assert ( c , waitRun ( "second" ) == nil )
2016-01-05 19:20:47 +00:00
// ping to first and its alias foo must succeed
_ , _ , err := dockerCmdWithError ( "exec" , "second" , "ping" , "-c" , "1" , "first" )
2019-04-04 13:23:19 +00:00
assert . NilError ( c , err )
2016-01-05 19:20:47 +00:00
_ , _ , err = dockerCmdWithError ( "exec" , "second" , "ping" , "-c" , "1" , "foo" )
2019-04-04 13:23:19 +00:00
assert . NilError ( c , err )
2016-01-05 19:20:47 +00:00
// ping to third and its alias must fail
_ , _ , err = dockerCmdWithError ( "exec" , "second" , "ping" , "-c" , "1" , "third" )
2019-04-04 13:23:19 +00:00
assert . ErrorContains ( c , err , "" )
2016-01-05 19:20:47 +00:00
_ , _ , err = dockerCmdWithError ( "exec" , "second" , "ping" , "-c" , "1" , "bar" )
2019-04-04 13:23:19 +00:00
assert . ErrorContains ( c , err , "" )
2016-01-05 19:20:47 +00:00
// start third container now
dockerCmd ( c , "run" , "-d" , "--net=udlinkNet" , "--name=third" , "busybox" , "top" )
2019-09-09 21:05:57 +00:00
assert . Assert ( c , waitRun ( "third" ) == nil )
2016-01-05 19:20:47 +00:00
// ping to third and its alias must succeed now
_ , _ , err = dockerCmdWithError ( "exec" , "second" , "ping" , "-c" , "1" , "third" )
2019-04-04 13:23:19 +00:00
assert . NilError ( c , err )
2016-01-05 19:20:47 +00:00
_ , _ , err = dockerCmdWithError ( "exec" , "second" , "ping" , "-c" , "1" , "bar" )
2019-04-04 13:23:19 +00:00
assert . NilError ( c , err )
2016-01-05 19:20:47 +00:00
}
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestUserDefinedNetworkLinksWithRestart ( c * testing . T ) {
2015-11-25 23:38:33 +00:00
testRequires ( c , DaemonIsLinux , NotUserNamespace , NotArm )
2016-01-05 19:20:47 +00:00
dockerCmd ( c , "network" , "create" , "-d" , "bridge" , "udlinkNet" )
dockerCmd ( c , "run" , "-d" , "--net=udlinkNet" , "--name=first" , "busybox" , "top" )
2019-09-09 21:05:57 +00:00
assert . Assert ( c , waitRun ( "first" ) == nil )
2016-01-05 19:20:47 +00:00
dockerCmd ( c , "run" , "-d" , "--net=udlinkNet" , "--name=second" , "--link=first:foo" ,
"busybox" , "top" )
2019-09-09 21:05:57 +00:00
assert . Assert ( c , waitRun ( "second" ) == nil )
2016-01-05 19:20:47 +00:00
// ping to first and its alias foo must succeed
_ , _ , err := dockerCmdWithError ( "exec" , "second" , "ping" , "-c" , "1" , "first" )
2019-04-04 13:23:19 +00:00
assert . NilError ( c , err )
2016-01-05 19:20:47 +00:00
_ , _ , err = dockerCmdWithError ( "exec" , "second" , "ping" , "-c" , "1" , "foo" )
2019-04-04 13:23:19 +00:00
assert . NilError ( c , err )
2016-01-05 19:20:47 +00:00
// Restart first container
dockerCmd ( c , "restart" , "first" )
2019-09-09 21:05:57 +00:00
assert . Assert ( c , waitRun ( "first" ) == nil )
2016-01-05 19:20:47 +00:00
// ping to first and its alias foo must still succeed
_ , _ , err = dockerCmdWithError ( "exec" , "second" , "ping" , "-c" , "1" , "first" )
2019-04-04 13:23:19 +00:00
assert . NilError ( c , err )
2016-01-05 19:20:47 +00:00
_ , _ , err = dockerCmdWithError ( "exec" , "second" , "ping" , "-c" , "1" , "foo" )
2019-04-04 13:23:19 +00:00
assert . NilError ( c , err )
2016-01-05 19:20:47 +00:00
// Restart second container
dockerCmd ( c , "restart" , "second" )
2019-09-09 21:05:57 +00:00
assert . Assert ( c , waitRun ( "second" ) == nil )
2016-01-05 19:20:47 +00:00
// ping to first and its alias foo must still succeed
_ , _ , err = dockerCmdWithError ( "exec" , "second" , "ping" , "-c" , "1" , "first" )
2019-04-04 13:23:19 +00:00
assert . NilError ( c , err )
2016-01-05 19:20:47 +00:00
_ , _ , err = dockerCmdWithError ( "exec" , "second" , "ping" , "-c" , "1" , "foo" )
2019-04-04 13:23:19 +00:00
assert . NilError ( c , err )
2016-01-05 19:20:47 +00:00
}
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunWithNetAliasOnDefaultNetworks ( c * testing . T ) {
2016-03-02 08:52:41 +00:00
testRequires ( c , DaemonIsLinux , NotUserNamespace , NotArm )
defaults := [ ] string { "bridge" , "host" , "none" }
for _ , net := range defaults {
out , _ , err := dockerCmdWithError ( "run" , "-d" , "--net" , net , "--net-alias" , "alias_" + net , "busybox" , "top" )
2019-04-04 13:23:19 +00:00
assert . ErrorContains ( c , err , "" )
2019-09-09 21:08:22 +00:00
assert . Assert ( c , strings . Contains ( out , runconfig . ErrUnsupportedNetworkAndAlias . Error ( ) ) )
2016-03-02 08:52:41 +00:00
}
}
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestUserDefinedNetworkAlias ( c * testing . T ) {
2015-11-25 23:38:33 +00:00
testRequires ( c , DaemonIsLinux , NotUserNamespace , NotArm )
2016-01-08 13:45:56 +00:00
dockerCmd ( c , "network" , "create" , "-d" , "bridge" , "net1" )
2018-02-27 06:49:30 +00:00
cid1 , _ := dockerCmd ( c , "run" , "-d" , "--net=net1" , "--name=first" , "--net-alias=foo1" , "--net-alias=foo2" , "busybox:glibc" , "top" )
2019-09-09 21:05:57 +00:00
assert . Assert ( c , waitRun ( "first" ) == nil )
2016-01-08 13:45:56 +00:00
2016-04-08 22:25:07 +00:00
// Check if default short-id alias is added automatically
id := strings . TrimSpace ( cid1 )
aliases := inspectField ( c , id , "NetworkSettings.Networks.net1.Aliases" )
2019-09-09 21:08:22 +00:00
assert . Assert ( c , strings . Contains ( aliases , stringid . TruncateID ( id ) ) )
2018-02-27 06:49:30 +00:00
cid2 , _ := dockerCmd ( c , "run" , "-d" , "--net=net1" , "--name=second" , "busybox:glibc" , "top" )
2019-09-09 21:05:57 +00:00
assert . Assert ( c , waitRun ( "second" ) == nil )
2016-01-08 13:45:56 +00:00
2016-04-08 22:25:07 +00:00
// Check if default short-id alias is added automatically
id = strings . TrimSpace ( cid2 )
aliases = inspectField ( c , id , "NetworkSettings.Networks.net1.Aliases" )
2019-09-09 21:08:22 +00:00
assert . Assert ( c , strings . Contains ( aliases , stringid . TruncateID ( id ) ) )
2016-01-08 13:45:56 +00:00
// ping to first and its network-scoped aliases
_ , _ , err := dockerCmdWithError ( "exec" , "second" , "ping" , "-c" , "1" , "first" )
2019-04-04 13:23:19 +00:00
assert . NilError ( c , err )
2016-01-08 13:45:56 +00:00
_ , _ , err = dockerCmdWithError ( "exec" , "second" , "ping" , "-c" , "1" , "foo1" )
2019-04-04 13:23:19 +00:00
assert . NilError ( c , err )
2016-01-08 13:45:56 +00:00
_ , _ , err = dockerCmdWithError ( "exec" , "second" , "ping" , "-c" , "1" , "foo2" )
2019-04-04 13:23:19 +00:00
assert . NilError ( c , err )
2016-04-08 22:25:07 +00:00
// ping first container's short-id alias
_ , _ , err = dockerCmdWithError ( "exec" , "second" , "ping" , "-c" , "1" , stringid . TruncateID ( cid1 ) )
2019-04-04 13:23:19 +00:00
assert . NilError ( c , err )
2016-01-08 13:45:56 +00:00
// Restart first container
dockerCmd ( c , "restart" , "first" )
2019-09-09 21:05:57 +00:00
assert . Assert ( c , waitRun ( "first" ) == nil )
2016-01-08 13:45:56 +00:00
// ping to first and its network-scoped aliases must succeed
_ , _ , err = dockerCmdWithError ( "exec" , "second" , "ping" , "-c" , "1" , "first" )
2019-04-04 13:23:19 +00:00
assert . NilError ( c , err )
2016-01-08 13:45:56 +00:00
_ , _ , err = dockerCmdWithError ( "exec" , "second" , "ping" , "-c" , "1" , "foo1" )
2019-04-04 13:23:19 +00:00
assert . NilError ( c , err )
2016-01-08 13:45:56 +00:00
_ , _ , err = dockerCmdWithError ( "exec" , "second" , "ping" , "-c" , "1" , "foo2" )
2019-04-04 13:23:19 +00:00
assert . NilError ( c , err )
2016-04-08 22:25:07 +00:00
// ping first container's short-id alias
_ , _ , err = dockerCmdWithError ( "exec" , "second" , "ping" , "-c" , "1" , stringid . TruncateID ( cid1 ) )
2019-04-04 13:23:19 +00:00
assert . NilError ( c , err )
2016-01-08 13:45:56 +00:00
}
2015-05-01 14:00:43 +00:00
// Issue 9677.
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunWithDaemonFlags ( c * testing . T ) {
2015-11-09 14:37:24 +00:00
out , _ , err := dockerCmdWithError ( "--exec-opt" , "foo=bar" , "run" , "-i" , "busybox" , "true" )
2019-04-04 13:23:19 +00:00
assert . ErrorContains ( c , err , "" )
2019-09-09 21:08:22 +00:00
assert . Assert ( c , strings . Contains ( out , "unknown flag: --exec-opt" ) )
2015-05-01 14:00:43 +00:00
}
2014-04-03 14:27:07 +00:00
// Regression test for #4979
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunWithVolumesFromExited ( c * testing . T ) {
2015-09-23 23:04:51 +00:00
var (
out string
exitCode int
)
// Create a file in a volume
2018-01-15 14:32:06 +00:00
if testEnv . OSType == "windows" {
2018-01-15 14:31:02 +00:00
out , exitCode = dockerCmd ( c , "run" , "--name" , "test-data" , "--volume" , ` c:\some\dir ` , testEnv . PlatformDefaults . BaseImage , "cmd" , "/c" , ` echo hello > c:\some\dir\file ` )
2015-09-23 23:04:51 +00:00
} else {
out , exitCode = dockerCmd ( c , "run" , "--name" , "test-data" , "--volume" , "/some/dir" , "busybox" , "touch" , "/some/dir/file" )
}
2015-07-19 20:47:47 +00:00
if exitCode != 0 {
c . Fatal ( "1" , out , exitCode )
2014-04-03 14:27:07 +00:00
}
2015-09-23 23:04:51 +00:00
// Read the file from another container using --volumes-from to access the volume in the second container
2018-01-15 14:32:06 +00:00
if testEnv . OSType == "windows" {
2018-01-15 14:31:02 +00:00
out , exitCode = dockerCmd ( c , "run" , "--volumes-from" , "test-data" , testEnv . PlatformDefaults . BaseImage , "cmd" , "/c" , ` type c:\some\dir\file ` )
2015-09-23 23:04:51 +00:00
} else {
out , exitCode = dockerCmd ( c , "run" , "--volumes-from" , "test-data" , "busybox" , "cat" , "/some/dir/file" )
}
2015-07-19 20:47:47 +00:00
if exitCode != 0 {
c . Fatal ( "2" , out , exitCode )
2014-04-03 14:27:07 +00:00
}
}
2015-03-30 18:35:37 +00:00
// Volume path is a symlink which also exists on the host, and the host side is a file not a dir
// But the volume call is just a normal volume, not a bind mount
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunCreateVolumesInSymlinkDir ( c * testing . T ) {
2015-09-23 23:04:51 +00:00
var (
dockerFile string
containerPath string
cmd string
)
2016-11-23 22:28:06 +00:00
// This test cannot run on a Windows daemon as
2016-04-05 20:21:20 +00:00
// Windows does not support symlinks inside a volume path
2018-12-24 12:25:53 +00:00
testRequires ( c , testEnv . IsLocalDaemon , DaemonIsLinux )
2015-03-30 18:35:37 +00:00
name := "test-volume-symlink"
dir , err := ioutil . TempDir ( "" , name )
if err != nil {
2015-04-18 16:46:47 +00:00
c . Fatal ( err )
2015-03-29 05:35:36 +00:00
}
2015-03-30 18:35:37 +00:00
defer os . RemoveAll ( dir )
2016-01-28 22:52:34 +00:00
// In the case of Windows to Windows CI, if the machine is setup so that
// the temp directory is not the C: drive, this test is invalid and will
// not work.
2018-01-15 14:32:06 +00:00
if testEnv . OSType == "windows" && strings . ToLower ( dir [ : 1 ] ) != "c" {
2016-01-28 22:52:34 +00:00
c . Skip ( "Requires TEMP to point to C: drive" )
}
2015-03-30 18:35:37 +00:00
f , err := os . OpenFile ( filepath . Join ( dir , "test" ) , os . O_CREATE , 0700 )
2015-03-29 05:35:36 +00:00
if err != nil {
2015-04-18 16:46:47 +00:00
c . Fatal ( err )
2015-03-30 18:35:37 +00:00
}
f . Close ( )
2018-01-15 14:32:06 +00:00
if testEnv . OSType == "windows" {
2018-01-15 14:31:02 +00:00
dockerFile = fmt . Sprintf ( "FROM %s\nRUN mkdir %s\nRUN mklink /D c:\\test %s" , testEnv . PlatformDefaults . BaseImage , dir , dir )
2015-09-23 23:04:51 +00:00
containerPath = ` c:\test\test `
cmd = "tasklist"
} else {
dockerFile = fmt . Sprintf ( "FROM busybox\nRUN mkdir -p %s\nRUN ln -s %s /test" , dir , dir )
containerPath = "/test/test"
cmd = "true"
}
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , name , build . WithDockerfile ( dockerFile ) )
2015-09-23 23:04:51 +00:00
dockerCmd ( c , "run" , "-v" , containerPath , name , cmd )
2015-03-29 05:35:36 +00:00
}
2016-01-28 22:52:34 +00:00
// Volume path is a symlink in the container
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunCreateVolumesInSymlinkDir2 ( c * testing . T ) {
2016-01-28 22:52:34 +00:00
var (
dockerFile string
containerPath string
cmd string
)
2016-11-23 22:28:06 +00:00
// This test cannot run on a Windows daemon as
2016-04-05 20:21:20 +00:00
// Windows does not support symlinks inside a volume path
2018-12-24 12:25:53 +00:00
testRequires ( c , testEnv . IsLocalDaemon , DaemonIsLinux )
2016-01-28 22:52:34 +00:00
name := "test-volume-symlink2"
2018-01-15 14:32:06 +00:00
if testEnv . OSType == "windows" {
2018-01-15 14:31:02 +00:00
dockerFile = fmt . Sprintf ( "FROM %s\nRUN mkdir c:\\%s\nRUN mklink /D c:\\test c:\\%s" , testEnv . PlatformDefaults . BaseImage , name , name )
2016-01-28 22:52:34 +00:00
containerPath = ` c:\test\test `
cmd = "tasklist"
} else {
dockerFile = fmt . Sprintf ( "FROM busybox\nRUN mkdir -p /%s\nRUN ln -s /%s /test" , name , name )
containerPath = "/test/test"
cmd = "true"
}
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , name , build . WithDockerfile ( dockerFile ) )
2016-01-28 22:52:34 +00:00
dockerCmd ( c , "run" , "-v" , containerPath , name , cmd )
}
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunVolumesMountedAsReadonly ( c * testing . T ) {
2015-07-27 18:13:25 +00:00
if _ , code , err := dockerCmdWithError ( "run" , "-v" , "/test:/test:ro" , "busybox" , "touch" , "/test/somefile" ) ; err == nil || code == 0 {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "run should fail because volume is ro: exit code %d" , code )
2014-04-08 01:23:22 +00:00
}
}
2014-04-08 09:26:09 +00:00
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunVolumesFromInReadonlyModeFails ( c * testing . T ) {
2015-09-23 23:04:51 +00:00
var (
volumeDir string
fileInVol string
)
2018-01-15 14:32:06 +00:00
if testEnv . OSType == "windows" {
2015-09-23 23:04:51 +00:00
volumeDir = ` c:/test ` // Forward-slash as using busybox
fileInVol = ` c:/test/file `
} else {
testRequires ( c , DaemonIsLinux )
volumeDir = "/test"
fileInVol = ` /test/file `
}
dockerCmd ( c , "run" , "--name" , "parent" , "-v" , volumeDir , "busybox" , "true" )
2014-04-08 09:26:09 +00:00
2015-09-23 23:04:51 +00:00
if _ , code , err := dockerCmdWithError ( "run" , "--volumes-from" , "parent:ro" , "busybox" , "touch" , fileInVol ) ; err == nil || code == 0 {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "run should fail because volume is ro: exit code %d" , code )
2014-04-08 09:26:09 +00:00
}
}
// Regression test for #1201
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunVolumesFromInReadWriteMode ( c * testing . T ) {
2015-09-23 23:04:51 +00:00
var (
volumeDir string
fileInVol string
)
2018-01-15 14:32:06 +00:00
if testEnv . OSType == "windows" {
2015-09-23 23:04:51 +00:00
volumeDir = ` c:/test ` // Forward-slash as using busybox
fileInVol = ` c:/test/file `
} else {
volumeDir = "/test"
fileInVol = "/test/file"
}
dockerCmd ( c , "run" , "--name" , "parent" , "-v" , volumeDir , "busybox" , "true" )
dockerCmd ( c , "run" , "--volumes-from" , "parent:rw" , "busybox" , "touch" , fileInVol )
2014-10-03 22:33:11 +00:00
Remove static errors from errors package.
Moving all strings to the errors package wasn't a good idea after all.
Our custom implementation of Go errors predates everything that's nice
and good about working with errors in Go. Take as an example what we
have to do to get an error message:
```go
func GetErrorMessage(err error) string {
switch err.(type) {
case errcode.Error:
e, _ := err.(errcode.Error)
return e.Message
case errcode.ErrorCode:
ec, _ := err.(errcode.ErrorCode)
return ec.Message()
default:
return err.Error()
}
}
```
This goes against every good practice for Go development. The language already provides a simple, intuitive and standard way to get error messages, that is calling the `Error()` method from an error. Reinventing the error interface is a mistake.
Our custom implementation also makes very hard to reason about errors, another nice thing about Go. I found several (>10) error declarations that we don't use anywhere. This is a clear sign about how little we know about the errors we return. I also found several error usages where the number of arguments was different than the parameters declared in the error, another clear example of how difficult is to reason about errors.
Moreover, our custom implementation didn't really make easier for people to return custom HTTP status code depending on the errors. Again, it's hard to reason about when to set custom codes and how. Take an example what we have to do to extract the message and status code from an error before returning a response from the API:
```go
switch err.(type) {
case errcode.ErrorCode:
daError, _ := err.(errcode.ErrorCode)
statusCode = daError.Descriptor().HTTPStatusCode
errMsg = daError.Message()
case errcode.Error:
// For reference, if you're looking for a particular error
// then you can do something like :
// import ( derr "github.com/docker/docker/errors" )
// if daError.ErrorCode() == derr.ErrorCodeNoSuchContainer { ... }
daError, _ := err.(errcode.Error)
statusCode = daError.ErrorCode().Descriptor().HTTPStatusCode
errMsg = daError.Message
default:
// This part of will be removed once we've
// converted everything over to use the errcode package
// FIXME: this is brittle and should not be necessary.
// If we need to differentiate between different possible error types,
// we should create appropriate error types with clearly defined meaning
errStr := strings.ToLower(err.Error())
for keyword, status := range map[string]int{
"not found": http.StatusNotFound,
"no such": http.StatusNotFound,
"bad parameter": http.StatusBadRequest,
"conflict": http.StatusConflict,
"impossible": http.StatusNotAcceptable,
"wrong login/password": http.StatusUnauthorized,
"hasn't been activated": http.StatusForbidden,
} {
if strings.Contains(errStr, keyword) {
statusCode = status
break
}
}
}
```
You can notice two things in that code:
1. We have to explain how errors work, because our implementation goes against how easy to use Go errors are.
2. At no moment we arrived to remove that `switch` statement that was the original reason to use our custom implementation.
This change removes all our status errors from the errors package and puts them back in their specific contexts.
IT puts the messages back with their contexts. That way, we know right away when errors used and how to generate their messages.
It uses custom interfaces to reason about errors. Errors that need to response with a custom status code MUST implementent this simple interface:
```go
type errorWithStatus interface {
HTTPErrorStatusCode() int
}
```
This interface is very straightforward to implement. It also preserves Go errors real behavior, getting the message is as simple as using the `Error()` method.
I included helper functions to generate errors that use custom status code in `errors/errors.go`.
By doing this, we remove the hard dependency we have eeverywhere to our custom errors package. Yes, you can use it as a helper to generate error, but it's still very easy to generate errors without it.
Please, read this fantastic blog post about errors in Go: http://dave.cheney.net/2014/12/24/inspecting-errors
Signed-off-by: David Calavera <david.calavera@gmail.com>
2016-02-25 15:53:35 +00:00
if out , _ , err := dockerCmdWithError ( "run" , "--volumes-from" , "parent:bar" , "busybox" , "touch" , fileInVol ) ; err == nil || ! strings . Contains ( out , ` invalid mode: bar ` ) {
2015-10-26 21:19:44 +00:00
c . Fatalf ( "running --volumes-from parent:bar should have failed with invalid mode: %q" , out )
2014-10-03 22:33:11 +00:00
}
2015-09-23 23:04:51 +00:00
dockerCmd ( c , "run" , "--volumes-from" , "parent" , "busybox" , "touch" , fileInVol )
2014-04-08 09:26:09 +00:00
}
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestVolumesFromGetsProperMode ( c * testing . T ) {
2018-12-24 12:25:53 +00:00
testRequires ( c , testEnv . IsLocalDaemon )
2016-05-25 20:56:36 +00:00
prefix , slash := getPrefixAndSlashFromDaemonPlatform ( )
2018-01-15 14:32:06 +00:00
hostpath := RandomTmpDirPath ( "test" , testEnv . OSType )
2016-06-17 22:46:45 +00:00
if err := os . MkdirAll ( hostpath , 0755 ) ; err != nil {
c . Fatalf ( "Failed to create %s: %q" , hostpath , err )
}
defer os . RemoveAll ( hostpath )
2016-05-25 20:56:36 +00:00
2016-06-17 22:46:45 +00:00
dockerCmd ( c , "run" , "--name" , "parent" , "-v" , hostpath + ":" + prefix + slash + "test:ro" , "busybox" , "true" )
2015-07-19 20:47:47 +00:00
2015-04-20 17:54:47 +00:00
// Expect this "rw" mode to be be ignored since the inherited volume is "ro"
2016-05-25 20:56:36 +00:00
if _ , _ , err := dockerCmdWithError ( "run" , "--volumes-from" , "parent:rw" , "busybox" , "touch" , prefix + slash + "test" + slash + "file" ) ; err == nil {
2015-04-18 16:46:47 +00:00
c . Fatal ( "Expected volumes-from to inherit read-only volume even when passing in `rw`" )
2014-08-28 14:18:08 +00:00
}
2016-06-17 22:46:45 +00:00
dockerCmd ( c , "run" , "--name" , "parent2" , "-v" , hostpath + ":" + prefix + slash + "test:ro" , "busybox" , "true" )
2015-07-19 20:47:47 +00:00
2014-08-28 14:18:08 +00:00
// Expect this to be read-only since both are "ro"
2016-05-25 20:56:36 +00:00
if _ , _ , err := dockerCmdWithError ( "run" , "--volumes-from" , "parent2:ro" , "busybox" , "touch" , prefix + slash + "test" + slash + "file" ) ; err == nil {
2015-04-18 16:46:47 +00:00
c . Fatal ( "Expected volumes-from to inherit read-only volume even when passing in `ro`" )
2014-08-21 21:57:46 +00:00
}
}
2015-02-06 22:00:53 +00:00
// Test for GH#10618
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunNoDupVolumes ( c * testing . T ) {
2018-01-15 14:32:06 +00:00
path1 := RandomTmpDirPath ( "test1" , testEnv . OSType )
path2 := RandomTmpDirPath ( "test2" , testEnv . OSType )
2015-09-23 23:04:51 +00:00
someplace := ":/someplace"
2018-01-15 14:32:06 +00:00
if testEnv . OSType == "windows" {
2015-09-23 23:04:51 +00:00
// Windows requires that the source directory exists before calling HCS
2018-12-24 12:25:53 +00:00
testRequires ( c , testEnv . IsLocalDaemon )
2015-09-23 23:04:51 +00:00
someplace = ` :c:\someplace `
if err := os . MkdirAll ( path1 , 0755 ) ; err != nil {
c . Fatalf ( "Failed to create %s: %q" , path1 , err )
}
defer os . RemoveAll ( path1 )
if err := os . MkdirAll ( path2 , 0755 ) ; err != nil {
c . Fatalf ( "Failed to create %s: %q" , path1 , err )
}
defer os . RemoveAll ( path2 )
}
mountstr1 := path1 + someplace
mountstr2 := path2 + someplace
2015-02-09 16:17:41 +00:00
2015-07-27 18:13:25 +00:00
if out , _ , err := dockerCmdWithError ( "run" , "-v" , mountstr1 , "-v" , mountstr2 , "busybox" , "true" ) ; err == nil {
2015-12-01 18:39:34 +00:00
c . Fatal ( "Expected error about duplicate mount definitions" )
2015-02-06 22:00:53 +00:00
} else {
2015-12-01 18:39:34 +00:00
if ! strings . Contains ( out , "Duplicate mount point" ) {
c . Fatalf ( "Expected 'duplicate mount point' error, got %v" , out )
2015-02-06 22:00:53 +00:00
}
}
2016-05-07 02:48:02 +00:00
// Test for https://github.com/docker/docker/issues/22093
volumename1 := "test1"
volumename2 := "test2"
volume1 := volumename1 + someplace
volume2 := volumename2 + someplace
if out , _ , err := dockerCmdWithError ( "run" , "-v" , volume1 , "-v" , volume2 , "busybox" , "true" ) ; err == nil {
c . Fatal ( "Expected error about duplicate mount definitions" )
} else {
if ! strings . Contains ( out , "Duplicate mount point" ) {
c . Fatalf ( "Expected 'duplicate mount point' error, got %v" , out )
}
}
// create failed should have create volume volumename1 or volumename2
// we should remove volumename2 or volumename2 successfully
out , _ := dockerCmd ( c , "volume" , "ls" )
if strings . Contains ( out , volumename1 ) {
dockerCmd ( c , "volume" , "rm" , volumename1 )
} else {
dockerCmd ( c , "volume" , "rm" , volumename2 )
}
2015-02-06 22:00:53 +00:00
}
2014-04-08 09:26:09 +00:00
// Test for #1351
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunApplyVolumesFromBeforeVolumes ( c * testing . T ) {
2015-09-23 23:04:51 +00:00
prefix := ""
2018-01-15 14:32:06 +00:00
if testEnv . OSType == "windows" {
2015-09-23 23:04:51 +00:00
prefix = ` c: `
}
dockerCmd ( c , "run" , "--name" , "parent" , "-v" , prefix + "/test" , "busybox" , "touch" , prefix + "/test/foo" )
dockerCmd ( c , "run" , "--volumes-from" , "parent" , "-v" , prefix + "/test" , "busybox" , "cat" , prefix + "/test/foo" )
2014-04-08 09:26:09 +00:00
}
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunMultipleVolumesFrom ( c * testing . T ) {
2015-09-23 23:04:51 +00:00
prefix := ""
2018-01-15 14:32:06 +00:00
if testEnv . OSType == "windows" {
2015-09-23 23:04:51 +00:00
prefix = ` c: `
}
dockerCmd ( c , "run" , "--name" , "parent1" , "-v" , prefix + "/test" , "busybox" , "touch" , prefix + "/test/foo" )
dockerCmd ( c , "run" , "--name" , "parent2" , "-v" , prefix + "/other" , "busybox" , "touch" , prefix + "/other/bar" )
2015-07-19 20:47:47 +00:00
dockerCmd ( c , "run" , "--volumes-from" , "parent1" , "--volumes-from" , "parent2" , "busybox" , "sh" , "-c" , "cat /test/foo && cat /other/bar" )
2014-04-08 09:26:09 +00:00
}
2014-04-18 01:58:20 +00:00
2014-04-18 21:35:16 +00:00
// this tests verifies the ID format for the container
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunVerifyContainerID ( c * testing . T ) {
2015-07-27 18:13:25 +00:00
out , exit , err := dockerCmdWithError ( "run" , "-d" , "busybox" , "true" )
2014-04-18 21:35:16 +00:00
if err != nil {
2015-04-18 16:46:47 +00:00
c . Fatal ( err )
2014-04-18 21:35:16 +00:00
}
if exit != 0 {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "expected exit code 0 received %d" , exit )
2014-04-18 21:35:16 +00:00
}
2015-07-19 20:47:47 +00:00
2014-04-18 21:35:16 +00:00
match , err := regexp . MatchString ( "^[0-9a-f]{64}$" , strings . TrimSuffix ( out , "\n" ) )
if err != nil {
2015-04-18 16:46:47 +00:00
c . Fatal ( err )
2014-04-18 21:35:16 +00:00
}
if ! match {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "Invalid container ID: %s" , out )
2014-04-18 21:35:16 +00:00
}
}
// Test that creating a container with a volume doesn't crash. Regression test for #995.
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunCreateVolume ( c * testing . T ) {
2015-09-23 23:04:51 +00:00
prefix := ""
2018-01-15 14:32:06 +00:00
if testEnv . OSType == "windows" {
2015-09-23 23:04:51 +00:00
prefix = ` c: `
}
dockerCmd ( c , "run" , "-v" , prefix + "/var/lib/data" , "busybox" , "true" )
2014-04-18 21:35:16 +00:00
}
2014-04-25 01:22:22 +00:00
// Test that creating a volume with a symlink in its path works correctly. Test for #5152.
// Note that this bug happens only with symlinks with a target that starts with '/'.
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunCreateVolumeWithSymlink ( c * testing . T ) {
2015-09-23 23:04:51 +00:00
// Cannot run on Windows as relies on Linux-specific functionality (sh -c mount...)
2015-08-28 17:36:42 +00:00
testRequires ( c , DaemonIsLinux )
2016-12-19 12:25:11 +00:00
workingDirectory , err := ioutil . TempDir ( "" , "TestRunCreateVolumeWithSymlink" )
2019-04-04 13:23:19 +00:00
assert . NilError ( c , err )
2015-02-20 06:56:02 +00:00
image := "docker-test-createvolumewithsymlink"
buildCmd := exec . Command ( dockerBinary , "build" , "-t" , image , "-" )
2014-05-27 21:54:38 +00:00
buildCmd . Stdin = strings . NewReader ( ` FROM busybox
2015-01-23 12:17:05 +00:00
RUN ln - s home / bar ` )
2014-05-27 21:54:38 +00:00
buildCmd . Dir = workingDirectory
2016-12-19 12:25:11 +00:00
err = buildCmd . Run ( )
2014-04-25 01:22:22 +00:00
if err != nil {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "could not build '%s': %v" , image , err )
2014-04-25 01:22:22 +00:00
}
2015-07-27 18:13:25 +00:00
_ , exitCode , err := dockerCmdWithError ( "run" , "-v" , "/bar/foo" , "--name" , "test-createvolumewithsymlink" , image , "sh" , "-c" , "mount | grep -q /home/foo" )
2014-04-25 01:22:22 +00:00
if err != nil || exitCode != 0 {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "[run] err: %v, exitcode: %d" , err , exitCode )
2014-04-25 01:22:22 +00:00
}
2015-07-23 22:11:06 +00:00
volPath , err := inspectMountSourceField ( "test-createvolumewithsymlink" , "/bar/foo" )
2019-04-04 13:23:19 +00:00
assert . NilError ( c , err )
2014-04-25 01:22:22 +00:00
2015-07-27 18:13:25 +00:00
_ , exitCode , err = dockerCmdWithError ( "rm" , "-v" , "test-createvolumewithsymlink" )
2014-04-25 01:22:22 +00:00
if err != nil || exitCode != 0 {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "[rm] err: %v, exitcode: %d" , err , exitCode )
2014-04-25 01:22:22 +00:00
}
2015-07-23 22:11:06 +00:00
_ , err = os . Stat ( volPath )
2014-04-25 01:22:22 +00:00
if ! os . IsNotExist ( err ) {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "[open] (expecting 'file does not exist' error) err: %v, volPath: %s" , err , volPath )
2014-04-25 01:22:22 +00:00
}
}
2014-05-27 21:49:43 +00:00
// Tests that a volume path that has a symlink exists in a container mounting it with `--volumes-from`.
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunVolumesFromSymlinkPath ( c * testing . T ) {
2016-11-23 22:28:06 +00:00
// This test cannot run on a Windows daemon as
2016-04-05 20:21:20 +00:00
// Windows does not support symlinks inside a volume path
testRequires ( c , DaemonIsLinux )
2016-12-19 12:25:11 +00:00
workingDirectory , err := ioutil . TempDir ( "" , "TestRunVolumesFromSymlinkPath" )
2019-04-04 13:23:19 +00:00
assert . NilError ( c , err )
2014-11-17 16:05:49 +00:00
name := "docker-test-volumesfromsymlinkpath"
2015-09-23 23:04:51 +00:00
prefix := ""
dfContents := ` FROM busybox
RUN ln - s home / foo
VOLUME [ "/foo/bar" ] `
2018-01-15 14:32:06 +00:00
if testEnv . OSType == "windows" {
2015-09-23 23:04:51 +00:00
prefix = ` c: `
2018-01-15 14:31:02 +00:00
dfContents = ` FROM ` + testEnv . PlatformDefaults . BaseImage + `
2015-09-23 23:04:51 +00:00
RUN mkdir c : \ home
2015-10-29 15:55:48 +00:00
RUN mklink / D c : \ foo c : \ home
2015-09-23 23:04:51 +00:00
VOLUME [ "c:/foo/bar" ]
ENTRYPOINT c : \ windows \ system32 \ cmd . exe `
}
2015-02-20 06:56:02 +00:00
2014-11-17 16:05:49 +00:00
buildCmd := exec . Command ( dockerBinary , "build" , "-t" , name , "-" )
2015-09-23 23:04:51 +00:00
buildCmd . Stdin = strings . NewReader ( dfContents )
2014-05-27 21:49:43 +00:00
buildCmd . Dir = workingDirectory
2016-12-19 12:25:11 +00:00
err = buildCmd . Run ( )
2014-05-27 21:49:43 +00:00
if err != nil {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "could not build 'docker-test-volumesfromsymlinkpath': %v" , err )
2014-05-27 21:49:43 +00:00
}
2015-09-23 23:04:51 +00:00
out , exitCode , err := dockerCmdWithError ( "run" , "--name" , "test-volumesfromsymlinkpath" , name )
2014-05-27 21:49:43 +00:00
if err != nil || exitCode != 0 {
2015-09-23 23:04:51 +00:00
c . Fatalf ( "[run] (volume) err: %v, exitcode: %d, out: %s" , err , exitCode , out )
2014-05-27 21:49:43 +00:00
}
2015-09-23 23:04:51 +00:00
_ , exitCode , err = dockerCmdWithError ( "run" , "--volumes-from" , "test-volumesfromsymlinkpath" , "busybox" , "sh" , "-c" , "ls " + prefix + "/foo | grep -q bar" )
2014-05-27 21:49:43 +00:00
if err != nil || exitCode != 0 {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "[run] err: %v, exitcode: %d" , err , exitCode )
2014-05-27 21:49:43 +00:00
}
}
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunExitCode ( c * testing . T ) {
2015-09-01 21:37:04 +00:00
var (
exit int
err error
)
2015-09-23 22:12:23 +00:00
_ , exit , err = dockerCmdWithError ( "run" , "busybox" , "/bin/sh" , "-c" , "exit 72" )
2014-04-18 21:35:16 +00:00
if err == nil {
2015-04-18 16:46:47 +00:00
c . Fatal ( "should not have a non nil error" )
2014-04-18 21:35:16 +00:00
}
if exit != 72 {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "expected exit code 72 received %d" , exit )
2014-04-18 21:35:16 +00:00
}
}
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunUserDefaults ( c * testing . T ) {
2015-09-01 21:37:04 +00:00
expected := "uid=0(root) gid=0(root)"
2018-01-15 14:32:06 +00:00
if testEnv . OSType == "windows" {
2019-03-19 20:06:27 +00:00
expected = "uid=0(root) gid=0(root) groups=0(root)"
2015-09-01 21:37:04 +00:00
}
2015-07-19 20:47:47 +00:00
out , _ := dockerCmd ( c , "run" , "busybox" , "id" )
2015-09-01 21:37:04 +00:00
if ! strings . Contains ( out , expected ) {
c . Fatalf ( "expected '%s' got %s" , expected , out )
2014-04-18 21:35:16 +00:00
}
}
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunUserByName ( c * testing . T ) {
2015-09-01 21:37:04 +00:00
// TODO Windows: This test cannot run on a Windows daemon as Windows does
// not support the use of -u
2015-08-28 17:36:42 +00:00
testRequires ( c , DaemonIsLinux )
2015-07-19 20:47:47 +00:00
out , _ := dockerCmd ( c , "run" , "-u" , "root" , "busybox" , "id" )
2014-04-18 21:35:16 +00:00
if ! strings . Contains ( out , "uid=0(root) gid=0(root)" ) {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "expected root user got %s" , out )
2014-04-18 21:35:16 +00:00
}
}
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunUserByID ( c * testing . T ) {
2015-09-01 21:37:04 +00:00
// TODO Windows: This test cannot run on a Windows daemon as Windows does
// not support the use of -u
2015-08-28 17:36:42 +00:00
testRequires ( c , DaemonIsLinux )
2015-07-19 20:47:47 +00:00
out , _ := dockerCmd ( c , "run" , "-u" , "1" , "busybox" , "id" )
2014-04-18 21:35:16 +00:00
if ! strings . Contains ( out , "uid=1(daemon) gid=1(daemon)" ) {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "expected daemon user got %s" , out )
2014-04-18 21:35:16 +00:00
}
}
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunUserByIDBig ( c * testing . T ) {
2015-09-01 21:37:04 +00:00
// TODO Windows: This test cannot run on a Windows daemon as Windows does
// not support the use of -u
2015-11-25 23:38:33 +00:00
testRequires ( c , DaemonIsLinux , NotArm )
2015-07-27 18:13:25 +00:00
out , _ , err := dockerCmdWithError ( "run" , "-u" , "2147483648" , "busybox" , "id" )
2014-05-17 18:43:31 +00:00
if err == nil {
2015-04-18 16:46:47 +00:00
c . Fatal ( "No error, but must be." , out )
2014-05-17 18:43:31 +00:00
}
2018-01-13 01:57:50 +00:00
if ! strings . Contains ( strings . ToLower ( out ) , "uids and gids must be in range" ) {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "expected error about uids range, got %s" , out )
2014-05-17 18:43:31 +00:00
}
}
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunUserByIDNegative ( c * testing . T ) {
2015-09-01 21:37:04 +00:00
// TODO Windows: This test cannot run on a Windows daemon as Windows does
// not support the use of -u
2015-08-28 17:36:42 +00:00
testRequires ( c , DaemonIsLinux )
2015-07-27 18:13:25 +00:00
out , _ , err := dockerCmdWithError ( "run" , "-u" , "-1" , "busybox" , "id" )
2014-05-17 18:43:31 +00:00
if err == nil {
2015-04-18 16:46:47 +00:00
c . Fatal ( "No error, but must be." , out )
2014-05-17 18:43:31 +00:00
}
2018-01-13 01:57:50 +00:00
if ! strings . Contains ( strings . ToLower ( out ) , "uids and gids must be in range" ) {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "expected error about uids range, got %s" , out )
2014-05-17 18:43:31 +00:00
}
}
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunUserByIDZero ( c * testing . T ) {
2015-09-01 21:37:04 +00:00
// TODO Windows: This test cannot run on a Windows daemon as Windows does
// not support the use of -u
2015-08-28 17:36:42 +00:00
testRequires ( c , DaemonIsLinux )
2015-07-27 18:13:25 +00:00
out , _ , err := dockerCmdWithError ( "run" , "-u" , "0" , "busybox" , "id" )
2014-05-17 18:43:31 +00:00
if err != nil {
2015-04-18 16:46:47 +00:00
c . Fatal ( err , out )
2014-05-17 18:43:31 +00:00
}
if ! strings . Contains ( out , "uid=0(root) gid=0(root) groups=10(wheel)" ) {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "expected daemon user got %s" , out )
2014-05-17 18:43:31 +00:00
}
}
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunUserNotFound ( c * testing . T ) {
2015-09-01 21:37:04 +00:00
// TODO Windows: This test cannot run on a Windows daemon as Windows does
// not support the use of -u
testRequires ( c , DaemonIsLinux )
2015-07-27 18:13:25 +00:00
_ , _ , err := dockerCmdWithError ( "run" , "-u" , "notme" , "busybox" , "id" )
2014-04-18 21:35:16 +00:00
if err == nil {
2015-04-18 16:46:47 +00:00
c . Fatal ( "unknown user should cause container to fail" )
2014-04-18 21:35:16 +00:00
}
}
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunTwoConcurrentContainers ( c * testing . T ) {
2015-09-01 21:37:04 +00:00
sleepTime := "2"
2014-04-18 21:35:16 +00:00
group := sync . WaitGroup { }
group . Add ( 2 )
2015-04-27 17:29:48 +00:00
errChan := make ( chan error , 2 )
2014-04-18 21:35:16 +00:00
for i := 0 ; i < 2 ; i ++ {
go func ( ) {
defer group . Done ( )
2015-09-01 21:37:04 +00:00
_ , _ , err := dockerCmdWithError ( "run" , "busybox" , "sleep" , sleepTime )
2015-04-27 17:29:48 +00:00
errChan <- err
2014-04-18 21:35:16 +00:00
} ( )
}
group . Wait ( )
2015-04-27 17:29:48 +00:00
close ( errChan )
for err := range errChan {
2019-04-04 13:23:19 +00:00
assert . NilError ( c , err )
2015-04-27 17:29:48 +00:00
}
2014-04-18 21:35:16 +00:00
}
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunEnvironment ( c * testing . T ) {
2015-09-01 21:37:04 +00:00
// TODO Windows: Environment handling is different between Linux and
2015-11-04 19:39:12 +00:00
// Windows and this test relies currently on unix functionality.
2015-08-28 17:36:42 +00:00
testRequires ( c , DaemonIsLinux )
2017-01-05 11:38:34 +00:00
result := icmd . RunCmd ( icmd . Cmd {
Command : [ ] string { dockerBinary , "run" , "-h" , "testing" , "-e=FALSE=true" , "-e=TRUE" , "-e=TRICKY" , "-e=HOME=" , "busybox" , "env" } ,
Env : append ( os . Environ ( ) ,
"TRUE=false" ,
"TRICKY=tri\ncky\n" ,
) ,
} )
result . Assert ( c , icmd . Success )
2014-04-18 21:35:16 +00:00
2017-09-06 21:32:56 +00:00
actualEnv := strings . Split ( strings . TrimSuffix ( result . Stdout ( ) , "\n" ) , "\n" )
2014-04-18 21:35:16 +00:00
sort . Strings ( actualEnv )
goodEnv := [ ] string {
2017-01-05 11:38:34 +00:00
// The first two should not be tested here, those are "inherent" environment variable. This test validates
// the -e behavior, not the default environment variable (that could be subject to change)
2014-04-18 21:35:16 +00:00
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" ,
"HOSTNAME=testing" ,
"FALSE=true" ,
"TRUE=false" ,
"TRICKY=tri" ,
"cky" ,
"" ,
2014-02-23 03:06:37 +00:00
"HOME=/root" ,
2014-04-18 21:35:16 +00:00
}
sort . Strings ( goodEnv )
if len ( goodEnv ) != len ( actualEnv ) {
2016-03-31 10:36:59 +00:00
c . Fatalf ( "Wrong environment: should be %d variables, not %d: %q" , len ( goodEnv ) , len ( actualEnv ) , strings . Join ( actualEnv , ", " ) )
2014-04-18 21:35:16 +00:00
}
for i := range goodEnv {
if actualEnv [ i ] != goodEnv [ i ] {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "Wrong environment variable: should be %s, not %s" , goodEnv [ i ] , actualEnv [ i ] )
2014-04-18 21:35:16 +00:00
}
}
}
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunEnvironmentErase ( c * testing . T ) {
2015-09-01 21:37:04 +00:00
// TODO Windows: Environment handling is different between Linux and
2015-11-04 19:39:12 +00:00
// Windows and this test relies currently on unix functionality.
2015-08-28 17:36:42 +00:00
testRequires ( c , DaemonIsLinux )
2015-09-01 21:37:04 +00:00
2015-01-16 20:57:08 +00:00
// Test to make sure that when we use -e on env vars that are
// not set in our local env that they're removed (if present) in
// the container
2015-02-20 06:56:02 +00:00
2017-01-05 11:38:34 +00:00
result := icmd . RunCmd ( icmd . Cmd {
Command : [ ] string { dockerBinary , "run" , "-e" , "FOO" , "-e" , "HOSTNAME" , "busybox" , "env" } ,
2017-01-05 18:08:24 +00:00
Env : appendBaseEnv ( true ) ,
2017-01-05 11:38:34 +00:00
} )
result . Assert ( c , icmd . Success )
2015-01-16 20:57:08 +00:00
2017-01-05 11:38:34 +00:00
actualEnv := strings . Split ( strings . TrimSpace ( result . Combined ( ) ) , "\n" )
2015-01-16 20:57:08 +00:00
sort . Strings ( actualEnv )
goodEnv := [ ] string {
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" ,
"HOME=/root" ,
}
sort . Strings ( goodEnv )
if len ( goodEnv ) != len ( actualEnv ) {
2016-03-31 10:36:59 +00:00
c . Fatalf ( "Wrong environment: should be %d variables, not %d: %q" , len ( goodEnv ) , len ( actualEnv ) , strings . Join ( actualEnv , ", " ) )
2015-01-16 20:57:08 +00:00
}
for i := range goodEnv {
if actualEnv [ i ] != goodEnv [ i ] {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "Wrong environment variable: should be %s, not %s" , goodEnv [ i ] , actualEnv [ i ] )
2015-01-16 20:57:08 +00:00
}
}
}
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunEnvironmentOverride ( c * testing . T ) {
2015-09-01 21:37:04 +00:00
// TODO Windows: Environment handling is different between Linux and
2015-11-04 19:39:12 +00:00
// Windows and this test relies currently on unix functionality.
2015-08-28 17:36:42 +00:00
testRequires ( c , DaemonIsLinux )
2015-09-01 21:37:04 +00:00
2015-01-16 20:57:08 +00:00
// Test to make sure that when we use -e on env vars that are
// already in the env that we're overriding them
2015-02-20 06:56:02 +00:00
2017-01-05 11:38:34 +00:00
result := icmd . RunCmd ( icmd . Cmd {
Command : [ ] string { dockerBinary , "run" , "-e" , "HOSTNAME" , "-e" , "HOME=/root2" , "busybox" , "env" } ,
2017-01-05 18:08:24 +00:00
Env : appendBaseEnv ( true , "HOSTNAME=bar" ) ,
2017-01-05 11:38:34 +00:00
} )
result . Assert ( c , icmd . Success )
2015-01-16 20:57:08 +00:00
2017-01-05 11:38:34 +00:00
actualEnv := strings . Split ( strings . TrimSpace ( result . Combined ( ) ) , "\n" )
2015-01-16 20:57:08 +00:00
sort . Strings ( actualEnv )
goodEnv := [ ] string {
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" ,
"HOME=/root2" ,
"HOSTNAME=bar" ,
}
sort . Strings ( goodEnv )
if len ( goodEnv ) != len ( actualEnv ) {
2016-03-31 10:36:59 +00:00
c . Fatalf ( "Wrong environment: should be %d variables, not %d: %q" , len ( goodEnv ) , len ( actualEnv ) , strings . Join ( actualEnv , ", " ) )
2015-01-16 20:57:08 +00:00
}
for i := range goodEnv {
if actualEnv [ i ] != goodEnv [ i ] {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "Wrong environment variable: should be %s, not %s" , goodEnv [ i ] , actualEnv [ i ] )
2015-01-16 20:57:08 +00:00
}
}
}
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunContainerNetwork ( c * testing . T ) {
2018-01-15 14:32:06 +00:00
if testEnv . OSType == "windows" {
2015-09-01 21:37:04 +00:00
// Windows busybox does not have ping. Use built in ping instead.
2018-01-15 14:31:02 +00:00
dockerCmd ( c , "run" , testEnv . PlatformDefaults . BaseImage , "ping" , "-n" , "1" , "127.0.0.1" )
2015-09-01 21:37:04 +00:00
} else {
dockerCmd ( c , "run" , "busybox" , "ping" , "-c" , "1" , "127.0.0.1" )
}
2014-04-18 21:35:16 +00:00
}
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunNetHostNotAllowedWithLinks ( c * testing . T ) {
2015-09-01 21:37:04 +00:00
// TODO Windows: This is Linux specific as --link is not supported and
2015-12-13 16:00:39 +00:00
// this will be deprecated in favor of container networking model.
2015-09-18 17:41:12 +00:00
testRequires ( c , DaemonIsLinux , NotUserNamespace )
2015-07-19 20:47:47 +00:00
dockerCmd ( c , "run" , "--name" , "linked" , "busybox" , "true" )
2015-07-27 18:13:25 +00:00
_ , _ , err := dockerCmdWithError ( "run" , "--net=host" , "--link" , "linked:linked" , "busybox" , "true" )
2014-07-16 21:09:30 +00:00
if err == nil {
2015-04-18 16:46:47 +00:00
c . Fatal ( "Expected error" )
2014-07-16 21:09:30 +00:00
}
}
2014-09-24 15:00:01 +00:00
// #7851 hostname outside container shows FQDN, inside only shortname
// For testing purposes it is not required to set host's hostname directly
// and use "--net=host" (as the original issue submitter did), as the same
// codepath is executed with "docker run -h <hostname>". Both were manually
// tested, but this testcase takes the simpler path of using "run -h .."
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunFullHostnameSet ( c * testing . T ) {
2015-09-01 21:37:04 +00:00
// TODO Windows: -h is not yet functional.
2015-08-28 17:36:42 +00:00
testRequires ( c , DaemonIsLinux )
2015-07-19 20:47:47 +00:00
out , _ := dockerCmd ( c , "run" , "-h" , "foo.bar.baz" , "busybox" , "hostname" )
2014-09-24 15:00:01 +00:00
if actual := strings . Trim ( out , "\r\n" ) ; actual != "foo.bar.baz" {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "expected hostname 'foo.bar.baz', received %s" , actual )
2014-09-24 15:00:01 +00:00
}
}
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunPrivilegedCanMknod ( c * testing . T ) {
2015-09-01 21:37:04 +00:00
// Not applicable for Windows as Windows daemon does not support
// the concept of --privileged, and mknod is a Unix concept.
2015-09-18 17:41:12 +00:00
testRequires ( c , DaemonIsLinux , NotUserNamespace )
2015-07-19 20:47:47 +00:00
out , _ := dockerCmd ( c , "run" , "--privileged" , "busybox" , "sh" , "-c" , "mknod /tmp/sda b 8 0 && echo ok" )
2014-04-18 21:35:16 +00:00
if actual := strings . Trim ( out , "\r\n" ) ; actual != "ok" {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "expected output ok received %s" , actual )
2014-04-18 21:35:16 +00:00
}
}
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunUnprivilegedCanMknod ( c * testing . T ) {
2015-09-01 21:37:04 +00:00
// Not applicable for Windows as Windows daemon does not support
// the concept of --privileged, and mknod is a Unix concept.
2015-09-18 17:41:12 +00:00
testRequires ( c , DaemonIsLinux , NotUserNamespace )
2015-07-19 20:47:47 +00:00
out , _ := dockerCmd ( c , "run" , "busybox" , "sh" , "-c" , "mknod /tmp/sda b 8 0 && echo ok" )
2014-04-18 21:35:16 +00:00
if actual := strings . Trim ( out , "\r\n" ) ; actual != "ok" {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "expected output ok received %s" , actual )
2014-04-18 21:35:16 +00:00
}
}
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunCapDropInvalid ( c * testing . T ) {
2015-09-01 21:37:04 +00:00
// Not applicable for Windows as there is no concept of --cap-drop
2015-08-28 17:36:42 +00:00
testRequires ( c , DaemonIsLinux )
2015-07-27 18:13:25 +00:00
out , _ , err := dockerCmdWithError ( "run" , "--cap-drop=CHPASS" , "busybox" , "ls" )
2014-07-10 23:38:11 +00:00
if err == nil {
2015-04-18 16:46:47 +00:00
c . Fatal ( err , out )
2014-07-10 23:38:11 +00:00
}
}
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunCapDropCannotMknod ( c * testing . T ) {
2015-09-01 21:37:04 +00:00
// Not applicable for Windows as there is no concept of --cap-drop or mknod
2015-08-28 17:36:42 +00:00
testRequires ( c , DaemonIsLinux )
2015-07-27 18:13:25 +00:00
out , _ , err := dockerCmdWithError ( "run" , "--cap-drop=MKNOD" , "busybox" , "sh" , "-c" , "mknod /tmp/sda b 8 0 && echo ok" )
2015-07-19 20:47:47 +00:00
2014-07-10 21:51:15 +00:00
if err == nil {
2015-04-18 16:46:47 +00:00
c . Fatal ( err , out )
2014-07-10 21:51:15 +00:00
}
if actual := strings . Trim ( out , "\r\n" ) ; actual == "ok" {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "expected output not ok received %s" , actual )
2014-07-10 21:51:15 +00:00
}
}
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunCapDropCannotMknodLowerCase ( c * testing . T ) {
2015-09-01 21:37:04 +00:00
// Not applicable for Windows as there is no concept of --cap-drop or mknod
2015-08-28 17:36:42 +00:00
testRequires ( c , DaemonIsLinux )
2015-07-27 18:13:25 +00:00
out , _ , err := dockerCmdWithError ( "run" , "--cap-drop=mknod" , "busybox" , "sh" , "-c" , "mknod /tmp/sda b 8 0 && echo ok" )
2015-07-19 20:47:47 +00:00
2014-07-16 18:47:55 +00:00
if err == nil {
2015-04-18 16:46:47 +00:00
c . Fatal ( err , out )
2014-07-16 18:47:55 +00:00
}
if actual := strings . Trim ( out , "\r\n" ) ; actual == "ok" {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "expected output not ok received %s" , actual )
2014-07-16 18:47:55 +00:00
}
}
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunCapDropALLCannotMknod ( c * testing . T ) {
2015-09-01 21:37:04 +00:00
// Not applicable for Windows as there is no concept of --cap-drop or mknod
2015-08-28 17:36:42 +00:00
testRequires ( c , DaemonIsLinux )
2015-07-27 18:13:25 +00:00
out , _ , err := dockerCmdWithError ( "run" , "--cap-drop=ALL" , "--cap-add=SETGID" , "busybox" , "sh" , "-c" , "mknod /tmp/sda b 8 0 && echo ok" )
2014-07-10 22:31:01 +00:00
if err == nil {
2015-04-18 16:46:47 +00:00
c . Fatal ( err , out )
2014-07-10 22:31:01 +00:00
}
if actual := strings . Trim ( out , "\r\n" ) ; actual == "ok" {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "expected output not ok received %s" , actual )
2014-07-10 22:31:01 +00:00
}
}
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunCapDropALLAddMknodCanMknod ( c * testing . T ) {
2015-09-01 21:37:04 +00:00
// Not applicable for Windows as there is no concept of --cap-drop or mknod
2015-09-18 17:41:12 +00:00
testRequires ( c , DaemonIsLinux , NotUserNamespace )
2015-07-19 20:47:47 +00:00
out , _ := dockerCmd ( c , "run" , "--cap-drop=ALL" , "--cap-add=MKNOD" , "--cap-add=SETGID" , "busybox" , "sh" , "-c" , "mknod /tmp/sda b 8 0 && echo ok" )
2014-07-10 23:02:39 +00:00
if actual := strings . Trim ( out , "\r\n" ) ; actual != "ok" {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "expected output ok received %s" , actual )
2014-07-10 23:02:39 +00:00
}
}
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunCapAddInvalid ( c * testing . T ) {
2015-09-01 21:37:04 +00:00
// Not applicable for Windows as there is no concept of --cap-add
2015-08-28 17:36:42 +00:00
testRequires ( c , DaemonIsLinux )
2015-07-27 18:13:25 +00:00
out , _ , err := dockerCmdWithError ( "run" , "--cap-add=CHPASS" , "busybox" , "ls" )
2014-07-10 23:38:11 +00:00
if err == nil {
2015-04-18 16:46:47 +00:00
c . Fatal ( err , out )
2014-07-10 23:38:11 +00:00
}
}
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunCapAddCanDownInterface ( c * testing . T ) {
2015-09-01 21:37:04 +00:00
// Not applicable for Windows as there is no concept of --cap-add
2015-08-28 17:36:42 +00:00
testRequires ( c , DaemonIsLinux )
2015-07-19 20:47:47 +00:00
out , _ := dockerCmd ( c , "run" , "--cap-add=NET_ADMIN" , "busybox" , "sh" , "-c" , "ip link set eth0 down && echo ok" )
2014-07-10 21:51:15 +00:00
if actual := strings . Trim ( out , "\r\n" ) ; actual != "ok" {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "expected output ok received %s" , actual )
2014-07-10 21:51:15 +00:00
}
}
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunCapAddALLCanDownInterface ( c * testing . T ) {
2015-09-01 21:37:04 +00:00
// Not applicable for Windows as there is no concept of --cap-add
2015-08-28 17:36:42 +00:00
testRequires ( c , DaemonIsLinux )
2015-07-19 20:47:47 +00:00
out , _ := dockerCmd ( c , "run" , "--cap-add=ALL" , "busybox" , "sh" , "-c" , "ip link set eth0 down && echo ok" )
2014-07-10 22:31:01 +00:00
if actual := strings . Trim ( out , "\r\n" ) ; actual != "ok" {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "expected output ok received %s" , actual )
2014-07-10 22:31:01 +00:00
}
}
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunCapAddALLDropNetAdminCanDownInterface ( c * testing . T ) {
2015-09-01 21:37:04 +00:00
// Not applicable for Windows as there is no concept of --cap-add
2015-08-28 17:36:42 +00:00
testRequires ( c , DaemonIsLinux )
2015-07-27 18:13:25 +00:00
out , _ , err := dockerCmdWithError ( "run" , "--cap-add=ALL" , "--cap-drop=NET_ADMIN" , "busybox" , "sh" , "-c" , "ip link set eth0 down && echo ok" )
2014-07-10 23:02:39 +00:00
if err == nil {
2015-04-18 16:46:47 +00:00
c . Fatal ( err , out )
2014-07-10 23:02:39 +00:00
}
if actual := strings . Trim ( out , "\r\n" ) ; actual == "ok" {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "expected output not ok received %s" , actual )
2014-07-10 23:02:39 +00:00
}
}
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunGroupAdd ( c * testing . T ) {
2015-09-01 21:37:04 +00:00
// Not applicable for Windows as there is no concept of --group-add
2015-11-05 00:40:58 +00:00
testRequires ( c , DaemonIsLinux )
2015-10-13 16:39:05 +00:00
out , _ := dockerCmd ( c , "run" , "--group-add=audio" , "--group-add=staff" , "--group-add=777" , "busybox" , "sh" , "-c" , "id" )
2015-06-17 18:39:59 +00:00
2015-10-13 16:39:05 +00:00
groupsList := "uid=0(root) gid=0(root) groups=10(wheel),29(audio),50(staff),777"
2015-06-17 18:39:59 +00:00
if actual := strings . Trim ( out , "\r\n" ) ; actual != groupsList {
c . Fatalf ( "expected output %s received %s" , groupsList , actual )
}
}
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunPrivilegedCanMount ( c * testing . T ) {
2015-09-01 21:37:04 +00:00
// Not applicable for Windows as there is no concept of --privileged
2015-09-18 17:41:12 +00:00
testRequires ( c , DaemonIsLinux , NotUserNamespace )
2015-07-19 20:47:47 +00:00
out , _ := dockerCmd ( c , "run" , "--privileged" , "busybox" , "sh" , "-c" , "mount -t tmpfs none /tmp && echo ok" )
2014-04-18 21:35:16 +00:00
if actual := strings . Trim ( out , "\r\n" ) ; actual != "ok" {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "expected output ok received %s" , actual )
2014-04-18 21:35:16 +00:00
}
}
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunUnprivilegedCannotMount ( c * testing . T ) {
2015-09-01 21:37:04 +00:00
// Not applicable for Windows as there is no concept of unprivileged
2015-08-28 17:36:42 +00:00
testRequires ( c , DaemonIsLinux )
2015-07-27 18:13:25 +00:00
out , _ , err := dockerCmdWithError ( "run" , "busybox" , "sh" , "-c" , "mount -t tmpfs none /tmp && echo ok" )
2015-07-19 20:47:47 +00:00
2014-04-18 21:35:16 +00:00
if err == nil {
2015-04-18 16:46:47 +00:00
c . Fatal ( err , out )
2014-04-18 21:35:16 +00:00
}
if actual := strings . Trim ( out , "\r\n" ) ; actual == "ok" {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "expected output not ok received %s" , actual )
2014-04-18 21:35:16 +00:00
}
}
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunSysNotWritableInNonPrivilegedContainers ( c * testing . T ) {
2015-09-01 21:37:04 +00:00
// Not applicable for Windows as there is no concept of unprivileged
2015-11-25 23:38:33 +00:00
testRequires ( c , DaemonIsLinux , NotArm )
2015-07-27 18:13:25 +00:00
if _ , code , err := dockerCmdWithError ( "run" , "busybox" , "touch" , "/sys/kernel/profiling" ) ; err == nil || code == 0 {
2015-04-18 16:46:47 +00:00
c . Fatal ( "sys should not be writable in a non privileged container" )
2014-04-18 03:20:17 +00:00
}
}
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunSysWritableInPrivilegedContainers ( c * testing . T ) {
2015-09-01 21:37:04 +00:00
// Not applicable for Windows as there is no concept of unprivileged
2015-11-25 23:38:33 +00:00
testRequires ( c , DaemonIsLinux , NotUserNamespace , NotArm )
2015-07-27 18:13:25 +00:00
if _ , code , err := dockerCmdWithError ( "run" , "--privileged" , "busybox" , "touch" , "/sys/kernel/profiling" ) ; err != nil || code != 0 {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "sys should be writable in privileged container" )
2014-04-18 03:20:17 +00:00
}
2014-05-01 01:00:42 +00:00
}
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunProcNotWritableInNonPrivilegedContainers ( c * testing . T ) {
2015-09-01 21:37:04 +00:00
// Not applicable for Windows as there is no concept of unprivileged
2015-08-28 17:36:42 +00:00
testRequires ( c , DaemonIsLinux )
2015-07-27 18:13:25 +00:00
if _ , code , err := dockerCmdWithError ( "run" , "busybox" , "touch" , "/proc/sysrq-trigger" ) ; err == nil || code == 0 {
2015-04-18 16:46:47 +00:00
c . Fatal ( "proc should not be writable in a non privileged container" )
2014-05-01 01:00:42 +00:00
}
}
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunProcWritableInPrivilegedContainers ( c * testing . T ) {
2015-09-01 21:37:04 +00:00
// Not applicable for Windows as there is no concept of --privileged
2015-09-18 17:41:12 +00:00
testRequires ( c , DaemonIsLinux , NotUserNamespace )
2016-04-04 21:27:44 +00:00
if _ , code := dockerCmd ( c , "run" , "--privileged" , "busybox" , "sh" , "-c" , "touch /proc/sysrq-trigger" ) ; code != 0 {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "proc should be writable in privileged container" )
2014-05-01 01:00:42 +00:00
}
2015-04-08 08:58:59 +00:00
}
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunDeviceNumbers ( c * testing . T ) {
2015-09-01 21:37:04 +00:00
// Not applicable on Windows as /dev/ is a Unix specific concept
2015-09-18 17:41:12 +00:00
// TODO: NotUserNamespace could be removed here if "root" "root" is replaced w user
testRequires ( c , DaemonIsLinux , NotUserNamespace )
2015-07-19 20:47:47 +00:00
out , _ := dockerCmd ( c , "run" , "busybox" , "sh" , "-c" , "ls -l /dev/null" )
2014-02-17 23:14:30 +00:00
deviceLineFields := strings . Fields ( out )
deviceLineFields [ 6 ] = ""
deviceLineFields [ 7 ] = ""
deviceLineFields [ 8 ] = ""
expected := [ ] string { "crw-rw-rw-" , "1" , "root" , "root" , "1," , "3" , "" , "" , "" , "/dev/null" }
if ! ( reflect . DeepEqual ( deviceLineFields , expected ) ) {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "expected output\ncrw-rw-rw- 1 root root 1, 3 May 24 13:29 /dev/null\n received\n %s\n" , out )
2014-02-17 23:14:30 +00:00
}
}
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunThatCharacterDevicesActLikeCharacterDevices ( c * testing . T ) {
2015-09-01 21:37:04 +00:00
// Not applicable on Windows as /dev/ is a Unix specific concept
2015-08-28 17:36:42 +00:00
testRequires ( c , DaemonIsLinux )
2015-07-19 20:47:47 +00:00
out , _ := dockerCmd ( c , "run" , "busybox" , "sh" , "-c" , "dd if=/dev/zero of=/zero bs=1k count=5 2> /dev/null ; du -h /zero" )
2014-02-17 23:14:30 +00:00
if actual := strings . Trim ( out , "\r\n" ) ; actual [ 0 ] == '0' {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "expected a new file called /zero to be create that is greater than 0 bytes long, but du says: %s" , actual )
2014-02-17 23:14:30 +00:00
}
}
2014-06-03 01:23:47 +00:00
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunUnprivilegedWithChroot ( c * testing . T ) {
2015-09-01 21:37:04 +00:00
// Not applicable on Windows as it does not support chroot
2015-08-28 17:36:42 +00:00
testRequires ( c , DaemonIsLinux )
2015-07-19 20:47:47 +00:00
dockerCmd ( c , "run" , "busybox" , "chroot" , "/" , "true" )
2014-06-03 01:23:47 +00:00
}
2014-06-12 19:11:51 +00:00
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunAddingOptionalDevices ( c * testing . T ) {
2015-09-01 21:37:04 +00:00
// Not applicable on Windows as Windows does not support --device
2015-09-18 17:41:12 +00:00
testRequires ( c , DaemonIsLinux , NotUserNamespace )
2015-07-19 20:47:47 +00:00
out , _ := dockerCmd ( c , "run" , "--device" , "/dev/zero:/dev/nulo" , "busybox" , "sh" , "-c" , "ls /dev/nulo" )
2014-05-31 04:00:47 +00:00
if actual := strings . Trim ( out , "\r\n" ) ; actual != "/dev/nulo" {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "expected output /dev/nulo, received %s" , actual )
2014-05-31 04:00:47 +00:00
}
}
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunAddingOptionalDevicesNoSrc ( c * testing . T ) {
2015-09-01 21:37:04 +00:00
// Not applicable on Windows as Windows does not support --device
2015-09-18 17:41:12 +00:00
testRequires ( c , DaemonIsLinux , NotUserNamespace )
2015-08-24 09:57:12 +00:00
out , _ := dockerCmd ( c , "run" , "--device" , "/dev/zero:rw" , "busybox" , "sh" , "-c" , "ls /dev/zero" )
if actual := strings . Trim ( out , "\r\n" ) ; actual != "/dev/zero" {
c . Fatalf ( "expected output /dev/zero, received %s" , actual )
}
}
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunAddingOptionalDevicesInvalidMode ( c * testing . T ) {
2015-09-01 21:37:04 +00:00
// Not applicable on Windows as Windows does not support --device
2015-09-18 17:41:12 +00:00
testRequires ( c , DaemonIsLinux , NotUserNamespace )
2015-08-24 09:57:12 +00:00
_ , _ , err := dockerCmdWithError ( "run" , "--device" , "/dev/zero:ro" , "busybox" , "sh" , "-c" , "ls /dev/zero" )
if err == nil {
c . Fatalf ( "run container with device mode ro should fail" )
}
}
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunModeHostname ( c * testing . T ) {
2015-09-01 21:37:04 +00:00
// Not applicable on Windows as Windows does not support -h
2018-12-24 12:25:53 +00:00
testRequires ( c , testEnv . IsLocalDaemon , DaemonIsLinux , NotUserNamespace )
2014-06-12 19:11:51 +00:00
2015-07-19 20:47:47 +00:00
out , _ := dockerCmd ( c , "run" , "-h=testhostname" , "busybox" , "cat" , "/etc/hostname" )
2014-06-12 19:11:51 +00:00
if actual := strings . Trim ( out , "\r\n" ) ; actual != "testhostname" {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "expected 'testhostname', but says: %q" , actual )
2014-06-12 19:11:51 +00:00
}
2015-07-19 20:47:47 +00:00
out , _ = dockerCmd ( c , "run" , "--net=host" , "busybox" , "cat" , "/etc/hostname" )
2014-06-12 19:11:51 +00:00
hostname , err := os . Hostname ( )
if err != nil {
2015-04-18 16:46:47 +00:00
c . Fatal ( err )
2014-06-12 19:11:51 +00:00
}
if actual := strings . Trim ( out , "\r\n" ) ; actual != hostname {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "expected %q, but says: %q" , hostname , actual )
2014-06-12 19:11:51 +00:00
}
2014-06-24 16:53:53 +00:00
}
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunRootWorkdir ( c * testing . T ) {
2015-07-19 20:47:47 +00:00
out , _ := dockerCmd ( c , "run" , "--workdir" , "/" , "busybox" , "pwd" )
2015-09-01 21:37:04 +00:00
expected := "/\n"
2018-01-15 14:32:06 +00:00
if testEnv . OSType == "windows" {
2015-09-01 21:37:04 +00:00
expected = "C:" + expected
}
if out != expected {
c . Fatalf ( "pwd returned %q (expected %s)" , s , expected )
2014-06-24 16:53:53 +00:00
}
}
2014-06-26 17:50:18 +00:00
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunAllowBindMountingRoot ( c * testing . T ) {
2018-01-15 14:32:06 +00:00
if testEnv . OSType == "windows" {
2015-09-23 23:04:51 +00:00
// Windows busybox will fail with Permission Denied on items such as pagefile.sys
2018-01-15 14:31:02 +00:00
dockerCmd ( c , "run" , "-v" , ` c:\:c:\host ` , testEnv . PlatformDefaults . BaseImage , "cmd" , "-c" , "dir" , ` c:\host ` )
2015-09-23 23:04:51 +00:00
} else {
dockerCmd ( c , "run" , "-v" , "/:/host" , "busybox" , "ls" , "/host" )
}
2014-06-26 17:50:18 +00:00
}
2014-06-27 16:51:24 +00:00
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunDisallowBindMountingRootToRoot ( c * testing . T ) {
2015-09-23 23:04:51 +00:00
mount := "/:/"
targetDir := "/host"
2018-01-15 14:32:06 +00:00
if testEnv . OSType == "windows" {
2015-09-23 23:04:51 +00:00
mount = ` c:\:c\ `
targetDir = "c:/host" // Forward slash as using busybox
}
out , _ , err := dockerCmdWithError ( "run" , "-v" , mount , "busybox" , "ls" , targetDir )
2014-06-27 16:51:24 +00:00
if err == nil {
2015-04-18 16:46:47 +00:00
c . Fatal ( out , err )
2014-06-27 16:51:24 +00:00
}
}
2014-06-26 11:03:23 +00:00
2015-01-09 17:06:48 +00:00
// Verify that a container gets default DNS when only localhost resolvers exist
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunDNSDefaultOptions ( c * testing . T ) {
2015-09-01 21:37:04 +00:00
// Not applicable on Windows as this is testing Unix specific functionality
2018-12-24 12:25:53 +00:00
testRequires ( c , testEnv . IsLocalDaemon , DaemonIsLinux )
2015-01-09 17:06:48 +00:00
// preserve original resolv.conf for restoring after test
2014-10-08 00:58:39 +00:00
origResolvConf , err := ioutil . ReadFile ( "/etc/resolv.conf" )
if os . IsNotExist ( err ) {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "/etc/resolv.conf does not exist" )
2014-10-08 00:58:39 +00:00
}
2015-01-09 17:06:48 +00:00
// defer restored original conf
2014-10-08 00:58:39 +00:00
defer func ( ) {
if err := ioutil . WriteFile ( "/etc/resolv.conf" , origResolvConf , 0644 ) ; err != nil {
2015-04-18 16:46:47 +00:00
c . Fatal ( err )
2014-10-08 00:58:39 +00:00
}
} ( )
2015-01-09 17:06:48 +00:00
// test 3 cases: standard IPv4 localhost, commented out localhost, and IPv6 localhost
// 2 are removed from the file at container start, and the 3rd (commented out) one is ignored by
// GetNameservers(), leading to a replacement of nameservers with the default set
tmpResolvConf := [ ] byte ( "nameserver 127.0.0.1\n#nameserver 127.0.2.1\nnameserver ::1" )
if err := ioutil . WriteFile ( "/etc/resolv.conf" , tmpResolvConf , 0644 ) ; err != nil {
2015-04-18 16:46:47 +00:00
c . Fatal ( err )
2015-01-09 17:06:48 +00:00
}
2015-07-19 20:47:47 +00:00
actual , _ := dockerCmd ( c , "run" , "busybox" , "cat" , "/etc/resolv.conf" )
2015-01-09 17:06:48 +00:00
// check that the actual defaults are appended to the commented out
// localhost resolver (which should be preserved)
// NOTE: if we ever change the defaults from google dns, this will break
2015-09-02 23:43:28 +00:00
expected := "#nameserver 127.0.2.1\n\nnameserver 8.8.8.8\nnameserver 8.8.4.4\n"
2014-10-08 00:58:39 +00:00
if actual != expected {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "expected resolv.conf be: %q, but was: %q" , expected , actual )
2014-06-26 11:03:23 +00:00
}
}
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunDNSOptions ( c * testing . T ) {
2015-09-01 21:37:04 +00:00
// Not applicable on Windows as Windows does not support --dns*, or
// the Unix-specific functionality of resolv.conf.
2015-08-28 17:36:42 +00:00
testRequires ( c , DaemonIsLinux )
2017-03-27 15:12:48 +00:00
result := cli . DockerCmd ( c , "run" , "--dns=127.0.0.1" , "--dns-search=mydomain" , "--dns-opt=ndots:9" , "busybox" , "cat" , "/etc/resolv.conf" )
2014-06-26 11:03:23 +00:00
2015-03-10 14:22:29 +00:00
// The client will get a warning on stderr when setting DNS to a localhost address; verify this:
2017-03-27 15:12:48 +00:00
if ! strings . Contains ( result . Stderr ( ) , "Localhost DNS setting" ) {
c . Fatalf ( "Expected warning on stderr about localhost resolver, but got %q" , result . Stderr ( ) )
2015-03-10 14:22:29 +00:00
}
2017-03-27 15:12:48 +00:00
actual := strings . Replace ( strings . Trim ( result . Stdout ( ) , "\r\n" ) , "\n" , " " , - 1 )
2015-08-31 18:47:25 +00:00
if actual != "search mydomain nameserver 127.0.0.1 options ndots:9" {
c . Fatalf ( "expected 'search mydomain nameserver 127.0.0.1 options ndots:9', but says: %q" , actual )
2014-06-26 11:03:23 +00:00
}
2017-03-27 15:12:48 +00:00
out := cli . DockerCmd ( c , "run" , "--dns=1.1.1.1" , "--dns-search=." , "--dns-opt=ndots:3" , "busybox" , "cat" , "/etc/resolv.conf" ) . Combined ( )
2014-06-26 11:03:23 +00:00
actual = strings . Replace ( strings . Trim ( strings . Trim ( out , "\r\n" ) , " " ) , "\n" , " " , - 1 )
2017-01-18 02:08:31 +00:00
if actual != "nameserver 1.1.1.1 options ndots:3" {
c . Fatalf ( "expected 'nameserver 1.1.1.1 options ndots:3', but says: %q" , actual )
2015-08-31 18:47:25 +00:00
}
}
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunDNSRepeatOptions ( c * testing . T ) {
2015-08-31 18:47:25 +00:00
testRequires ( c , DaemonIsLinux )
2017-03-27 15:12:48 +00:00
out := cli . DockerCmd ( c , "run" , "--dns=1.1.1.1" , "--dns=2.2.2.2" , "--dns-search=mydomain" , "--dns-search=mydomain2" , "--dns-opt=ndots:9" , "--dns-opt=timeout:3" , "busybox" , "cat" , "/etc/resolv.conf" ) . Stdout ( )
2015-08-31 18:47:25 +00:00
actual := strings . Replace ( strings . Trim ( out , "\r\n" ) , "\n" , " " , - 1 )
if actual != "search mydomain mydomain2 nameserver 1.1.1.1 nameserver 2.2.2.2 options ndots:9 timeout:3" {
c . Fatalf ( "expected 'search mydomain mydomain2 nameserver 1.1.1.1 nameserver 2.2.2.2 options ndots:9 timeout:3', but says: %q" , actual )
2014-06-26 11:03:23 +00:00
}
}
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunDNSOptionsBasedOnHostResolvConf ( c * testing . T ) {
2015-09-01 21:37:04 +00:00
// Not applicable on Windows as testing Unix specific functionality
2018-12-24 12:25:53 +00:00
testRequires ( c , testEnv . IsLocalDaemon , DaemonIsLinux )
2014-10-07 22:35:32 +00:00
origResolvConf , err := ioutil . ReadFile ( "/etc/resolv.conf" )
2014-06-26 11:03:23 +00:00
if os . IsNotExist ( err ) {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "/etc/resolv.conf does not exist" )
2014-06-26 11:03:23 +00:00
}
2016-05-18 13:26:16 +00:00
hostNameservers := resolvconf . GetNameservers ( origResolvConf , types . IP )
2014-10-07 22:35:32 +00:00
hostSearch := resolvconf . GetSearchDomains ( origResolvConf )
2014-06-26 11:03:23 +00:00
2015-02-19 04:06:23 +00:00
var out string
2015-07-19 20:47:47 +00:00
out , _ = dockerCmd ( c , "run" , "--dns=127.0.0.1" , "busybox" , "cat" , "/etc/resolv.conf" )
2014-06-26 11:03:23 +00:00
2019-08-05 15:54:15 +00:00
if actualNameservers := resolvconf . GetNameservers ( [ ] byte ( out ) , types . IP ) ; actualNameservers [ 0 ] != "127.0.0.1" {
c . Fatalf ( "expected '127.0.0.1', but says: %q" , actualNameservers [ 0 ] )
2014-06-26 11:03:23 +00:00
}
actualSearch := resolvconf . GetSearchDomains ( [ ] byte ( out ) )
if len ( actualSearch ) != len ( hostSearch ) {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "expected %q search domain(s), but it has: %q" , len ( hostSearch ) , len ( actualSearch ) )
2014-06-26 11:03:23 +00:00
}
for i := range actualSearch {
if actualSearch [ i ] != hostSearch [ i ] {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "expected %q domain, but says: %q" , actualSearch [ i ] , hostSearch [ i ] )
2014-06-26 11:03:23 +00:00
}
}
2015-07-19 20:47:47 +00:00
out , _ = dockerCmd ( c , "run" , "--dns-search=mydomain" , "busybox" , "cat" , "/etc/resolv.conf" )
2014-06-26 11:03:23 +00:00
2016-05-08 07:33:16 +00:00
actualNameservers := resolvconf . GetNameservers ( [ ] byte ( out ) , types . IP )
2016-05-18 13:26:16 +00:00
if len ( actualNameservers ) != len ( hostNameservers ) {
c . Fatalf ( "expected %q nameserver(s), but it has: %q" , len ( hostNameservers ) , len ( actualNameservers ) )
2014-06-26 11:03:23 +00:00
}
for i := range actualNameservers {
2016-05-18 13:26:16 +00:00
if actualNameservers [ i ] != hostNameservers [ i ] {
c . Fatalf ( "expected %q nameserver, but says: %q" , actualNameservers [ i ] , hostNameservers [ i ] )
2014-06-26 11:03:23 +00:00
}
}
2019-08-05 15:54:15 +00:00
if actualSearch = resolvconf . GetSearchDomains ( [ ] byte ( out ) ) ; actualSearch [ 0 ] != "mydomain" {
c . Fatalf ( "expected 'mydomain', but says: %q" , actualSearch [ 0 ] )
2014-10-07 22:35:32 +00:00
}
// test with file
tmpResolvConf := [ ] byte ( "search example.com\nnameserver 12.34.56.78\nnameserver 127.0.0.1" )
if err := ioutil . WriteFile ( "/etc/resolv.conf" , tmpResolvConf , 0644 ) ; err != nil {
2015-04-18 16:46:47 +00:00
c . Fatal ( err )
2014-10-07 22:35:32 +00:00
}
// put the old resolvconf back
defer func ( ) {
if err := ioutil . WriteFile ( "/etc/resolv.conf" , origResolvConf , 0644 ) ; err != nil {
2015-04-18 16:46:47 +00:00
c . Fatal ( err )
2014-10-07 22:35:32 +00:00
}
} ( )
resolvConf , err := ioutil . ReadFile ( "/etc/resolv.conf" )
if os . IsNotExist ( err ) {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "/etc/resolv.conf does not exist" )
2014-10-07 22:35:32 +00:00
}
hostSearch = resolvconf . GetSearchDomains ( resolvConf )
2015-07-19 20:47:47 +00:00
out , _ = dockerCmd ( c , "run" , "busybox" , "cat" , "/etc/resolv.conf" )
2019-08-05 15:54:15 +00:00
if actualNameservers = resolvconf . GetNameservers ( [ ] byte ( out ) , types . IP ) ; actualNameservers [ 0 ] != "12.34.56.78" || len ( actualNameservers ) != 1 {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "expected '12.34.56.78', but has: %v" , actualNameservers )
2014-10-07 22:35:32 +00:00
}
actualSearch = resolvconf . GetSearchDomains ( [ ] byte ( out ) )
if len ( actualSearch ) != len ( hostSearch ) {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "expected %q search domain(s), but it has: %q" , len ( hostSearch ) , len ( actualSearch ) )
2014-10-07 22:35:32 +00:00
}
for i := range actualSearch {
if actualSearch [ i ] != hostSearch [ i ] {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "expected %q domain, but says: %q" , actualSearch [ i ] , hostSearch [ i ] )
2014-10-07 22:35:32 +00:00
}
2014-06-26 11:03:23 +00:00
}
}
2014-07-16 17:47:12 +00:00
2015-10-13 16:39:05 +00:00
// Test to see if a non-root user can resolve a DNS name. Also
2015-08-07 22:24:18 +00:00
// check if the container resolv.conf file has at least 0644 perm.
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunNonRootUserResolvName ( c * testing . T ) {
2015-09-01 21:37:04 +00:00
// Not applicable on Windows as Windows does not support --user
2018-12-24 12:25:53 +00:00
testRequires ( c , testEnv . IsLocalDaemon , Network , DaemonIsLinux , NotArm )
2015-05-20 06:06:44 +00:00
2015-10-13 16:39:05 +00:00
dockerCmd ( c , "run" , "--name=testperm" , "--user=nobody" , "busybox" , "nslookup" , "apt.dockerproject.org" )
2015-05-20 06:06:44 +00:00
2017-01-16 10:30:14 +00:00
cID := getIDByName ( c , "testperm" )
2015-05-20 06:06:44 +00:00
fmode := ( os . FileMode ) ( 0644 )
finfo , err := os . Stat ( containerStorageFile ( cID , "resolv.conf" ) )
if err != nil {
c . Fatal ( err )
}
if ( finfo . Mode ( ) & fmode ) != fmode {
2015-08-07 22:24:18 +00:00
c . Fatalf ( "Expected container resolv.conf mode to be at least %s, instead got %s" , fmode . String ( ) , finfo . Mode ( ) . String ( ) )
2015-05-20 06:06:44 +00:00
}
}
2015-05-06 22:39:29 +00:00
// Test if container resolv.conf gets updated the next time it restarts
// if host /etc/resolv.conf has changed. This only applies if the container
// uses the host's /etc/resolv.conf and does not have any dns options provided.
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunResolvconfUpdate ( c * testing . T ) {
2015-09-01 21:37:04 +00:00
// Not applicable on Windows as testing unix specific functionality
2018-12-24 12:25:53 +00:00
testRequires ( c , testEnv . IsLocalDaemon , DaemonIsLinux )
2016-06-14 04:27:26 +00:00
c . Skip ( "Unstable test, to be re-activated once #19937 is resolved" )
2014-12-10 05:55:09 +00:00
2015-09-02 23:43:28 +00:00
tmpResolvConf := [ ] byte ( "search pommesfrites.fr\nnameserver 12.34.56.78\n" )
2014-12-10 05:55:09 +00:00
tmpLocalhostResolvConf := [ ] byte ( "nameserver 127.0.0.1" )
2019-11-27 14:36:45 +00:00
// take a copy of resolv.conf for restoring after test completes
2014-12-10 05:55:09 +00:00
resolvConfSystem , err := ioutil . ReadFile ( "/etc/resolv.conf" )
if err != nil {
2015-04-18 16:46:47 +00:00
c . Fatal ( err )
2014-12-10 05:55:09 +00:00
}
2015-02-11 20:01:30 +00:00
// This test case is meant to test monitoring resolv.conf when it is
2015-04-18 16:46:47 +00:00
// a regular file not a bind mounc. So we unmount resolv.conf and replace
2015-02-11 20:01:30 +00:00
// it with a file containing the original settings.
2016-06-21 08:38:45 +00:00
mounted , err := mount . Mounted ( "/etc/resolv.conf" )
if err != nil {
2015-04-18 16:46:47 +00:00
c . Fatal ( err )
2015-02-11 20:01:30 +00:00
}
2016-06-21 08:38:45 +00:00
if mounted {
2016-12-13 20:21:51 +00:00
icmd . RunCommand ( "umount" , "/etc/resolv.conf" ) . Assert ( c , icmd . Success )
2016-06-21 08:38:45 +00:00
}
2015-02-11 20:01:30 +00:00
2019-11-27 14:36:45 +00:00
// cleanup
2014-12-10 05:55:09 +00:00
defer func ( ) {
if err := ioutil . WriteFile ( "/etc/resolv.conf" , resolvConfSystem , 0644 ) ; err != nil {
2015-04-18 16:46:47 +00:00
c . Fatal ( err )
2014-12-10 05:55:09 +00:00
}
} ( )
2019-11-27 14:36:45 +00:00
// 1. test that a restarting container gets an updated resolv.conf
2016-06-01 05:19:13 +00:00
dockerCmd ( c , "run" , "--name=first" , "busybox" , "true" )
2017-01-16 10:30:14 +00:00
containerID1 := getIDByName ( c , "first" )
2014-12-10 05:55:09 +00:00
// replace resolv.conf with our temporary copy
2019-08-05 15:54:15 +00:00
if err := ioutil . WriteFile ( "/etc/resolv.conf" , tmpResolvConf , 0644 ) ; err != nil {
2015-04-18 16:46:47 +00:00
c . Fatal ( err )
2014-12-10 05:55:09 +00:00
}
2015-05-06 22:39:29 +00:00
// start the container again to pickup changes
2015-07-19 20:47:47 +00:00
dockerCmd ( c , "start" , "first" )
2015-05-06 22:39:29 +00:00
2014-12-10 05:55:09 +00:00
// check for update in container
2017-01-16 15:39:12 +00:00
containerResolv := readContainerFile ( c , containerID1 , "resolv.conf" )
2019-08-05 15:54:15 +00:00
if ! bytes . Equal ( containerResolv , tmpResolvConf ) {
2015-05-06 22:39:29 +00:00
c . Fatalf ( "Restarted container does not have updated resolv.conf; expected %q, got %q" , tmpResolvConf , string ( containerResolv ) )
2014-12-10 05:55:09 +00:00
}
2019-11-27 14:36:45 +00:00
/ * // make a change to resolv.conf (in this case replacing our tmp copy with orig copy)
2015-06-24 17:23:00 +00:00
if err := ioutil . WriteFile ( "/etc/resolv.conf" , resolvConfSystem , 0644 ) ; err != nil {
2015-07-19 20:47:47 +00:00
c . Fatal ( err )
} * /
2019-11-27 14:36:45 +00:00
// 2. test that a restarting container does not receive resolv.conf updates
2014-12-10 05:55:09 +00:00
// if it modified the container copy of the starting point resolv.conf
2016-06-01 05:19:13 +00:00
dockerCmd ( c , "run" , "--name=second" , "busybox" , "sh" , "-c" , "echo 'search mylittlepony.com' >>/etc/resolv.conf" )
2017-01-16 10:30:14 +00:00
containerID2 := getIDByName ( c , "second" )
2014-12-10 05:55:09 +00:00
2019-11-27 14:36:45 +00:00
// make a change to resolv.conf (in this case replacing our tmp copy with orig copy)
2014-12-10 05:55:09 +00:00
if err := ioutil . WriteFile ( "/etc/resolv.conf" , resolvConfSystem , 0644 ) ; err != nil {
2015-04-18 16:46:47 +00:00
c . Fatal ( err )
2014-12-10 05:55:09 +00:00
}
2015-05-06 22:39:29 +00:00
// start the container again
2015-07-19 20:47:47 +00:00
dockerCmd ( c , "start" , "second" )
2015-05-06 22:39:29 +00:00
// check for update in container
2017-01-16 15:39:12 +00:00
containerResolv = readContainerFile ( c , containerID2 , "resolv.conf" )
2015-05-06 22:39:29 +00:00
if bytes . Equal ( containerResolv , resolvConfSystem ) {
2015-11-20 04:44:42 +00:00
c . Fatalf ( "Container's resolv.conf should not have been updated with host resolv.conf: %q" , string ( containerResolv ) )
2014-12-10 05:55:09 +00:00
}
2019-11-27 14:36:45 +00:00
// 3. test that a running container's resolv.conf is not modified while running
2015-07-19 20:47:47 +00:00
out , _ := dockerCmd ( c , "run" , "-d" , "busybox" , "top" )
2014-12-10 05:55:09 +00:00
runningContainerID := strings . TrimSpace ( out )
// replace resolv.conf
2019-08-05 15:54:15 +00:00
if err := ioutil . WriteFile ( "/etc/resolv.conf" , tmpResolvConf , 0644 ) ; err != nil {
2015-04-18 16:46:47 +00:00
c . Fatal ( err )
2014-12-10 05:55:09 +00:00
}
2015-05-06 22:39:29 +00:00
// check for update in container
2017-01-16 15:39:12 +00:00
containerResolv = readContainerFile ( c , runningContainerID , "resolv.conf" )
2019-08-05 15:54:15 +00:00
if bytes . Equal ( containerResolv , tmpResolvConf ) {
2015-05-06 22:39:29 +00:00
c . Fatalf ( "Running container should not have updated resolv.conf; expected %q, got %q" , string ( resolvConfSystem ) , string ( containerResolv ) )
2014-12-10 05:55:09 +00:00
}
2019-11-27 14:36:45 +00:00
// 4. test that a running container's resolv.conf is updated upon restart
2014-12-10 05:55:09 +00:00
// (the above container is still running..)
2015-07-19 20:47:47 +00:00
dockerCmd ( c , "restart" , runningContainerID )
2014-12-10 05:55:09 +00:00
// check for update in container
2017-01-16 15:39:12 +00:00
containerResolv = readContainerFile ( c , runningContainerID , "resolv.conf" )
2019-08-05 15:54:15 +00:00
if ! bytes . Equal ( containerResolv , tmpResolvConf ) {
c . Fatalf ( "Restarted container should have updated resolv.conf; expected %q, got %q" , string ( tmpResolvConf ) , string ( containerResolv ) )
2014-12-10 05:55:09 +00:00
}
2019-11-27 14:36:45 +00:00
// 5. test that additions of a localhost resolver are cleaned from
2014-12-10 05:55:09 +00:00
// host resolv.conf before updating container's resolv.conf copies
// replace resolv.conf with a localhost-only nameserver copy
2019-08-05 15:54:15 +00:00
if err = ioutil . WriteFile ( "/etc/resolv.conf" , tmpLocalhostResolvConf , 0644 ) ; err != nil {
2015-04-18 16:46:47 +00:00
c . Fatal ( err )
2014-12-10 05:55:09 +00:00
}
2015-05-06 22:39:29 +00:00
// start the container again to pickup changes
2015-07-19 20:47:47 +00:00
dockerCmd ( c , "start" , "first" )
2015-05-06 22:39:29 +00:00
2014-12-10 05:55:09 +00:00
// our first exited container ID should have been updated, but with default DNS
// after the cleanup of resolv.conf found only a localhost nameserver:
2017-01-16 15:39:12 +00:00
containerResolv = readContainerFile ( c , containerID1 , "resolv.conf" )
2015-09-02 23:43:28 +00:00
expected := "\nnameserver 8.8.8.8\nnameserver 8.8.4.4\n"
2014-12-10 05:55:09 +00:00
if ! bytes . Equal ( containerResolv , [ ] byte ( expected ) ) {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "Container does not have cleaned/replaced DNS in resolv.conf; expected %q, got %q" , expected , string ( containerResolv ) )
2014-12-10 05:55:09 +00:00
}
2019-11-27 14:36:45 +00:00
// 6. Test that replacing (as opposed to modifying) resolv.conf triggers an update
2015-02-11 20:01:30 +00:00
// of containers' resolv.conf.
// Restore the original resolv.conf
if err := ioutil . WriteFile ( "/etc/resolv.conf" , resolvConfSystem , 0644 ) ; err != nil {
2015-04-18 16:46:47 +00:00
c . Fatal ( err )
2015-02-11 20:01:30 +00:00
}
// Run the container so it picks up the old settings
2016-06-01 05:19:13 +00:00
dockerCmd ( c , "run" , "--name=third" , "busybox" , "true" )
2017-01-16 10:30:14 +00:00
containerID3 := getIDByName ( c , "third" )
2015-02-11 20:01:30 +00:00
// Create a modified resolv.conf.aside and override resolv.conf with it
2019-08-05 15:54:15 +00:00
if err := ioutil . WriteFile ( "/etc/resolv.conf.aside" , tmpResolvConf , 0644 ) ; err != nil {
2015-04-18 16:46:47 +00:00
c . Fatal ( err )
2015-02-11 20:01:30 +00:00
}
err = os . Rename ( "/etc/resolv.conf.aside" , "/etc/resolv.conf" )
if err != nil {
2015-04-18 16:46:47 +00:00
c . Fatal ( err )
2015-02-11 20:01:30 +00:00
}
2015-05-06 22:39:29 +00:00
// start the container again to pickup changes
2015-07-19 20:47:47 +00:00
dockerCmd ( c , "start" , "third" )
2015-05-06 22:39:29 +00:00
2015-02-11 20:01:30 +00:00
// check for update in container
2017-01-16 15:39:12 +00:00
containerResolv = readContainerFile ( c , containerID3 , "resolv.conf" )
2019-08-05 15:54:15 +00:00
if ! bytes . Equal ( containerResolv , tmpResolvConf ) {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "Stopped container does not have updated resolv.conf; expected\n%q\n got\n%q" , tmpResolvConf , string ( containerResolv ) )
2015-02-11 20:01:30 +00:00
}
2019-11-27 14:36:45 +00:00
// cleanup, restore original resolv.conf happens in defer func()
2014-12-10 05:55:09 +00:00
}
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunAddHost ( c * testing . T ) {
2015-09-01 21:37:04 +00:00
// Not applicable on Windows as it does not support --add-host
2015-08-28 17:36:42 +00:00
testRequires ( c , DaemonIsLinux )
2015-07-19 20:47:47 +00:00
out , _ := dockerCmd ( c , "run" , "--add-host=extra:86.75.30.9" , "busybox" , "grep" , "extra" , "/etc/hosts" )
2014-09-13 04:35:59 +00:00
actual := strings . Trim ( out , "\r\n" )
if actual != "86.75.30.9\textra" {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "expected '86.75.30.9\textra', but says: %q" , actual )
2014-09-13 04:35:59 +00:00
}
}
2014-07-16 17:47:12 +00:00
// Regression test for #6983
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunAttachStdErrOnlyTTYMode ( c * testing . T ) {
2015-07-19 20:47:47 +00:00
_ , exitCode := dockerCmd ( c , "run" , "-t" , "-a" , "stderr" , "busybox" , "true" )
if exitCode != 0 {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "Container should have exited with error code 0" )
2014-07-16 17:47:12 +00:00
}
}
// Regression test for #6983
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunAttachStdOutOnlyTTYMode ( c * testing . T ) {
2015-07-19 20:47:47 +00:00
_ , exitCode := dockerCmd ( c , "run" , "-t" , "-a" , "stdout" , "busybox" , "true" )
if exitCode != 0 {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "Container should have exited with error code 0" )
2014-07-16 17:47:12 +00:00
}
}
// Regression test for #6983
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunAttachStdOutAndErrTTYMode ( c * testing . T ) {
2015-07-19 20:47:47 +00:00
_ , exitCode := dockerCmd ( c , "run" , "-t" , "-a" , "stdout" , "-a" , "stderr" , "busybox" , "true" )
if exitCode != 0 {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "Container should have exited with error code 0" )
2014-07-16 17:47:12 +00:00
}
}
2014-07-17 06:15:23 +00:00
2015-01-28 21:03:21 +00:00
// Test for #10388 - this will run the same test as TestRunAttachStdOutAndErrTTYMode
// but using --attach instead of -a to make sure we read the flag correctly
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunAttachWithDetach ( c * testing . T ) {
2016-12-13 20:21:51 +00:00
icmd . RunCommand ( dockerBinary , "run" , "-d" , "--attach" , "stdout" , "busybox" , "true" ) . Assert ( c , icmd . Expected {
ExitCode : 1 ,
Error : "exit status 1" ,
Err : "Conflicting options: -a and -d" ,
} )
2015-01-28 21:03:21 +00:00
}
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunState ( c * testing . T ) {
2015-09-01 21:37:04 +00:00
// TODO Windows: This needs some rework as Windows busybox does not support top
2015-08-28 17:36:42 +00:00
testRequires ( c , DaemonIsLinux )
2015-07-19 20:47:47 +00:00
out , _ := dockerCmd ( c , "run" , "-d" , "busybox" , "top" )
2014-07-17 06:15:23 +00:00
id := strings . TrimSpace ( out )
2016-01-28 14:19:25 +00:00
state := inspectField ( c , id , "State.Running" )
2014-07-17 06:15:23 +00:00
if state != "true" {
2015-04-18 16:46:47 +00:00
c . Fatal ( "Container state is 'not running'" )
2014-07-17 06:15:23 +00:00
}
2016-01-28 14:19:25 +00:00
pid1 := inspectField ( c , id , "State.Pid" )
2014-07-17 06:15:23 +00:00
if pid1 == "0" {
2015-04-18 16:46:47 +00:00
c . Fatal ( "Container state Pid 0" )
2014-07-17 06:15:23 +00:00
}
2015-07-19 20:47:47 +00:00
dockerCmd ( c , "stop" , id )
2016-01-28 14:19:25 +00:00
state = inspectField ( c , id , "State.Running" )
2014-07-17 06:15:23 +00:00
if state != "false" {
2015-04-18 16:46:47 +00:00
c . Fatal ( "Container state is 'running'" )
2014-07-17 06:15:23 +00:00
}
2016-01-28 14:19:25 +00:00
pid2 := inspectField ( c , id , "State.Pid" )
2014-07-17 06:15:23 +00:00
if pid2 == pid1 {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "Container state Pid %s, but expected %s" , pid2 , pid1 )
2014-07-17 06:15:23 +00:00
}
2015-07-19 20:47:47 +00:00
dockerCmd ( c , "start" , id )
2016-01-28 14:19:25 +00:00
state = inspectField ( c , id , "State.Running" )
2014-07-17 06:15:23 +00:00
if state != "true" {
2015-04-18 16:46:47 +00:00
c . Fatal ( "Container state is 'not running'" )
2014-07-17 06:15:23 +00:00
}
2016-01-28 14:19:25 +00:00
pid3 := inspectField ( c , id , "State.Pid" )
2014-07-17 06:15:23 +00:00
if pid3 == pid1 {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "Container state Pid %s, but expected %s" , pid2 , pid1 )
2014-07-17 06:15:23 +00:00
}
}
2014-07-16 19:40:04 +00:00
// Test for #1737
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunCopyVolumeUIDGID ( c * testing . T ) {
2015-09-23 23:04:51 +00:00
// Not applicable on Windows as it does not support uid or gid in this way
2015-08-28 17:36:42 +00:00
testRequires ( c , DaemonIsLinux )
2014-07-16 19:40:04 +00:00
name := "testrunvolumesuidgid"
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , name , build . WithDockerfile ( ` FROM busybox
2014-07-16 19:40:04 +00:00
RUN echo ' dockerio : x : 1001 : 1001 : : / bin : / bin / false ' >> / etc / passwd
RUN echo ' dockerio : x : 1001 : ' >> / etc / group
2017-01-16 10:30:14 +00:00
RUN mkdir - p / hello && touch / hello / test && chown dockerio . dockerio / hello ` ) )
2014-07-16 19:40:04 +00:00
// Test that the uid and gid is copied from the image to the volume
2015-07-19 20:47:47 +00:00
out , _ := dockerCmd ( c , "run" , "--rm" , "-v" , "/hello" , name , "sh" , "-c" , "ls -l / | grep hello | awk '{print $3\":\"$4}'" )
2014-07-16 19:40:04 +00:00
out = strings . TrimSpace ( out )
if out != "dockerio:dockerio" {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "Wrong /hello ownership: %s, expected dockerio:dockerio" , out )
2014-07-16 19:40:04 +00:00
}
}
2014-07-17 17:36:45 +00:00
// Test for #1582
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunCopyVolumeContent ( c * testing . T ) {
2016-11-23 22:28:06 +00:00
// TODO Windows, post RS1. Windows does not yet support volume functionality
2015-09-23 23:04:51 +00:00
// that copies from the image to the volume.
2015-08-28 17:36:42 +00:00
testRequires ( c , DaemonIsLinux )
2014-07-17 17:36:45 +00:00
name := "testruncopyvolumecontent"
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , name , build . WithDockerfile ( ` FROM busybox
2017-01-16 10:30:14 +00:00
RUN mkdir - p / hello / local && echo hello > / hello / local / world ` ) )
2014-07-17 17:36:45 +00:00
// Test that the content is copied from the image to the volume
2015-07-19 20:47:47 +00:00
out , _ := dockerCmd ( c , "run" , "--rm" , "-v" , "/hello" , name , "find" , "/hello" )
2014-07-17 17:36:45 +00:00
if ! ( strings . Contains ( out , "/hello/local/world" ) && strings . Contains ( out , "/hello/local" ) ) {
2015-04-18 16:46:47 +00:00
c . Fatal ( "Container failed to transfer content to volume" )
2014-07-17 17:36:45 +00:00
}
}
2014-07-10 05:46:11 +00:00
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunCleanupCmdOnEntrypoint ( c * testing . T ) {
2014-07-10 05:46:11 +00:00
name := "testrunmdcleanuponentrypoint"
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , name , build . WithDockerfile ( ` FROM busybox
2014-07-10 05:46:11 +00:00
ENTRYPOINT [ "echo" ]
2017-01-16 10:30:14 +00:00
CMD [ "testingpoint" ] ` ) )
2015-07-19 20:47:47 +00:00
out , exit := dockerCmd ( c , "run" , "--entrypoint" , "whoami" , name )
2014-07-10 05:46:11 +00:00
if exit != 0 {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "expected exit code 0 received %d, out: %q" , exit , out )
2014-07-10 05:46:11 +00:00
}
out = strings . TrimSpace ( out )
2015-09-01 21:37:04 +00:00
expected := "root"
2018-01-15 14:32:06 +00:00
if testEnv . OSType == "windows" {
2019-08-14 21:26:34 +00:00
if strings . Contains ( testEnv . PlatformDefaults . BaseImage , "servercore" ) {
2016-07-22 16:05:38 +00:00
expected = ` user manager\containeradministrator `
} else {
expected = ` ContainerAdministrator ` // nanoserver
}
2015-09-01 21:37:04 +00:00
}
if out != expected {
2018-01-15 14:31:02 +00:00
c . Fatalf ( "Expected output %s, got %q. %s" , expected , out , testEnv . PlatformDefaults . BaseImage )
2014-07-10 05:46:11 +00:00
}
}
2014-08-12 07:48:36 +00:00
// TestRunWorkdirExistsAndIsFile checks that if 'docker run -w' with existing file can be detected
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunWorkdirExistsAndIsFile ( c * testing . T ) {
2015-09-01 21:37:04 +00:00
existingFile := "/bin/cat"
2016-03-08 15:40:30 +00:00
expected := "not a directory"
2018-01-15 14:32:06 +00:00
if testEnv . OSType == "windows" {
2015-09-01 21:37:04 +00:00
existingFile = ` \windows\system32\ntdll.dll `
Windows: Unify workdir handling
Signed-off-by: John Howard <jhoward@microsoft.com>
Working directory processing was handled differently for Hyper-V and Windows-Server containers, as annotated in the builder documentation (updated in this PR). For Hyper-V containers, the working directory set by WORKDIR was not created. This PR makes Hyper-V containers work the same as Windows Server containers (and the same as Linux).
Example (only applies to Hyper-V containers, so not reproducible under CI environment)
Dockerfile:
FROM microsoft/nanoserver
WORKDIR c:\installer
ENV GOROOT=c:\installer
ADD go.exe .
RUN go --help
Running on Windows Server 2016, using docker master without this change, but with daemon set to --exec-opt isolation=hyperv as it would be for Client operating systems.
PS E:\go\src\github.com\docker\docker> dockerd -g c:\control --exec-opt isolation=hyperv
time="2017-02-01T15:48:09.657286100-08:00" level=info msg="Windows default isolation mode: hyperv"
time="2017-02-01T15:48:09.662720900-08:00" level=info msg="[graphdriver] using prior storage driver: windowsfilter"
time="2017-02-01T15:48:10.011588000-08:00" level=info msg="Graph migration to content-addressability took 0.00 seconds"
time="2017-02-01T15:48:10.016655800-08:00" level=info msg="Loading containers: start."
time="2017-02-01T15:48:10.460820000-08:00" level=info msg="Loading containers: done."
time="2017-02-01T15:48:10.509859600-08:00" level=info msg="Daemon has completed initialization"
time="2017-02-01T15:48:10.509859600-08:00" level=info msg="Docker daemon" commit=3c64061 graphdriver=windowsfilter version=1.14.0-dev
First with no explicit isolation:
PS E:\docker\build\unifyworkdir> docker build --no-cache .
Sending build context to Docker daemon 10.1 MB
Step 1/5 : FROM microsoft/nanoserver
---> 89b8556cb9ca
Step 2/5 : WORKDIR c:\installer
---> 7e0f41d08204
Removing intermediate container 236c7802042a
Step 3/5 : ENV GOROOT c:\installer
---> Running in 8ea5237183c1
---> 394b70435261
Removing intermediate container 8ea5237183c1
Step 4/5 : ADD go.exe .
---> e47401a1745c
Removing intermediate container 88dcc28e74b1
Step 5/5 : RUN go --help
---> Running in efe90e1b6b8b
container efe90e1b6b8b76586abc5c1dc0e2797b75adc26517c48733d90651e767c8463b encountered an error during CreateProcess: failure in a Windows system call: The directory name is invalid. (0x10b) extra info: {"ApplicationName":"","CommandLine":"cmd /S /C go --help","User":"","WorkingDirectory":"C:\\installer","Environment":{"GOROOT":"c:\\installer"},"EmulateConsole":false,"CreateStdInPipe":true,"CreateStdOutPipe":true,"CreateStdErrPipe":true,"ConsoleSize":[0,0]}
PS E:\docker\build\unifyworkdir>
Then forcing process isolation:
PS E:\docker\build\unifyworkdir> docker build --isolation=process --no-cache .
Sending build context to Docker daemon 10.1 MB
Step 1/5 : FROM microsoft/nanoserver
---> 89b8556cb9ca
Step 2/5 : WORKDIR c:\installer
---> 350c955980c8
Removing intermediate container 8339c1e9250c
Step 3/5 : ENV GOROOT c:\installer
---> Running in bde511c5e3e0
---> b8820063b5b6
Removing intermediate container bde511c5e3e0
Step 4/5 : ADD go.exe .
---> e4ac32f8902b
Removing intermediate container d586e8492eda
Step 5/5 : RUN go --help
---> Running in 9e1aa235af5f
Cannot mkdir: C:\installer is not a directory
PS E:\docker\build\unifyworkdir>
Now compare the same results after this PR. Again, first with no explicit isolation (defaulting to Hyper-V containers as that's what the daemon it set to) - note it now succeeds 😄
PS E:\docker\build\unifyworkdir> docker build --no-cache .
Sending build context to Docker daemon 10.1 MB
Step 1/5 : FROM microsoft/nanoserver
---> 89b8556cb9ca
Step 2/5 : WORKDIR c:\installer
---> 4f319f301c69
Removing intermediate container 61b9c0b1ff6f
Step 3/5 : ENV GOROOT c:\installer
---> Running in c464a1d612d8
---> 96a26ab9a7b5
Removing intermediate container c464a1d612d8
Step 4/5 : ADD go.exe .
---> 0290d61faf57
Removing intermediate container dc5a085fffe3
Step 5/5 : RUN go --help
---> Running in 60bd56042ff8
Go is a tool for managing Go source code.
Usage:
go command [arguments]
The commands are:
build compile packages and dependencies
clean remove object files
doc show documentation for package or symbol
env print Go environment information
fix run go tool fix on packages
fmt run gofmt on package sources
generate generate Go files by processing source
get download and install packages and dependencies
install compile and install packages and dependencies
list list packages
run compile and run Go program
test test packages
tool run specified go tool
version print Go version
vet run go tool vet on packages
Use "go help [command]" for more information about a command.
Additional help topics:
c calling between Go and C
buildmode description of build modes
filetype file types
gopath GOPATH environment variable
environment environment variables
importpath import path syntax
packages description of package lists
testflag description of testing flags
testfunc description of testing functions
Use "go help [topic]" for more information about that topic.
The command 'cmd /S /C go --help' returned a non-zero code: 2
And the same with forcing process isolation. Also works 😄
PS E:\docker\build\unifyworkdir> docker build --isolation=process --no-cache .
Sending build context to Docker daemon 10.1 MB
Step 1/5 : FROM microsoft/nanoserver
---> 89b8556cb9ca
Step 2/5 : WORKDIR c:\installer
---> f423b9cc3e78
Removing intermediate container 41330c88893d
Step 3/5 : ENV GOROOT c:\installer
---> Running in 0b99a2d7bf19
---> e051144bf8ec
Removing intermediate container 0b99a2d7bf19
Step 4/5 : ADD go.exe .
---> 7072e32b7c37
Removing intermediate container a7a97aa37fd1
Step 5/5 : RUN go --help
---> Running in 7097438a54e5
Go is a tool for managing Go source code.
Usage:
go command [arguments]
The commands are:
build compile packages and dependencies
clean remove object files
doc show documentation for package or symbol
env print Go environment information
fix run go tool fix on packages
fmt run gofmt on package sources
generate generate Go files by processing source
get download and install packages and dependencies
install compile and install packages and dependencies
list list packages
run compile and run Go program
test test packages
tool run specified go tool
version print Go version
vet run go tool vet on packages
Use "go help [command]" for more information about a command.
Additional help topics:
c calling between Go and C
buildmode description of build modes
filetype file types
gopath GOPATH environment variable
environment environment variables
importpath import path syntax
packages description of package lists
testflag description of testing flags
testfunc description of testing functions
Use "go help [topic]" for more information about that topic.
The command 'cmd /S /C go --help' returned a non-zero code: 2
PS E:\docker\build\unifyworkdir>
2017-02-01 22:56:19 +00:00
expected = ` The directory name is invalid. `
2015-09-01 21:37:04 +00:00
}
2015-07-29 12:21:16 +00:00
out , exitCode , err := dockerCmdWithError ( "run" , "-w" , existingFile , "busybox" )
if ! ( err != nil && exitCode == 125 && strings . Contains ( out , expected ) ) {
2016-03-08 15:40:30 +00:00
c . Fatalf ( "Existing binary as a directory should error out with exitCode 125; we got: %s, exitCode: %d" , out , exitCode )
2014-08-12 07:48:36 +00:00
}
}
2014-08-12 09:36:49 +00:00
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunExitOnStdinClose ( c * testing . T ) {
2014-08-12 09:36:49 +00:00
name := "testrunexitonstdinclose"
2015-09-01 21:37:04 +00:00
meow := "/bin/cat"
2016-04-14 19:16:43 +00:00
delay := 60
2018-01-15 14:32:06 +00:00
if testEnv . OSType == "windows" {
2015-09-01 21:37:04 +00:00
meow = "cat"
}
runCmd := exec . Command ( dockerBinary , "run" , "--name" , name , "-i" , "busybox" , meow )
2014-08-12 09:36:49 +00:00
stdin , err := runCmd . StdinPipe ( )
if err != nil {
2015-04-18 16:46:47 +00:00
c . Fatal ( err )
2014-08-12 09:36:49 +00:00
}
stdout , err := runCmd . StdoutPipe ( )
if err != nil {
2015-04-18 16:46:47 +00:00
c . Fatal ( err )
2014-08-12 09:36:49 +00:00
}
if err := runCmd . Start ( ) ; err != nil {
2015-04-18 16:46:47 +00:00
c . Fatal ( err )
2014-08-12 09:36:49 +00:00
}
if _ , err := stdin . Write ( [ ] byte ( "hello\n" ) ) ; err != nil {
2015-04-18 16:46:47 +00:00
c . Fatal ( err )
2014-08-12 09:36:49 +00:00
}
r := bufio . NewReader ( stdout )
line , err := r . ReadString ( '\n' )
if err != nil {
2015-04-18 16:46:47 +00:00
c . Fatal ( err )
2014-08-12 09:36:49 +00:00
}
line = strings . TrimSpace ( line )
if line != "hello" {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "Output should be 'hello', got '%q'" , line )
2014-08-12 09:36:49 +00:00
}
if err := stdin . Close ( ) ; err != nil {
2015-04-18 16:46:47 +00:00
c . Fatal ( err )
2014-08-12 09:36:49 +00:00
}
2015-04-27 17:29:48 +00:00
finish := make ( chan error )
2014-08-12 09:36:49 +00:00
go func ( ) {
2015-04-27 17:29:48 +00:00
finish <- runCmd . Wait ( )
2014-08-12 09:36:49 +00:00
close ( finish )
} ( )
select {
2015-04-27 17:29:48 +00:00
case err := <- finish :
2019-04-04 13:23:19 +00:00
assert . NilError ( c , err )
2015-09-01 21:37:04 +00:00
case <- time . After ( time . Duration ( delay ) * time . Second ) :
2015-04-18 16:46:47 +00:00
c . Fatal ( "docker run failed to exit on stdin close" )
2014-08-12 09:36:49 +00:00
}
2016-01-28 14:19:25 +00:00
state := inspectField ( c , name , "State.Running" )
2015-04-27 17:29:48 +00:00
2014-08-12 09:36:49 +00:00
if state != "false" {
2015-04-18 16:46:47 +00:00
c . Fatal ( "Container must be stopped after stdin closing" )
2014-08-12 09:36:49 +00:00
}
}
2014-07-22 18:16:15 +00:00
2016-05-17 02:30:06 +00:00
// Test run -i --restart xxx doesn't hang
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunInteractiveWithRestartPolicy ( c * testing . T ) {
2016-05-17 02:30:06 +00:00
name := "test-inter-restart"
2019-09-02 23:12:58 +00:00
result := icmd . RunCmd ( icmd . Cmd {
2016-08-04 16:57:34 +00:00
Command : [ ] string { dockerBinary , "run" , "-i" , "--name" , name , "--restart=always" , "busybox" , "sh" } ,
Stdin : bytes . NewBufferString ( "exit 11" ) ,
} )
defer func ( ) {
2019-09-02 23:12:58 +00:00
cli . Docker ( cli . Args ( "stop" , name ) ) . Assert ( c , icmd . Success )
2016-05-17 02:30:06 +00:00
} ( )
2017-08-23 21:01:29 +00:00
result . Assert ( c , icmd . Expected { ExitCode : 11 } )
2016-05-17 02:30:06 +00:00
}
2014-07-22 18:16:15 +00:00
// Test for #2267
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunWriteSpecialFilesAndNotCommit ( c * testing . T ) {
2017-01-02 22:42:45 +00:00
// Cannot run on Windows as this files are not present in Windows
2015-08-28 17:36:42 +00:00
testRequires ( c , DaemonIsLinux )
2017-01-02 22:42:45 +00:00
testRunWriteSpecialFilesAndNotCommit ( c , "writehosts" , "/etc/hosts" )
testRunWriteSpecialFilesAndNotCommit ( c , "writehostname" , "/etc/hostname" )
testRunWriteSpecialFilesAndNotCommit ( c , "writeresolv" , "/etc/resolv.conf" )
}
2019-09-09 21:05:55 +00:00
func testRunWriteSpecialFilesAndNotCommit ( c * testing . T , name , path string ) {
2017-01-02 22:42:45 +00:00
command := fmt . Sprintf ( "echo test2267 >> %s && cat %s" , path , path )
out , _ := dockerCmd ( c , "run" , "--name" , name , "busybox" , "sh" , "-c" , command )
2014-07-22 18:16:15 +00:00
if ! strings . Contains ( out , "test2267" ) {
2017-01-02 22:42:45 +00:00
c . Fatalf ( "%s should contain 'test2267'" , path )
2014-07-22 18:16:15 +00:00
}
2015-07-19 20:47:47 +00:00
out , _ = dockerCmd ( c , "diff" , name )
2015-04-18 16:46:47 +00:00
if len ( strings . Trim ( out , "\r\n" ) ) != 0 && ! eqToBaseDiff ( out , c ) {
c . Fatal ( "diff should be empty" )
2014-07-22 18:16:15 +00:00
}
}
2019-09-09 21:05:55 +00:00
func eqToBaseDiff ( out string , c * testing . T ) bool {
2017-10-28 00:28:19 +00:00
name := "eqToBaseDiff" + testutil . GenerateRandomAlphaOnlyString ( 32 )
2016-02-28 10:47:37 +00:00
dockerCmd ( c , "run" , "--name" , name , "busybox" , "echo" , "hello" )
2017-01-16 10:30:14 +00:00
cID := getIDByName ( c , name )
2015-07-19 20:47:47 +00:00
baseDiff , _ := dockerCmd ( c , "diff" , cID )
2015-03-26 01:40:23 +00:00
baseArr := strings . Split ( baseDiff , "\n" )
sort . Strings ( baseArr )
outArr := strings . Split ( out , "\n" )
sort . Strings ( outArr )
return sliceEq ( baseArr , outArr )
2015-01-20 00:32:29 +00:00
}
func sliceEq ( a , b [ ] string ) bool {
if len ( a ) != len ( b ) {
return false
}
for i := range a {
if a [ i ] != b [ i ] {
return false
}
}
return true
}
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunWithBadDevice ( c * testing . T ) {
2015-09-01 21:37:04 +00:00
// Cannot run on Windows as Windows does not support --device
2015-08-28 17:36:42 +00:00
testRequires ( c , DaemonIsLinux )
2014-08-24 10:09:30 +00:00
name := "baddevice"
2015-07-27 18:13:25 +00:00
out , _ , err := dockerCmdWithError ( "run" , "--name" , name , "--device" , "/etc" , "busybox" , "true" )
2015-07-19 20:47:47 +00:00
2014-08-24 10:09:30 +00:00
if err == nil {
2015-04-18 16:46:47 +00:00
c . Fatal ( "Run should fail with bad device" )
2014-08-24 10:09:30 +00:00
}
2015-05-09 18:33:06 +00:00
expected := ` "/etc": not a device node `
2014-08-24 10:09:30 +00:00
if ! strings . Contains ( out , expected ) {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "Output should contain %q, actual out: %q" , expected , out )
2014-08-24 10:09:30 +00:00
}
}
2014-08-28 00:25:10 +00:00
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunEntrypoint ( c * testing . T ) {
2014-08-28 00:25:10 +00:00
name := "entrypoint"
2015-07-19 20:47:47 +00:00
2016-03-29 00:26:34 +00:00
out , _ := dockerCmd ( c , "run" , "--name" , name , "--entrypoint" , "echo" , "busybox" , "-n" , "foobar" )
expected := "foobar"
2015-09-01 21:37:04 +00:00
2014-08-28 00:25:10 +00:00
if out != expected {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "Output should be %q, actual out: %q" , expected , out )
2014-08-28 00:25:10 +00:00
}
}
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunBindMounts ( c * testing . T ) {
2018-12-24 12:25:53 +00:00
testRequires ( c , testEnv . IsLocalDaemon )
2018-01-15 14:32:06 +00:00
if testEnv . OSType == "linux" {
2015-09-23 23:04:51 +00:00
testRequires ( c , DaemonIsLinux , NotUserNamespace )
}
2014-11-17 16:05:49 +00:00
2019-03-19 20:27:51 +00:00
if testEnv . OSType == "windows" {
// Disabled prior to RS5 due to how volumes are mapped
2019-04-17 10:39:07 +00:00
testRequires ( c , DaemonIsWindowsAtLeastBuild ( osversion . RS5 ) )
2019-03-19 20:27:51 +00:00
}
2016-05-25 20:56:36 +00:00
prefix , _ := getPrefixAndSlashFromDaemonPlatform ( )
2014-08-28 00:25:10 +00:00
tmpDir , err := ioutil . TempDir ( "" , "docker-test-container" )
if err != nil {
2015-04-18 16:46:47 +00:00
c . Fatal ( err )
2014-08-28 00:25:10 +00:00
}
defer os . RemoveAll ( tmpDir )
2015-04-18 16:46:47 +00:00
writeFile ( path . Join ( tmpDir , "touch-me" ) , "" , c )
2014-08-28 00:25:10 +00:00
2016-11-23 22:28:06 +00:00
// Test reading from a read-only bind mount
2019-03-19 20:27:51 +00:00
out , _ := dockerCmd ( c , "run" , "-v" , fmt . Sprintf ( "%s:%s/tmpx:ro" , tmpDir , prefix ) , "busybox" , "ls" , prefix + "/tmpx" )
2016-11-23 22:28:06 +00:00
if ! strings . Contains ( out , "touch-me" ) {
c . Fatal ( "Container failed to read from bind mount" )
2014-08-28 00:25:10 +00:00
}
// test writing to bind mount
2018-01-15 14:32:06 +00:00
if testEnv . OSType == "windows" {
2015-09-23 23:04:51 +00:00
dockerCmd ( c , "run" , "-v" , fmt . Sprintf ( ` %s:c:\tmp:rw ` , tmpDir ) , "busybox" , "touch" , "c:/tmp/holla" )
} else {
dockerCmd ( c , "run" , "-v" , fmt . Sprintf ( "%s:/tmp:rw" , tmpDir ) , "busybox" , "touch" , "/tmp/holla" )
}
2015-07-19 20:47:47 +00:00
2015-04-18 16:46:47 +00:00
readFile ( path . Join ( tmpDir , "holla" ) , c ) // Will fail if the file doesn't exist
2014-08-28 00:25:10 +00:00
// test mounting to an illegal destination directory
2015-07-27 18:13:25 +00:00
_ , _ , err = dockerCmdWithError ( "run" , "-v" , fmt . Sprintf ( "%s:." , tmpDir ) , "busybox" , "ls" , "." )
2014-08-28 00:25:10 +00:00
if err == nil {
2015-04-18 16:46:47 +00:00
c . Fatal ( "Container bind mounted illegal directory" )
2014-08-28 00:25:10 +00:00
}
2015-09-23 23:04:51 +00:00
// Windows does not (and likely never will) support mounting a single file
2018-01-15 14:32:06 +00:00
if testEnv . OSType != "windows" {
2015-09-23 23:04:51 +00:00
// test mount a file
dockerCmd ( c , "run" , "-v" , fmt . Sprintf ( "%s/holla:/tmp/holla:rw" , tmpDir ) , "busybox" , "sh" , "-c" , "echo -n 'yotta' > /tmp/holla" )
content := readFile ( path . Join ( tmpDir , "holla" ) , c ) // Will fail if the file doesn't exist
expected := "yotta"
if content != expected {
c . Fatalf ( "Output should be %q, actual out: %q" , expected , content )
}
2014-08-28 00:25:10 +00:00
}
}
2014-07-14 23:19:37 +00:00
2014-09-01 15:55:39 +00:00
// Ensure that CIDFile gets deleted if it's empty
// Perform this test by making `docker run` fail
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunCidFileCleanupIfEmpty ( c * testing . T ) {
2016-09-21 18:11:13 +00:00
// Skip on Windows. Base image on Windows has a CMD set in the image.
testRequires ( c , DaemonIsLinux )
2016-06-28 20:04:42 +00:00
2014-09-01 15:55:39 +00:00
tmpDir , err := ioutil . TempDir ( "" , "TestRunCidFile" )
if err != nil {
2015-04-18 16:46:47 +00:00
c . Fatal ( err )
2014-09-01 15:55:39 +00:00
}
defer os . RemoveAll ( tmpDir )
tmpCidFile := path . Join ( tmpDir , "cid" )
2015-07-19 20:47:47 +00:00
2015-09-01 21:37:04 +00:00
image := "emptyfs"
2018-01-15 14:32:06 +00:00
if testEnv . OSType == "windows" {
2015-09-01 21:37:04 +00:00
// Windows can't support an emptyfs image. Just use the regular Windows image
2018-01-15 14:31:02 +00:00
image = testEnv . PlatformDefaults . BaseImage
2015-09-01 21:37:04 +00:00
}
out , _ , err := dockerCmdWithError ( "run" , "--cidfile" , tmpCidFile , image )
2014-09-01 15:55:39 +00:00
if err == nil {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "Run without command must fail. out=%s" , out )
2015-03-06 06:01:49 +00:00
} else if ! strings . Contains ( out , "No command specified" ) {
2015-04-27 20:33:30 +00:00
c . Fatalf ( "Run without command failed with wrong output. out=%s\nerr=%v" , out , err )
2014-09-01 15:55:39 +00:00
}
if _ , err := os . Stat ( tmpCidFile ) ; err == nil {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "empty CIDFile %q should've been deleted" , tmpCidFile )
2014-09-01 15:55:39 +00:00
}
}
2014-09-01 16:15:20 +00:00
// #2098 - Docker cidFiles only contain short version of the containerId
2019-11-27 14:36:45 +00:00
// sudo docker run --cidfile /tmp/docker_tesc.cid ubuntu echo "test"
2014-09-01 16:15:20 +00:00
// TestRunCidFile tests that run --cidfile returns the longid
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunCidFileCheckIDLength ( c * testing . T ) {
2014-09-01 16:15:20 +00:00
tmpDir , err := ioutil . TempDir ( "" , "TestRunCidFile" )
if err != nil {
2015-04-18 16:46:47 +00:00
c . Fatal ( err )
2014-09-01 16:15:20 +00:00
}
tmpCidFile := path . Join ( tmpDir , "cid" )
defer os . RemoveAll ( tmpDir )
2015-07-19 20:47:47 +00:00
out , _ := dockerCmd ( c , "run" , "-d" , "--cidfile" , tmpCidFile , "busybox" , "true" )
2014-09-01 16:15:20 +00:00
id := strings . TrimSpace ( out )
buffer , err := ioutil . ReadFile ( tmpCidFile )
if err != nil {
2015-04-18 16:46:47 +00:00
c . Fatal ( err )
2014-09-01 16:15:20 +00:00
}
cid := string ( buffer )
if len ( cid ) != 64 {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "--cidfile should be a long id, not %q" , id )
2014-09-01 16:15:20 +00:00
}
if cid != id {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "cid must be equal to %s, got %s" , id , cid )
2014-09-01 16:15:20 +00:00
}
}
2014-09-04 05:50:58 +00:00
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunSetMacAddress ( c * testing . T ) {
2014-10-03 21:02:17 +00:00
mac := "12:34:56:78:9a:bc"
2015-09-01 21:37:04 +00:00
var out string
2018-01-15 14:32:06 +00:00
if testEnv . OSType == "windows" {
2015-09-01 21:37:04 +00:00
out , _ = dockerCmd ( c , "run" , "-i" , "--rm" , fmt . Sprintf ( "--mac-address=%s" , mac ) , "busybox" , "sh" , "-c" , "ipconfig /all | grep 'Physical Address' | awk '{print $12}'" )
2015-09-23 23:04:51 +00:00
mac = strings . Replace ( strings . ToUpper ( mac ) , ":" , "-" , - 1 ) // To Windows-style MACs
2015-09-01 21:37:04 +00:00
} else {
out , _ = dockerCmd ( c , "run" , "-i" , "--rm" , fmt . Sprintf ( "--mac-address=%s" , mac ) , "busybox" , "/bin/sh" , "-c" , "ip link show eth0 | tail -1 | awk '{print $2}'" )
}
2015-07-19 20:47:47 +00:00
2014-10-03 21:02:17 +00:00
actualMac := strings . TrimSpace ( out )
if actualMac != mac {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "Set MAC address with --mac-address failed. The container has an incorrect MAC address: %q, expected: %q" , actualMac , mac )
2014-10-03 21:02:17 +00:00
}
}
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunInspectMacAddress ( c * testing . T ) {
2015-09-01 21:37:04 +00:00
// TODO Windows. Network settings are not propagated back to inspect.
2015-08-28 17:36:42 +00:00
testRequires ( c , DaemonIsLinux )
2014-10-03 21:02:17 +00:00
mac := "12:34:56:78:9a:bc"
2015-07-19 20:47:47 +00:00
out , _ := dockerCmd ( c , "run" , "-d" , "--mac-address=" + mac , "busybox" , "top" )
2014-10-03 21:02:17 +00:00
id := strings . TrimSpace ( out )
2016-01-28 14:19:25 +00:00
inspectedMac := inspectField ( c , id , "NetworkSettings.Networks.bridge.MacAddress" )
2014-10-03 21:02:17 +00:00
if inspectedMac != mac {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "docker inspect outputs wrong MAC address: %q, should be: %q" , inspectedMac , mac )
2014-10-03 21:02:17 +00:00
}
}
2016-02-22 19:22:20 +00:00
// test docker run use an invalid mac address
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunWithInvalidMacAddress ( c * testing . T ) {
2015-07-27 18:13:25 +00:00
out , _ , err := dockerCmdWithError ( "run" , "--mac-address" , "92:d0:c6:0a:29" , "busybox" )
2019-11-27 14:36:45 +00:00
// use an invalid mac address should with an error out
2015-02-27 15:27:12 +00:00
if err == nil || ! strings . Contains ( out , "is not a valid mac address" ) {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "run with an invalid --mac-address should with error out" )
2015-02-27 15:27:12 +00:00
}
}
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunDeallocatePortOnMissingIptablesRule ( c * testing . T ) {
2015-09-01 21:37:04 +00:00
// TODO Windows. Network settings are not propagated back to inspect.
2018-12-24 12:25:53 +00:00
testRequires ( c , testEnv . IsLocalDaemon , DaemonIsLinux )
2015-02-20 06:56:02 +00:00
2017-04-11 17:42:54 +00:00
out := cli . DockerCmd ( c , "run" , "-d" , "-p" , "23:23" , "busybox" , "top" ) . Combined ( )
2015-07-19 20:47:47 +00:00
2014-09-09 12:47:25 +00:00
id := strings . TrimSpace ( out )
2016-01-28 14:19:25 +00:00
ip := inspectField ( c , id , "NetworkSettings.Networks.bridge.IPAddress" )
2017-01-05 11:38:34 +00:00
icmd . RunCommand ( "iptables" , "-D" , "DOCKER" , "-d" , fmt . Sprintf ( "%s/32" , ip ) ,
"!" , "-i" , "docker0" , "-o" , "docker0" , "-p" , "tcp" , "-m" , "tcp" , "--dport" , "23" , "-j" , "ACCEPT" ) . Assert ( c , icmd . Success )
2017-04-11 17:42:54 +00:00
cli . DockerCmd ( c , "rm" , "-fv" , id )
2015-07-19 20:47:47 +00:00
2017-04-11 17:42:54 +00:00
cli . DockerCmd ( c , "run" , "-d" , "-p" , "23:23" , "busybox" , "top" )
2014-09-09 12:47:25 +00:00
}
2014-09-06 01:59:31 +00:00
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunPortInUse ( c * testing . T ) {
2015-09-01 21:37:04 +00:00
// TODO Windows. The duplicate NAT message returned by Windows will be
// changing as is currently completely undecipherable. Does need modifying
// to run sh rather than top though as top isn't in Windows busybox.
2018-12-24 12:25:53 +00:00
testRequires ( c , testEnv . IsLocalDaemon , DaemonIsLinux )
2015-02-20 06:56:02 +00:00
2014-09-06 01:59:31 +00:00
port := "1234"
2015-07-19 20:47:47 +00:00
dockerCmd ( c , "run" , "-d" , "-p" , port + ":80" , "busybox" , "top" )
2014-10-08 12:41:26 +00:00
2015-07-27 18:13:25 +00:00
out , _ , err := dockerCmdWithError ( "run" , "-d" , "-p" , port + ":80" , "busybox" , "top" )
2014-11-11 00:19:16 +00:00
if err == nil {
c . Fatalf ( "Binding on used port must fail" )
2014-10-08 12:41:26 +00:00
}
2014-11-11 00:19:16 +00:00
if ! strings . Contains ( out , "port is already allocated" ) {
c . Fatalf ( "Out must be about \"port is already allocated\", got %s" , out )
2014-10-08 12:41:26 +00:00
}
}
2015-04-08 05:31:47 +00:00
// https://github.com/docker/docker/issues/12148
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunAllocatePortInReservedRange ( c * testing . T ) {
2015-09-01 21:37:04 +00:00
// TODO Windows. -P is not yet supported
2015-08-28 17:36:42 +00:00
testRequires ( c , DaemonIsLinux )
2015-04-08 05:31:47 +00:00
// allocate a dynamic port to get the most recent
2015-07-19 20:47:47 +00:00
out , _ := dockerCmd ( c , "run" , "-d" , "-P" , "-p" , "80" , "busybox" , "top" )
2015-04-08 05:31:47 +00:00
id := strings . TrimSpace ( out )
2015-07-19 20:47:47 +00:00
out , _ = dockerCmd ( c , "port" , id , "80" )
2015-04-08 05:31:47 +00:00
strPort := strings . Split ( strings . TrimSpace ( out ) , ":" ) [ 1 ]
port , err := strconv . ParseInt ( strPort , 10 , 64 )
if err != nil {
c . Fatalf ( "invalid port, got: %s, error: %s" , strPort , err )
}
// allocate a static port and a dynamic port together, with static port
// takes the next recent port in dynamic port range.
2015-07-19 20:47:47 +00:00
dockerCmd ( c , "run" , "-d" , "-P" , "-p" , "80" , "-p" , fmt . Sprintf ( "%d:8080" , port + 1 ) , "busybox" , "top" )
2015-04-08 05:31:47 +00:00
}
2014-09-16 00:51:06 +00:00
// Regression test for #7792
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunMountOrdering ( c * testing . T ) {
2016-11-23 22:28:06 +00:00
// TODO Windows: Post RS1. Windows does not support nested mounts.
2018-12-24 12:25:53 +00:00
testRequires ( c , testEnv . IsLocalDaemon , DaemonIsLinux , NotUserNamespace )
2016-02-03 14:16:00 +00:00
prefix , _ := getPrefixAndSlashFromDaemonPlatform ( )
2015-02-20 06:56:02 +00:00
2014-09-16 00:51:06 +00:00
tmpDir , err := ioutil . TempDir ( "" , "docker_nested_mount_test" )
if err != nil {
2015-04-18 16:46:47 +00:00
c . Fatal ( err )
2014-09-16 00:51:06 +00:00
}
defer os . RemoveAll ( tmpDir )
tmpDir2 , err := ioutil . TempDir ( "" , "docker_nested_mount_test2" )
if err != nil {
2015-04-18 16:46:47 +00:00
c . Fatal ( err )
2014-09-16 00:51:06 +00:00
}
defer os . RemoveAll ( tmpDir2 )
2015-04-18 16:46:47 +00:00
// Create a temporary tmpfs mounc.
2014-09-16 00:51:06 +00:00
fooDir := filepath . Join ( tmpDir , "foo" )
if err := os . MkdirAll ( filepath . Join ( tmpDir , "foo" ) , 0755 ) ; err != nil {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "failed to mkdir at %s - %s" , fooDir , err )
2014-09-16 00:51:06 +00:00
}
if err := ioutil . WriteFile ( fmt . Sprintf ( "%s/touch-me" , fooDir ) , [ ] byte { } , 0644 ) ; err != nil {
2015-04-18 16:46:47 +00:00
c . Fatal ( err )
2014-09-16 00:51:06 +00:00
}
if err := ioutil . WriteFile ( fmt . Sprintf ( "%s/touch-me" , tmpDir ) , [ ] byte { } , 0644 ) ; err != nil {
2015-04-18 16:46:47 +00:00
c . Fatal ( err )
2014-09-16 00:51:06 +00:00
}
if err := ioutil . WriteFile ( fmt . Sprintf ( "%s/touch-me" , tmpDir2 ) , [ ] byte { } , 0644 ) ; err != nil {
2015-04-18 16:46:47 +00:00
c . Fatal ( err )
2014-09-16 00:51:06 +00:00
}
2015-07-19 20:47:47 +00:00
dockerCmd ( c , "run" ,
2015-09-23 23:04:51 +00:00
"-v" , fmt . Sprintf ( "%s:" + prefix + "/tmp" , tmpDir ) ,
"-v" , fmt . Sprintf ( "%s:" + prefix + "/tmp/foo" , fooDir ) ,
"-v" , fmt . Sprintf ( "%s:" + prefix + "/tmp/tmp2" , tmpDir2 ) ,
"-v" , fmt . Sprintf ( "%s:" + prefix + "/tmp/tmp2/foo" , fooDir ) ,
2015-05-19 20:05:25 +00:00
"busybox:latest" , "sh" , "-c" ,
2015-09-23 23:04:51 +00:00
"ls " + prefix + "/tmp/touch-me && ls " + prefix + "/tmp/foo/touch-me && ls " + prefix + "/tmp/tmp2/touch-me && ls " + prefix + "/tmp/tmp2/foo/touch-me" )
2014-09-16 00:51:06 +00:00
}
2014-09-10 16:43:16 +00:00
2014-09-26 18:28:21 +00:00
// Regression test for https://github.com/docker/docker/issues/8259
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunReuseBindVolumeThatIsSymlink ( c * testing . T ) {
2015-09-01 21:37:04 +00:00
// Not applicable on Windows as Windows does not support volumes
2018-12-24 12:25:53 +00:00
testRequires ( c , testEnv . IsLocalDaemon , DaemonIsLinux , NotUserNamespace )
2016-02-03 14:16:00 +00:00
prefix , _ := getPrefixAndSlashFromDaemonPlatform ( )
2015-02-20 06:56:02 +00:00
2014-09-26 18:28:21 +00:00
tmpDir , err := ioutil . TempDir ( os . TempDir ( ) , "testlink" )
if err != nil {
2015-04-18 16:46:47 +00:00
c . Fatal ( err )
2014-09-26 18:28:21 +00:00
}
defer os . RemoveAll ( tmpDir )
linkPath := os . TempDir ( ) + "/testlink2"
if err := os . Symlink ( tmpDir , linkPath ) ; err != nil {
2015-04-18 16:46:47 +00:00
c . Fatal ( err )
2014-09-26 18:28:21 +00:00
}
defer os . RemoveAll ( linkPath )
// Create first container
2015-09-23 23:04:51 +00:00
dockerCmd ( c , "run" , "-v" , fmt . Sprintf ( "%s:" + prefix + "/tmp/test" , linkPath ) , "busybox" , "ls" , prefix + "/tmp/test" )
2014-09-26 18:28:21 +00:00
// Create second container with same symlinked path
// This will fail if the referenced issue is hit with a "Volume exists" error
2015-09-23 23:04:51 +00:00
dockerCmd ( c , "run" , "-v" , fmt . Sprintf ( "%s:" + prefix + "/tmp/test" , linkPath ) , "busybox" , "ls" , prefix + "/tmp/test" )
2014-09-26 18:28:21 +00:00
}
2014-10-06 17:30:42 +00:00
2019-11-27 14:36:45 +00:00
// GH#10604: Test an "/etc" volume doesn't overlay special bind mounts in container
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunCreateVolumeEtc ( c * testing . T ) {
2015-09-23 23:04:51 +00:00
// While Windows supports volumes, it does not support --add-host hence
// this test is not applicable on Windows.
2015-08-28 17:36:42 +00:00
testRequires ( c , DaemonIsLinux )
2015-07-19 20:47:47 +00:00
out , _ := dockerCmd ( c , "run" , "--dns=127.0.0.1" , "-v" , "/etc" , "busybox" , "cat" , "/etc/resolv.conf" )
2015-02-12 02:39:07 +00:00
if ! strings . Contains ( out , "nameserver 127.0.0.1" ) {
2015-04-18 16:46:47 +00:00
c . Fatal ( "/etc volume mount hides /etc/resolv.conf" )
2015-02-12 02:39:07 +00:00
}
2015-07-19 20:47:47 +00:00
out , _ = dockerCmd ( c , "run" , "-h=test123" , "-v" , "/etc" , "busybox" , "cat" , "/etc/hostname" )
2015-02-12 02:39:07 +00:00
if ! strings . Contains ( out , "test123" ) {
2015-04-18 16:46:47 +00:00
c . Fatal ( "/etc volume mount hides /etc/hostname" )
2015-02-12 02:39:07 +00:00
}
2015-07-19 20:47:47 +00:00
out , _ = dockerCmd ( c , "run" , "--add-host=test:192.168.0.1" , "-v" , "/etc" , "busybox" , "cat" , "/etc/hosts" )
2015-02-12 02:39:07 +00:00
out = strings . Replace ( out , "\n" , " " , - 1 )
2015-03-05 14:41:56 +00:00
if ! strings . Contains ( out , "192.168.0.1\ttest" ) || ! strings . Contains ( out , "127.0.0.1\tlocalhost" ) {
2015-04-18 16:46:47 +00:00
c . Fatal ( "/etc volume mount hides /etc/hosts" )
2015-02-12 02:39:07 +00:00
}
}
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestVolumesNoCopyData ( c * testing . T ) {
2016-09-06 22:38:19 +00:00
// TODO Windows (Post RS1). Windows does not support volumes which
2015-09-23 23:04:51 +00:00
// are pre-populated such as is built in the dockerfile used in this test.
2015-08-28 17:36:42 +00:00
testRequires ( c , DaemonIsLinux )
2016-09-06 22:38:19 +00:00
prefix , slash := getPrefixAndSlashFromDaemonPlatform ( )
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , "dataimage" , build . WithDockerfile ( ` FROM busybox
2016-09-06 22:38:19 +00:00
RUN [ "mkdir" , "-p" , "/foo" ]
2017-01-16 10:30:14 +00:00
RUN [ "touch" , "/foo/bar" ] ` ) )
2016-09-06 22:38:19 +00:00
dockerCmd ( c , "run" , "--name" , "test" , "-v" , prefix + slash + "foo" , "busybox" )
2014-10-06 17:30:42 +00:00
2015-07-27 18:13:25 +00:00
if out , _ , err := dockerCmdWithError ( "run" , "--volumes-from" , "test" , "dataimage" , "ls" , "-lh" , "/foo/bar" ) ; err == nil || ! strings . Contains ( out , "No such file or directory" ) {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "Data was copied on volumes-from but shouldn't be:\n%q" , out )
2014-10-06 17:30:42 +00:00
}
2018-01-15 14:32:06 +00:00
tmpDir := RandomTmpDirPath ( "docker_test_bind_mount_copy_data" , testEnv . OSType )
2015-07-27 18:13:25 +00:00
if out , _ , err := dockerCmdWithError ( "run" , "-v" , tmpDir + ":/foo" , "dataimage" , "ls" , "-lh" , "/foo/bar" ) ; err == nil || ! strings . Contains ( out , "No such file or directory" ) {
2017-08-19 14:23:38 +00:00
c . Fatalf ( "Data was copied on bind mount but shouldn't be:\n%q" , out )
2014-10-06 17:30:42 +00:00
}
}
2014-10-08 19:01:25 +00:00
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunNoOutputFromPullInStdout ( c * testing . T ) {
2014-10-17 18:06:05 +00:00
// just run with unknown image
cmd := exec . Command ( dockerBinary , "run" , "asdfsg" )
stdout := bytes . NewBuffer ( nil )
cmd . Stdout = stdout
if err := cmd . Run ( ) ; err == nil {
2015-04-18 16:46:47 +00:00
c . Fatal ( "Run with unknown image should fail" )
2014-10-17 18:06:05 +00:00
}
if stdout . Len ( ) != 0 {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "Stdout contains output from pull: %s" , stdout )
2014-10-17 18:06:05 +00:00
}
}
2014-10-20 19:27:26 +00:00
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunVolumesCleanPaths ( c * testing . T ) {
2018-12-24 12:25:53 +00:00
testRequires ( c , testEnv . IsLocalDaemon )
2016-02-03 14:16:00 +00:00
prefix , slash := getPrefixAndSlashFromDaemonPlatform ( )
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , "run_volumes_clean_paths" , build . WithDockerfile ( ` FROM busybox
2017-01-16 10:30:14 +00:00
VOLUME ` +prefix+ ` / foo / ` ) )
2015-09-23 23:04:51 +00:00
dockerCmd ( c , "run" , "-v" , prefix + "/foo" , "-v" , prefix + "/bar/" , "--name" , "dark_helmet" , "run_volumes_clean_paths" )
2014-10-20 19:27:26 +00:00
2015-09-23 23:04:51 +00:00
out , err := inspectMountSourceField ( "dark_helmet" , prefix + slash + "foo" + slash )
2015-07-22 12:59:24 +00:00
if err != errMountNotFound {
2015-09-23 23:04:51 +00:00
c . Fatalf ( "Found unexpected volume entry for '%s/foo/' in volumes\n%q" , prefix , out )
2014-10-20 19:27:26 +00:00
}
2015-09-23 23:04:51 +00:00
out , err = inspectMountSourceField ( "dark_helmet" , prefix + slash + ` foo ` )
2019-04-04 13:23:19 +00:00
assert . NilError ( c , err )
2017-08-25 22:48:36 +00:00
if ! strings . Contains ( strings . ToLower ( out ) , strings . ToLower ( testEnv . PlatformDefaults . VolumesConfigPath ) ) {
2015-09-23 23:04:51 +00:00
c . Fatalf ( "Volume was not defined for %s/foo\n%q" , prefix , out )
2014-10-20 19:27:26 +00:00
}
2015-09-23 23:04:51 +00:00
out , err = inspectMountSourceField ( "dark_helmet" , prefix + slash + "bar" + slash )
2015-07-22 12:59:24 +00:00
if err != errMountNotFound {
2015-09-23 23:04:51 +00:00
c . Fatalf ( "Found unexpected volume entry for '%s/bar/' in volumes\n%q" , prefix , out )
2014-10-20 19:27:26 +00:00
}
2015-06-03 19:21:38 +00:00
2015-09-23 23:04:51 +00:00
out , err = inspectMountSourceField ( "dark_helmet" , prefix + slash + "bar" )
2019-04-04 13:23:19 +00:00
assert . NilError ( c , err )
2017-08-25 22:48:36 +00:00
if ! strings . Contains ( strings . ToLower ( out ) , strings . ToLower ( testEnv . PlatformDefaults . VolumesConfigPath ) ) {
2015-09-23 23:04:51 +00:00
c . Fatalf ( "Volume was not defined for %s/bar\n%q" , prefix , out )
2014-10-20 19:27:26 +00:00
}
}
2014-10-03 17:38:44 +00:00
// Regression test for #3631
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunSlowStdoutConsumer ( c * testing . T ) {
2015-09-01 21:37:04 +00:00
// TODO Windows: This should be able to run on Windows if can find an
// alternate to /dev/zero and /dev/stdout.
2015-08-28 17:36:42 +00:00
testRequires ( c , DaemonIsLinux )
2018-01-08 06:15:24 +00:00
2018-02-13 04:52:10 +00:00
args := [ ] string { "run" , "--rm" , "busybox" , "/bin/sh" , "-c" , "dd if=/dev/zero of=/dev/stdout bs=1024 count=2000 | cat -v" }
2018-01-08 06:15:24 +00:00
cont := exec . Command ( dockerBinary , args ... )
2014-10-03 17:38:44 +00:00
2015-04-18 16:46:47 +00:00
stdout , err := cont . StdoutPipe ( )
2014-10-03 17:38:44 +00:00
if err != nil {
2015-04-18 16:46:47 +00:00
c . Fatal ( err )
2014-10-03 17:38:44 +00:00
}
2015-04-18 16:46:47 +00:00
if err := cont . Start ( ) ; err != nil {
c . Fatal ( err )
2014-10-03 17:38:44 +00:00
}
2017-09-22 13:52:41 +00:00
defer func ( ) { go cont . Wait ( ) } ( )
2017-08-21 22:58:25 +00:00
n , err := ConsumeWithSpeed ( stdout , 10000 , 5 * time . Millisecond , nil )
2014-10-03 17:38:44 +00:00
if err != nil {
2015-04-18 16:46:47 +00:00
c . Fatal ( err )
2014-10-03 17:38:44 +00:00
}
expected := 2 * 1024 * 2000
if n != expected {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "Expected %d, got %d" , expected , n )
2014-10-03 17:38:44 +00:00
}
}
2014-09-17 01:08:30 +00:00
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunAllowPortRangeThroughExpose ( c * testing . T ) {
2015-09-01 21:37:04 +00:00
// TODO Windows: -P is not currently supported. Also network
// settings are not propagated back.
2015-08-28 17:36:42 +00:00
testRequires ( c , DaemonIsLinux )
2015-07-19 20:47:47 +00:00
out , _ := dockerCmd ( c , "run" , "-d" , "--expose" , "3000-3003" , "-P" , "busybox" , "top" )
2014-09-17 01:08:30 +00:00
id := strings . TrimSpace ( out )
2016-01-28 14:19:25 +00:00
portstr := inspectFieldJSON ( c , id , "NetworkSettings.Ports" )
2014-09-17 01:08:30 +00:00
var ports nat . PortMap
2016-08-04 16:17:37 +00:00
if err := json . Unmarshal ( [ ] byte ( portstr ) , & ports ) ; err != nil {
2015-04-18 16:46:47 +00:00
c . Fatal ( err )
2015-03-26 03:18:42 +00:00
}
2014-09-17 01:08:30 +00:00
for port , binding := range ports {
portnum , _ := strconv . Atoi ( strings . Split ( string ( port ) , "/" ) [ 0 ] )
if portnum < 3000 || portnum > 3003 {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "Port %d is out of range " , portnum )
2014-09-17 01:08:30 +00:00
}
if binding == nil || len ( binding ) != 1 || len ( binding [ 0 ] . HostPort ) == 0 {
2015-08-19 08:47:33 +00:00
c . Fatalf ( "Port is not mapped for the port %s" , port )
2014-09-17 01:08:30 +00:00
}
}
}
2014-11-06 02:23:42 +00:00
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunExposePort ( c * testing . T ) {
2015-07-27 18:13:25 +00:00
out , _ , err := dockerCmdWithError ( "run" , "--expose" , "80000" , "busybox" )
2019-09-09 21:08:22 +00:00
assert . Assert ( c , err != nil , "--expose with an invalid port should error out" )
2019-09-09 21:08:22 +00:00
assert . Assert ( c , strings . Contains ( out , "invalid range format for --expose" ) )
2015-02-19 23:18:13 +00:00
}
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunModeIpcHost ( c * testing . T ) {
2015-09-01 21:37:04 +00:00
// Not applicable on Windows as uses Unix-specific capabilities
2018-12-24 12:25:53 +00:00
testRequires ( c , testEnv . IsLocalDaemon , DaemonIsLinux , NotUserNamespace )
2015-02-20 06:56:02 +00:00
2014-11-10 21:14:17 +00:00
hostIpc , err := os . Readlink ( "/proc/1/ns/ipc" )
if err != nil {
2015-04-18 16:46:47 +00:00
c . Fatal ( err )
2014-11-10 21:14:17 +00:00
}
2015-07-19 20:47:47 +00:00
out , _ := dockerCmd ( c , "run" , "--ipc=host" , "busybox" , "readlink" , "/proc/self/ns/ipc" )
out = strings . Trim ( out , "\n" )
if hostIpc != out {
c . Fatalf ( "IPC different with --ipc=host %s != %s\n" , hostIpc , out )
2014-11-10 21:14:17 +00:00
}
2015-07-19 20:47:47 +00:00
out , _ = dockerCmd ( c , "run" , "busybox" , "readlink" , "/proc/self/ns/ipc" )
out = strings . Trim ( out , "\n" )
if hostIpc == out {
c . Fatalf ( "IPC should be different without --ipc=host %s == %s\n" , hostIpc , out )
2014-11-10 21:14:17 +00:00
}
}
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunModeIpcContainerNotExists ( c * testing . T ) {
2015-09-01 21:37:04 +00:00
// Not applicable on Windows as uses Unix-specific capabilities
2016-03-23 13:37:15 +00:00
testRequires ( c , DaemonIsLinux )
2015-07-27 18:13:25 +00:00
out , _ , err := dockerCmdWithError ( "run" , "-d" , "--ipc" , "container:abcd1234" , "busybox" , "top" )
2015-03-28 01:07:20 +00:00
if ! strings . Contains ( out , "abcd1234" ) || err == nil {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "run IPC from a non exists container should with correct error out" )
2015-03-28 01:07:20 +00:00
}
}
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunModeIpcContainerNotRunning ( c * testing . T ) {
2015-09-01 21:37:04 +00:00
// Not applicable on Windows as uses Unix-specific capabilities
2018-12-24 12:25:53 +00:00
testRequires ( c , testEnv . IsLocalDaemon , DaemonIsLinux )
2015-05-22 23:15:14 +00:00
2015-07-19 20:47:47 +00:00
out , _ := dockerCmd ( c , "create" , "busybox" )
2015-05-22 23:15:14 +00:00
2015-07-19 20:47:47 +00:00
id := strings . TrimSpace ( out )
2015-07-27 18:13:25 +00:00
out , _ , err := dockerCmdWithError ( "run" , fmt . Sprintf ( "--ipc=container:%s" , id ) , "busybox" )
2015-05-22 23:15:14 +00:00
if err == nil {
c . Fatalf ( "Run container with ipc mode container should fail with non running container: %s\n%s" , out , err )
}
}
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunModePIDContainer ( c * testing . T ) {
2016-05-06 18:56:03 +00:00
// Not applicable on Windows as uses Unix-specific capabilities
2018-12-24 12:25:53 +00:00
testRequires ( c , testEnv . IsLocalDaemon , DaemonIsLinux )
2016-05-06 18:56:03 +00:00
out , _ := dockerCmd ( c , "run" , "-d" , "busybox" , "sh" , "-c" , "top" )
id := strings . TrimSpace ( out )
state := inspectField ( c , id , "State.Running" )
if state != "true" {
c . Fatal ( "Container state is 'not running'" )
}
pid1 := inspectField ( c , id , "State.Pid" )
parentContainerPid , err := os . Readlink ( fmt . Sprintf ( "/proc/%s/ns/pid" , pid1 ) )
if err != nil {
c . Fatal ( err )
}
out , _ = dockerCmd ( c , "run" , fmt . Sprintf ( "--pid=container:%s" , id ) , "busybox" , "readlink" , "/proc/self/ns/pid" )
out = strings . Trim ( out , "\n" )
if parentContainerPid != out {
c . Fatalf ( "PID different with --pid=container:%s %s != %s\n" , id , parentContainerPid , out )
}
}
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunModePIDContainerNotExists ( c * testing . T ) {
2016-05-06 18:56:03 +00:00
// Not applicable on Windows as uses Unix-specific capabilities
testRequires ( c , DaemonIsLinux )
out , _ , err := dockerCmdWithError ( "run" , "-d" , "--pid" , "container:abcd1234" , "busybox" , "top" )
if ! strings . Contains ( out , "abcd1234" ) || err == nil {
c . Fatalf ( "run PID from a non exists container should with correct error out" )
}
}
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunModePIDContainerNotRunning ( c * testing . T ) {
2016-05-06 18:56:03 +00:00
// Not applicable on Windows as uses Unix-specific capabilities
2018-12-24 12:25:53 +00:00
testRequires ( c , testEnv . IsLocalDaemon , DaemonIsLinux )
2016-05-06 18:56:03 +00:00
out , _ := dockerCmd ( c , "create" , "busybox" )
id := strings . TrimSpace ( out )
out , _ , err := dockerCmdWithError ( "run" , fmt . Sprintf ( "--pid=container:%s" , id ) , "busybox" )
if err == nil {
c . Fatalf ( "Run container with pid mode container should fail with non running container: %s\n%s" , out , err )
}
}
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunMountShmMqueueFromHost ( c * testing . T ) {
2015-10-02 03:11:55 +00:00
// Not applicable on Windows as uses Unix-specific capabilities
2018-12-24 12:25:53 +00:00
testRequires ( c , testEnv . IsLocalDaemon , DaemonIsLinux , NotUserNamespace )
2015-10-02 03:11:55 +00:00
2016-02-09 00:51:45 +00:00
dockerCmd ( c , "run" , "-d" , "--name" , "shmfromhost" , "-v" , "/dev/shm:/dev/shm" , "-v" , "/dev/mqueue:/dev/mqueue" , "busybox" , "sh" , "-c" , "echo -n test > /dev/shm/test && touch /dev/mqueue/toto && top" )
defer os . Remove ( "/dev/mqueue/toto" )
defer os . Remove ( "/dev/shm/test" )
2015-10-02 03:11:55 +00:00
volPath , err := inspectMountSourceField ( "shmfromhost" , "/dev/shm" )
2019-04-04 13:23:19 +00:00
assert . NilError ( c , err )
2015-10-02 03:11:55 +00:00
if volPath != "/dev/shm" {
c . Fatalf ( "volumePath should have been /dev/shm, was %s" , volPath )
}
out , _ := dockerCmd ( c , "run" , "--name" , "ipchost" , "--ipc" , "host" , "busybox" , "cat" , "/dev/shm/test" )
if out != "test" {
c . Fatalf ( "Output of /dev/shm/test expected test but found: %s" , out )
}
2016-02-09 00:51:45 +00:00
// Check that the mq was created
if _ , err := os . Stat ( "/dev/mqueue/toto" ) ; err != nil {
c . Fatalf ( "Failed to confirm '/dev/mqueue/toto' presence on host: %s" , err . Error ( ) )
}
2015-10-02 03:11:55 +00:00
}
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestContainerNetworkMode ( c * testing . T ) {
2015-09-01 21:37:04 +00:00
// Not applicable on Windows as uses Unix-specific capabilities
2018-12-24 12:25:53 +00:00
testRequires ( c , testEnv . IsLocalDaemon , DaemonIsLinux )
2015-02-20 06:56:02 +00:00
2015-07-19 20:47:47 +00:00
out , _ := dockerCmd ( c , "run" , "-d" , "busybox" , "top" )
2014-11-18 23:10:07 +00:00
id := strings . TrimSpace ( out )
2019-04-04 13:23:19 +00:00
assert . NilError ( c , waitRun ( id ) )
2016-01-28 14:19:25 +00:00
pid1 := inspectField ( c , id , "State.Pid" )
2014-11-18 23:10:07 +00:00
parentContainerNet , err := os . Readlink ( fmt . Sprintf ( "/proc/%s/ns/net" , pid1 ) )
if err != nil {
2015-04-18 16:46:47 +00:00
c . Fatal ( err )
2014-11-18 23:10:07 +00:00
}
2015-07-19 20:47:47 +00:00
out , _ = dockerCmd ( c , "run" , fmt . Sprintf ( "--net=container:%s" , id ) , "busybox" , "readlink" , "/proc/self/ns/net" )
out = strings . Trim ( out , "\n" )
if parentContainerNet != out {
c . Fatalf ( "NET different with --net=container:%s %s != %s\n" , id , parentContainerNet , out )
2014-11-18 23:10:07 +00:00
}
}
2014-11-20 15:29:04 +00:00
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunModePIDHost ( c * testing . T ) {
2015-09-01 21:37:04 +00:00
// Not applicable on Windows as uses Unix-specific capabilities
2018-12-24 12:25:53 +00:00
testRequires ( c , testEnv . IsLocalDaemon , DaemonIsLinux , NotUserNamespace )
2015-02-20 06:56:02 +00:00
2015-01-14 00:39:08 +00:00
hostPid , err := os . Readlink ( "/proc/1/ns/pid" )
if err != nil {
2015-04-18 16:46:47 +00:00
c . Fatal ( err )
2015-01-14 00:39:08 +00:00
}
2015-07-19 20:47:47 +00:00
out , _ := dockerCmd ( c , "run" , "--pid=host" , "busybox" , "readlink" , "/proc/self/ns/pid" )
out = strings . Trim ( out , "\n" )
if hostPid != out {
c . Fatalf ( "PID different with --pid=host %s != %s\n" , hostPid , out )
2015-01-14 00:39:08 +00:00
}
2015-07-19 20:47:47 +00:00
out , _ = dockerCmd ( c , "run" , "busybox" , "readlink" , "/proc/self/ns/pid" )
out = strings . Trim ( out , "\n" )
if hostPid == out {
c . Fatalf ( "PID should be different without --pid=host %s == %s\n" , hostPid , out )
2015-01-14 00:39:08 +00:00
}
}
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunModeUTSHost ( c * testing . T ) {
2015-09-01 21:37:04 +00:00
// Not applicable on Windows as uses Unix-specific capabilities
2018-12-24 12:25:53 +00:00
testRequires ( c , testEnv . IsLocalDaemon , DaemonIsLinux )
2015-05-05 22:32:36 +00:00
hostUTS , err := os . Readlink ( "/proc/1/ns/uts" )
if err != nil {
c . Fatal ( err )
}
2015-07-19 20:47:47 +00:00
out , _ := dockerCmd ( c , "run" , "--uts=host" , "busybox" , "readlink" , "/proc/self/ns/uts" )
out = strings . Trim ( out , "\n" )
if hostUTS != out {
c . Fatalf ( "UTS different with --uts=host %s != %s\n" , hostUTS , out )
2015-05-05 22:32:36 +00:00
}
2015-07-19 20:47:47 +00:00
out , _ = dockerCmd ( c , "run" , "busybox" , "readlink" , "/proc/self/ns/uts" )
out = strings . Trim ( out , "\n" )
if hostUTS == out {
c . Fatalf ( "UTS should be different without --uts=host %s == %s\n" , hostUTS , out )
2015-05-05 22:32:36 +00:00
}
2016-03-10 01:40:12 +00:00
out , _ = dockerCmdWithFail ( c , "run" , "-h=name" , "--uts=host" , "busybox" , "ps" )
2019-09-09 21:08:22 +00:00
assert . Assert ( c , strings . Contains ( out , runconfig . ErrConflictUTSHostname . Error ( ) ) )
2015-05-05 22:32:36 +00:00
}
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunTLSVerify ( c * testing . T ) {
2016-02-24 22:59:11 +00:00
// Remote daemons use TLS and this test is not applicable when TLS is required.
2018-12-24 12:25:53 +00:00
testRequires ( c , testEnv . IsLocalDaemon )
2015-07-27 18:13:25 +00:00
if out , code , err := dockerCmdWithError ( "ps" ) ; err != nil || code != 0 {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "Should have worked: %v:\n%v" , err , out )
2014-11-20 15:29:04 +00:00
}
// Regardless of whether we specify true or false we need to
// test to make sure tls is turned on if --tlsverify is specified at all
2016-08-03 16:20:46 +00:00
result := dockerCmdWithResult ( "--tlsverify=false" , "ps" )
2016-09-08 22:37:45 +00:00
result . Assert ( c , icmd . Expected { ExitCode : 1 , Err : "error during connect" } )
2014-11-20 15:29:04 +00:00
2016-08-03 16:20:46 +00:00
result = dockerCmdWithResult ( "--tlsverify=true" , "ps" )
result . Assert ( c , icmd . Expected { ExitCode : 1 , Err : "cert" } )
2014-11-20 15:29:04 +00:00
}
2014-12-02 00:24:43 +00:00
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunPortFromDockerRangeInUse ( c * testing . T ) {
2015-09-01 21:37:04 +00:00
// TODO Windows. Once moved to libnetwork/CNM, this may be able to be
// re-instated.
2015-08-28 17:36:42 +00:00
testRequires ( c , DaemonIsLinux )
2014-12-02 00:24:43 +00:00
// first find allocator current position
2015-07-19 20:47:47 +00:00
out , _ := dockerCmd ( c , "run" , "-d" , "-p" , ":80" , "busybox" , "top" )
2014-12-02 00:24:43 +00:00
id := strings . TrimSpace ( out )
2015-07-19 20:47:47 +00:00
out , _ = dockerCmd ( c , "port" , id )
2015-02-17 10:15:51 +00:00
2015-07-19 20:47:47 +00:00
out = strings . TrimSpace ( out )
2015-02-17 10:15:51 +00:00
if out == "" {
2015-04-18 16:46:47 +00:00
c . Fatal ( "docker port command output is empty" )
2015-02-17 10:15:51 +00:00
}
2014-12-02 00:24:43 +00:00
out = strings . Split ( out , ":" ) [ 1 ]
lastPort , err := strconv . Atoi ( out )
if err != nil {
2015-04-18 16:46:47 +00:00
c . Fatal ( err )
2014-12-02 00:24:43 +00:00
}
port := lastPort + 1
l , err := net . Listen ( "tcp" , ":" + strconv . Itoa ( port ) )
if err != nil {
2015-04-18 16:46:47 +00:00
c . Fatal ( err )
2014-12-02 00:24:43 +00:00
}
defer l . Close ( )
2015-07-19 20:47:47 +00:00
out , _ = dockerCmd ( c , "run" , "-d" , "-p" , ":80" , "busybox" , "top" )
2014-12-02 00:24:43 +00:00
id = strings . TrimSpace ( out )
2015-07-19 20:47:47 +00:00
dockerCmd ( c , "port" , id )
2014-12-02 00:24:43 +00:00
}
2014-12-06 00:50:56 +00:00
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunTTYWithPipe ( c * testing . T ) {
2015-04-27 17:29:48 +00:00
errChan := make ( chan error )
2014-12-06 00:50:56 +00:00
go func ( ) {
2015-04-27 17:29:48 +00:00
defer close ( errChan )
2014-12-06 00:50:56 +00:00
cmd := exec . Command ( dockerBinary , "run" , "-ti" , "busybox" , "true" )
if _ , err := cmd . StdinPipe ( ) ; err != nil {
2015-04-27 17:29:48 +00:00
errChan <- err
return
2014-12-06 00:50:56 +00:00
}
2016-05-25 17:19:17 +00:00
expected := "the input device is not a TTY"
if runtime . GOOS == "windows" {
expected += ". If you are using mintty, try prefixing the command with 'winpty'"
}
2014-12-06 00:50:56 +00:00
if out , _ , err := runCommandWithOutput ( cmd ) ; err == nil {
2015-04-27 17:29:48 +00:00
errChan <- fmt . Errorf ( "run should have failed" )
return
2014-12-06 00:50:56 +00:00
} else if ! strings . Contains ( out , expected ) {
2015-04-27 17:29:48 +00:00
errChan <- fmt . Errorf ( "run failed with error %q: expected %q" , out , expected )
return
2014-12-06 00:50:56 +00:00
}
} ( )
select {
2015-04-27 17:29:48 +00:00
case err := <- errChan :
2019-04-04 13:23:19 +00:00
assert . NilError ( c , err )
2016-05-25 17:19:17 +00:00
case <- time . After ( 30 * time . Second ) :
2015-04-18 16:46:47 +00:00
c . Fatal ( "container is running but should have failed" )
2014-12-06 00:50:56 +00:00
}
}
2014-12-22 22:54:55 +00:00
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunNonLocalMacAddress ( c * testing . T ) {
2014-12-22 22:54:55 +00:00
addr := "00:16:3E:08:00:50"
2016-03-29 00:26:34 +00:00
args := [ ] string { "run" , "--mac-address" , addr }
2015-09-01 21:37:04 +00:00
expected := addr
2018-01-15 14:32:06 +00:00
if testEnv . OSType != "windows" {
2016-03-29 00:26:34 +00:00
args = append ( args , "busybox" , "ifconfig" )
} else {
2018-01-15 14:31:02 +00:00
args = append ( args , testEnv . PlatformDefaults . BaseImage , "ipconfig" , "/all" )
2015-09-23 23:04:51 +00:00
expected = strings . Replace ( strings . ToUpper ( addr ) , ":" , "-" , - 1 )
2015-09-01 21:37:04 +00:00
}
2016-03-29 00:26:34 +00:00
if out , _ := dockerCmd ( c , args ... ) ; ! strings . Contains ( out , expected ) {
2015-09-01 21:37:04 +00:00
c . Fatalf ( "Output should have contained %q: %s" , expected , out )
2014-12-22 22:54:55 +00:00
}
}
2014-12-25 04:40:41 +00:00
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunNetHost ( c * testing . T ) {
2015-09-01 21:37:04 +00:00
// Not applicable on Windows as uses Unix-specific capabilities
2018-12-24 12:25:53 +00:00
testRequires ( c , testEnv . IsLocalDaemon , DaemonIsLinux , NotUserNamespace )
2015-02-26 04:16:44 +00:00
2014-12-29 20:56:07 +00:00
hostNet , err := os . Readlink ( "/proc/1/ns/net" )
2014-12-25 04:40:41 +00:00
if err != nil {
2015-04-18 16:46:47 +00:00
c . Fatal ( err )
2014-12-25 04:40:41 +00:00
}
2015-07-19 20:47:47 +00:00
out , _ := dockerCmd ( c , "run" , "--net=host" , "busybox" , "readlink" , "/proc/self/ns/net" )
out = strings . Trim ( out , "\n" )
if hostNet != out {
c . Fatalf ( "Net namespace different with --net=host %s != %s\n" , hostNet , out )
2014-12-29 20:56:07 +00:00
}
2015-07-19 20:47:47 +00:00
out , _ = dockerCmd ( c , "run" , "busybox" , "readlink" , "/proc/self/ns/net" )
out = strings . Trim ( out , "\n" )
if hostNet == out {
c . Fatalf ( "Net namespace should be different without --net=host %s == %s\n" , hostNet , out )
2014-12-29 20:56:07 +00:00
}
2014-12-25 04:40:41 +00:00
}
2014-11-03 18:15:55 +00:00
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunNetHostTwiceSameName ( c * testing . T ) {
2015-09-01 21:37:04 +00:00
// TODO Windows. As Windows networking evolves and converges towards
// CNM, this test may be possible to enable on Windows.
2018-12-24 12:25:53 +00:00
testRequires ( c , testEnv . IsLocalDaemon , DaemonIsLinux , NotUserNamespace )
2015-06-24 17:23:00 +00:00
2015-07-19 20:47:47 +00:00
dockerCmd ( c , "run" , "--rm" , "--name=thost" , "--net=host" , "busybox" , "true" )
dockerCmd ( c , "run" , "--rm" , "--name=thost" , "--net=host" , "busybox" , "true" )
2015-06-24 17:23:00 +00:00
}
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunNetContainerWhichHost ( c * testing . T ) {
2015-09-01 21:37:04 +00:00
// Not applicable on Windows as uses Unix-specific capabilities
2018-12-24 12:25:53 +00:00
testRequires ( c , testEnv . IsLocalDaemon , DaemonIsLinux , NotUserNamespace )
2015-04-07 22:20:39 +00:00
hostNet , err := os . Readlink ( "/proc/1/ns/net" )
if err != nil {
2015-04-18 16:46:47 +00:00
c . Fatal ( err )
2015-04-07 22:20:39 +00:00
}
2015-07-19 20:47:47 +00:00
dockerCmd ( c , "run" , "-d" , "--net=host" , "--name=test" , "busybox" , "top" )
2015-04-07 22:20:39 +00:00
2015-07-19 20:47:47 +00:00
out , _ := dockerCmd ( c , "run" , "--net=container:test" , "busybox" , "readlink" , "/proc/self/ns/net" )
2015-04-07 22:20:39 +00:00
out = strings . Trim ( out , "\n" )
if hostNet != out {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "Container should have host network namespace" )
2015-04-07 22:20:39 +00:00
}
}
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunAllowPortRangeThroughPublish ( c * testing . T ) {
2015-09-01 21:37:04 +00:00
// TODO Windows. This may be possible to enable in the future. However,
// Windows does not currently support --expose, or populate the network
// settings seen through inspect.
2015-08-28 17:36:42 +00:00
testRequires ( c , DaemonIsLinux )
2015-07-19 20:47:47 +00:00
out , _ := dockerCmd ( c , "run" , "-d" , "--expose" , "3000-3003" , "-p" , "3000-3003" , "busybox" , "top" )
2014-11-03 18:15:55 +00:00
id := strings . TrimSpace ( out )
2016-01-28 14:19:25 +00:00
portstr := inspectFieldJSON ( c , id , "NetworkSettings.Ports" )
2015-07-19 20:47:47 +00:00
2014-11-03 18:15:55 +00:00
var ports nat . PortMap
2016-08-04 16:17:37 +00:00
err := json . Unmarshal ( [ ] byte ( portstr ) , & ports )
2019-04-04 13:23:19 +00:00
assert . NilError ( c , err , "failed to unmarshal: %v" , portstr )
2014-11-03 18:15:55 +00:00
for port , binding := range ports {
portnum , _ := strconv . Atoi ( strings . Split ( string ( port ) , "/" ) [ 0 ] )
if portnum < 3000 || portnum > 3003 {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "Port %d is out of range " , portnum )
2014-11-03 18:15:55 +00:00
}
if binding == nil || len ( binding ) != 1 || len ( binding [ 0 ] . HostPort ) == 0 {
2015-04-18 16:46:47 +00:00
c . Fatal ( "Port is not mapped for the port " + port , out )
2014-11-03 18:15:55 +00:00
}
}
}
2015-01-09 23:42:55 +00:00
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunSetDefaultRestartPolicy ( c * testing . T ) {
2016-05-03 17:52:09 +00:00
runSleepingContainer ( c , "--name=testrunsetdefaultrestartpolicy" )
out := inspectField ( c , "testrunsetdefaultrestartpolicy" , "HostConfig.RestartPolicy.Name" )
2015-03-10 02:09:12 +00:00
if out != "no" {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "Set default restart policy failed" )
2015-03-10 02:09:12 +00:00
}
}
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunRestartMaxRetries ( c * testing . T ) {
2015-07-19 20:47:47 +00:00
out , _ := dockerCmd ( c , "run" , "-d" , "--restart=on-failure:3" , "busybox" , "false" )
2015-09-01 21:37:04 +00:00
timeout := 10 * time . Second
2018-01-15 14:32:06 +00:00
if testEnv . OSType == "windows" {
2016-02-04 19:59:13 +00:00
timeout = 120 * time . Second
2015-09-01 21:37:04 +00:00
}
2015-07-19 20:47:47 +00:00
2019-08-05 15:54:15 +00:00
id := strings . TrimSpace ( out )
2015-09-01 21:37:04 +00:00
if err := waitInspect ( id , "{{ .State.Restarting }} {{ .State.Running }}" , "false false" , timeout ) ; err != nil {
2015-04-18 16:46:47 +00:00
c . Fatal ( err )
2015-01-13 23:19:12 +00:00
}
2015-07-19 20:47:47 +00:00
2016-01-28 14:19:25 +00:00
count := inspectField ( c , id , "RestartCount" )
2015-01-13 23:19:12 +00:00
if count != "3" {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "Container was restarted %s times, expected %d" , count , 3 )
2015-01-13 23:19:12 +00:00
}
2015-07-19 20:47:47 +00:00
2016-01-28 14:19:25 +00:00
MaximumRetryCount := inspectField ( c , id , "HostConfig.RestartPolicy.MaximumRetryCount" )
2015-03-17 05:19:59 +00:00
if MaximumRetryCount != "3" {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "Container Maximum Retry Count is %s, expected %s" , MaximumRetryCount , "3" )
2015-03-17 05:19:59 +00:00
}
2015-01-13 23:19:12 +00:00
}
2015-01-13 21:52:51 +00:00
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunContainerWithWritableRootfs ( c * testing . T ) {
2015-07-19 20:47:47 +00:00
dockerCmd ( c , "run" , "--rm" , "busybox" , "touch" , "/file" )
2015-01-13 21:52:51 +00:00
}
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunContainerWithReadonlyRootfs ( c * testing . T ) {
2015-09-01 21:37:04 +00:00
// Not applicable on Windows which does not support --read-only
2016-08-09 16:14:38 +00:00
testRequires ( c , DaemonIsLinux , UserNamespaceROMount )
2015-02-26 04:16:44 +00:00
2016-08-09 16:14:38 +00:00
testPriv := true
// don't test privileged mode subtest if user namespaces enabled
if root := os . Getenv ( "DOCKER_REMAP_ROOT" ) ; root != "" {
testPriv = false
}
2018-04-06 13:01:38 +00:00
testReadOnlyFile ( c , testPriv , "/file" , "/etc/hosts" , "/etc/resolv.conf" , "/etc/hostname" )
2015-05-02 15:29:00 +00:00
}
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestPermissionsPtsReadonlyRootfs ( c * testing . T ) {
2015-09-01 21:37:04 +00:00
// Not applicable on Windows due to use of Unix specific functionality, plus
// the use of --read-only which is not supported.
2016-08-09 16:14:38 +00:00
testRequires ( c , DaemonIsLinux , UserNamespaceROMount )
2015-06-02 16:16:43 +00:00
// Ensure we have not broken writing /dev/pts
out , status := dockerCmd ( c , "run" , "--read-only" , "--rm" , "busybox" , "mount" )
if status != 0 {
c . Fatal ( "Could not obtain mounts when checking /dev/pts mntpnt." )
}
expected := "type devpts (rw,"
2019-08-05 15:54:15 +00:00
if ! strings . Contains ( out , expected ) {
2015-06-02 16:16:43 +00:00
c . Fatalf ( "expected output to contain %s but contains %s" , expected , out )
}
}
2019-09-09 21:05:55 +00:00
func testReadOnlyFile ( c * testing . T , testPriv bool , filenames ... string ) {
2016-03-12 10:58:03 +00:00
touch := "touch " + strings . Join ( filenames , " " )
out , _ , err := dockerCmdWithError ( "run" , "--read-only" , "--rm" , "busybox" , "sh" , "-c" , touch )
2019-04-04 13:23:19 +00:00
assert . ErrorContains ( c , err , "" )
2015-05-02 15:29:00 +00:00
2016-03-12 10:58:03 +00:00
for _ , f := range filenames {
expected := "touch: " + f + ": Read-only file system"
2019-04-04 13:23:19 +00:00
assert . Assert ( c , strings . Contains ( out , expected ) )
2015-01-13 21:52:51 +00:00
}
2015-06-02 16:16:43 +00:00
2016-08-09 16:14:38 +00:00
if ! testPriv {
return
}
2016-03-12 10:58:03 +00:00
out , _ , err = dockerCmdWithError ( "run" , "--read-only" , "--privileged" , "--rm" , "busybox" , "sh" , "-c" , touch )
2019-04-04 13:23:19 +00:00
assert . ErrorContains ( c , err , "" )
2016-03-12 10:58:03 +00:00
for _ , f := range filenames {
expected := "touch: " + f + ": Read-only file system"
2019-04-04 13:23:19 +00:00
assert . Assert ( c , strings . Contains ( out , expected ) )
2015-01-13 21:52:51 +00:00
}
}
2014-12-18 14:57:36 +00:00
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunContainerWithReadonlyEtcHostsAndLinkedContainer ( c * testing . T ) {
2015-09-01 21:37:04 +00:00
// Not applicable on Windows which does not support --link
2016-08-09 16:14:38 +00:00
testRequires ( c , DaemonIsLinux , UserNamespaceROMount )
2015-05-02 15:29:00 +00:00
2015-07-19 20:47:47 +00:00
dockerCmd ( c , "run" , "-d" , "--name" , "test-etc-hosts-ro-linked" , "busybox" , "top" )
2015-05-02 15:29:00 +00:00
2015-07-19 20:47:47 +00:00
out , _ := dockerCmd ( c , "run" , "--read-only" , "--link" , "test-etc-hosts-ro-linked:testlinked" , "busybox" , "cat" , "/etc/hosts" )
2019-08-05 15:54:15 +00:00
if ! strings . Contains ( out , "testlinked" ) {
2015-05-02 15:29:00 +00:00
c . Fatal ( "Expected /etc/hosts to be updated even if --read-only enabled" )
}
}
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunContainerWithReadonlyRootfsWithDNSFlag ( c * testing . T ) {
2015-09-18 17:41:12 +00:00
// Not applicable on Windows which does not support either --read-only or --dns.
2016-08-09 16:14:38 +00:00
testRequires ( c , DaemonIsLinux , UserNamespaceROMount )
2015-05-02 15:29:00 +00:00
2015-07-19 20:47:47 +00:00
out , _ := dockerCmd ( c , "run" , "--read-only" , "--dns" , "1.1.1.1" , "busybox" , "/bin/cat" , "/etc/resolv.conf" )
2019-08-05 15:54:15 +00:00
if ! strings . Contains ( out , "1.1.1.1" ) {
2015-05-02 15:29:00 +00:00
c . Fatal ( "Expected /etc/resolv.conf to be updated even if --read-only enabled and --dns flag used" )
}
}
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunContainerWithReadonlyRootfsWithAddHostFlag ( c * testing . T ) {
2015-09-01 21:37:04 +00:00
// Not applicable on Windows which does not support --read-only
2016-08-09 16:14:38 +00:00
testRequires ( c , DaemonIsLinux , UserNamespaceROMount )
2015-05-02 15:29:00 +00:00
2015-07-19 20:47:47 +00:00
out , _ := dockerCmd ( c , "run" , "--read-only" , "--add-host" , "testreadonly:127.0.0.1" , "busybox" , "/bin/cat" , "/etc/hosts" )
2019-08-05 15:54:15 +00:00
if ! strings . Contains ( out , "testreadonly" ) {
2015-05-02 15:29:00 +00:00
c . Fatal ( "Expected /etc/hosts to be updated even if --read-only enabled and --add-host flag used" )
}
}
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunVolumesFromRestartAfterRemoved ( c * testing . T ) {
2016-02-03 14:16:00 +00:00
prefix , _ := getPrefixAndSlashFromDaemonPlatform ( )
2016-05-03 17:52:09 +00:00
runSleepingContainer ( c , "--name=voltest" , "-v" , prefix + "/foo" )
runSleepingContainer ( c , "--name=restarter" , "--volumes-from" , "voltest" )
2014-12-18 14:57:36 +00:00
// Remove the main volume container and restart the consuming container
2015-07-19 20:47:47 +00:00
dockerCmd ( c , "rm" , "-f" , "voltest" )
2014-12-18 14:57:36 +00:00
// This should not fail since the volumes-from were already applied
2015-07-19 20:47:47 +00:00
dockerCmd ( c , "restart" , "restarter" )
2014-12-18 14:57:36 +00:00
}
2015-03-22 18:09:12 +00:00
// run container with --rm should remove container if exit code != 0
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunContainerWithRmFlagExitCodeNotEqualToZero ( c * testing . T ) {
2017-09-08 15:16:15 +00:00
existingContainers := ExistingContainerIDs ( c )
2015-04-08 23:20:42 +00:00
name := "flowers"
2017-04-11 17:42:54 +00:00
cli . Docker ( cli . Args ( "run" , "--name" , name , "--rm" , "busybox" , "ls" , "/notexists" ) ) . Assert ( c , icmd . Expected {
ExitCode : 1 ,
} )
2015-03-22 18:09:12 +00:00
2017-04-11 17:42:54 +00:00
out := cli . DockerCmd ( c , "ps" , "-q" , "-a" ) . Combined ( )
2017-09-08 15:16:15 +00:00
out = RemoveOutputForExistingElements ( out , existingContainers )
2015-03-22 18:09:12 +00:00
if out != "" {
2015-04-18 16:46:47 +00:00
c . Fatal ( "Expected not to have containers" , out )
2015-03-22 18:09:12 +00:00
}
}
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunContainerWithRmFlagCannotStartContainer ( c * testing . T ) {
2017-09-08 15:16:15 +00:00
existingContainers := ExistingContainerIDs ( c )
2015-04-08 23:20:42 +00:00
name := "sparkles"
2017-04-11 17:42:54 +00:00
cli . Docker ( cli . Args ( "run" , "--name" , name , "--rm" , "busybox" , "commandNotFound" ) ) . Assert ( c , icmd . Expected {
ExitCode : 127 ,
} )
out := cli . DockerCmd ( c , "ps" , "-q" , "-a" ) . Combined ( )
2017-09-08 15:16:15 +00:00
out = RemoveOutputForExistingElements ( out , existingContainers )
2015-03-22 18:09:12 +00:00
if out != "" {
2015-04-18 16:46:47 +00:00
c . Fatal ( "Expected not to have containers" , out )
2015-03-22 18:09:12 +00:00
}
}
2015-04-10 18:04:30 +00:00
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunPIDHostWithChildIsKillable ( c * testing . T ) {
2015-09-01 21:37:04 +00:00
// Not applicable on Windows as uses Unix specific functionality
2015-09-18 17:41:12 +00:00
testRequires ( c , DaemonIsLinux , NotUserNamespace )
2015-04-10 18:04:30 +00:00
name := "ibuildthecloud"
2015-07-19 20:47:47 +00:00
dockerCmd ( c , "run" , "-d" , "--pid=host" , "--name" , name , "busybox" , "sh" , "-c" , "sleep 30; echo hi" )
2019-09-09 21:05:57 +00:00
assert . Assert ( c , waitRun ( name ) == nil )
2015-08-11 07:41:11 +00:00
2015-04-10 18:04:30 +00:00
errchan := make ( chan error )
go func ( ) {
2015-07-27 18:13:25 +00:00
if out , _ , err := dockerCmdWithError ( "kill" , name ) ; err != nil {
2015-04-10 18:04:30 +00:00
errchan <- fmt . Errorf ( "%v:\n%s" , err , out )
}
close ( errchan )
} ( )
select {
case err := <- errchan :
2019-04-04 13:23:19 +00:00
assert . NilError ( c , err )
2015-04-10 18:04:30 +00:00
case <- time . After ( 5 * time . Second ) :
2015-04-18 16:46:47 +00:00
c . Fatal ( "Kill container timed out" )
2015-04-10 18:04:30 +00:00
}
}
2015-04-20 18:58:24 +00:00
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunWithTooSmallMemoryLimit ( c * testing . T ) {
2015-09-01 21:37:04 +00:00
// TODO Windows. This may be possible to enable once Windows supports
// memory limits on containers
2015-08-28 17:36:42 +00:00
testRequires ( c , DaemonIsLinux )
2015-04-20 18:58:24 +00:00
// this memory limit is 1 byte less than the min, which is 4MB
// https://github.com/docker/docker/blob/v1.5.0/daemon/create.go#L22
2015-07-27 18:13:25 +00:00
out , _ , err := dockerCmdWithError ( "run" , "-m" , "4194303" , "busybox" )
2015-04-20 18:58:24 +00:00
if err == nil || ! strings . Contains ( out , "Minimum memory limit allowed is 4MB" ) {
2015-05-07 22:02:08 +00:00
c . Fatalf ( "expected run to fail when using too low a memory limit: %q" , out )
2015-04-20 18:58:24 +00:00
}
}
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunWriteToProcAsound ( c * testing . T ) {
2015-09-01 21:37:04 +00:00
// Not applicable on Windows as uses Unix specific functionality
2015-08-28 17:36:42 +00:00
testRequires ( c , DaemonIsLinux )
2015-07-27 18:13:25 +00:00
_ , code , err := dockerCmdWithError ( "run" , "busybox" , "sh" , "-c" , "echo 111 >> /proc/asound/version" )
2015-04-20 18:58:24 +00:00
if err == nil || code == 0 {
2015-05-07 22:02:08 +00:00
c . Fatal ( "standard container should not be able to write to /proc/asound" )
2015-04-20 18:58:24 +00:00
}
}
2015-04-20 20:54:49 +00:00
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunReadProcTimer ( c * testing . T ) {
2015-09-01 21:37:04 +00:00
// Not applicable on Windows as uses Unix specific functionality
2015-11-05 00:40:58 +00:00
testRequires ( c , DaemonIsLinux )
2015-07-27 18:13:25 +00:00
out , code , err := dockerCmdWithError ( "run" , "busybox" , "cat" , "/proc/timer_stats" )
2015-07-28 18:48:18 +00:00
if code != 0 {
return
}
if err != nil {
2015-05-07 22:02:08 +00:00
c . Fatal ( err )
2015-04-29 18:20:31 +00:00
}
if strings . Trim ( out , "\n " ) != "" {
2015-05-07 22:02:08 +00:00
c . Fatalf ( "expected to receive no output from /proc/timer_stats but received %q" , out )
2015-04-20 20:54:49 +00:00
}
}
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunReadProcLatency ( c * testing . T ) {
2015-09-01 21:37:04 +00:00
// Not applicable on Windows as uses Unix specific functionality
2015-11-05 00:40:58 +00:00
testRequires ( c , DaemonIsLinux )
2015-04-29 18:20:31 +00:00
// some kernels don't have this configured so skip the test if this file is not found
// on the host running the tests.
if _ , err := os . Stat ( "/proc/latency_stats" ) ; err != nil {
2016-02-22 19:22:20 +00:00
c . Skip ( "kernel doesn't have latency_stats configured" )
2015-04-29 18:20:31 +00:00
return
}
2015-07-27 18:13:25 +00:00
out , code , err := dockerCmdWithError ( "run" , "busybox" , "cat" , "/proc/latency_stats" )
2015-07-28 18:48:18 +00:00
if code != 0 {
return
}
if err != nil {
2015-05-07 22:02:08 +00:00
c . Fatal ( err )
2015-04-29 18:20:31 +00:00
}
if strings . Trim ( out , "\n " ) != "" {
2015-05-07 22:02:08 +00:00
c . Fatalf ( "expected to receive no output from /proc/latency_stats but received %q" , out )
2015-04-20 20:54:49 +00:00
}
}
2015-04-22 00:31:05 +00:00
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunReadFilteredProc ( c * testing . T ) {
2015-09-01 21:37:04 +00:00
// Not applicable on Windows as uses Unix specific functionality
2015-09-18 17:41:12 +00:00
testRequires ( c , Apparmor , DaemonIsLinux , NotUserNamespace )
2015-07-28 18:48:18 +00:00
testReadPaths := [ ] string {
"/proc/latency_stats" ,
"/proc/timer_stats" ,
"/proc/kcore" ,
}
for i , filePath := range testReadPaths {
name := fmt . Sprintf ( "procsieve-%d" , i )
shellCmd := fmt . Sprintf ( "exec 3<%s" , filePath )
2016-03-15 22:34:29 +00:00
out , exitCode , err := dockerCmdWithError ( "run" , "--privileged" , "--security-opt" , "apparmor=docker-default" , "--name" , name , "busybox" , "sh" , "-c" , shellCmd )
2015-07-29 20:57:14 +00:00
if exitCode != 0 {
return
}
if err != nil {
2015-07-28 18:48:18 +00:00
c . Fatalf ( "Open FD for read should have failed with permission denied, got: %s, %v" , out , err )
}
}
}
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestMountIntoProc ( c * testing . T ) {
2015-09-01 21:37:04 +00:00
// Not applicable on Windows as uses Unix specific functionality
2015-08-28 17:36:42 +00:00
testRequires ( c , DaemonIsLinux )
2015-07-27 18:13:25 +00:00
_ , code , err := dockerCmdWithError ( "run" , "-v" , "/proc//sys" , "busybox" , "true" )
2015-04-22 00:31:05 +00:00
if err == nil || code == 0 {
2015-05-07 22:02:08 +00:00
c . Fatal ( "container should not be able to mount into /proc" )
2015-04-22 00:31:05 +00:00
}
}
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestMountIntoSys ( c * testing . T ) {
2015-09-01 21:37:04 +00:00
// Not applicable on Windows as uses Unix specific functionality
2015-09-18 17:41:12 +00:00
testRequires ( c , DaemonIsLinux )
2015-11-05 00:40:58 +00:00
testRequires ( c , NotUserNamespace )
2015-07-19 20:47:47 +00:00
dockerCmd ( c , "run" , "-v" , "/sys/fs/cgroup" , "busybox" , "true" )
2015-04-22 00:31:05 +00:00
}
2015-05-20 16:35:24 +00:00
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunUnshareProc ( c * testing . T ) {
2015-09-01 21:37:04 +00:00
// Not applicable on Windows as uses Unix specific functionality
2015-11-17 19:49:31 +00:00
testRequires ( c , Apparmor , DaemonIsLinux , NotUserNamespace )
2015-05-04 20:20:01 +00:00
2016-03-04 05:15:41 +00:00
// In this test goroutines are used to run test cases in parallel to prevent the test from taking a long time to run.
errChan := make ( chan error )
2015-05-04 20:20:01 +00:00
2016-03-04 05:15:41 +00:00
go func ( ) {
name := "acidburn"
2016-03-15 22:34:29 +00:00
out , _ , err := dockerCmdWithError ( "run" , "--name" , name , "--security-opt" , "seccomp=unconfined" , "debian:jessie" , "unshare" , "-p" , "-m" , "-f" , "-r" , "--mount-proc=/proc" , "mount" )
2016-03-04 05:15:41 +00:00
if err == nil ||
! ( strings . Contains ( strings . ToLower ( out ) , "permission denied" ) ||
strings . Contains ( strings . ToLower ( out ) , "operation not permitted" ) ) {
errChan <- fmt . Errorf ( "unshare with --mount-proc should have failed with 'permission denied' or 'operation not permitted', got: %s, %v" , out , err )
} else {
errChan <- nil
}
} ( )
go func ( ) {
name := "cereal"
2016-03-15 22:34:29 +00:00
out , _ , err := dockerCmdWithError ( "run" , "--name" , name , "--security-opt" , "seccomp=unconfined" , "debian:jessie" , "unshare" , "-p" , "-m" , "-f" , "-r" , "mount" , "-t" , "proc" , "none" , "/proc" )
2016-03-04 05:15:41 +00:00
if err == nil ||
! ( strings . Contains ( strings . ToLower ( out ) , "mount: cannot mount none" ) ||
2016-03-18 18:50:19 +00:00
strings . Contains ( strings . ToLower ( out ) , "permission denied" ) ||
strings . Contains ( strings . ToLower ( out ) , "operation not permitted" ) ) {
2016-03-04 05:15:41 +00:00
errChan <- fmt . Errorf ( "unshare and mount of /proc should have failed with 'mount: cannot mount none' or 'permission denied', got: %s, %v" , out , err )
} else {
errChan <- nil
}
} ( )
2015-05-28 18:55:22 +00:00
/* Ensure still fails if running privileged with the default policy */
2016-03-04 05:15:41 +00:00
go func ( ) {
name := "crashoverride"
2016-03-15 22:34:29 +00:00
out , _ , err := dockerCmdWithError ( "run" , "--privileged" , "--security-opt" , "seccomp=unconfined" , "--security-opt" , "apparmor=docker-default" , "--name" , name , "debian:jessie" , "unshare" , "-p" , "-m" , "-f" , "-r" , "mount" , "-t" , "proc" , "none" , "/proc" )
2016-03-04 05:15:41 +00:00
if err == nil ||
! ( strings . Contains ( strings . ToLower ( out ) , "mount: cannot mount none" ) ||
2016-03-18 18:50:19 +00:00
strings . Contains ( strings . ToLower ( out ) , "permission denied" ) ||
strings . Contains ( strings . ToLower ( out ) , "operation not permitted" ) ) {
2016-03-04 05:15:41 +00:00
errChan <- fmt . Errorf ( "privileged unshare with apparmor should have failed with 'mount: cannot mount none' or 'permission denied', got: %s, %v" , out , err )
} else {
errChan <- nil
}
} ( )
2017-01-11 20:38:52 +00:00
var retErr error
2016-03-04 05:15:41 +00:00
for i := 0 ; i < 3 ; i ++ {
err := <- errChan
2017-01-11 20:38:52 +00:00
if retErr == nil && err != nil {
retErr = err
2016-03-04 05:15:41 +00:00
}
2015-05-04 20:20:01 +00:00
}
2017-01-11 20:38:52 +00:00
if retErr != nil {
c . Fatal ( retErr )
}
2015-05-04 20:20:01 +00:00
}
2015-05-17 18:57:17 +00:00
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunPublishPort ( c * testing . T ) {
2015-09-01 21:37:04 +00:00
// TODO Windows: This may be possible once Windows moves to libnetwork and CNM
2015-08-28 17:36:42 +00:00
testRequires ( c , DaemonIsLinux )
2015-07-19 20:47:47 +00:00
dockerCmd ( c , "run" , "-d" , "--name" , "test" , "--expose" , "8080" , "busybox" , "top" )
out , _ := dockerCmd ( c , "port" , "test" )
2015-05-17 18:57:17 +00:00
out = strings . Trim ( out , "\r\n" )
if out != "" {
c . Fatalf ( "run without --publish-all should not publish port, out should be nil, but got: %s" , out )
}
}
2015-05-29 15:29:56 +00:00
// Issue #10184.
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestDevicePermissions ( c * testing . T ) {
2015-09-01 21:37:04 +00:00
// Not applicable on Windows as uses Unix specific functionality
2015-08-28 17:36:42 +00:00
testRequires ( c , DaemonIsLinux )
2015-05-29 15:29:56 +00:00
const permissions = "crw-rw-rw-"
out , status := dockerCmd ( c , "run" , "--device" , "/dev/fuse:/dev/fuse:mrw" , "busybox:latest" , "ls" , "-l" , "/dev/fuse" )
if status != 0 {
c . Fatalf ( "expected status 0, got %d" , status )
}
if ! strings . HasPrefix ( out , permissions ) {
c . Fatalf ( "output should begin with %q, got %q" , permissions , out )
}
}
2015-05-27 07:31:06 +00:00
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunCapAddCHOWN ( c * testing . T ) {
2015-09-01 21:37:04 +00:00
// Not applicable on Windows as uses Unix specific functionality
2015-08-28 17:36:42 +00:00
testRequires ( c , DaemonIsLinux )
2015-07-19 20:47:47 +00:00
out , _ := dockerCmd ( c , "run" , "--cap-drop=ALL" , "--cap-add=CHOWN" , "busybox" , "sh" , "-c" , "adduser -D -H newuser && chown newuser /home && echo ok" )
2015-07-03 15:25:52 +00:00
if actual := strings . Trim ( out , "\r\n" ) ; actual != "ok" {
c . Fatalf ( "expected output ok received %s" , actual )
}
}
2015-07-09 14:40:39 +00:00
// https://github.com/docker/docker/pull/14498
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestVolumeFromMixedRWOptions ( c * testing . T ) {
2016-02-03 14:16:00 +00:00
prefix , slash := getPrefixAndSlashFromDaemonPlatform ( )
2015-09-23 23:04:51 +00:00
dockerCmd ( c , "run" , "--name" , "parent" , "-v" , prefix + "/test" , "busybox" , "true" )
2016-05-25 20:56:36 +00:00
2016-11-23 22:28:06 +00:00
dockerCmd ( c , "run" , "--volumes-from" , "parent:ro" , "--name" , "test-volumes-1" , "busybox" , "true" )
2015-07-09 14:40:39 +00:00
dockerCmd ( c , "run" , "--volumes-from" , "parent:rw" , "--name" , "test-volumes-2" , "busybox" , "true" )
2018-01-15 14:32:06 +00:00
if testEnv . OSType != "windows" {
2015-09-23 23:04:51 +00:00
mRO , err := inspectMountPoint ( "test-volumes-1" , prefix + slash + "test" )
2019-04-04 13:23:19 +00:00
assert . NilError ( c , err , "failed to inspect mount point" )
2015-09-23 23:04:51 +00:00
if mRO . RW {
c . Fatalf ( "Expected RO volume was RW" )
}
2015-07-09 14:40:39 +00:00
}
2015-06-03 19:21:38 +00:00
2015-09-23 23:04:51 +00:00
mRW , err := inspectMountPoint ( "test-volumes-2" , prefix + slash + "test" )
2019-04-04 13:23:19 +00:00
assert . NilError ( c , err , "failed to inspect mount point" )
2015-06-03 19:21:38 +00:00
if ! mRW . RW {
2015-07-09 14:40:39 +00:00
c . Fatalf ( "Expected RW volume was RO" )
}
}
2015-05-12 03:00:05 +00:00
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunWriteFilteredProc ( c * testing . T ) {
2015-09-01 21:37:04 +00:00
// Not applicable on Windows as uses Unix specific functionality
2015-11-05 00:40:58 +00:00
testRequires ( c , Apparmor , DaemonIsLinux , NotUserNamespace )
2015-05-12 03:00:05 +00:00
testWritePaths := [ ] string {
/ * modprobe and core_pattern should both be denied by generic
* policy of denials for / proc / sys / kernel . These files have been
* picked to be checked as they are particularly sensitive to writes * /
"/proc/sys/kernel/modprobe" ,
"/proc/sys/kernel/core_pattern" ,
"/proc/sysrq-trigger" ,
2015-07-28 18:48:18 +00:00
"/proc/kcore" ,
2015-05-12 03:00:05 +00:00
}
for i , filePath := range testWritePaths {
name := fmt . Sprintf ( "writeprocsieve-%d" , i )
shellCmd := fmt . Sprintf ( "exec 3>%s" , filePath )
2016-03-15 22:34:29 +00:00
out , code , err := dockerCmdWithError ( "run" , "--privileged" , "--security-opt" , "apparmor=docker-default" , "--name" , name , "busybox" , "sh" , "-c" , shellCmd )
2015-07-29 20:57:14 +00:00
if code != 0 {
return
}
if err != nil {
2015-05-12 03:00:05 +00:00
c . Fatalf ( "Open FD for write should have failed with permission denied, got: %s, %v" , out , err )
}
}
}
2015-07-14 00:54:00 +00:00
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunNetworkFilesBindMount ( c * testing . T ) {
2015-09-01 21:37:04 +00:00
// Not applicable on Windows as uses Unix specific functionality
2018-12-24 12:25:53 +00:00
testRequires ( c , testEnv . IsLocalDaemon , DaemonIsLinux )
2015-07-14 00:54:00 +00:00
2015-07-24 18:23:20 +00:00
expected := "test123"
2015-07-14 00:54:00 +00:00
2015-07-24 18:23:20 +00:00
filename := createTmpFile ( c , expected )
2015-07-14 00:54:00 +00:00
defer os . Remove ( filename )
2017-07-23 02:11:09 +00:00
// for user namespaced test runs, the temp file must be accessible to unprivileged root
if err := os . Chmod ( filename , 0646 ) ; err != nil {
c . Fatalf ( "error modifying permissions of %s: %v" , filename , err )
}
2015-07-24 18:23:20 +00:00
nwfiles := [ ] string { "/etc/resolv.conf" , "/etc/hosts" , "/etc/hostname" }
2015-07-14 00:54:00 +00:00
2015-07-24 18:23:20 +00:00
for i := range nwfiles {
actual , _ := dockerCmd ( c , "run" , "-v" , filename + ":" + nwfiles [ i ] , "busybox" , "cat" , nwfiles [ i ] )
if actual != expected {
c . Fatalf ( "expected %s be: %q, but was: %q" , nwfiles [ i ] , expected , actual )
}
}
}
2015-07-14 00:54:00 +00:00
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunNetworkFilesBindMountRO ( c * testing . T ) {
2015-09-01 21:37:04 +00:00
// Not applicable on Windows as uses Unix specific functionality
2018-12-24 12:25:53 +00:00
testRequires ( c , testEnv . IsLocalDaemon , DaemonIsLinux )
2015-07-24 18:23:20 +00:00
filename := createTmpFile ( c , "test123" )
defer os . Remove ( filename )
2017-07-23 02:11:09 +00:00
// for user namespaced test runs, the temp file must be accessible to unprivileged root
if err := os . Chmod ( filename , 0646 ) ; err != nil {
c . Fatalf ( "error modifying permissions of %s: %v" , filename , err )
}
2015-07-24 18:23:20 +00:00
nwfiles := [ ] string { "/etc/resolv.conf" , "/etc/hosts" , "/etc/hostname" }
for i := range nwfiles {
_ , exitCode , err := dockerCmdWithError ( "run" , "-v" , filename + ":" + nwfiles [ i ] + ":ro" , "busybox" , "touch" , nwfiles [ i ] )
if err == nil || exitCode == 0 {
c . Fatalf ( "run should fail because bind mount of %s is ro: exit code %d" , nwfiles [ i ] , exitCode )
}
}
}
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunNetworkFilesBindMountROFilesystem ( c * testing . T ) {
2015-09-01 21:37:04 +00:00
// Not applicable on Windows as uses Unix specific functionality
2018-12-24 12:25:53 +00:00
testRequires ( c , testEnv . IsLocalDaemon , DaemonIsLinux , UserNamespaceROMount )
2015-07-24 18:23:20 +00:00
filename := createTmpFile ( c , "test123" )
defer os . Remove ( filename )
2017-07-23 02:11:09 +00:00
// for user namespaced test runs, the temp file must be accessible to unprivileged root
if err := os . Chmod ( filename , 0646 ) ; err != nil {
c . Fatalf ( "error modifying permissions of %s: %v" , filename , err )
}
2015-07-24 18:23:20 +00:00
nwfiles := [ ] string { "/etc/resolv.conf" , "/etc/hosts" , "/etc/hostname" }
for i := range nwfiles {
_ , exitCode := dockerCmd ( c , "run" , "-v" , filename + ":" + nwfiles [ i ] , "--read-only" , "busybox" , "touch" , nwfiles [ i ] )
if exitCode != 0 {
c . Fatalf ( "run should not fail because %s is mounted writable on read-only root filesystem: exit code %d" , nwfiles [ i ] , exitCode )
}
}
for i := range nwfiles {
_ , exitCode , err := dockerCmdWithError ( "run" , "-v" , filename + ":" + nwfiles [ i ] + ":ro" , "--read-only" , "busybox" , "touch" , nwfiles [ i ] )
if err == nil || exitCode == 0 {
c . Fatalf ( "run should fail because %s is mounted read-only on read-only root filesystem: exit code %d" , nwfiles [ i ] , exitCode )
}
2015-07-14 00:54:00 +00:00
}
}
2015-07-22 16:14:48 +00:00
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestPtraceContainerProcsFromHost ( c * testing . T ) {
2015-09-01 21:37:04 +00:00
// Not applicable on Windows as uses Unix specific functionality
2018-12-24 12:25:53 +00:00
testRequires ( c , DaemonIsLinux , testEnv . IsLocalDaemon )
2015-07-30 16:54:21 +00:00
out , _ := dockerCmd ( c , "run" , "-d" , "busybox" , "top" )
id := strings . TrimSpace ( out )
2019-04-04 13:23:19 +00:00
assert . NilError ( c , waitRun ( id ) )
2016-01-28 14:19:25 +00:00
pid1 := inspectField ( c , id , "State.Pid" )
2015-07-30 16:54:21 +00:00
2016-01-28 14:19:25 +00:00
_ , err := os . Readlink ( fmt . Sprintf ( "/proc/%s/ns/net" , pid1 ) )
2015-07-30 16:54:21 +00:00
if err != nil {
c . Fatal ( err )
}
}
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestAppArmorDeniesPtrace ( c * testing . T ) {
2015-09-01 21:37:04 +00:00
// Not applicable on Windows as uses Unix specific functionality
2018-12-24 12:25:53 +00:00
testRequires ( c , testEnv . IsLocalDaemon , Apparmor , DaemonIsLinux )
2015-07-30 16:54:21 +00:00
// Run through 'sh' so we are NOT pid 1. Pid 1 may be able to trace
// itself, but pid>1 should not be able to trace pid1.
2015-10-10 04:35:09 +00:00
_ , exitCode , _ := dockerCmdWithError ( "run" , "busybox" , "sh" , "-c" , "sh -c readlink /proc/1/ns/net" )
2015-07-30 16:54:21 +00:00
if exitCode == 0 {
c . Fatal ( "ptrace was not successfully restricted by AppArmor" )
}
}
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestAppArmorTraceSelf ( c * testing . T ) {
2015-09-01 21:37:04 +00:00
// Not applicable on Windows as uses Unix specific functionality
2018-12-24 12:25:53 +00:00
testRequires ( c , DaemonIsLinux , testEnv . IsLocalDaemon , Apparmor )
2015-07-30 16:54:21 +00:00
_ , exitCode , _ := dockerCmdWithError ( "run" , "busybox" , "readlink" , "/proc/1/ns/net" )
if exitCode != 0 {
c . Fatal ( "ptrace of self failed." )
}
}
2015-07-31 04:53:46 +00:00
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestAppArmorDeniesChmodProc ( c * testing . T ) {
2015-09-01 21:37:04 +00:00
// Not applicable on Windows as uses Unix specific functionality
2018-12-24 12:25:53 +00:00
testRequires ( c , testEnv . IsLocalDaemon , Apparmor , DaemonIsLinux , NotUserNamespace )
2015-08-13 16:35:03 +00:00
_ , exitCode , _ := dockerCmdWithError ( "run" , "busybox" , "chmod" , "744" , "/proc/cpuinfo" )
if exitCode == 0 {
// If our test failed, attempt to repair the host system...
_ , exitCode , _ := dockerCmdWithError ( "run" , "busybox" , "chmod" , "444" , "/proc/cpuinfo" )
if exitCode == 0 {
c . Fatal ( "AppArmor was unsuccessful in prohibiting chmod of /proc/* files." )
}
}
}
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunCapAddSYSTIME ( c * testing . T ) {
2015-09-01 21:37:04 +00:00
// Not applicable on Windows as uses Unix specific functionality
2015-11-05 00:40:58 +00:00
testRequires ( c , DaemonIsLinux )
2015-08-01 02:07:40 +00:00
2015-07-31 04:53:46 +00:00
dockerCmd ( c , "run" , "--cap-drop=ALL" , "--cap-add=SYS_TIME" , "busybox" , "sh" , "-c" , "grep ^CapEff /proc/self/status | sed 's/^CapEff:\t//' | grep ^0000000002000000$" )
}
2015-08-11 14:21:52 +00:00
// run create container failed should clean up the container
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunCreateContainerFailedCleanUp ( c * testing . T ) {
2015-09-01 21:37:04 +00:00
// TODO Windows. This may be possible to enable once link is supported
2015-08-28 17:36:42 +00:00
testRequires ( c , DaemonIsLinux )
2015-08-11 14:21:52 +00:00
name := "unique_name"
_ , _ , err := dockerCmdWithError ( "run" , "--name" , name , "--link" , "nothing:nothing" , "busybox" )
2019-09-09 21:08:22 +00:00
assert . Assert ( c , err != nil , "Expected docker run to fail!" )
2015-08-11 14:21:52 +00:00
2016-01-28 14:19:25 +00:00
containerID , err := inspectFieldWithError ( name , "Id" )
2019-09-11 10:57:29 +00:00
assert . Assert ( c , err != nil , "Expected not to have this container: %s!" , containerID )
2019-09-09 21:08:22 +00:00
assert . Equal ( c , containerID , "" , fmt . Sprintf ( "Expected not to have this container: %s!" , containerID ) )
2015-08-11 14:21:52 +00:00
}
2015-06-12 13:25:32 +00:00
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunNamedVolume ( c * testing . T ) {
2016-02-03 14:16:00 +00:00
prefix , _ := getPrefixAndSlashFromDaemonPlatform ( )
2015-08-28 17:36:42 +00:00
testRequires ( c , DaemonIsLinux )
2016-02-01 00:30:15 +00:00
dockerCmd ( c , "run" , "--name=test" , "-v" , "testing:" + prefix + "/foo" , "busybox" , "sh" , "-c" , "echo hello > " + prefix + "/foo/bar" )
2015-06-12 13:25:32 +00:00
2015-09-23 23:04:51 +00:00
out , _ := dockerCmd ( c , "run" , "--volumes-from" , "test" , "busybox" , "sh" , "-c" , "cat " + prefix + "/foo/bar" )
2019-09-09 21:05:56 +00:00
assert . Equal ( c , strings . TrimSpace ( out ) , "hello" )
2015-06-12 13:25:32 +00:00
2016-02-01 00:30:15 +00:00
out , _ = dockerCmd ( c , "run" , "-v" , "testing:" + prefix + "/foo" , "busybox" , "sh" , "-c" , "cat " + prefix + "/foo/bar" )
2019-09-09 21:05:56 +00:00
assert . Equal ( c , strings . TrimSpace ( out ) , "hello" )
2015-06-12 13:25:32 +00:00
}
2015-09-01 16:42:19 +00:00
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunWithUlimits ( c * testing . T ) {
2015-09-01 21:37:04 +00:00
// Not applicable on Windows as uses Unix specific functionality
2015-11-05 00:40:58 +00:00
testRequires ( c , DaemonIsLinux )
2015-09-01 16:42:19 +00:00
out , _ := dockerCmd ( c , "run" , "--name=testulimits" , "--ulimit" , "nofile=42" , "busybox" , "/bin/sh" , "-c" , "ulimit -n" )
ul := strings . TrimSpace ( out )
if ul != "42" {
c . Fatalf ( "expected `ulimit -n` to be 42, got %s" , ul )
}
}
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunContainerWithCgroupParent ( c * testing . T ) {
2015-09-01 21:37:04 +00:00
// Not applicable on Windows as uses Unix specific functionality
2015-11-05 00:40:58 +00:00
testRequires ( c , DaemonIsLinux )
2015-09-01 16:42:19 +00:00
2017-01-02 22:42:45 +00:00
// cgroup-parent relative path
testRunContainerWithCgroupParent ( c , "test" , "cgroup-test" )
2015-09-01 16:42:19 +00:00
2017-01-02 22:42:45 +00:00
// cgroup-parent absolute path
testRunContainerWithCgroupParent ( c , "/cgroup-parent/test" , "cgroup-test-absolute" )
2015-09-01 16:42:19 +00:00
}
2019-09-09 21:05:55 +00:00
func testRunContainerWithCgroupParent ( c * testing . T , cgroupParent , name string ) {
2015-09-01 16:42:19 +00:00
out , _ , err := dockerCmdWithError ( "run" , "--cgroup-parent" , cgroupParent , "--name" , name , "busybox" , "cat" , "/proc/self/cgroup" )
if err != nil {
2019-08-05 15:54:15 +00:00
c . Fatalf ( "unexpected failure when running container with --cgroup-parent option - %s\n%v" , out , err )
2015-09-01 16:42:19 +00:00
}
2019-08-05 15:54:15 +00:00
cgroupPaths := ParseCgroupPaths ( out )
2015-09-01 16:42:19 +00:00
if len ( cgroupPaths ) == 0 {
2019-08-05 15:54:15 +00:00
c . Fatalf ( "unexpected output - %q" , out )
2015-09-01 16:42:19 +00:00
}
2017-01-16 10:30:14 +00:00
id := getIDByName ( c , name )
2015-09-01 16:42:19 +00:00
expectedCgroup := path . Join ( cgroupParent , id )
found := false
for _ , path := range cgroupPaths {
if strings . HasSuffix ( path , expectedCgroup ) {
found = true
break
}
}
if ! found {
c . Fatalf ( "unexpected cgroup paths. Expected at least one cgroup path to have suffix %q. Cgroup Paths: %v" , expectedCgroup , cgroupPaths )
2016-01-04 12:29:32 +00:00
}
}
// TestRunInvalidCgroupParent checks that a specially-crafted cgroup parent doesn't cause Docker to crash or start modifying /.
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunInvalidCgroupParent ( c * testing . T ) {
2016-01-04 12:29:32 +00:00
// Not applicable on Windows as uses Unix specific functionality
testRequires ( c , DaemonIsLinux )
2017-01-02 22:42:45 +00:00
testRunInvalidCgroupParent ( c , "../../../../../../../../SHOULD_NOT_EXIST" , "SHOULD_NOT_EXIST" , "cgroup-invalid-test" )
2016-01-04 12:29:32 +00:00
2017-01-02 22:42:45 +00:00
testRunInvalidCgroupParent ( c , "/../../../../../../../../SHOULD_NOT_EXIST" , "/SHOULD_NOT_EXIST" , "cgroup-absolute-invalid-test" )
2016-01-04 12:29:32 +00:00
}
2019-09-09 21:05:55 +00:00
func testRunInvalidCgroupParent ( c * testing . T , cgroupParent , cleanCgroupParent , name string ) {
2016-01-04 12:29:32 +00:00
out , _ , err := dockerCmdWithError ( "run" , "--cgroup-parent" , cgroupParent , "--name" , name , "busybox" , "cat" , "/proc/self/cgroup" )
if err != nil {
// XXX: This may include a daemon crash.
2019-08-05 15:54:15 +00:00
c . Fatalf ( "unexpected failure when running container with --cgroup-parent option - %s\n%v" , out , err )
2016-01-04 12:29:32 +00:00
}
// We expect "/SHOULD_NOT_EXIST" to not exist. If not, we have a security issue.
if _ , err := os . Stat ( "/SHOULD_NOT_EXIST" ) ; err == nil || ! os . IsNotExist ( err ) {
2017-01-02 22:42:45 +00:00
c . Fatalf ( "SECURITY: --cgroup-parent with ../../ relative paths cause files to be created in the host (this is bad) !!" )
2016-01-04 12:29:32 +00:00
}
2019-08-05 15:54:15 +00:00
cgroupPaths := ParseCgroupPaths ( out )
2016-01-04 12:29:32 +00:00
if len ( cgroupPaths ) == 0 {
2019-08-05 15:54:15 +00:00
c . Fatalf ( "unexpected output - %q" , out )
2016-01-04 12:29:32 +00:00
}
2017-01-16 10:30:14 +00:00
id := getIDByName ( c , name )
2016-01-04 12:29:32 +00:00
expectedCgroup := path . Join ( cleanCgroupParent , id )
found := false
for _ , path := range cgroupPaths {
if strings . HasSuffix ( path , expectedCgroup ) {
found = true
break
}
}
if ! found {
c . Fatalf ( "unexpected cgroup paths. Expected at least one cgroup path to have suffix %q. Cgroup Paths: %v" , expectedCgroup , cgroupPaths )
2015-09-01 16:42:19 +00:00
}
}
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunContainerWithCgroupMountRO ( c * testing . T ) {
2015-09-01 21:37:04 +00:00
// Not applicable on Windows as uses Unix specific functionality
2015-09-18 17:41:12 +00:00
// --read-only + userns has remount issues
2015-11-05 00:40:58 +00:00
testRequires ( c , DaemonIsLinux , NotUserNamespace )
2015-09-01 16:42:19 +00:00
filename := "/sys/fs/cgroup/devices/test123"
out , _ , err := dockerCmdWithError ( "run" , "busybox" , "touch" , filename )
if err == nil {
c . Fatal ( "expected cgroup mount point to be read-only, touch file should fail" )
}
expected := "Read-only file system"
if ! strings . Contains ( out , expected ) {
c . Fatalf ( "expected output from failure to contain %s but contains %s" , expected , out )
}
}
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunContainerNetworkModeToSelf ( c * testing . T ) {
2015-09-01 21:37:04 +00:00
// Not applicable on Windows which does not support --net=container
2016-03-23 13:37:15 +00:00
testRequires ( c , DaemonIsLinux )
2015-09-01 16:42:19 +00:00
out , _ , err := dockerCmdWithError ( "run" , "--name=me" , "--net=container:me" , "busybox" , "true" )
if err == nil || ! strings . Contains ( out , "cannot join own network" ) {
2015-09-16 18:56:26 +00:00
c . Fatalf ( "using container net mode to self should result in an error\nerr: %q\nout: %s" , err , out )
2015-09-01 16:42:19 +00:00
}
}
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunContainerNetModeWithDNSMacHosts ( c * testing . T ) {
2015-09-01 21:37:04 +00:00
// Not applicable on Windows which does not support --net=container
2016-03-23 13:37:15 +00:00
testRequires ( c , DaemonIsLinux )
2015-09-01 16:42:19 +00:00
out , _ , err := dockerCmdWithError ( "run" , "-d" , "--name" , "parent" , "busybox" , "top" )
if err != nil {
c . Fatalf ( "failed to run container: %v, output: %q" , err , out )
}
out , _ , err = dockerCmdWithError ( "run" , "--dns" , "1.2.3.4" , "--net=container:parent" , "busybox" )
2015-12-01 22:01:51 +00:00
if err == nil || ! strings . Contains ( out , runconfig . ErrConflictNetworkAndDNS . Error ( ) ) {
2015-09-01 16:42:19 +00:00
c . Fatalf ( "run --net=container with --dns should error out" )
}
out , _ , err = dockerCmdWithError ( "run" , "--mac-address" , "92:d0:c6:0a:29:33" , "--net=container:parent" , "busybox" )
2015-12-01 22:01:51 +00:00
if err == nil || ! strings . Contains ( out , runconfig . ErrConflictContainerNetworkAndMac . Error ( ) ) {
2015-09-01 16:42:19 +00:00
c . Fatalf ( "run --net=container with --mac-address should error out" )
}
out , _ , err = dockerCmdWithError ( "run" , "--add-host" , "test:192.168.2.109" , "--net=container:parent" , "busybox" )
2015-12-01 22:01:51 +00:00
if err == nil || ! strings . Contains ( out , runconfig . ErrConflictNetworkHosts . Error ( ) ) {
2015-09-01 16:42:19 +00:00
c . Fatalf ( "run --net=container with --add-host should error out" )
}
}
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunContainerNetModeWithExposePort ( c * testing . T ) {
2015-09-01 21:37:04 +00:00
// Not applicable on Windows which does not support --net=container
2016-03-23 13:37:15 +00:00
testRequires ( c , DaemonIsLinux )
2015-09-01 16:42:19 +00:00
dockerCmd ( c , "run" , "-d" , "--name" , "parent" , "busybox" , "top" )
out , _ , err := dockerCmdWithError ( "run" , "-p" , "5000:5000" , "--net=container:parent" , "busybox" )
2015-12-01 22:01:51 +00:00
if err == nil || ! strings . Contains ( out , runconfig . ErrConflictNetworkPublishPorts . Error ( ) ) {
2015-09-01 16:42:19 +00:00
c . Fatalf ( "run --net=container with -p should error out" )
}
out , _ , err = dockerCmdWithError ( "run" , "-P" , "--net=container:parent" , "busybox" )
2015-12-01 22:01:51 +00:00
if err == nil || ! strings . Contains ( out , runconfig . ErrConflictNetworkPublishPorts . Error ( ) ) {
2015-09-01 16:42:19 +00:00
c . Fatalf ( "run --net=container with -P should error out" )
}
out , _ , err = dockerCmdWithError ( "run" , "--expose" , "5000" , "--net=container:parent" , "busybox" )
2015-12-01 22:01:51 +00:00
if err == nil || ! strings . Contains ( out , runconfig . ErrConflictNetworkExposePorts . Error ( ) ) {
2015-09-01 16:42:19 +00:00
c . Fatalf ( "run --net=container with --expose should error out" )
}
}
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunLinkToContainerNetMode ( c * testing . T ) {
2015-09-01 21:37:04 +00:00
// Not applicable on Windows which does not support --net=container or --link
2016-03-23 13:37:15 +00:00
testRequires ( c , DaemonIsLinux )
2015-09-01 16:42:19 +00:00
dockerCmd ( c , "run" , "--name" , "test" , "-d" , "busybox" , "top" )
dockerCmd ( c , "run" , "--name" , "parent" , "-d" , "--net=container:test" , "busybox" , "top" )
dockerCmd ( c , "run" , "-d" , "--link=parent:parent" , "busybox" , "top" )
dockerCmd ( c , "run" , "--name" , "child" , "-d" , "--net=container:parent" , "busybox" , "top" )
dockerCmd ( c , "run" , "-d" , "--link=child:child" , "busybox" , "top" )
}
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunLoopbackOnlyExistsWhenNetworkingDisabled ( c * testing . T ) {
2015-09-01 21:37:04 +00:00
// TODO Windows: This may be possible to convert.
2015-08-28 17:36:42 +00:00
testRequires ( c , DaemonIsLinux )
2015-09-01 16:42:19 +00:00
out , _ := dockerCmd ( c , "run" , "--net=none" , "busybox" , "ip" , "-o" , "-4" , "a" , "show" , "up" )
var (
count = 0
parts = strings . Split ( out , "\n" )
)
for _ , l := range parts {
if l != "" {
count ++
}
}
if count != 1 {
c . Fatalf ( "Wrong interface count in container %d" , count )
}
if ! strings . HasPrefix ( out , "1: lo" ) {
c . Fatalf ( "Wrong interface in test container: expected [1: lo], got %s" , out )
}
}
// Issue #4681
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunLoopbackWhenNetworkDisabled ( c * testing . T ) {
2018-01-15 14:32:06 +00:00
if testEnv . OSType == "windows" {
2018-01-15 14:31:02 +00:00
dockerCmd ( c , "run" , "--net=none" , testEnv . PlatformDefaults . BaseImage , "ping" , "-n" , "1" , "127.0.0.1" )
2015-09-01 21:37:04 +00:00
} else {
dockerCmd ( c , "run" , "--net=none" , "busybox" , "ping" , "-c" , "1" , "127.0.0.1" )
}
2015-09-01 16:42:19 +00:00
}
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunModeNetContainerHostname ( c * testing . T ) {
2015-09-01 21:37:04 +00:00
// Windows does not support --net=container
2019-07-08 16:31:34 +00:00
testRequires ( c , DaemonIsLinux )
2015-09-01 16:42:19 +00:00
dockerCmd ( c , "run" , "-i" , "-d" , "--name" , "parent" , "busybox" , "top" )
out , _ := dockerCmd ( c , "exec" , "parent" , "cat" , "/etc/hostname" )
out1 , _ := dockerCmd ( c , "run" , "--net=container:parent" , "busybox" , "cat" , "/etc/hostname" )
if out1 != out {
c . Fatal ( "containers with shared net namespace should have same hostname" )
}
}
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunNetworkNotInitializedNoneMode ( c * testing . T ) {
2015-09-01 21:37:04 +00:00
// TODO Windows: Network settings are not currently propagated. This may
// be resolved in the future with the move to libnetwork and CNM.
2015-08-28 17:36:42 +00:00
testRequires ( c , DaemonIsLinux )
2015-09-08 21:00:25 +00:00
out , _ := dockerCmd ( c , "run" , "-d" , "--net=none" , "busybox" , "top" )
2015-09-01 16:42:19 +00:00
id := strings . TrimSpace ( out )
2016-01-28 14:19:25 +00:00
res := inspectField ( c , id , "NetworkSettings.Networks.none.IPAddress" )
2015-09-01 16:42:19 +00:00
if res != "" {
c . Fatalf ( "For 'none' mode network must not be initialized, but container got IP: %s" , res )
}
}
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestTwoContainersInNetHost ( c * testing . T ) {
2015-09-01 21:37:04 +00:00
// Not applicable as Windows does not support --net=host
2015-09-18 17:41:12 +00:00
testRequires ( c , DaemonIsLinux , NotUserNamespace , NotUserNamespace )
2015-09-01 16:42:19 +00:00
dockerCmd ( c , "run" , "-d" , "--net=host" , "--name=first" , "busybox" , "top" )
dockerCmd ( c , "run" , "-d" , "--net=host" , "--name=second" , "busybox" , "top" )
dockerCmd ( c , "stop" , "first" )
dockerCmd ( c , "stop" , "second" )
}
2015-09-14 20:34:23 +00:00
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestContainersInUserDefinedNetwork ( c * testing . T ) {
2015-11-25 23:38:33 +00:00
testRequires ( c , DaemonIsLinux , NotUserNamespace , NotArm )
2015-09-25 10:19:17 +00:00
dockerCmd ( c , "network" , "create" , "-d" , "bridge" , "testnetwork" )
dockerCmd ( c , "run" , "-d" , "--net=testnetwork" , "--name=first" , "busybox" , "top" )
2019-09-09 21:05:57 +00:00
assert . Assert ( c , waitRun ( "first" ) == nil )
2015-09-25 10:19:17 +00:00
dockerCmd ( c , "run" , "-t" , "--net=testnetwork" , "--name=second" , "busybox" , "ping" , "-c" , "1" , "first" )
}
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestContainersInMultipleNetworks ( c * testing . T ) {
2015-11-25 23:38:33 +00:00
testRequires ( c , DaemonIsLinux , NotUserNamespace , NotArm )
2015-09-25 10:19:17 +00:00
// Create 2 networks using bridge driver
dockerCmd ( c , "network" , "create" , "-d" , "bridge" , "testnetwork1" )
dockerCmd ( c , "network" , "create" , "-d" , "bridge" , "testnetwork2" )
// Run and connect containers to testnetwork1
dockerCmd ( c , "run" , "-d" , "--net=testnetwork1" , "--name=first" , "busybox" , "top" )
2019-09-09 21:05:57 +00:00
assert . Assert ( c , waitRun ( "first" ) == nil )
2015-09-25 10:19:17 +00:00
dockerCmd ( c , "run" , "-d" , "--net=testnetwork1" , "--name=second" , "busybox" , "top" )
2019-09-09 21:05:57 +00:00
assert . Assert ( c , waitRun ( "second" ) == nil )
2015-09-25 10:19:17 +00:00
// Check connectivity between containers in testnetwork2
dockerCmd ( c , "exec" , "first" , "ping" , "-c" , "1" , "second.testnetwork1" )
// Connect containers to testnetwork2
dockerCmd ( c , "network" , "connect" , "testnetwork2" , "first" )
dockerCmd ( c , "network" , "connect" , "testnetwork2" , "second" )
// Check connectivity between containers
dockerCmd ( c , "exec" , "second" , "ping" , "-c" , "1" , "first.testnetwork2" )
}
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestContainersNetworkIsolation ( c * testing . T ) {
2015-11-25 23:38:33 +00:00
testRequires ( c , DaemonIsLinux , NotUserNamespace , NotArm )
2015-09-25 10:19:17 +00:00
// Create 2 networks using bridge driver
dockerCmd ( c , "network" , "create" , "-d" , "bridge" , "testnetwork1" )
dockerCmd ( c , "network" , "create" , "-d" , "bridge" , "testnetwork2" )
2015-09-27 11:09:27 +00:00
// Run 1 container in testnetwork1 and another in testnetwork2
2015-09-25 10:19:17 +00:00
dockerCmd ( c , "run" , "-d" , "--net=testnetwork1" , "--name=first" , "busybox" , "top" )
2019-09-09 21:05:57 +00:00
assert . Assert ( c , waitRun ( "first" ) == nil )
2015-09-25 10:19:17 +00:00
dockerCmd ( c , "run" , "-d" , "--net=testnetwork2" , "--name=second" , "busybox" , "top" )
2019-09-09 21:05:57 +00:00
assert . Assert ( c , waitRun ( "second" ) == nil )
2015-09-25 10:19:17 +00:00
// Check Isolation between containers : ping must fail
_ , _ , err := dockerCmdWithError ( "exec" , "first" , "ping" , "-c" , "1" , "second" )
2019-04-04 13:23:19 +00:00
assert . ErrorContains ( c , err , "" )
2015-09-25 10:19:17 +00:00
// Connect first container to testnetwork2
dockerCmd ( c , "network" , "connect" , "testnetwork2" , "first" )
// ping must succeed now
_ , _ , err = dockerCmdWithError ( "exec" , "first" , "ping" , "-c" , "1" , "second" )
2019-04-04 13:23:19 +00:00
assert . NilError ( c , err )
2015-09-25 10:19:17 +00:00
// Disconnect first container from testnetwork2
dockerCmd ( c , "network" , "disconnect" , "testnetwork2" , "first" )
// ping must fail again
_ , _ , err = dockerCmdWithError ( "exec" , "first" , "ping" , "-c" , "1" , "second" )
2019-04-04 13:23:19 +00:00
assert . ErrorContains ( c , err , "" )
2015-09-25 10:19:17 +00:00
}
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestNetworkRmWithActiveContainers ( c * testing . T ) {
2015-09-18 17:41:12 +00:00
testRequires ( c , DaemonIsLinux , NotUserNamespace )
2015-09-25 10:19:17 +00:00
// Create 2 networks using bridge driver
dockerCmd ( c , "network" , "create" , "-d" , "bridge" , "testnetwork1" )
// Run and connect containers to testnetwork1
dockerCmd ( c , "run" , "-d" , "--net=testnetwork1" , "--name=first" , "busybox" , "top" )
2019-09-09 21:05:57 +00:00
assert . Assert ( c , waitRun ( "first" ) == nil )
2015-09-25 10:19:17 +00:00
dockerCmd ( c , "run" , "-d" , "--net=testnetwork1" , "--name=second" , "busybox" , "top" )
2019-09-09 21:05:57 +00:00
assert . Assert ( c , waitRun ( "second" ) == nil )
2015-09-25 10:19:17 +00:00
// Network delete with active containers must fail
_ , _ , err := dockerCmdWithError ( "network" , "rm" , "testnetwork1" )
2019-04-04 13:23:19 +00:00
assert . ErrorContains ( c , err , "" )
2015-09-25 10:19:17 +00:00
dockerCmd ( c , "stop" , "first" )
_ , _ , err = dockerCmdWithError ( "network" , "rm" , "testnetwork1" )
2019-04-04 13:23:19 +00:00
assert . ErrorContains ( c , err , "" )
2015-09-25 10:19:17 +00:00
}
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestContainerRestartInMultipleNetworks ( c * testing . T ) {
2015-11-25 23:38:33 +00:00
testRequires ( c , DaemonIsLinux , NotUserNamespace , NotArm )
2015-09-25 10:19:17 +00:00
// Create 2 networks using bridge driver
dockerCmd ( c , "network" , "create" , "-d" , "bridge" , "testnetwork1" )
dockerCmd ( c , "network" , "create" , "-d" , "bridge" , "testnetwork2" )
2015-10-13 21:18:05 +00:00
2015-09-25 10:19:17 +00:00
// Run and connect containers to testnetwork1
dockerCmd ( c , "run" , "-d" , "--net=testnetwork1" , "--name=first" , "busybox" , "top" )
2019-09-09 21:05:57 +00:00
assert . Assert ( c , waitRun ( "first" ) == nil )
2015-09-25 10:19:17 +00:00
dockerCmd ( c , "run" , "-d" , "--net=testnetwork1" , "--name=second" , "busybox" , "top" )
2019-09-09 21:05:57 +00:00
assert . Assert ( c , waitRun ( "second" ) == nil )
2015-09-25 10:19:17 +00:00
// Check connectivity between containers in testnetwork2
dockerCmd ( c , "exec" , "first" , "ping" , "-c" , "1" , "second.testnetwork1" )
// Connect containers to testnetwork2
dockerCmd ( c , "network" , "connect" , "testnetwork2" , "first" )
dockerCmd ( c , "network" , "connect" , "testnetwork2" , "second" )
// Check connectivity between containers
dockerCmd ( c , "exec" , "second" , "ping" , "-c" , "1" , "first.testnetwork2" )
// Stop second container and test ping failures on both networks
dockerCmd ( c , "stop" , "second" )
_ , _ , err := dockerCmdWithError ( "exec" , "first" , "ping" , "-c" , "1" , "second.testnetwork1" )
2019-04-04 13:23:19 +00:00
assert . ErrorContains ( c , err , "" )
2015-09-25 10:19:17 +00:00
_ , _ , err = dockerCmdWithError ( "exec" , "first" , "ping" , "-c" , "1" , "second.testnetwork2" )
2019-04-04 13:23:19 +00:00
assert . ErrorContains ( c , err , "" )
2015-09-25 10:19:17 +00:00
// Start second container and connectivity must be restored on both networks
dockerCmd ( c , "start" , "second" )
dockerCmd ( c , "exec" , "first" , "ping" , "-c" , "1" , "second.testnetwork1" )
dockerCmd ( c , "exec" , "second" , "ping" , "-c" , "1" , "first.testnetwork2" )
}
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestContainerWithConflictingHostNetworks ( c * testing . T ) {
2015-09-18 17:41:12 +00:00
testRequires ( c , DaemonIsLinux , NotUserNamespace )
2015-09-25 10:19:17 +00:00
// Run a container with --net=host
dockerCmd ( c , "run" , "-d" , "--net=host" , "--name=first" , "busybox" , "top" )
2019-09-09 21:05:57 +00:00
assert . Assert ( c , waitRun ( "first" ) == nil )
2015-09-25 10:19:17 +00:00
// Create a network using bridge driver
dockerCmd ( c , "network" , "create" , "-d" , "bridge" , "testnetwork1" )
// Connecting to the user defined network must fail
_ , _ , err := dockerCmdWithError ( "network" , "connect" , "testnetwork1" , "first" )
2019-04-04 13:23:19 +00:00
assert . ErrorContains ( c , err , "" )
2015-09-25 10:19:17 +00:00
}
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestContainerWithConflictingSharedNetwork ( c * testing . T ) {
2016-03-23 13:37:15 +00:00
testRequires ( c , DaemonIsLinux )
2015-09-25 10:19:17 +00:00
dockerCmd ( c , "run" , "-d" , "--name=first" , "busybox" , "top" )
2019-09-09 21:05:57 +00:00
assert . Assert ( c , waitRun ( "first" ) == nil )
2015-09-25 10:19:17 +00:00
// Run second container in first container's network namespace
dockerCmd ( c , "run" , "-d" , "--net=container:first" , "--name=second" , "busybox" , "top" )
2019-09-09 21:05:57 +00:00
assert . Assert ( c , waitRun ( "second" ) == nil )
2015-09-25 10:19:17 +00:00
// Create a network using bridge driver
dockerCmd ( c , "network" , "create" , "-d" , "bridge" , "testnetwork1" )
// Connecting to the user defined network must fail
2015-09-27 11:09:27 +00:00
out , _ , err := dockerCmdWithError ( "network" , "connect" , "testnetwork1" , "second" )
2019-04-04 13:23:19 +00:00
assert . ErrorContains ( c , err , "" )
2019-09-09 21:08:22 +00:00
assert . Assert ( c , strings . Contains ( out , runconfig . ErrConflictSharedNetwork . Error ( ) ) )
2015-09-27 11:09:27 +00:00
}
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestContainerWithConflictingNoneNetwork ( c * testing . T ) {
2016-03-23 13:37:15 +00:00
testRequires ( c , DaemonIsLinux )
2015-09-27 11:09:27 +00:00
dockerCmd ( c , "run" , "-d" , "--net=none" , "--name=first" , "busybox" , "top" )
2019-09-09 21:05:57 +00:00
assert . Assert ( c , waitRun ( "first" ) == nil )
2015-09-27 11:09:27 +00:00
// Create a network using bridge driver
dockerCmd ( c , "network" , "create" , "-d" , "bridge" , "testnetwork1" )
// Connecting to the user defined network must fail
out , _ , err := dockerCmdWithError ( "network" , "connect" , "testnetwork1" , "first" )
2019-04-04 13:23:19 +00:00
assert . ErrorContains ( c , err , "" )
2019-09-09 21:08:22 +00:00
assert . Assert ( c , strings . Contains ( out , runconfig . ErrConflictNoNetwork . Error ( ) ) )
2015-09-27 11:09:27 +00:00
// create a container connected to testnetwork1
dockerCmd ( c , "run" , "-d" , "--net=testnetwork1" , "--name=second" , "busybox" , "top" )
2019-09-09 21:05:57 +00:00
assert . Assert ( c , waitRun ( "second" ) == nil )
2015-09-27 11:09:27 +00:00
// Connect second container to none network. it must fail as well
_ , _ , err = dockerCmdWithError ( "network" , "connect" , "none" , "second" )
2019-04-04 13:23:19 +00:00
assert . ErrorContains ( c , err , "" )
2015-09-25 10:19:17 +00:00
}
2015-09-14 20:34:23 +00:00
// #11957 - stdin with no tty does not exit if stdin is not closed even though container exited
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunStdinBlockedAfterContainerExit ( c * testing . T ) {
2015-09-14 20:34:23 +00:00
cmd := exec . Command ( dockerBinary , "run" , "-i" , "--name=test" , "busybox" , "true" )
in , err := cmd . StdinPipe ( )
2019-04-04 13:23:19 +00:00
assert . NilError ( c , err )
2015-09-14 20:34:23 +00:00
defer in . Close ( )
2016-03-24 16:43:04 +00:00
stdout := bytes . NewBuffer ( nil )
cmd . Stdout = stdout
cmd . Stderr = stdout
2019-09-09 21:05:57 +00:00
assert . Assert ( c , cmd . Start ( ) == nil )
2015-09-14 20:34:23 +00:00
waitChan := make ( chan error )
go func ( ) {
waitChan <- cmd . Wait ( )
} ( )
select {
case err := <- waitChan :
2019-09-09 21:08:22 +00:00
assert . Assert ( c , err == nil , stdout . String ( ) )
2015-09-28 21:08:26 +00:00
case <- time . After ( 30 * time . Second ) :
2015-09-14 20:34:23 +00:00
c . Fatal ( "timeout waiting for command to exit" )
}
}
2015-09-08 18:40:55 +00:00
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunWrongCpusetCpusFlagValue ( c * testing . T ) {
2015-09-23 23:04:51 +00:00
// TODO Windows: This needs validation (error out) in the daemon.
testRequires ( c , DaemonIsLinux )
2015-07-29 12:21:16 +00:00
out , exitCode , err := dockerCmdWithError ( "run" , "--cpuset-cpus" , "1-10,11--" , "busybox" , "true" )
2019-04-04 13:23:19 +00:00
assert . ErrorContains ( c , err , "" )
2015-09-08 18:40:55 +00:00
expected := "Error response from daemon: Invalid value 1-10,11-- for cpuset cpus.\n"
2015-07-29 12:21:16 +00:00
if ! ( strings . Contains ( out , expected ) || exitCode == 125 ) {
c . Fatalf ( "Expected output to contain %q with exitCode 125, got out: %q exitCode: %v" , expected , out , exitCode )
}
2015-09-08 18:40:55 +00:00
}
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunWrongCpusetMemsFlagValue ( c * testing . T ) {
2015-09-23 23:04:51 +00:00
// TODO Windows: This needs validation (error out) in the daemon.
testRequires ( c , DaemonIsLinux )
2015-07-29 12:21:16 +00:00
out , exitCode , err := dockerCmdWithError ( "run" , "--cpuset-mems" , "1-42--" , "busybox" , "true" )
2019-04-04 13:23:19 +00:00
assert . ErrorContains ( c , err , "" )
2015-09-08 18:40:55 +00:00
expected := "Error response from daemon: Invalid value 1-42-- for cpuset mems.\n"
2015-07-29 12:21:16 +00:00
if ! ( strings . Contains ( out , expected ) || exitCode == 125 ) {
c . Fatalf ( "Expected output to contain %q with exitCode 125, got out: %q exitCode: %v" , expected , out , exitCode )
}
}
// TestRunNonExecutableCmd checks that 'docker run busybox foo' exits with error code 127'
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunNonExecutableCmd ( c * testing . T ) {
2015-07-29 12:21:16 +00:00
name := "testNonExecutableCmd"
2017-01-05 11:38:34 +00:00
icmd . RunCommand ( dockerBinary , "run" , "--name" , name , "busybox" , "foo" ) . Assert ( c , icmd . Expected {
ExitCode : 127 ,
2017-01-05 18:08:24 +00:00
Error : "exit status 127" ,
2017-01-05 11:38:34 +00:00
} )
2015-07-29 12:21:16 +00:00
}
// TestRunNonExistingCmd checks that 'docker run busybox /bin/foo' exits with code 127.
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunNonExistingCmd ( c * testing . T ) {
2015-07-29 12:21:16 +00:00
name := "testNonExistingCmd"
2017-01-05 11:38:34 +00:00
icmd . RunCommand ( dockerBinary , "run" , "--name" , name , "busybox" , "/bin/foo" ) . Assert ( c , icmd . Expected {
ExitCode : 127 ,
2017-01-05 18:08:24 +00:00
Error : "exit status 127" ,
2017-01-05 11:38:34 +00:00
} )
2015-07-29 12:21:16 +00:00
}
2016-01-08 21:49:43 +00:00
// TestCmdCannotBeInvoked checks that 'docker run busybox /etc' exits with 126, or
// 127 on Windows. The difference is that in Windows, the container must be started
2016-07-21 10:03:37 +00:00
// as that's when the check is made (and yes, by its design...)
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestCmdCannotBeInvoked ( c * testing . T ) {
2016-01-08 21:49:43 +00:00
expected := 126
2018-01-15 14:32:06 +00:00
if testEnv . OSType == "windows" {
2016-01-08 21:49:43 +00:00
expected = 127
}
2015-07-29 12:21:16 +00:00
name := "testCmdCannotBeInvoked"
2017-01-05 11:38:34 +00:00
icmd . RunCommand ( dockerBinary , "run" , "--name" , name , "busybox" , "/etc" ) . Assert ( c , icmd . Expected {
ExitCode : expected ,
2017-01-05 18:08:24 +00:00
Error : fmt . Sprintf ( "exit status %d" , expected ) ,
2017-01-05 11:38:34 +00:00
} )
2015-07-29 12:21:16 +00:00
}
// TestRunNonExistingImage checks that 'docker run foo' exits with error msg 125 and contains 'Unable to find image'
2017-01-05 11:38:34 +00:00
// FIXME(vdemeester) should be a unit test
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunNonExistingImage ( c * testing . T ) {
2017-01-05 11:38:34 +00:00
icmd . RunCommand ( dockerBinary , "run" , "foo" ) . Assert ( c , icmd . Expected {
ExitCode : 125 ,
2017-01-05 18:08:24 +00:00
Err : "Unable to find image" ,
2017-01-05 11:38:34 +00:00
} )
2015-07-29 12:21:16 +00:00
}
// TestDockerFails checks that 'docker run -foo busybox' exits with 125 to signal docker run failed
2017-01-05 11:38:34 +00:00
// FIXME(vdemeester) should be a unit test
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestDockerFails ( c * testing . T ) {
2017-01-05 11:38:34 +00:00
icmd . RunCommand ( dockerBinary , "run" , "-foo" , "busybox" ) . Assert ( c , icmd . Expected {
ExitCode : 125 ,
2017-01-05 18:08:24 +00:00
Error : "exit status 125" ,
2017-01-05 11:38:34 +00:00
} )
2015-09-08 18:40:55 +00:00
}
2015-11-18 22:20:54 +00:00
// TestRunInvalidReference invokes docker run with a bad reference.
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunInvalidReference ( c * testing . T ) {
2015-11-18 22:20:54 +00:00
out , exit , _ := dockerCmdWithError ( "run" , "busybox@foo" )
if exit == 0 {
c . Fatalf ( "expected non-zero exist code; received %d" , exit )
}
2017-01-11 21:54:52 +00:00
if ! strings . Contains ( out , "invalid reference format" ) {
c . Fatalf ( ` Expected "invalid reference format" in output; got: %s ` , out )
2015-11-18 22:20:54 +00:00
}
}
2015-10-13 09:26:27 +00:00
2015-12-04 17:18:05 +00:00
// Test fix for issue #17854
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunInitLayerPathOwnership ( c * testing . T ) {
2015-12-04 17:18:05 +00:00
// Not applicable on Windows as it does not support Linux uid/gid ownership
testRequires ( c , DaemonIsLinux )
name := "testetcfileownership"
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , name , build . WithDockerfile ( ` FROM busybox
2015-12-04 17:18:05 +00:00
RUN echo ' dockerio : x : 1001 : 1001 : : / bin : / bin / false ' >> / etc / passwd
RUN echo ' dockerio : x : 1001 : ' >> / etc / group
2017-01-16 10:30:14 +00:00
RUN chown dockerio : dockerio / etc ` ) )
2015-12-04 17:18:05 +00:00
// Test that dockerio ownership of /etc is retained at runtime
out , _ := dockerCmd ( c , "run" , "--rm" , name , "stat" , "-c" , "%U:%G" , "/etc" )
out = strings . TrimSpace ( out )
if out != "dockerio:dockerio" {
c . Fatalf ( "Wrong /etc ownership: expected dockerio:dockerio, got %q" , out )
}
}
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunWithOomScoreAdj ( c * testing . T ) {
2015-10-13 09:26:27 +00:00
testRequires ( c , DaemonIsLinux )
expected := "642"
out , _ := dockerCmd ( c , "run" , "--oom-score-adj" , expected , "busybox" , "cat" , "/proc/self/oom_score_adj" )
oomScoreAdj := strings . TrimSpace ( out )
if oomScoreAdj != "642" {
c . Fatalf ( "Expected oom_score_adj set to %q, got %q instead" , expected , oomScoreAdj )
}
}
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunWithOomScoreAdjInvalidRange ( c * testing . T ) {
2015-10-13 09:26:27 +00:00
testRequires ( c , DaemonIsLinux )
out , _ , err := dockerCmdWithError ( "run" , "--oom-score-adj" , "1001" , "busybox" , "true" )
2019-04-04 13:23:19 +00:00
assert . ErrorContains ( c , err , "" )
2015-10-13 09:26:27 +00:00
expected := "Invalid value 1001, range for oom score adj is [-1000, 1000]."
if ! strings . Contains ( out , expected ) {
c . Fatalf ( "Expected output to contain %q, got %q instead" , expected , out )
}
out , _ , err = dockerCmdWithError ( "run" , "--oom-score-adj" , "-1001" , "busybox" , "true" )
2019-04-04 13:23:19 +00:00
assert . ErrorContains ( c , err , "" )
2015-10-13 09:26:27 +00:00
expected = "Invalid value -1001, range for oom score adj is [-1000, 1000]."
if ! strings . Contains ( out , expected ) {
c . Fatalf ( "Expected output to contain %q, got %q instead" , expected , out )
}
}
2015-12-14 15:39:53 +00:00
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunVolumesMountedAsShared ( c * testing . T ) {
2015-12-14 15:39:53 +00:00
// Volume propagation is linux only. Also it creates directories for
// bind mounting, so needs to be same host.
2018-12-24 12:25:53 +00:00
testRequires ( c , DaemonIsLinux , testEnv . IsLocalDaemon , NotUserNamespace )
2015-12-14 15:39:53 +00:00
// Prepare a source directory to bind mount
tmpDir , err := ioutil . TempDir ( "" , "volume-source" )
if err != nil {
c . Fatal ( err )
}
defer os . RemoveAll ( tmpDir )
if err := os . Mkdir ( path . Join ( tmpDir , "mnt1" ) , 0755 ) ; err != nil {
c . Fatal ( err )
}
// Convert this directory into a shared mount point so that we do
// not rely on propagation properties of parent mount.
2016-12-13 20:21:51 +00:00
icmd . RunCommand ( "mount" , "--bind" , tmpDir , tmpDir ) . Assert ( c , icmd . Success )
icmd . RunCommand ( "mount" , "--make-private" , "--make-shared" , tmpDir ) . Assert ( c , icmd . Success )
2015-12-14 15:39:53 +00:00
dockerCmd ( c , "run" , "--privileged" , "-v" , fmt . Sprintf ( "%s:/volume-dest:shared" , tmpDir ) , "busybox" , "mount" , "--bind" , "/volume-dest/mnt1" , "/volume-dest/mnt1" )
// Make sure a bind mount under a shared volume propagated to host.
if mounted , _ := mount . Mounted ( path . Join ( tmpDir , "mnt1" ) ) ; ! mounted {
c . Fatalf ( "Bind mount under shared volume did not propagate to host" )
}
mount . Unmount ( path . Join ( tmpDir , "mnt1" ) )
}
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunVolumesMountedAsSlave ( c * testing . T ) {
2015-12-14 15:39:53 +00:00
// Volume propagation is linux only. Also it creates directories for
// bind mounting, so needs to be same host.
2018-12-24 12:25:53 +00:00
testRequires ( c , DaemonIsLinux , testEnv . IsLocalDaemon , NotUserNamespace )
2015-12-14 15:39:53 +00:00
// Prepare a source directory to bind mount
tmpDir , err := ioutil . TempDir ( "" , "volume-source" )
if err != nil {
c . Fatal ( err )
}
defer os . RemoveAll ( tmpDir )
if err := os . Mkdir ( path . Join ( tmpDir , "mnt1" ) , 0755 ) ; err != nil {
c . Fatal ( err )
}
// Prepare a source directory with file in it. We will bind mount this
2016-10-29 07:03:26 +00:00
// directory and see if file shows up.
2015-12-14 15:39:53 +00:00
tmpDir2 , err := ioutil . TempDir ( "" , "volume-source2" )
if err != nil {
c . Fatal ( err )
}
defer os . RemoveAll ( tmpDir2 )
if err := ioutil . WriteFile ( path . Join ( tmpDir2 , "slave-testfile" ) , [ ] byte ( "Test" ) , 0644 ) ; err != nil {
c . Fatal ( err )
}
// Convert this directory into a shared mount point so that we do
// not rely on propagation properties of parent mount.
2016-12-13 20:21:51 +00:00
icmd . RunCommand ( "mount" , "--bind" , tmpDir , tmpDir ) . Assert ( c , icmd . Success )
icmd . RunCommand ( "mount" , "--make-private" , "--make-shared" , tmpDir ) . Assert ( c , icmd . Success )
2015-12-14 15:39:53 +00:00
dockerCmd ( c , "run" , "-i" , "-d" , "--name" , "parent" , "-v" , fmt . Sprintf ( "%s:/volume-dest:slave" , tmpDir ) , "busybox" , "top" )
// Bind mount tmpDir2/ onto tmpDir/mnt1. If mount propagates inside
// container then contents of tmpDir2/slave-testfile should become
// visible at "/volume-dest/mnt1/slave-testfile"
2016-12-13 20:21:51 +00:00
icmd . RunCommand ( "mount" , "--bind" , tmpDir2 , path . Join ( tmpDir , "mnt1" ) ) . Assert ( c , icmd . Success )
2015-12-14 15:39:53 +00:00
out , _ := dockerCmd ( c , "exec" , "parent" , "cat" , "/volume-dest/mnt1/slave-testfile" )
mount . Unmount ( path . Join ( tmpDir , "mnt1" ) )
if out != "Test" {
c . Fatalf ( "Bind mount under slave volume did not propagate to container" )
}
}
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunNamedVolumesMountedAsShared ( c * testing . T ) {
2015-12-14 15:39:53 +00:00
testRequires ( c , DaemonIsLinux , NotUserNamespace )
Add new `HostConfig` field, `Mounts`.
`Mounts` allows users to specify in a much safer way the volumes they
want to use in the container.
This replaces `Binds` and `Volumes`, which both still exist, but
`Mounts` and `Binds`/`Volumes` are exclussive.
The CLI will continue to use `Binds` and `Volumes` due to concerns with
parsing the volume specs on the client side and cross-platform support
(for now).
The new API follows exactly the services mount API.
Example usage of `Mounts`:
```
$ curl -XPOST localhost:2375/containers/create -d '{
"Image": "alpine:latest",
"HostConfig": {
"Mounts": [{
"Type": "Volume",
"Target": "/foo"
},{
"Type": "bind",
"Source": "/var/run/docker.sock",
"Target": "/var/run/docker.sock",
},{
"Type": "volume",
"Name": "important_data",
"Target": "/var/data",
"ReadOnly": true,
"VolumeOptions": {
"DriverConfig": {
Name: "awesomeStorage",
Options: {"size": "10m"},
Labels: {"some":"label"}
}
}]
}
}'
```
There are currently 2 types of mounts:
- **bind**: Paths on the host that get mounted into the
container. Paths must exist prior to creating the container.
- **volume**: Volumes that persist after the
container is removed.
Not all fields are available in each type, and validation is done to
ensure these fields aren't mixed up between types.
Signed-off-by: Brian Goff <cpuguy83@gmail.com>
2016-04-26 18:25:35 +00:00
out , exitCode , _ := dockerCmdWithError ( "run" , "-v" , "foo:/test:shared" , "busybox" , "touch" , "/test/somefile" )
2019-09-09 21:05:56 +00:00
assert . Assert ( c , exitCode != 0 )
2019-09-09 21:08:22 +00:00
assert . Assert ( c , strings . Contains ( out , "invalid mount config" ) )
2016-01-08 02:38:38 +00:00
}
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunNamedVolumeCopyImageData ( c * testing . T ) {
2016-01-08 02:38:38 +00:00
testRequires ( c , DaemonIsLinux )
2015-12-14 15:39:53 +00:00
2016-01-08 02:38:38 +00:00
testImg := "testvolumecopy"
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , testImg , build . WithDockerfile ( `
2016-01-08 02:38:38 +00:00
FROM busybox
RUN mkdir - p / foo && echo hello > / foo / hello
2017-01-16 10:30:14 +00:00
` ) )
2016-01-08 02:38:38 +00:00
dockerCmd ( c , "run" , "-v" , "foo:/foo" , testImg )
out , _ := dockerCmd ( c , "run" , "-v" , "foo:/foo" , "busybox" , "cat" , "/foo/hello" )
2019-09-09 21:05:56 +00:00
assert . Equal ( c , strings . TrimSpace ( out ) , "hello" )
2015-12-14 15:39:53 +00:00
}
2016-01-22 02:57:53 +00:00
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunNamedVolumeNotRemoved ( c * testing . T ) {
2016-02-03 14:16:00 +00:00
prefix , _ := getPrefixAndSlashFromDaemonPlatform ( )
2016-01-22 02:57:53 +00:00
2016-06-14 22:42:30 +00:00
dockerCmd ( c , "volume" , "create" , "test" )
2016-01-22 02:57:53 +00:00
dockerCmd ( c , "run" , "--rm" , "-v" , "test:" + prefix + "/foo" , "-v" , prefix + "/bar" , "busybox" , "true" )
dockerCmd ( c , "volume" , "inspect" , "test" )
out , _ := dockerCmd ( c , "volume" , "ls" , "-q" )
2019-04-04 13:23:19 +00:00
assert . Assert ( c , strings . Contains ( out , "test" ) )
2016-01-22 02:57:53 +00:00
dockerCmd ( c , "run" , "--name=test" , "-v" , "test:" + prefix + "/foo" , "-v" , prefix + "/bar" , "busybox" , "true" )
dockerCmd ( c , "rm" , "-fv" , "test" )
dockerCmd ( c , "volume" , "inspect" , "test" )
out , _ = dockerCmd ( c , "volume" , "ls" , "-q" )
2019-04-04 13:23:19 +00:00
assert . Assert ( c , strings . Contains ( out , "test" ) )
2016-01-22 02:57:53 +00:00
}
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunNamedVolumesFromNotRemoved ( c * testing . T ) {
2016-02-03 14:16:00 +00:00
prefix , _ := getPrefixAndSlashFromDaemonPlatform ( )
2016-01-22 02:57:53 +00:00
2016-06-14 22:42:30 +00:00
dockerCmd ( c , "volume" , "create" , "test" )
2017-09-15 13:16:38 +00:00
cid , _ := dockerCmd ( c , "run" , "-d" , "--name=parent" , "-v" , "test:" + prefix + "/foo" , "-v" , prefix + "/bar" , "busybox" , "true" )
2016-01-22 02:57:53 +00:00
dockerCmd ( c , "run" , "--name=child" , "--volumes-from=parent" , "busybox" , "true" )
2019-01-03 21:49:00 +00:00
cli , err := client . NewClientWithOpts ( client . FromEnv )
2019-04-04 13:23:19 +00:00
assert . NilError ( c , err )
2017-09-15 13:16:38 +00:00
defer cli . Close ( )
container , err := cli . ContainerInspect ( context . Background ( ) , strings . TrimSpace ( cid ) )
2019-04-04 13:23:19 +00:00
assert . NilError ( c , err )
2017-09-15 13:16:38 +00:00
var vname string
for _ , v := range container . Mounts {
if v . Name != "test" {
vname = v . Name
}
}
2019-09-09 21:05:56 +00:00
assert . Assert ( c , vname != "" )
2017-09-15 13:16:38 +00:00
2016-01-22 02:57:53 +00:00
// Remove the parent so there are not other references to the volumes
dockerCmd ( c , "rm" , "-f" , "parent" )
// now remove the child and ensure the named volume (and only the named volume) still exists
dockerCmd ( c , "rm" , "-fv" , "child" )
dockerCmd ( c , "volume" , "inspect" , "test" )
out , _ := dockerCmd ( c , "volume" , "ls" , "-q" )
2019-04-04 13:23:19 +00:00
assert . Assert ( c , strings . Contains ( out , "test" ) )
2019-09-09 21:07:46 +00:00
assert . Assert ( c , ! strings . Contains ( strings . TrimSpace ( out ) , vname ) )
2016-01-22 02:57:53 +00:00
}
2016-03-09 00:54:33 +00:00
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunAttachFailedNoLeak ( c * testing . T ) {
2016-03-14 22:52:50 +00:00
nroutines , err := getGoroutineNumber ( )
2019-04-04 13:23:19 +00:00
assert . NilError ( c , err )
2016-03-09 00:54:33 +00:00
runSleepingContainer ( c , "--name=test" , "-p" , "8000:8000" )
2016-03-16 15:21:29 +00:00
// Wait until container is fully up and running
2019-09-09 21:05:57 +00:00
assert . Assert ( c , waitRun ( "test" ) == nil )
2016-03-16 15:21:29 +00:00
2016-03-19 03:24:57 +00:00
out , _ , err := dockerCmdWithError ( "run" , "--name=fail" , "-p" , "8000:8000" , "busybox" , "true" )
// We will need the following `inspect` to diagnose the issue if test fails (#21247)
out1 , err1 := dockerCmd ( c , "inspect" , "--format" , "{{json .State}}" , "test" )
out2 , err2 := dockerCmd ( c , "inspect" , "--format" , "{{json .State}}" , "fail" )
2019-09-11 10:57:29 +00:00
assert . Assert ( c , err != nil , "Command should have failed but succeeded with: %s\nContainer 'test' [%+v]: %s\nContainer 'fail' [%+v]: %s" , out , err1 , out1 , err2 , out2 )
2016-03-09 00:54:33 +00:00
// check for windows error as well
2016-03-18 18:50:19 +00:00
// TODO Windows Post TP5. Fix the error message string
2019-11-25 17:45:12 +00:00
outLowerCase := strings . ToLower ( out )
assert . Assert ( c , strings . Contains ( outLowerCase , "port is already allocated" ) ||
strings . Contains ( outLowerCase , "were not connected because a duplicate name exists" ) ||
strings . Contains ( outLowerCase , "the specified port already exists" ) ||
strings . Contains ( outLowerCase , "hns failed with error : failed to create endpoint" ) ||
strings . Contains ( outLowerCase , "hns failed with error : the object already exists" ) , fmt . Sprintf ( "Output: %s" , out ) )
2016-03-09 00:54:33 +00:00
dockerCmd ( c , "rm" , "-f" , "test" )
// NGoroutines is not updated right away, so we need to wait before failing
2019-09-09 21:05:57 +00:00
assert . Assert ( c , waitForGoroutines ( nroutines ) == nil )
2016-03-09 00:54:33 +00:00
}
2016-03-11 01:06:53 +00:00
// Test for one character directory name case (#20122)
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunVolumeWithOneCharacter ( c * testing . T ) {
2016-03-11 01:06:53 +00:00
testRequires ( c , DaemonIsLinux )
out , _ := dockerCmd ( c , "run" , "-v" , "/tmp/q:/foo" , "busybox" , "sh" , "-c" , "find /foo" )
2019-04-04 13:23:19 +00:00
assert . Equal ( c , strings . TrimSpace ( out ) , "/foo" )
2016-03-11 01:06:53 +00:00
}
2016-03-15 03:31:42 +00:00
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunVolumeCopyFlag ( c * testing . T ) {
2016-03-15 03:31:42 +00:00
testRequires ( c , DaemonIsLinux ) // Windows does not support copying data from image to the volume
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , "volumecopy" , build . WithDockerfile ( ` FROM busybox
2016-03-15 03:31:42 +00:00
RUN mkdir / foo && echo hello > / foo / bar
2017-01-16 10:30:14 +00:00
CMD cat / foo / bar ` ) )
2016-06-14 22:42:30 +00:00
dockerCmd ( c , "volume" , "create" , "test" )
2016-03-15 03:31:42 +00:00
// test with the nocopy flag
out , _ , err := dockerCmdWithError ( "run" , "-v" , "test:/foo:nocopy" , "volumecopy" )
2019-04-04 13:23:19 +00:00
assert . ErrorContains ( c , err , "" , out )
2016-03-15 03:31:42 +00:00
// test default behavior which is to copy for non-binds
out , _ = dockerCmd ( c , "run" , "-v" , "test:/foo" , "volumecopy" )
2019-04-04 13:23:19 +00:00
assert . Equal ( c , strings . TrimSpace ( out ) , "hello" )
2016-03-15 03:31:42 +00:00
// error out when the volume is already populated
out , _ , err = dockerCmdWithError ( "run" , "-v" , "test:/foo:copy" , "volumecopy" )
2019-04-04 13:23:19 +00:00
assert . ErrorContains ( c , err , "" , out )
2016-03-15 03:31:42 +00:00
// do not error out when copy isn't explicitly set even though it's already populated
out , _ = dockerCmd ( c , "run" , "-v" , "test:/foo" , "volumecopy" )
2019-04-04 13:23:19 +00:00
assert . Equal ( c , strings . TrimSpace ( out ) , "hello" )
2016-03-15 03:31:42 +00:00
// do not allow copy modes on volumes-from
dockerCmd ( c , "run" , "--name=test" , "-v" , "/foo" , "busybox" , "true" )
out , _ , err = dockerCmdWithError ( "run" , "--volumes-from=test:copy" , "busybox" , "true" )
2019-04-04 13:23:19 +00:00
assert . ErrorContains ( c , err , "" , out )
2016-03-15 03:31:42 +00:00
out , _ , err = dockerCmdWithError ( "run" , "--volumes-from=test:nocopy" , "busybox" , "true" )
2019-04-04 13:23:19 +00:00
assert . ErrorContains ( c , err , "" , out )
2016-03-15 03:31:42 +00:00
// do not allow copy modes on binds
out , _ , err = dockerCmdWithError ( "run" , "-v" , "/foo:/bar:copy" , "busybox" , "true" )
2019-04-04 13:23:19 +00:00
assert . ErrorContains ( c , err , "" , out )
2016-03-15 03:31:42 +00:00
out , _ , err = dockerCmdWithError ( "run" , "-v" , "/foo:/bar:nocopy" , "busybox" , "true" )
2019-04-04 13:23:19 +00:00
assert . ErrorContains ( c , err , "" , out )
2016-03-15 03:31:42 +00:00
}
2016-03-24 04:41:21 +00:00
2016-04-29 05:46:57 +00:00
// Test case for #21976
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunDNSInHostMode ( c * testing . T ) {
2016-04-29 05:46:57 +00:00
testRequires ( c , DaemonIsLinux , NotUserNamespace )
expectedOutput := "nameserver 127.0.0.1"
expectedWarning := "Localhost DNS setting"
2017-03-27 15:12:48 +00:00
cli . DockerCmd ( c , "run" , "--dns=127.0.0.1" , "--net=host" , "busybox" , "cat" , "/etc/resolv.conf" ) . Assert ( c , icmd . Expected {
Out : expectedOutput ,
Err : expectedWarning ,
} )
2016-04-29 05:46:57 +00:00
expectedOutput = "nameserver 1.2.3.4"
2017-03-27 15:12:48 +00:00
cli . DockerCmd ( c , "run" , "--dns=1.2.3.4" , "--net=host" , "busybox" , "cat" , "/etc/resolv.conf" ) . Assert ( c , icmd . Expected {
Out : expectedOutput ,
} )
2016-04-29 05:46:57 +00:00
expectedOutput = "search example.com"
2017-03-27 15:12:48 +00:00
cli . DockerCmd ( c , "run" , "--dns-search=example.com" , "--net=host" , "busybox" , "cat" , "/etc/resolv.conf" ) . Assert ( c , icmd . Expected {
Out : expectedOutput ,
} )
2016-04-29 05:46:57 +00:00
expectedOutput = "options timeout:3"
2017-03-27 15:12:48 +00:00
cli . DockerCmd ( c , "run" , "--dns-opt=timeout:3" , "--net=host" , "busybox" , "cat" , "/etc/resolv.conf" ) . Assert ( c , icmd . Expected {
Out : expectedOutput ,
} )
2016-04-29 05:46:57 +00:00
expectedOutput1 := "nameserver 1.2.3.4"
expectedOutput2 := "search example.com"
expectedOutput3 := "options timeout:3"
2017-03-27 15:12:48 +00:00
out := cli . DockerCmd ( c , "run" , "--dns=1.2.3.4" , "--dns-search=example.com" , "--dns-opt=timeout:3" , "--net=host" , "busybox" , "cat" , "/etc/resolv.conf" ) . Combined ( )
2019-09-11 10:57:29 +00:00
assert . Assert ( c , strings . Contains ( out , expectedOutput1 ) , "Expected '%s', but got %q" , expectedOutput1 , out )
assert . Assert ( c , strings . Contains ( out , expectedOutput2 ) , "Expected '%s', but got %q" , expectedOutput2 , out )
assert . Assert ( c , strings . Contains ( out , expectedOutput3 ) , "Expected '%s', but got %q" , expectedOutput3 , out )
2016-04-29 05:46:57 +00:00
}
2016-05-25 01:49:11 +00:00
// Test case for #21976
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunAddHostInHostMode ( c * testing . T ) {
2016-05-25 01:49:11 +00:00
testRequires ( c , DaemonIsLinux , NotUserNamespace )
expectedOutput := "1.2.3.4\textra"
out , _ := dockerCmd ( c , "run" , "--add-host=extra:1.2.3.4" , "--net=host" , "busybox" , "cat" , "/etc/hosts" )
2019-09-11 10:57:29 +00:00
assert . Assert ( c , strings . Contains ( out , expectedOutput ) , "Expected '%s', but got %q" , expectedOutput , out )
2016-05-25 01:49:11 +00:00
}
2016-06-18 21:16:05 +00:00
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunRmAndWait ( c * testing . T ) {
2016-03-01 16:30:27 +00:00
dockerCmd ( c , "run" , "--name=test" , "--rm" , "-d" , "busybox" , "sh" , "-c" , "sleep 3;exit 2" )
out , code , err := dockerCmdWithError ( "wait" , "test" )
2019-09-11 10:57:29 +00:00
assert . Assert ( c , err == nil , "out: %s; exit code: %d" , out , code )
2019-04-04 13:23:19 +00:00
assert . Equal ( c , out , "2\n" , "exit code: %d" , code )
2019-09-09 21:05:56 +00:00
assert . Equal ( c , code , 0 )
2016-03-01 16:30:27 +00:00
}
2017-03-09 11:29:20 +00:00
// Test that auto-remove is performed by the daemon (API 1.25 and above)
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunRm ( c * testing . T ) {
2017-03-09 11:29:20 +00:00
name := "miss-me-when-im-gone"
2017-03-27 15:12:48 +00:00
cli . DockerCmd ( c , "run" , "--name=" + name , "--rm" , "busybox" )
2017-03-09 11:29:20 +00:00
2017-03-27 15:12:48 +00:00
cli . Docker ( cli . Inspect ( name ) , cli . Format ( ".name" ) ) . Assert ( c , icmd . Expected {
ExitCode : 1 ,
Err : "No such object: " + name ,
} )
2017-03-09 11:29:20 +00:00
}
// Test that auto-remove is performed by the client on API versions that do not support daemon-side api-remove (API < 1.25)
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunRmPre125Api ( c * testing . T ) {
2017-03-09 11:29:20 +00:00
name := "miss-me-when-im-gone"
2017-09-08 15:17:28 +00:00
envs := appendBaseEnv ( os . Getenv ( "DOCKER_TLS_VERIFY" ) != "" , "DOCKER_API_VERSION=1.24" )
2017-03-27 15:12:48 +00:00
cli . Docker ( cli . Args ( "run" , "--name=" + name , "--rm" , "busybox" ) , cli . WithEnvironmentVariables ( envs ... ) ) . Assert ( c , icmd . Success )
2017-03-09 11:29:20 +00:00
2017-03-27 15:12:48 +00:00
cli . Docker ( cli . Inspect ( name ) , cli . Format ( ".name" ) ) . Assert ( c , icmd . Expected {
ExitCode : 1 ,
Err : "No such object: " + name ,
} )
2017-03-09 11:29:20 +00:00
}
2016-06-18 21:16:05 +00:00
// Test case for #23498
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunUnsetEntrypoint ( c * testing . T ) {
2016-06-18 21:16:05 +00:00
testRequires ( c , DaemonIsLinux )
name := "test-entrypoint"
dockerfile := ` FROM busybox
ADD entrypoint . sh / entrypoint . sh
RUN chmod 755 / entrypoint . sh
ENTRYPOINT [ "/entrypoint.sh" ]
CMD echo foobar `
2017-04-10 12:42:21 +00:00
ctx := fakecontext . New ( c , "" ,
fakecontext . WithDockerfile ( dockerfile ) ,
fakecontext . WithFiles ( map [ string ] string {
"entrypoint.sh" : ` # ! / bin / sh
2016-06-18 21:16:05 +00:00
echo "I am an entrypoint"
exec "$@" ` ,
2017-04-10 12:42:21 +00:00
} ) )
2016-06-18 21:16:05 +00:00
defer ctx . Close ( )
2017-04-10 12:42:21 +00:00
cli . BuildCmd ( c , name , build . WithExternalBuildContext ( ctx ) )
2016-06-18 21:16:05 +00:00
2017-04-10 12:42:21 +00:00
out := cli . DockerCmd ( c , "run" , "--entrypoint=" , "-t" , name , "echo" , "foo" ) . Combined ( )
2019-09-09 21:05:56 +00:00
assert . Equal ( c , strings . TrimSpace ( out ) , "foo" )
2016-06-18 21:16:05 +00:00
// CMD will be reset as well (the same as setting a custom entrypoint)
2017-04-10 12:42:21 +00:00
cli . Docker ( cli . Args ( "run" , "--entrypoint=" , "-t" , name ) ) . Assert ( c , icmd . Expected {
ExitCode : 125 ,
Err : "No command specified" ,
} )
2016-06-18 21:16:05 +00:00
}
2016-09-08 04:23:56 +00:00
2019-09-09 21:05:55 +00:00
func ( s * DockerDaemonSuite ) TestRunWithUlimitAndDaemonDefault ( c * testing . T ) {
2016-12-09 22:20:14 +00:00
s . d . StartWithBusybox ( c , "--debug" , "--default-ulimit=nofile=65535" )
2016-09-08 04:23:56 +00:00
name := "test-A"
_ , err := s . d . Cmd ( "run" , "--name" , name , "-d" , "busybox" , "top" )
2019-04-04 13:23:19 +00:00
assert . NilError ( c , err )
assert . NilError ( c , s . d . WaitRun ( name ) )
2016-09-08 04:23:56 +00:00
out , err := s . d . Cmd ( "inspect" , "--format" , "{{.HostConfig.Ulimits}}" , name )
2019-04-04 13:23:19 +00:00
assert . NilError ( c , err )
2019-09-09 21:08:22 +00:00
assert . Assert ( c , strings . Contains ( out , "[nofile=65535:65535]" ) )
2016-09-08 04:23:56 +00:00
name = "test-B"
_ , err = s . d . Cmd ( "run" , "--name" , name , "--ulimit=nofile=42" , "-d" , "busybox" , "top" )
2019-04-04 13:23:19 +00:00
assert . NilError ( c , err )
assert . NilError ( c , s . d . WaitRun ( name ) )
2016-09-08 04:23:56 +00:00
out , err = s . d . Cmd ( "inspect" , "--format" , "{{.HostConfig.Ulimits}}" , name )
2019-04-04 13:23:19 +00:00
assert . NilError ( c , err )
assert . Assert ( c , strings . Contains ( out , "[nofile=42:42]" ) )
2016-09-08 04:23:56 +00:00
}
2016-09-20 15:10:04 +00:00
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunStoppedLoggingDriverNoLeak ( c * testing . T ) {
2016-09-20 15:10:04 +00:00
nroutines , err := getGoroutineNumber ( )
2019-04-04 13:23:19 +00:00
assert . NilError ( c , err )
2016-09-20 15:10:04 +00:00
out , _ , err := dockerCmdWithError ( "run" , "--name=fail" , "--log-driver=splunk" , "busybox" , "true" )
2019-04-04 13:23:19 +00:00
assert . ErrorContains ( c , err , "" )
2019-09-11 10:57:29 +00:00
assert . Assert ( c , strings . Contains ( out , "failed to initialize logging driver" ) , "error should be about logging driver, got output %s" , out )
2016-09-20 15:10:04 +00:00
// NGoroutines is not updated right away, so we need to wait before failing
2019-09-09 21:05:57 +00:00
assert . Assert ( c , waitForGoroutines ( nroutines ) == nil )
2016-09-20 15:10:04 +00:00
}
2016-06-07 19:15:50 +00:00
// Handles error conditions for --credentialspec. Validating E2E success cases
// requires additional infrastructure (AD for example) on CI servers.
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunCredentialSpecFailures ( c * testing . T ) {
2016-06-07 19:15:50 +00:00
testRequires ( c , DaemonIsWindows )
2019-03-07 01:44:36 +00:00
2016-06-07 19:15:50 +00:00
attempts := [ ] struct { value , expectedError string } {
2019-03-07 01:44:36 +00:00
{ "rubbish" , "invalid credential spec security option - value must be prefixed by 'file://', 'registry://', or 'raw://' followed by a non-empty value" } ,
{ "rubbish://" , "invalid credential spec security option - value must be prefixed by 'file://', 'registry://', or 'raw://' followed by a non-empty value" } ,
{ "file://" , "invalid credential spec security option - value must be prefixed by 'file://', 'registry://', or 'raw://' followed by a non-empty value" } ,
{ "registry://" , "invalid credential spec security option - value must be prefixed by 'file://', 'registry://', or 'raw://' followed by a non-empty value" } ,
2016-06-07 19:15:50 +00:00
{ ` file://c:\blah.txt ` , "path cannot be absolute" } ,
{ ` file://doesnotexist.txt ` , "The system cannot find the file specified" } ,
}
for _ , attempt := range attempts {
_ , _ , err := dockerCmdWithError ( "run" , "--security-opt=credentialspec=" + attempt . value , "busybox" , "true" )
2019-09-11 10:57:29 +00:00
assert . Assert ( c , err != nil , "%s expected non-nil err" , attempt . value )
assert . Assert ( c , strings . Contains ( err . Error ( ) , attempt . expectedError ) , "%s expected %s got %s" , attempt . value , attempt . expectedError , err )
2016-06-07 19:15:50 +00:00
}
}
2016-10-07 17:42:54 +00:00
2016-10-18 18:45:32 +00:00
// Windows specific test to validate credential specs with a well-formed spec.
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunCredentialSpecWellFormed ( c * testing . T ) {
2018-12-24 12:25:53 +00:00
testRequires ( c , DaemonIsWindows , testEnv . IsLocalDaemon )
2019-03-07 01:44:36 +00:00
validCredSpecs := readFile ( ` fixtures\credentialspecs\valid.json ` , c )
writeFile ( filepath . Join ( testEnv . DaemonInfo . DockerRootDir , ` credentialspecs\valid.json ` ) , validCredSpecs , c )
for _ , value := range [ ] string { "file://valid.json" , "raw://" + validCredSpecs } {
// `nltest /PARENTDOMAIN` simply reads the local config, and does not require having an AD
// controller handy
out , _ := dockerCmd ( c , "run" , "--rm" , "--security-opt=credentialspec=" + value , minimalBaseImage ( ) , "nltest" , "/PARENTDOMAIN" )
2019-09-09 21:08:22 +00:00
assert . Assert ( c , strings . Contains ( out , "hyperv.local." ) )
assert . Assert ( c , strings . Contains ( out , "The command completed successfully" ) )
2019-03-07 01:44:36 +00:00
}
2016-10-18 18:45:32 +00:00
}
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunDuplicateMount ( c * testing . T ) {
2018-12-24 12:25:53 +00:00
testRequires ( c , testEnv . IsLocalDaemon , DaemonIsLinux , NotUserNamespace )
2016-11-02 01:47:55 +00:00
tmpFile , err := ioutil . TempFile ( "" , "touch-me" )
2019-04-04 13:23:19 +00:00
assert . NilError ( c , err )
2016-11-02 01:47:55 +00:00
defer tmpFile . Close ( )
data := "touch-me-foo-bar\n"
if _ , err := tmpFile . Write ( [ ] byte ( data ) ) ; err != nil {
c . Fatal ( err )
}
name := "test"
out , _ := dockerCmd ( c , "run" , "--name" , name , "-v" , "/tmp:/tmp" , "-v" , "/tmp:/tmp" , "busybox" , "sh" , "-c" , "cat " + tmpFile . Name ( ) + " && ls /" )
2019-09-09 21:07:46 +00:00
assert . Assert ( c , ! strings . Contains ( out , "tmp:" ) )
2019-09-09 21:08:22 +00:00
assert . Assert ( c , strings . Contains ( out , data ) )
2016-11-02 01:47:55 +00:00
out = inspectFieldJSON ( c , name , "Config.Volumes" )
2019-09-09 21:08:22 +00:00
assert . Assert ( c , strings . Contains ( out , "null" ) )
2016-11-02 01:47:55 +00:00
}
2016-10-25 03:26:54 +00:00
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunWindowsWithCPUCount ( c * testing . T ) {
2016-11-01 20:02:46 +00:00
testRequires ( c , DaemonIsWindows )
out , _ := dockerCmd ( c , "run" , "--cpu-count=1" , "--name" , "test" , "busybox" , "echo" , "testing" )
2019-04-04 13:23:19 +00:00
assert . Equal ( c , strings . TrimSpace ( out ) , "testing" )
2016-11-01 20:02:46 +00:00
out = inspectField ( c , "test" , "HostConfig.CPUCount" )
2019-04-04 13:23:19 +00:00
assert . Equal ( c , out , "1" )
2016-11-01 20:02:46 +00:00
}
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunWindowsWithCPUShares ( c * testing . T ) {
2016-11-01 20:02:46 +00:00
testRequires ( c , DaemonIsWindows )
out , _ := dockerCmd ( c , "run" , "--cpu-shares=1000" , "--name" , "test" , "busybox" , "echo" , "testing" )
2019-04-04 13:23:19 +00:00
assert . Equal ( c , strings . TrimSpace ( out ) , "testing" )
2016-11-01 20:02:46 +00:00
out = inspectField ( c , "test" , "HostConfig.CPUShares" )
2019-04-04 13:23:19 +00:00
assert . Equal ( c , out , "1000" )
2016-11-01 20:02:46 +00:00
}
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunWindowsWithCPUPercent ( c * testing . T ) {
2016-11-01 20:02:46 +00:00
testRequires ( c , DaemonIsWindows )
out , _ := dockerCmd ( c , "run" , "--cpu-percent=80" , "--name" , "test" , "busybox" , "echo" , "testing" )
2019-04-04 13:23:19 +00:00
assert . Equal ( c , strings . TrimSpace ( out ) , "testing" )
2016-11-01 20:02:46 +00:00
out = inspectField ( c , "test" , "HostConfig.CPUPercent" )
2019-04-04 13:23:19 +00:00
assert . Equal ( c , out , "80" )
2016-11-01 20:02:46 +00:00
}
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunProcessIsolationWithCPUCountCPUSharesAndCPUPercent ( c * testing . T ) {
2019-08-07 08:29:39 +00:00
testRequires ( c , IsolationIsProcess )
2016-11-01 20:02:46 +00:00
out , _ := dockerCmd ( c , "run" , "--cpu-count=1" , "--cpu-shares=1000" , "--cpu-percent=80" , "--name" , "test" , "busybox" , "echo" , "testing" )
2019-09-09 21:08:22 +00:00
assert . Assert ( c , strings . Contains ( strings . TrimSpace ( out ) , "WARNING: Conflicting options: CPU count takes priority over CPU shares on Windows Server Containers. CPU shares discarded" ) )
assert . Assert ( c , strings . Contains ( strings . TrimSpace ( out ) , "WARNING: Conflicting options: CPU count takes priority over CPU percent on Windows Server Containers. CPU percent discarded" ) )
assert . Assert ( c , strings . Contains ( strings . TrimSpace ( out ) , "testing" ) )
2016-11-01 20:02:46 +00:00
out = inspectField ( c , "test" , "HostConfig.CPUCount" )
2019-04-04 13:23:19 +00:00
assert . Equal ( c , out , "1" )
2016-11-01 20:02:46 +00:00
out = inspectField ( c , "test" , "HostConfig.CPUShares" )
2019-04-04 13:23:19 +00:00
assert . Equal ( c , out , "0" )
2016-11-01 20:02:46 +00:00
out = inspectField ( c , "test" , "HostConfig.CPUPercent" )
2019-04-04 13:23:19 +00:00
assert . Equal ( c , out , "0" )
2016-11-01 20:02:46 +00:00
}
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunHypervIsolationWithCPUCountCPUSharesAndCPUPercent ( c * testing . T ) {
2019-08-07 08:29:39 +00:00
testRequires ( c , IsolationIsHyperv )
2016-11-01 20:02:46 +00:00
out , _ := dockerCmd ( c , "run" , "--cpu-count=1" , "--cpu-shares=1000" , "--cpu-percent=80" , "--name" , "test" , "busybox" , "echo" , "testing" )
2019-09-09 21:08:22 +00:00
assert . Assert ( c , strings . Contains ( strings . TrimSpace ( out ) , "testing" ) )
2016-11-01 20:02:46 +00:00
out = inspectField ( c , "test" , "HostConfig.CPUCount" )
2019-04-04 13:23:19 +00:00
assert . Equal ( c , out , "1" )
2016-11-01 20:02:46 +00:00
out = inspectField ( c , "test" , "HostConfig.CPUShares" )
2019-04-04 13:23:19 +00:00
assert . Equal ( c , out , "1000" )
2016-11-01 20:02:46 +00:00
out = inspectField ( c , "test" , "HostConfig.CPUPercent" )
2019-04-04 13:23:19 +00:00
assert . Equal ( c , out , "80" )
2016-11-01 20:02:46 +00:00
}
2016-11-05 18:53:54 +00:00
// Test for #25099
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunEmptyEnv ( c * testing . T ) {
2016-11-05 18:53:54 +00:00
testRequires ( c , DaemonIsLinux )
expectedOutput := "invalid environment variable:"
out , _ , err := dockerCmdWithError ( "run" , "-e" , "" , "busybox" , "true" )
2019-04-04 13:23:19 +00:00
assert . ErrorContains ( c , err , "" )
assert . Assert ( c , strings . Contains ( out , expectedOutput ) )
2016-11-05 18:53:54 +00:00
out , _ , err = dockerCmdWithError ( "run" , "-e" , "=" , "busybox" , "true" )
2019-04-04 13:23:19 +00:00
assert . ErrorContains ( c , err , "" )
assert . Assert ( c , strings . Contains ( out , expectedOutput ) )
2016-11-05 18:53:54 +00:00
out , _ , err = dockerCmdWithError ( "run" , "-e" , "=foo" , "busybox" , "true" )
2019-04-04 13:23:19 +00:00
assert . ErrorContains ( c , err , "" )
assert . Assert ( c , strings . Contains ( out , expectedOutput ) )
2016-11-05 18:53:54 +00:00
}
2016-11-21 22:10:34 +00:00
// #28658
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestSlowStdinClosing ( c * testing . T ) {
2016-11-21 22:10:34 +00:00
name := "testslowstdinclosing"
repeat := 3 // regression happened 50% of the time
for i := 0 ; i < repeat ; i ++ {
2016-12-13 20:21:51 +00:00
cmd := icmd . Cmd {
Command : [ ] string { dockerBinary , "run" , "--rm" , "--name" , name , "-i" , "busybox" , "cat" } ,
Stdin : & delayedReader { } ,
}
2016-11-21 22:10:34 +00:00
done := make ( chan error , 1 )
go func ( ) {
2016-12-13 20:21:51 +00:00
err := icmd . RunCmd ( cmd ) . Error
2016-11-21 22:10:34 +00:00
done <- err
} ( )
select {
2018-03-13 03:27:28 +00:00
case <- time . After ( 30 * time . Second ) :
2016-11-21 22:10:34 +00:00
c . Fatal ( "running container timed out" ) // cleanup in teardown
case err := <- done :
2019-04-04 13:23:19 +00:00
assert . NilError ( c , err )
2016-11-21 22:10:34 +00:00
}
}
}
type delayedReader struct { }
func ( s * delayedReader ) Read ( [ ] byte ) ( int , error ) {
time . Sleep ( 500 * time . Millisecond )
return 0 , io . EOF
}
2016-11-25 05:54:38 +00:00
// #28823 (originally #28639)
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunMountReadOnlyDevShm ( c * testing . T ) {
2018-12-24 12:25:53 +00:00
testRequires ( c , testEnv . IsLocalDaemon , DaemonIsLinux , NotUserNamespace )
2016-11-25 05:54:38 +00:00
emptyDir , err := ioutil . TempDir ( "" , "test-read-only-dev-shm" )
2019-04-04 13:23:19 +00:00
assert . NilError ( c , err )
2016-11-25 05:54:38 +00:00
defer os . RemoveAll ( emptyDir )
out , _ , err := dockerCmdWithError ( "run" , "--rm" , "--read-only" ,
"-v" , fmt . Sprintf ( "%s:/dev/shm:ro" , emptyDir ) ,
"busybox" , "touch" , "/dev/shm/foo" )
2019-04-04 13:23:19 +00:00
assert . ErrorContains ( c , err , "" , out )
2019-09-09 21:08:22 +00:00
assert . Assert ( c , strings . Contains ( out , "Read-only file system" ) )
2016-11-25 05:54:38 +00:00
}
2016-12-05 16:56:42 +00:00
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunMount ( c * testing . T ) {
2018-12-24 12:25:53 +00:00
testRequires ( c , DaemonIsLinux , testEnv . IsLocalDaemon , NotUserNamespace )
2017-03-31 06:41:45 +00:00
// mnt1, mnt2, and testCatFooBar are commonly used in multiple test cases
tmpDir , err := ioutil . TempDir ( "" , "mount" )
if err != nil {
c . Fatal ( err )
}
defer os . RemoveAll ( tmpDir )
mnt1 , mnt2 := path . Join ( tmpDir , "mnt1" ) , path . Join ( tmpDir , "mnt2" )
if err := os . Mkdir ( mnt1 , 0755 ) ; err != nil {
c . Fatal ( err )
}
if err := os . Mkdir ( mnt2 , 0755 ) ; err != nil {
c . Fatal ( err )
}
if err := ioutil . WriteFile ( path . Join ( mnt1 , "test1" ) , [ ] byte ( "test1" ) , 0644 ) ; err != nil {
c . Fatal ( err )
}
if err := ioutil . WriteFile ( path . Join ( mnt2 , "test2" ) , [ ] byte ( "test2" ) , 0644 ) ; err != nil {
c . Fatal ( err )
}
testCatFooBar := func ( cName string ) error {
out , _ := dockerCmd ( c , "exec" , cName , "cat" , "/foo/test1" )
if out != "test1" {
return fmt . Errorf ( "%s not mounted on /foo" , mnt1 )
}
out , _ = dockerCmd ( c , "exec" , cName , "cat" , "/bar/test2" )
if out != "test2" {
return fmt . Errorf ( "%s not mounted on /bar" , mnt2 )
}
return nil
}
type testCase struct {
equivalents [ ] [ ] string
valid bool
// fn should be nil if valid==false
fn func ( cName string ) error
}
cases := [ ] testCase {
{
equivalents : [ ] [ ] string {
{
"--mount" , fmt . Sprintf ( "type=bind,src=%s,dst=/foo" , mnt1 ) ,
"--mount" , fmt . Sprintf ( "type=bind,src=%s,dst=/bar" , mnt2 ) ,
} ,
{
"--mount" , fmt . Sprintf ( "type=bind,src=%s,dst=/foo" , mnt1 ) ,
"--mount" , fmt . Sprintf ( "type=bind,src=%s,target=/bar" , mnt2 ) ,
} ,
{
"--volume" , mnt1 + ":/foo" ,
"--mount" , fmt . Sprintf ( "type=bind,src=%s,target=/bar" , mnt2 ) ,
} ,
} ,
valid : true ,
fn : testCatFooBar ,
} ,
{
equivalents : [ ] [ ] string {
{
"--mount" , fmt . Sprintf ( "type=volume,src=%s,dst=/foo" , mnt1 ) ,
"--mount" , fmt . Sprintf ( "type=volume,src=%s,dst=/bar" , mnt2 ) ,
} ,
{
"--mount" , fmt . Sprintf ( "type=volume,src=%s,dst=/foo" , mnt1 ) ,
"--mount" , fmt . Sprintf ( "type=volume,src=%s,target=/bar" , mnt2 ) ,
} ,
} ,
valid : false ,
} ,
{
equivalents : [ ] [ ] string {
{
"--mount" , fmt . Sprintf ( "type=bind,src=%s,dst=/foo" , mnt1 ) ,
"--mount" , fmt . Sprintf ( "type=volume,src=%s,dst=/bar" , mnt2 ) ,
} ,
{
"--volume" , mnt1 + ":/foo" ,
"--mount" , fmt . Sprintf ( "type=volume,src=%s,target=/bar" , mnt2 ) ,
} ,
} ,
valid : false ,
fn : testCatFooBar ,
} ,
{
equivalents : [ ] [ ] string {
{
"--read-only" ,
"--mount" , "type=volume,dst=/bar" ,
} ,
} ,
valid : true ,
fn : func ( cName string ) error {
_ , _ , err := dockerCmdWithError ( "exec" , cName , "touch" , "/bar/icanwritehere" )
return err
} ,
} ,
{
equivalents : [ ] [ ] string {
{
"--read-only" ,
"--mount" , fmt . Sprintf ( "type=bind,src=%s,dst=/foo" , mnt1 ) ,
"--mount" , "type=volume,dst=/bar" ,
} ,
{
"--read-only" ,
"--volume" , fmt . Sprintf ( "%s:/foo" , mnt1 ) ,
"--mount" , "type=volume,dst=/bar" ,
} ,
} ,
valid : true ,
fn : func ( cName string ) error {
out , _ := dockerCmd ( c , "exec" , cName , "cat" , "/foo/test1" )
if out != "test1" {
return fmt . Errorf ( "%s not mounted on /foo" , mnt1 )
}
_ , _ , err := dockerCmdWithError ( "exec" , cName , "touch" , "/bar/icanwritehere" )
return err
} ,
} ,
{
equivalents : [ ] [ ] string {
{
"--mount" , fmt . Sprintf ( "type=bind,src=%s,dst=/foo" , mnt1 ) ,
"--mount" , fmt . Sprintf ( "type=bind,src=%s,dst=/foo" , mnt2 ) ,
} ,
{
"--mount" , fmt . Sprintf ( "type=bind,src=%s,dst=/foo" , mnt1 ) ,
"--mount" , fmt . Sprintf ( "type=bind,src=%s,target=/foo" , mnt2 ) ,
} ,
{
"--volume" , fmt . Sprintf ( "%s:/foo" , mnt1 ) ,
"--mount" , fmt . Sprintf ( "type=bind,src=%s,target=/foo" , mnt2 ) ,
} ,
} ,
valid : false ,
} ,
{
equivalents : [ ] [ ] string {
{
"--volume" , fmt . Sprintf ( "%s:/foo" , mnt1 ) ,
"--mount" , fmt . Sprintf ( "type=volume,src=%s,target=/foo" , mnt2 ) ,
} ,
} ,
valid : false ,
} ,
{
equivalents : [ ] [ ] string {
{
"--mount" , "type=volume,target=/foo" ,
"--mount" , "type=volume,target=/foo" ,
} ,
} ,
valid : false ,
} ,
}
for i , testCase := range cases {
for j , opts := range testCase . equivalents {
cName := fmt . Sprintf ( "mount-%d-%d" , i , j )
_ , _ , err := dockerCmdWithError ( append ( [ ] string { "run" , "-i" , "-d" , "--name" , cName } ,
append ( opts , [ ] string { "busybox" , "top" } ... ) ... ) ... )
if testCase . valid {
2019-09-11 10:57:29 +00:00
assert . Assert ( c , err == nil , "got error while creating a container with %v (%s)" , opts , cName )
assert . Assert ( c , testCase . fn ( cName ) == nil , "got error while executing test for %v (%s)" , opts , cName )
2017-03-31 06:41:45 +00:00
dockerCmd ( c , "rm" , "-f" , cName )
} else {
2019-09-11 10:57:29 +00:00
assert . Assert ( c , err != nil , "got nil while creating a container with %v (%s)" , opts , cName )
2017-03-31 06:41:45 +00:00
}
}
}
}
2016-12-12 17:19:23 +00:00
// Test that passing a FQDN as hostname properly sets hostname, and
// /etc/hostname. Test case for 29100
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunHostnameFQDN ( c * testing . T ) {
2016-12-12 17:19:23 +00:00
testRequires ( c , DaemonIsLinux )
expectedOutput := "foobar.example.com\nfoobar.example.com\nfoobar\nexample.com\nfoobar.example.com"
out , _ := dockerCmd ( c , "run" , "--hostname=foobar.example.com" , "busybox" , "sh" , "-c" , ` cat /etc/hostname && hostname && hostname -s && hostname -d && hostname -f ` )
2019-04-04 13:23:19 +00:00
assert . Equal ( c , strings . TrimSpace ( out ) , expectedOutput )
2016-12-12 17:19:23 +00:00
out , _ = dockerCmd ( c , "run" , "--hostname=foobar.example.com" , "busybox" , "sh" , "-c" , ` cat /etc/hosts ` )
expectedOutput = "foobar.example.com foobar"
2019-09-09 21:08:22 +00:00
assert . Assert ( c , strings . Contains ( strings . TrimSpace ( out ) , expectedOutput ) )
2016-12-12 17:19:23 +00:00
}
2016-12-05 16:56:42 +00:00
// Test case for 29129
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunHostnameInHostMode ( c * testing . T ) {
2017-01-02 18:13:26 +00:00
testRequires ( c , DaemonIsLinux , NotUserNamespace )
2016-12-05 16:56:42 +00:00
expectedOutput := "foobar\nfoobar"
out , _ := dockerCmd ( c , "run" , "--net=host" , "--hostname=foobar" , "busybox" , "sh" , "-c" , ` echo $HOSTNAME && hostname ` )
2019-04-04 13:23:19 +00:00
assert . Equal ( c , strings . TrimSpace ( out ) , expectedOutput )
2016-12-05 16:56:42 +00:00
}
2016-05-06 22:09:46 +00:00
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestRunAddDeviceCgroupRule ( c * testing . T ) {
2016-05-06 22:09:46 +00:00
testRequires ( c , DaemonIsLinux )
deviceRule := "c 7:128 rwm"
out , _ := dockerCmd ( c , "run" , "--rm" , "busybox" , "cat" , "/sys/fs/cgroup/devices/devices.list" )
if strings . Contains ( out , deviceRule ) {
c . Fatalf ( "%s shouldn't been in the device.list" , deviceRule )
}
out , _ = dockerCmd ( c , "run" , "--rm" , fmt . Sprintf ( "--device-cgroup-rule=%s" , deviceRule ) , "busybox" , "grep" , deviceRule , "/sys/fs/cgroup/devices/devices.list" )
2019-04-04 13:23:19 +00:00
assert . Equal ( c , strings . TrimSpace ( out ) , deviceRule )
2016-05-06 22:09:46 +00:00
}
2017-01-10 23:54:24 +00:00
// Verifies that running as local system is operating correctly on Windows
2019-09-09 21:05:55 +00:00
func ( s * DockerSuite ) TestWindowsRunAsSystem ( c * testing . T ) {
2019-04-17 10:39:07 +00:00
testRequires ( c , DaemonIsWindowsAtLeastBuild ( osversion . RS3 ) )
2017-01-10 23:54:24 +00:00
out , _ := dockerCmd ( c , "run" , "--net=none" , ` --user=nt authority\system ` , "--hostname=XYZZY" , minimalBaseImage ( ) , "cmd" , "/c" , ` @echo %USERNAME% ` )
2019-04-04 13:23:19 +00:00
assert . Equal ( c , strings . TrimSpace ( out ) , "XYZZY$" )
2017-01-10 23:54:24 +00:00
}