func CreateContainer(containerName, image, domain string, portsToMap []Port, environmentVars map[string]string) (*docker.Container, error) { cfg := &docker.Config{} cfg.Image = image cfg.Hostname = containerName cfg.Domainname = domain var e struct{} exposedPorts := make(map[docker.Port]struct{}) for _, p := range portsToMap { prt := strconv.FormatUint(p.Private, 10) + "/" + p.Type exposedPorts[docker.Port(prt)] = e fmt.Printf("Exposing %s\n", prt) } cfg.ExposedPorts = exposedPorts envStrs := make([]string, 0, 10) for k, v := range environmentVars { envStrs = append(envStrs, k+"="+v) } cfg.Env = envStrs hostCfg := &docker.HostConfig{} hostCfg.PublishAllPorts = false hostCfg.Privileged = false hostPorts := make(map[docker.Port][]docker.PortBinding) for _, p := range portsToMap { prt := strconv.FormatUint(p.Private, 10) + "/" + p.Type bindings := make([]docker.PortBinding, 0, 4) bindings = append(bindings, docker.PortBinding{HostIP: "", HostPort: strconv.FormatUint(p.Public, 10)}) fmt.Printf("Binding %s to %s\n", prt, bindings[0]) hostPorts[docker.Port(prt)] = bindings } hostCfg.PortBindings = hostPorts opts := docker.CreateContainerOptions{} opts.Config = cfg opts.Name = containerName opts.HostConfig = hostCfg json, _ := data.PrettyPrint(opts) fmt.Printf("create options: %s\n", string(json)) container, err := client.CreateContainer(opts) if err != nil { fmt.Fprintf(os.Stderr, "Error creating container: %s\n", err.Error()) } else { fmt.Printf("Container created: %s\n", container.ID) } return container, err }
// DockerRun perform a docker run func DockerRun(req *DockerRunRequest) (DockerRunResponse, error) { response := DockerRunResponse{} //logit.Info.Println("DockerRun called") swarmURL := os.Getenv("SWARM_MANAGER_URL") if swarmURL == "" { logit.Error.Println("SWARM_MANAGER_URL not set") return response, errors.New("SWARM_MANAGER_URL not set") } var envvars []string var i = 0 if req.EnvVars != nil { envvars = make([]string, len(req.EnvVars)+1) for k, v := range req.EnvVars { envvars[i] = k + "=" + v i++ } } else { envvars = make([]string, 1) } if req.Profile == "" { return response, errors.New("Profile was empty and should not be") } //typical case is to always add the profile constraint env var //like SM, MED, LG, however in the case of a restore job, we //use a hard constraint of the host ipaddress to pin //the restored container to the same host as where the backup //is stored if req.IPAddress != "" { envvars[i] = "constraint:host==~" + req.IPAddress } else { envvars[i] = "constraint:profile==~" + req.Profile } docker, err := dockerapi.NewClient(swarmURL) if err != nil { logit.Error.Println(err.Error()) return response, err } options := dockerapi.CreateContainerOptions{} config := dockerapi.Config{} config.Hostname = req.ContainerName options.Config = &config hostConfig := dockerapi.HostConfig{} options.HostConfig = &hostConfig options.Name = req.ContainerName options.Config.Env = envvars options.Config.Image = "crunchydata/" + req.Image //logit.Info.Println("swarmapi using " + options.Config.Image + " as the image name") options.Config.Volumes = make(map[string]struct{}) //TODO figure out cpu shares and memory settings, these are different //than what I was using before due to me using the docker api directly //with this swarm implementation...use the defaults for now //options.HostConfig.CPUShares, err = strconv.ParseInt(req.CPU, 0, 64) //if err != nil { //logit.Error.Println(err.Error()) //return response, err //} //options.HostConfig.Memory = req.MEM options.HostConfig.Binds = make([]string, 3) options.HostConfig.Binds[0] = req.PGDataPath + ":/pgdata" options.HostConfig.Binds[1] = "/var/cpm/data/keys:/keys" options.HostConfig.Binds[2] = "/var/cpm/config:/syslogconfig" container, err3 := docker.CreateContainer(options) if err3 != nil { logit.Error.Println(err3.Error()) return response, err3 } var startResponse DockerStartResponse startRequest := DockerStartRequest{} startRequest.ContainerName = req.ContainerName startResponse, err = DockerStart(&startRequest) if err != nil { logit.Error.Println(err.Error()) return response, err } logit.Info.Println(startResponse.Output) //cmd := exec.Command(req.CommandPath, req.PGDataPath, req.ContainerName, //req.Image, req.CPU, req.MEM, allEnvVars) response.ID = container.ID return response, nil }
// // Start a docker container, and create a connection to /attach to it and send // and receive RPC commands. // func (d *Client) Start() (err error) { path := os.Getenv("DOCKER_CERT_PATH") if path != "" { ca := fmt.Sprintf("%s/ca.pem", path) cert := fmt.Sprintf("%s/cert.pem", path) key := fmt.Sprintf("%s/key.pem", path) d.dockerClient, err = docker.NewTLSClient(d.endpoint, cert, key, ca) } else { d.dockerClient, err = docker.NewClient(d.endpoint) } if err != nil { return err } defaultConfig := &docker.Config{ OpenStdin: true, Image: d.dockerImage, } defaultHostConfig := &docker.HostConfig{} opts := docker.CreateContainerOptions{ Config: defaultConfig, HostConfig: defaultHostConfig, } if d.name != "" { opts.Name = d.name } c, err := d.dockerClient.CreateContainer(opts) if err != nil { return err } d.ID = c.ID err = d.dockerClient.StartContainer(c.ID, defaultHostConfig) if err != nil { return err } attachOpts := docker.AttachToContainerOptions{ Container: d.ID, Stdout: true, Stdin: true, Stderr: true, Stream: true, } err = d.AttachStreamingContainer(attachOpts) if err != nil { return err } pipes := &dockerPipes{ d.clientConn, &d.stdErrBuf, 0, 0, } d.rpcClient = rpc.NewClientWithCodec(jsonrpc.NewClientCodec(pipes)) return nil }