package main import ( "fmt" "os" "strings" docker "github.com/fsouza/go-dockerclient" ) func inspectContainer(containerNameOrID string) (*docker.Container, error) { c, err := newVersionedDockerClientFromEnv(defaulDockerAPIVersion) if err != nil { return nil, fmt.Errorf("unable to connect to docker: %s", err) } container, err := c.InspectContainer(containerNameOrID) if err != nil { return nil, fmt.Errorf("unable to inspect container %s: %s", containerNameOrID, err) } return container, nil } func containerPid(containerID string) (int, error) { container, err := inspectContainer(containerID) if err != nil { return 0, err } if container.State.Pid == 0 { return 0, fmt.Errorf("container %s not running", containerID) } return container.State.Pid, nil } func containerID(args []string) error { if len(args) < 1 { cmdUsage("container-id", "") } container, err := inspectContainer(args[0]) if err != nil { return err } fmt.Print(container.ID) return nil } func containerState(args []string) error { if len(args) < 1 { cmdUsage("container-state", " []") } container, err := inspectContainer(args[0]) if err != nil { return err } if len(args) == 1 { fmt.Print(container.State.StateString()) } else { imagePrefix := args[1] if strings.HasPrefix(container.Config.Image, imagePrefix) { fmt.Print(container.State.StateString()) } else { if container.State.Running { fmt.Print("running image mismatch: ", container.Config.Image) } else { fmt.Print("image mismatch: ", container.Config.Image) } } } return nil } func containerFQDN(args []string) error { if len(args) < 1 { cmdUsage("container-fqdn", "") } container, err := inspectContainer(args[0]) if err != nil { return err } fmt.Print(container.Config.Hostname, ".", container.Config.Domainname) return nil } func parseContainerArgs(args []string) docker.CreateContainerOptions { env := []string{} labels := map[string]string{} name := "" net := "" pid := "" privileged := false restart := docker.NeverRestart() volumes := []string{} volumesFrom := []string{} done := false for i := 0; i < len(args) && !done; { switch args[i] { case "-e", "--env": if v := os.Getenv(args[i+1]); v != "" { env = append(env, args[i+1]+"="+v) } else { env = append(env, args[i+1]) } args = append(args[:i], args[i+2:]...) case "-l", "--label": key, value := parseLabel(args[i+1]) labels[key] = value args = append(args[:i], args[i+2:]...) case "--name": name = args[i+1] args = append(args[:i], args[i+2:]...) case "--net": net = args[i+1] args = append(args[:i], args[i+2:]...) case "--pid": pid = args[i+1] args = append(args[:i], args[i+2:]...) case "--privileged": privileged = true args = append(args[:i], args[i+1:]...) case "--restart": restart = docker.RestartPolicy{Name: args[i+1]} args = append(args[:i], args[i+2:]...) case "-v", "--volume": // Must dedup binds, otherwise, container fails creation skip := false for _, v := range volumes { if v == args[i+1] { skip = true } } if !skip { volumes = append(volumes, args[i+1]) } args = append(args[:i], args[i+2:]...) case "--volumes-from": volumesFrom = append(volumesFrom, args[i+1]) args = append(args[:i], args[i+2:]...) default: done = true } } if len(args) < 2 { cmdUsage("run-container", `[options] [[] [ ...]] -e, --env list Set environment variables --name string Assign a name to the container --net string Network Mode --pid string PID namespace to use --privileged Give extended privileges to this container --restart string Restart policy to apply when a container exits (default "no") -v, --volume list Bind mount a volume --volumes-from list Mount volumes from the specified container(s) `) } image := args[0] cmds := args[1:] config := docker.Config{Image: image, Env: env, Cmd: cmds, Labels: labels} hostConfig := docker.HostConfig{NetworkMode: net, PidMode: pid, Privileged: privileged, RestartPolicy: restart, Binds: volumes, VolumesFrom: volumesFrom} return docker.CreateContainerOptions{Name: name, Config: &config, HostConfig: &hostConfig} } func runContainer(args []string) error { containerOptions := parseContainerArgs(args) c, err := newVersionedDockerClientFromEnv(defaulDockerAPIVersion) if err != nil { return fmt.Errorf("unable to connect to docker: %s", err) } container, err := c.CreateContainer(containerOptions) if err != nil { return fmt.Errorf("unable to create container: %s", err) } err = c.StartContainer(container.ID, containerOptions.HostConfig) if err != nil { return fmt.Errorf("unable to start container: %s", err) } fmt.Print(container.ID) return nil } func parseLabel(s string) (key, value string) { pos := strings.Index(s, "=") if pos == -1 { // no value - set it to blank return s, "" } return s[:pos], s[pos+1:] } func listContainers(args []string) error { if len(args) > 1 { cmdUsage("list-containers", "[