// ContainerDefinition generates an ECS ContainerDefinition for a process. func (t *EmpireTemplate) ContainerDefinition(app *scheduler.App, p *scheduler.Process) *ecs.ContainerDefinition { command := []*string{} for _, s := range p.Command { ss := s command = append(command, &ss) } environment := envByKey{} for k, v := range scheduler.Env(app, p) { environment = append(environment, &ecs.KeyValuePair{ Name: aws.String(k), Value: aws.String(v), }) } sort.Sort(environment) labels := make(map[string]*string) for k, v := range scheduler.Labels(app, p) { labels[k] = aws.String(v) } ulimits := []*ecs.Ulimit{} if p.Nproc != 0 { ulimits = []*ecs.Ulimit{ &ecs.Ulimit{ Name: aws.String("nproc"), SoftLimit: aws.Int64(int64(p.Nproc)), HardLimit: aws.Int64(int64(p.Nproc)), }, } } return &ecs.ContainerDefinition{ Name: aws.String(p.Type), Cpu: aws.Int64(int64(p.CPUShares)), Command: command, Image: aws.String(p.Image.String()), Essential: aws.Bool(true), Memory: aws.Int64(int64(p.MemoryLimit / bytesize.MB)), Environment: environment, LogConfiguration: t.LogConfiguration, DockerLabels: labels, Ulimits: ulimits, } }
func (s *Scheduler) Run(ctx context.Context, app *scheduler.App, p *scheduler.Process, in io.Reader, out io.Writer) error { attached := out != nil || in != nil if !attached { return errors.New("cannot run detached processes with Docker scheduler") } labels := scheduler.Labels(app, p) labels[runLabel] = Attached if err := s.docker.PullImage(ctx, docker.PullImageOptions{ Registry: p.Image.Registry, Repository: p.Image.Repository, Tag: p.Image.Tag, OutputStream: replaceNL(out), }); err != nil { return fmt.Errorf("error pulling image: %v", err) } container, err := s.docker.CreateContainer(ctx, docker.CreateContainerOptions{ Name: uuid.New(), Config: &docker.Config{ Tty: true, AttachStdin: true, AttachStdout: true, AttachStderr: true, OpenStdin: true, Memory: int64(p.MemoryLimit), CPUShares: int64(p.CPUShares), Image: p.Image.String(), Cmd: p.Command, Env: envKeys(scheduler.Env(app, p)), Labels: labels, }, HostConfig: &docker.HostConfig{ LogConfig: docker.LogConfig{ Type: "json-file", }, }, }) if err != nil { return fmt.Errorf("error creating container: %v", err) } defer s.docker.RemoveContainer(ctx, docker.RemoveContainerOptions{ ID: container.ID, RemoveVolumes: true, Force: true, }) if err := s.docker.StartContainer(ctx, container.ID, nil); err != nil { return fmt.Errorf("error starting container: %v", err) } defer tryClose(out) if err := s.docker.AttachToContainer(ctx, docker.AttachToContainerOptions{ Container: container.ID, InputStream: in, OutputStream: out, ErrorStream: out, Logs: true, Stream: true, Stdin: true, Stdout: true, Stderr: true, RawTerminal: true, }); err != nil { return fmt.Errorf("error attaching to container: %v", err) } return nil }
func (m *Scheduler) taskDefinitionInput(app *scheduler.App, p *scheduler.Process, loadBalancer *lb.LoadBalancer) (*ecs.RegisterTaskDefinitionInput, error) { // ecs.ContainerDefinition{Command} is expecting a []*string var command []*string for _, s := range p.Command { ss := s command = append(command, &ss) } var environment []*ecs.KeyValuePair for k, v := range scheduler.Env(app, p) { environment = append(environment, &ecs.KeyValuePair{ Name: aws.String(k), Value: aws.String(v), }) } // If there's a load balancer attached, generate the port mappings and // expose the container port to the process via the PORT environment // variable. var ports []*ecs.PortMapping if loadBalancer != nil { ports = append(ports, &ecs.PortMapping{ HostPort: aws.Int64(loadBalancer.InstancePort), ContainerPort: aws.Int64(ContainerPort), }) environment = append(environment, &ecs.KeyValuePair{ Name: aws.String("PORT"), Value: aws.String(fmt.Sprintf("%d", ContainerPort)), }) } labels := make(map[string]*string) for k, v := range scheduler.Labels(app, p) { labels[k] = aws.String(v) } var ulimits []*ecs.Ulimit if p.Nproc != 0 { ulimits = []*ecs.Ulimit{ &ecs.Ulimit{ Name: aws.String("nproc"), SoftLimit: aws.Int64(int64(p.Nproc)), HardLimit: aws.Int64(int64(p.Nproc)), }, } } return &ecs.RegisterTaskDefinitionInput{ Family: aws.String(p.Type), ContainerDefinitions: []*ecs.ContainerDefinition{ &ecs.ContainerDefinition{ Name: aws.String(p.Type), Cpu: aws.Int64(int64(p.CPUShares)), Command: command, Image: aws.String(p.Image.String()), Essential: aws.Bool(true), Memory: aws.Int64(int64(p.MemoryLimit / MB)), Environment: environment, LogConfiguration: m.logConfiguration, PortMappings: ports, DockerLabels: labels, Ulimits: ulimits, }, }, }, nil }