github.com/defang-io/defang/src@v0.0.0-20240505002154-bdf411911834/pkg/docker/run.go (about)

     1  package docker
     2  
     3  import (
     4  	"context"
     5  	"strings"
     6  
     7  	"github.com/docker/docker/api/types"
     8  	"github.com/docker/docker/api/types/container"
     9  	v1 "github.com/opencontainers/image-spec/specs-go/v1"
    10  )
    11  
    12  func (d Docker) Run(ctx context.Context, env map[string]string, cmd ...string) (ContainerID, error) {
    13  	resp, err := d.ContainerCreate(ctx, &container.Config{
    14  		Image: d.image,
    15  		Env:   mapToSlice(env),
    16  		Cmd:   cmd,
    17  	}, &container.HostConfig{
    18  		AutoRemove:      true, // --rm; FIXME: this causes "No such container" if the container exits early
    19  		PublishAllPorts: true, // -P
    20  		Resources: container.Resources{
    21  			Memory: int64(d.memory),
    22  		},
    23  	}, nil, parsePlatform(d.platform), "")
    24  	if err != nil {
    25  		return nil, err
    26  	}
    27  
    28  	return &resp.ID, d.ContainerStart(ctx, resp.ID, types.ContainerStartOptions{})
    29  }
    30  
    31  func mapToSlice(m map[string]string) []string {
    32  	s := make([]string, 0, len(m))
    33  	for k, v := range m {
    34  		// Ensure no = in key
    35  		if strings.ContainsRune(k, '=') {
    36  			panic("invalid environment variable key")
    37  		}
    38  		s = append(s, k+"="+v)
    39  	}
    40  	return s
    41  }
    42  
    43  func parsePlatform(platform string) *v1.Platform {
    44  	parts := strings.Split(platform, "/")
    45  	var p = &v1.Platform{}
    46  	switch len(parts) {
    47  	case 3:
    48  		p.Variant = parts[2]
    49  		fallthrough
    50  	case 2:
    51  		p.OS = parts[0]
    52  		p.Architecture = parts[1]
    53  	case 1:
    54  		p.Architecture = parts[0]
    55  	default:
    56  		panic("invalid platform: " + platform)
    57  	}
    58  	return p
    59  }