go -- go 程序 啟動docker容器


package main

import (
    "io"
    "log"
    "os"
    "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"
    "golang.org/x/net/context"
)

const (
    imageName     string   = "my-gin:latest"                      //鏡像名稱
    containerName string   = "mygin-latest"                       //容器名稱
    indexName     string   = "/" + containerName                  //容器索引名稱,用於檢查該容器是否存在是使用
    cmd           string   = "./ginDocker2"                       //運行的cmd命令,用於啟動container中的程序
    workDir       string   = "/go/src/ginDocker2"                 //container工作目錄
    openPort      nat.Port = "7070"                               //container開放端口
    hostPort      string   = "7070"                               //container映射到宿主機的端口
    containerDir  string   = "/go/src/ginDocker2"                 //容器掛在目錄
    hostDir       string   = "/home/youngblood/Go/src/ginDocker2" //容器掛在到宿主機的目錄
    n             int      = 5                                    //每5s檢查一個容器是否在運行

)

func main() {
    ctx := context.Background()
    cli, err := client.NewEnvClient()
    defer cli.Close()
    if err != nil {
        panic(err)
    }
    checkAndStartContainer(ctx, cli)
}

//創建容器
func createContainer(ctx context.Context, cli *client.Client) {
    //創建容器
    cont, err := cli.ContainerCreate(ctx, &container.Config{
        Image:      imageName,     //鏡像名稱
        Tty:        true,          //docker run命令中的-t選項
        OpenStdin:  true,          //docker run命令中的-i選項
        Cmd:        []string{cmd}, //docker 容器中執行的命令
        WorkingDir: workDir,       //docker容器中的工作目錄
        ExposedPorts: nat.PortSet{
            openPort: struct{}{}, //docker容器對外開放的端口
        },
    }, &container.HostConfig{
        PortBindings: nat.PortMap{
            openPort: []nat.PortBinding{nat.PortBinding{
                HostIP:   "0.0.0.0", //docker容器映射的宿主機的ip
                HostPort: hostPort,  //docker 容器映射到宿主機的端口
            }},
        },
        Mounts: []mount.Mount{ //docker 容器目錄掛在到宿主機目錄
            mount.Mount{
                Type:   mount.TypeBind,
                Source: hostDir,
                Target: containerDir,
            },
        },
    }, nil, containerName)
    if err == nil {
        log.Printf("success create container:%s\n", cont.ID)
    } else {
        log.Println("failed to create container!!!!!!!!!!!!!")
    }
}

//啟動容器
func startContainer(ctx context.Context, containerID string, cli *client.Client) error {
    err := cli.ContainerStart(ctx, containerID, types.ContainerStartOptions{})
    if err == nil {
        log.Printf("success start container:%s\n", containerID)
    } else {
        log.Printf("failed to start container:%s!!!!!!!!!!!!!\n", containerID)
    }
    return err
}

//將容器的標准輸出輸出到控制台中
func printConsole(ctx context.Context, cli *client.Client, id string) {
    //將容器的標准輸出顯示出來
    out, err := cli.ContainerLogs(ctx, id, types.ContainerLogsOptions{ShowStdout: true})
    if err != nil {
        panic(err)
    }
    io.Copy(os.Stdout, out)

    //容器內部的運行狀態
    status, err := cli.ContainerStats(ctx, id, true)
    if err != nil {
        panic(err)
    }
    io.Copy(os.Stdout, status.Body)
}

//檢查容器是否存在並啟動容器
func checkAndStartContainer(ctx context.Context, cli *client.Client) {
    for {
        select {
        case <-isRuning(ctx, cli):
            //該container沒有在運行
            //獲取所有的container查看該container是否存在
            contTemp := getContainer(ctx, cli, true)
            if contTemp.ID == "" {
                //該容器不存在,創建該容器
                log.Printf("the container name[%s] is not exists!!!!!!!!!!!!!\n", containerName)
                createContainer(ctx, cli)
            } else {
                //該容器存在,啟動該容器
                log.Printf("the container name[%s] is exists\n", containerName)
                startContainer(ctx, contTemp.ID, cli)
            }

        }
    }
}

//獲取container
func getContainer(ctx context.Context, cli *client.Client, all bool) types.Container {
    containerList, err := cli.ContainerList(ctx, types.ContainerListOptions{All: all})
    if err != nil {
        panic(err)
    }
    var contTemp types.Container
    //找出名為“mygin-latest”的container並將其存入contTemp中
    for _, v1 := range containerList {
        for _, v2 := range v1.Names {
            if v2 == indexName {
                contTemp = v1
                break
            }
        }
    }
    return contTemp
}

//容器是否正在運行
func isRuning(ctx context.Context, cli *client.Client) <-chan bool {
    isRun := make(chan bool)
    var timer *time.Ticker
    go func(ctx context.Context, cli *client.Client) {
        for {
            //每n s檢查一次容器是否運行

            timer = time.NewTicker(time.Duration(n) * time.Second)
            select {
            case <-timer.C:
                //獲取正在運行的container list
                log.Printf("%s is checking the container[%s]is Runing??", os.Args[0], containerName)
                contTemp := getContainer(ctx, cli, false)
                if contTemp.ID == "" {
                    log.Print(":NO")
                    //說明container沒有運行
                    isRun <- true
                } else {
                    log.Print(":YES")
                    //說明該container正在運行
                    go printConsole(ctx, cli, contTemp.ID)
                }
            }

        }
    }(ctx, cli)
    return isRun
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM