github.com/devdivbcp/moby@v17.12.0-ce-rc1.0.20200726071732-2d4bfdc789ad+incompatible/integration-cli/docker_cli_create_test.go (about)

     1  package main
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"os"
     7  	"reflect"
     8  	"strings"
     9  	"testing"
    10  	"time"
    11  
    12  	"github.com/docker/docker/integration-cli/cli"
    13  	"github.com/docker/docker/integration-cli/cli/build"
    14  	"github.com/docker/docker/internal/test/fakecontext"
    15  	"github.com/docker/docker/pkg/stringid"
    16  	"github.com/docker/go-connections/nat"
    17  	"gotest.tools/assert"
    18  	is "gotest.tools/assert/cmp"
    19  )
    20  
    21  // Make sure we can create a simple container with some args
    22  func (s *DockerSuite) TestCreateArgs(c *testing.T) {
    23  	// Intentionally clear entrypoint, as the Windows busybox image needs an entrypoint, which breaks this test
    24  	out, _ := dockerCmd(c, "create", "--entrypoint=", "busybox", "command", "arg1", "arg2", "arg with space", "-c", "flags")
    25  
    26  	cleanedContainerID := strings.TrimSpace(out)
    27  
    28  	out, _ = dockerCmd(c, "inspect", cleanedContainerID)
    29  
    30  	var containers []struct {
    31  		ID      string
    32  		Created time.Time
    33  		Path    string
    34  		Args    []string
    35  		Image   string
    36  	}
    37  
    38  	err := json.Unmarshal([]byte(out), &containers)
    39  	assert.Assert(c, err == nil, "Error inspecting the container: %s", err)
    40  	assert.Equal(c, len(containers), 1)
    41  
    42  	cont := containers[0]
    43  	assert.Equal(c, cont.Path, "command", fmt.Sprintf("Unexpected container path. Expected command, received: %s", cont.Path))
    44  
    45  	b := false
    46  	expected := []string{"arg1", "arg2", "arg with space", "-c", "flags"}
    47  	for i, arg := range expected {
    48  		if arg != cont.Args[i] {
    49  			b = true
    50  			break
    51  		}
    52  	}
    53  	if len(cont.Args) != len(expected) || b {
    54  		c.Fatalf("Unexpected args. Expected %v, received: %v", expected, cont.Args)
    55  	}
    56  
    57  }
    58  
    59  // Make sure we can grow the container's rootfs at creation time.
    60  func (s *DockerSuite) TestCreateGrowRootfs(c *testing.T) {
    61  	// Windows and Devicemapper support growing the rootfs
    62  	if testEnv.OSType != "windows" {
    63  		testRequires(c, Devicemapper)
    64  	}
    65  	out, _ := dockerCmd(c, "create", "--storage-opt", "size=120G", "busybox")
    66  
    67  	cleanedContainerID := strings.TrimSpace(out)
    68  
    69  	inspectOut := inspectField(c, cleanedContainerID, "HostConfig.StorageOpt")
    70  	assert.Equal(c, inspectOut, "map[size:120G]")
    71  }
    72  
    73  // Make sure we cannot shrink the container's rootfs at creation time.
    74  func (s *DockerSuite) TestCreateShrinkRootfs(c *testing.T) {
    75  	testRequires(c, Devicemapper)
    76  
    77  	// Ensure this fails because of the defaultBaseFsSize is 10G
    78  	out, _, err := dockerCmdWithError("create", "--storage-opt", "size=5G", "busybox")
    79  	assert.ErrorContains(c, err, "", out)
    80  	assert.Assert(c, strings.Contains(out, "Container size cannot be smaller than"))
    81  }
    82  
    83  // Make sure we can set hostconfig options too
    84  func (s *DockerSuite) TestCreateHostConfig(c *testing.T) {
    85  	out, _ := dockerCmd(c, "create", "-P", "busybox", "echo")
    86  
    87  	cleanedContainerID := strings.TrimSpace(out)
    88  
    89  	out, _ = dockerCmd(c, "inspect", cleanedContainerID)
    90  
    91  	var containers []struct {
    92  		HostConfig *struct {
    93  			PublishAllPorts bool
    94  		}
    95  	}
    96  
    97  	err := json.Unmarshal([]byte(out), &containers)
    98  	assert.Assert(c, err == nil, "Error inspecting the container: %s", err)
    99  	assert.Equal(c, len(containers), 1)
   100  
   101  	cont := containers[0]
   102  	assert.Assert(c, cont.HostConfig != nil, "Expected HostConfig, got none")
   103  	assert.Assert(c, cont.HostConfig.PublishAllPorts, "Expected PublishAllPorts, got false")
   104  }
   105  
   106  func (s *DockerSuite) TestCreateWithPortRange(c *testing.T) {
   107  	out, _ := dockerCmd(c, "create", "-p", "3300-3303:3300-3303/tcp", "busybox", "echo")
   108  
   109  	cleanedContainerID := strings.TrimSpace(out)
   110  
   111  	out, _ = dockerCmd(c, "inspect", cleanedContainerID)
   112  
   113  	var containers []struct {
   114  		HostConfig *struct {
   115  			PortBindings map[nat.Port][]nat.PortBinding
   116  		}
   117  	}
   118  	err := json.Unmarshal([]byte(out), &containers)
   119  	assert.Assert(c, err == nil, "Error inspecting the container: %s", err)
   120  	assert.Equal(c, len(containers), 1)
   121  
   122  	cont := containers[0]
   123  
   124  	assert.Assert(c, cont.HostConfig != nil, "Expected HostConfig, got none")
   125  	assert.Equal(c, len(cont.HostConfig.PortBindings), 4, fmt.Sprintf("Expected 4 ports bindings, got %d", len(cont.HostConfig.PortBindings)))
   126  
   127  	for k, v := range cont.HostConfig.PortBindings {
   128  		assert.Equal(c, len(v), 1, fmt.Sprintf("Expected 1 ports binding, for the port  %s but found %s", k, v))
   129  		assert.Equal(c, k.Port(), v[0].HostPort, fmt.Sprintf("Expected host port %s to match published port %s", k.Port(), v[0].HostPort))
   130  
   131  	}
   132  
   133  }
   134  
   135  func (s *DockerSuite) TestCreateWithLargePortRange(c *testing.T) {
   136  	out, _ := dockerCmd(c, "create", "-p", "1-65535:1-65535/tcp", "busybox", "echo")
   137  
   138  	cleanedContainerID := strings.TrimSpace(out)
   139  
   140  	out, _ = dockerCmd(c, "inspect", cleanedContainerID)
   141  
   142  	var containers []struct {
   143  		HostConfig *struct {
   144  			PortBindings map[nat.Port][]nat.PortBinding
   145  		}
   146  	}
   147  
   148  	err := json.Unmarshal([]byte(out), &containers)
   149  	assert.Assert(c, err == nil, "Error inspecting the container: %s", err)
   150  	assert.Equal(c, len(containers), 1)
   151  
   152  	cont := containers[0]
   153  	assert.Assert(c, cont.HostConfig != nil, "Expected HostConfig, got none")
   154  	assert.Equal(c, len(cont.HostConfig.PortBindings), 65535)
   155  
   156  	for k, v := range cont.HostConfig.PortBindings {
   157  		assert.Equal(c, len(v), 1)
   158  		assert.Equal(c, k.Port(), v[0].HostPort, fmt.Sprintf("Expected host port %s to match published port %s", k.Port(), v[0].HostPort))
   159  	}
   160  
   161  }
   162  
   163  // "test123" should be printed by docker create + start
   164  func (s *DockerSuite) TestCreateEchoStdout(c *testing.T) {
   165  	out, _ := dockerCmd(c, "create", "busybox", "echo", "test123")
   166  
   167  	cleanedContainerID := strings.TrimSpace(out)
   168  
   169  	out, _ = dockerCmd(c, "start", "-ai", cleanedContainerID)
   170  	assert.Equal(c, out, "test123\n", "container should've printed 'test123', got %q", out)
   171  }
   172  
   173  func (s *DockerSuite) TestCreateVolumesCreated(c *testing.T) {
   174  	testRequires(c, testEnv.IsLocalDaemon)
   175  	prefix, slash := getPrefixAndSlashFromDaemonPlatform()
   176  
   177  	name := "test_create_volume"
   178  	dockerCmd(c, "create", "--name", name, "-v", prefix+slash+"foo", "busybox")
   179  
   180  	dir, err := inspectMountSourceField(name, prefix+slash+"foo")
   181  	assert.Assert(c, err == nil, "Error getting volume host path: %q", err)
   182  
   183  	if _, err := os.Stat(dir); err != nil && os.IsNotExist(err) {
   184  		c.Fatalf("Volume was not created")
   185  	}
   186  	if err != nil {
   187  		c.Fatalf("Error statting volume host path: %q", err)
   188  	}
   189  
   190  }
   191  
   192  func (s *DockerSuite) TestCreateLabels(c *testing.T) {
   193  	name := "test_create_labels"
   194  	expected := map[string]string{"k1": "v1", "k2": "v2"}
   195  	dockerCmd(c, "create", "--name", name, "-l", "k1=v1", "--label", "k2=v2", "busybox")
   196  
   197  	actual := make(map[string]string)
   198  	inspectFieldAndUnmarshall(c, name, "Config.Labels", &actual)
   199  
   200  	if !reflect.DeepEqual(expected, actual) {
   201  		c.Fatalf("Expected %s got %s", expected, actual)
   202  	}
   203  }
   204  
   205  func (s *DockerSuite) TestCreateLabelFromImage(c *testing.T) {
   206  	imageName := "testcreatebuildlabel"
   207  	buildImageSuccessfully(c, imageName, build.WithDockerfile(`FROM busybox
   208  		LABEL k1=v1 k2=v2`))
   209  
   210  	name := "test_create_labels_from_image"
   211  	expected := map[string]string{"k2": "x", "k3": "v3", "k1": "v1"}
   212  	dockerCmd(c, "create", "--name", name, "-l", "k2=x", "--label", "k3=v3", imageName)
   213  
   214  	actual := make(map[string]string)
   215  	inspectFieldAndUnmarshall(c, name, "Config.Labels", &actual)
   216  
   217  	if !reflect.DeepEqual(expected, actual) {
   218  		c.Fatalf("Expected %s got %s", expected, actual)
   219  	}
   220  }
   221  
   222  func (s *DockerSuite) TestCreateHostnameWithNumber(c *testing.T) {
   223  	image := "busybox"
   224  	// Busybox on Windows does not implement hostname command
   225  	if testEnv.OSType == "windows" {
   226  		image = testEnv.PlatformDefaults.BaseImage
   227  	}
   228  	out, _ := dockerCmd(c, "run", "-h", "web.0", image, "hostname")
   229  	assert.Equal(c, strings.TrimSpace(out), "web.0", "hostname not set, expected `web.0`, got: %s", out)
   230  }
   231  
   232  func (s *DockerSuite) TestCreateRM(c *testing.T) {
   233  	// Test to make sure we can 'rm' a new container that is in
   234  	// "Created" state, and has ever been run. Test "rm -f" too.
   235  
   236  	// create a container
   237  	out, _ := dockerCmd(c, "create", "busybox")
   238  	cID := strings.TrimSpace(out)
   239  
   240  	dockerCmd(c, "rm", cID)
   241  
   242  	// Now do it again so we can "rm -f" this time
   243  	out, _ = dockerCmd(c, "create", "busybox")
   244  
   245  	cID = strings.TrimSpace(out)
   246  	dockerCmd(c, "rm", "-f", cID)
   247  }
   248  
   249  func (s *DockerSuite) TestCreateModeIpcContainer(c *testing.T) {
   250  	// Uses Linux specific functionality (--ipc)
   251  	testRequires(c, DaemonIsLinux, testEnv.IsLocalDaemon)
   252  
   253  	out, _ := dockerCmd(c, "create", "busybox")
   254  	id := strings.TrimSpace(out)
   255  
   256  	dockerCmd(c, "create", fmt.Sprintf("--ipc=container:%s", id), "busybox")
   257  }
   258  
   259  func (s *DockerSuite) TestCreateByImageID(c *testing.T) {
   260  	imageName := "testcreatebyimageid"
   261  	buildImageSuccessfully(c, imageName, build.WithDockerfile(`FROM busybox
   262  		MAINTAINER dockerio`))
   263  	imageID := getIDByName(c, imageName)
   264  	truncatedImageID := stringid.TruncateID(imageID)
   265  
   266  	dockerCmd(c, "create", imageID)
   267  	dockerCmd(c, "create", truncatedImageID)
   268  
   269  	// Ensure this fails
   270  	out, exit, _ := dockerCmdWithError("create", fmt.Sprintf("%s:%s", imageName, imageID))
   271  	if exit == 0 {
   272  		c.Fatalf("expected non-zero exit code; received %d", exit)
   273  	}
   274  
   275  	if expected := "invalid reference format"; !strings.Contains(out, expected) {
   276  		c.Fatalf(`Expected %q in output; got: %s`, expected, out)
   277  	}
   278  
   279  	if i := strings.IndexRune(imageID, ':'); i >= 0 {
   280  		imageID = imageID[i+1:]
   281  	}
   282  	out, exit, _ = dockerCmdWithError("create", fmt.Sprintf("%s:%s", "wrongimage", imageID))
   283  	if exit == 0 {
   284  		c.Fatalf("expected non-zero exit code; received %d", exit)
   285  	}
   286  
   287  	if expected := "Unable to find image"; !strings.Contains(out, expected) {
   288  		c.Fatalf(`Expected %q in output; got: %s`, expected, out)
   289  	}
   290  }
   291  
   292  func (s *DockerSuite) TestCreateStopSignal(c *testing.T) {
   293  	name := "test_create_stop_signal"
   294  	dockerCmd(c, "create", "--name", name, "--stop-signal", "9", "busybox")
   295  
   296  	res := inspectFieldJSON(c, name, "Config.StopSignal")
   297  	assert.Assert(c, strings.Contains(res, "9"))
   298  }
   299  
   300  func (s *DockerSuite) TestCreateWithWorkdir(c *testing.T) {
   301  	name := "foo"
   302  
   303  	prefix, slash := getPrefixAndSlashFromDaemonPlatform()
   304  	dir := prefix + slash + "home" + slash + "foo" + slash + "bar"
   305  
   306  	dockerCmd(c, "create", "--name", name, "-w", dir, "busybox")
   307  	// Windows does not create the workdir until the container is started
   308  	if testEnv.OSType == "windows" {
   309  		dockerCmd(c, "start", name)
   310  		if IsolationIsHyperv() {
   311  			// Hyper-V isolated containers do not allow file-operations on a
   312  			// running container. This test currently uses `docker cp` to verify
   313  			// that the WORKDIR was automatically created, which cannot be done
   314  			// while the container is running.
   315  			dockerCmd(c, "stop", name)
   316  		}
   317  	}
   318  	// TODO: rewrite this test to not use `docker cp` for verifying that the WORKDIR was created
   319  	dockerCmd(c, "cp", fmt.Sprintf("%s:%s", name, dir), prefix+slash+"tmp")
   320  }
   321  
   322  func (s *DockerSuite) TestCreateWithInvalidLogOpts(c *testing.T) {
   323  	name := "test-invalidate-log-opts"
   324  	out, _, err := dockerCmdWithError("create", "--name", name, "--log-opt", "invalid=true", "busybox")
   325  	assert.ErrorContains(c, err, "")
   326  	assert.Assert(c, strings.Contains(out, "unknown log opt"))
   327  	assert.Assert(c, is.Contains(out, "unknown log opt"))
   328  
   329  	out, _ = dockerCmd(c, "ps", "-a")
   330  	assert.Assert(c, !strings.Contains(out, name))
   331  }
   332  
   333  // #20972
   334  func (s *DockerSuite) TestCreate64ByteHexID(c *testing.T) {
   335  	out := inspectField(c, "busybox", "Id")
   336  	imageID := strings.TrimPrefix(strings.TrimSpace(out), "sha256:")
   337  
   338  	dockerCmd(c, "create", imageID)
   339  }
   340  
   341  // Test case for #23498
   342  func (s *DockerSuite) TestCreateUnsetEntrypoint(c *testing.T) {
   343  	name := "test-entrypoint"
   344  	dockerfile := `FROM busybox
   345  ADD entrypoint.sh /entrypoint.sh
   346  RUN chmod 755 /entrypoint.sh
   347  ENTRYPOINT ["/entrypoint.sh"]
   348  CMD echo foobar`
   349  
   350  	ctx := fakecontext.New(c, "",
   351  		fakecontext.WithDockerfile(dockerfile),
   352  		fakecontext.WithFiles(map[string]string{
   353  			"entrypoint.sh": `#!/bin/sh
   354  echo "I am an entrypoint"
   355  exec "$@"`,
   356  		}))
   357  	defer ctx.Close()
   358  
   359  	cli.BuildCmd(c, name, build.WithExternalBuildContext(ctx))
   360  
   361  	out := cli.DockerCmd(c, "create", "--entrypoint=", name, "echo", "foo").Combined()
   362  	id := strings.TrimSpace(out)
   363  	assert.Assert(c, id != "")
   364  	out = cli.DockerCmd(c, "start", "-a", id).Combined()
   365  	assert.Equal(c, strings.TrimSpace(out), "foo")
   366  }
   367  
   368  // #22471
   369  func (s *DockerSuite) TestCreateStopTimeout(c *testing.T) {
   370  	name1 := "test_create_stop_timeout_1"
   371  	dockerCmd(c, "create", "--name", name1, "--stop-timeout", "15", "busybox")
   372  
   373  	res := inspectFieldJSON(c, name1, "Config.StopTimeout")
   374  	assert.Assert(c, strings.Contains(res, "15"))
   375  	name2 := "test_create_stop_timeout_2"
   376  	dockerCmd(c, "create", "--name", name2, "busybox")
   377  
   378  	res = inspectFieldJSON(c, name2, "Config.StopTimeout")
   379  	assert.Assert(c, strings.Contains(res, "null"))
   380  }