123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186 |
- package metabase
- import (
- "bufio"
- "context"
- "fmt"
- "runtime"
- "time"
- "github.com/docker/docker/api/types"
- "github.com/docker/docker/api/types/container"
- "github.com/docker/docker/api/types/mount"
- "github.com/docker/docker/client"
- "github.com/docker/go-connections/nat"
- log "github.com/sirupsen/logrus"
- )
- type Container struct {
- ListenAddr string
- ListenPort string
- SharedFolder string
- Image string
- Name string
- ID string
- CLI *client.Client
- MBDBUri string
- DockerGroupID string
- }
- func NewContainer(listenAddr string, listenPort string, sharedFolder string, containerName string, image string, mbDBURI string, dockerGroupID string) (*Container, error) {
- cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
- if err != nil {
- return nil, fmt.Errorf("failed to create docker client : %s", err)
- }
- return &Container{
- ListenAddr: listenAddr,
- ListenPort: listenPort,
- SharedFolder: sharedFolder,
- Image: image,
- Name: containerName,
- CLI: cli,
- MBDBUri: mbDBURI,
- DockerGroupID: dockerGroupID,
- }, nil
- }
- func (c *Container) Create() error {
- ctx := context.Background()
- log.Printf("Pulling docker image %s", c.Image)
- reader, err := c.CLI.ImagePull(ctx, c.Image, types.ImagePullOptions{})
- if err != nil {
- return fmt.Errorf("failed to pull docker image : %s", err)
- }
- defer reader.Close()
- scanner := bufio.NewScanner(reader)
- for scanner.Scan() {
- fmt.Print(".")
- }
- if err := scanner.Err(); err != nil {
- return fmt.Errorf("failed to read imagepull reader: %s", err)
- }
- fmt.Print("\n")
- hostConfig := &container.HostConfig{
- PortBindings: nat.PortMap{
- "3000/tcp": []nat.PortBinding{
- {
- HostIP: c.ListenAddr,
- HostPort: c.ListenPort,
- },
- },
- },
- Mounts: []mount.Mount{
- {
- Type: mount.TypeBind,
- Source: c.SharedFolder,
- Target: containerSharedFolder,
- },
- },
- }
- env := []string{
- fmt.Sprintf("MB_DB_FILE=%s/metabase.db", containerSharedFolder),
- }
- if c.MBDBUri != "" {
- env = append(env, c.MBDBUri)
- }
- env = append(env, fmt.Sprintf("MGID=%s", c.DockerGroupID))
- dockerConfig := &container.Config{
- Image: c.Image,
- Tty: true,
- Env: env,
- }
- os := runtime.GOOS
- switch os {
- case "linux":
- case "windows", "darwin":
- return fmt.Errorf("Mac and Windows are not supported yet")
- default:
- return fmt.Errorf("OS '%s' is not supported", os)
- }
- log.Infof("creating container '%s'", c.Name)
- resp, err := c.CLI.ContainerCreate(ctx, dockerConfig, hostConfig, nil, nil, c.Name)
- if err != nil {
- return fmt.Errorf("failed to create container : %s", err)
- }
- c.ID = resp.ID
- return nil
- }
- func (c *Container) Start() error {
- ctx := context.Background()
- if err := c.CLI.ContainerStart(ctx, c.Name, types.ContainerStartOptions{}); err != nil {
- return fmt.Errorf("failed while starting %s : %s", c.ID, err)
- }
- return nil
- }
- func StartContainer(name string) error {
- cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
- if err != nil {
- return fmt.Errorf("failed to create docker client : %s", err)
- }
- ctx := context.Background()
- if err := cli.ContainerStart(ctx, name, types.ContainerStartOptions{}); err != nil {
- return fmt.Errorf("failed while starting %s : %s", name, err)
- }
- return nil
- }
- func StopContainer(name string) error {
- cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
- if err != nil {
- return fmt.Errorf("failed to create docker client : %s", err)
- }
- ctx := context.Background()
- var to time.Duration = 20 * time.Second
- if err := cli.ContainerStop(ctx, name, &to); err != nil {
- return fmt.Errorf("failed while stopping %s : %s", name, err)
- }
- log.Printf("container stopped successfully")
- return nil
- }
- func RemoveContainer(name string) error {
- cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
- if err != nil {
- return fmt.Errorf("failed to create docker client : %s", err)
- }
- ctx := context.Background()
- log.Printf("Removing docker metabase %s", name)
- if err := cli.ContainerRemove(ctx, name, types.ContainerRemoveOptions{}); err != nil {
- return fmt.Errorf("failed remove container %s : %s", name, err)
- }
- return nil
- }
- func RemoveImageContainer() error {
- cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
- if err != nil {
- return fmt.Errorf("failed to create docker client : %s", err)
- }
- ctx := context.Background()
- log.Printf("Removing docker image '%s'", metabaseImage)
- if _, err := cli.ImageRemove(ctx, metabaseImage, types.ImageRemoveOptions{}); err != nil {
- return fmt.Errorf("failed remove image container %s : %s", metabaseImage, err)
- }
- return nil
- }
- func IsContainerExist(name string) bool {
- cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
- if err != nil {
- log.Fatalf("failed to create docker client : %s", err)
- }
- ctx := context.Background()
- if _, err := cli.ContainerInspect(ctx, name); err != nil {
- return false
- }
- return true
- }
|