예제 #1
0
// dockerRun mimics the 'docker run --rm' CLI command. It uses the Docker Remote
// API to create and start a container and stream its logs. The container is
// removed after it terminates.
func dockerRun(client DockerClient, createOpts docker.CreateContainerOptions, logsOpts docker.LogsOptions) error {
	// Create a new container.
	glog.V(4).Infof("Creating container with options {Name:%q Config:%+v HostConfig:%+v} ...", createOpts.Name, createOpts.Config, createOpts.HostConfig)
	c, err := client.CreateContainer(createOpts)
	if err != nil {
		return fmt.Errorf("create container %q: %v", createOpts.Name, err)
	}

	containerName := containerNameOrID(c)

	removeContainer := func() {
		glog.V(4).Infof("Removing container %q ...", containerName)
		if err := client.RemoveContainer(docker.RemoveContainerOptions{ID: c.ID}); err != nil {
			glog.V(0).Infof("warning: Failed to remove container %q: %v", containerName, err)
		} else {
			glog.V(4).Infof("Removed container %q", containerName)
		}
	}
	startWaitContainer := func() error {
		// Start the container.
		glog.V(4).Infof("Starting container %q ...", containerName)
		if err := client.StartContainer(c.ID, nil); err != nil {
			return fmt.Errorf("start container %q: %v", containerName, err)
		}

		// Stream container logs.
		logsOpts.Container = c.ID
		glog.V(4).Infof("Streaming logs of container %q with options %+v ...", containerName, logsOpts)
		if err := client.Logs(logsOpts); err != nil {
			return fmt.Errorf("streaming logs of %q: %v", containerName, err)
		}

		// Return an error if the exit code of the container is non-zero.
		glog.V(4).Infof("Waiting for container %q to stop ...", containerName)
		exitCode, err := client.WaitContainer(c.ID)
		if err != nil {
			return fmt.Errorf("waiting for container %q to stop: %v", containerName, err)
		}
		if exitCode != 0 {
			return fmt.Errorf("container %q returned non-zero exit code: %d", containerName, exitCode)
		}
		return nil
	}
	// the interrupt handler acts as a super-defer which will guarantee removeContainer is executed
	// either when startWaitContainer finishes, or when a SIGQUIT/SIGINT/SIGTERM is received.
	return interrupt.New(nil, removeContainer).Run(startWaitContainer)
}
예제 #2
0
// dockerRun mimics the 'docker run --rm' CLI command. It uses the Docker Remote
// API to create and start a container and stream its logs. The container is
// removed after it terminates.
func dockerRun(client DockerClient, createOpts docker.CreateContainerOptions, logsOpts docker.LogsOptions) error {
	// Create a new container.
	glog.V(4).Infof("Creating container with options {Name:%q Config:%+v HostConfig:%+v} ...", createOpts.Name, createOpts.Config, createOpts.HostConfig)
	c, err := client.CreateContainer(createOpts)
	if err != nil {
		return fmt.Errorf("create container %q: %v", createOpts.Name, err)
	}

	containerName := containerNameOrID(c)

	// Container was created, so we defer its removal.
	defer func() {
		glog.V(4).Infof("Removing container %q ...", containerName)
		if err := client.RemoveContainer(docker.RemoveContainerOptions{ID: c.ID}); err != nil {
			glog.Warningf("Failed to remove container %q: %v", containerName, err)
		} else {
			glog.V(4).Infof("Removed container %q", containerName)
		}
	}()

	// Start the container.
	glog.V(4).Infof("Starting container %q ...", containerName)
	if err := client.StartContainer(c.ID, nil); err != nil {
		return fmt.Errorf("start container %q: %v", containerName, err)
	}

	// Stream container logs.
	logsOpts.Container = c.ID
	glog.V(4).Infof("Streaming logs of container %q with options %+v ...", containerName, logsOpts)
	if err := client.Logs(logsOpts); err != nil {
		return fmt.Errorf("streaming logs of %q: %v", containerName, err)
	}

	// Return an error if the exit code of the container is non-zero.
	glog.V(4).Infof("Waiting for container %q to stop ...", containerName)
	exitCode, err := client.WaitContainer(c.ID)
	if err != nil {
		return fmt.Errorf("waiting for container %q to stop: %v", containerName, err)
	}
	if exitCode != 0 {
		return fmt.Errorf("container %q returned non-zero exit code: %d", containerName, exitCode)
	}

	return nil
}