zoukankan      html  css  js  c++  java
  • 如何用docker编译代码并且启动sever以及避免坑

    docker是很强大的容器,目前很多公司都在使用,今天简单说一下go的项目中启动docker,编译代码以及其中的一些坑。后续会有更多的模式和算法以及区块链相关的,如果你是想学习go语言或者是对设计模式或者算法感兴趣亦或是区块链开发工作者,都可以关注一下。(微信公众号/头条:Go语言之美,更多go语言知识信息等)。公众号会持续为大家分享更多干货。

    在我们安装docker之后,我们需要下载docker的sdk。附上docker sdk链接:

    https://docs.docker.com/develop/sdk/examples/
    我们可以调用docker的api来创建一个容器,同时编译代码,然后我们将编译好的文件可以再通过一个容器来作为我们的sever。这个使用场景是很常见的,每一个使用docker或者学习docker的人都应该掌握。

    如果我们将编译代码部分做成自动化那么我们就可以将写好的代码发送到指定的程序中,程序里面可通过使用docker将代码编译成文件,再启动这个文件作为sever。

    首先说创建容器时编译代码,下面的代码是官方文档上的示例代码创建容器:

    package main
    import (
    "io"
    "os"
    "github.com/docker/docker/api/types"
    "github.com/docker/docker/api/types/container"
    "github.com/docker/docker/client"
    "golang.org/x/net/context"
    )
    func main() {
    ctx := context.Background()
    cli, err := client.NewEnvClient()
    if err != nil {
    panic(err)
    }
    reader, err := cli.ImagePull(ctx, "docker.io/library/alpine", types.ImagePullOptions{})
    if err != nil {
    panic(err)
    }
    io.Copy(os.Stdout, reader)
    resp, err := cli.ContainerCreate(ctx, &container.Config{
    Image: "alpine",
    Cmd: []string{"echo", "hello world"},
    Tty: true,
    }, nil, nil, "")
    if err != nil {
    panic(err)
    }
    if err := cli.ContainerStart(ctx, resp.ID, types.ContainerStartOptions{}); err != nil {
    panic(err)
    }
    statusCh, errCh := cli.ContainerWait(ctx, resp.ID, container.WaitConditionNotRunning)
    select {
    case err := <-errCh:
    if err != nil {
    panic(err)
    }
    case <-statusCh:
    }
    out, err := cli.ContainerLogs(ctx, resp.ID, types.ContainerLogsOptions{ShowStdout: true})
    if err != nil {
    panic(err)
    }
    io.Copy(os.Stdout, out)
    }


    在启动容器是我们可以执行一些命令,如果我们要编译代码就需要执行 go install 命令(go语言示例),同时我们再指定对应的GOPATH等需要的命令,这样在启动时就会执行这个命令,当然,要想使用go的命令首先要有golang的image,我们可以使用代码pull下来,同样可以提前手动pull下来。接下来我们要把准备编译的代码mount到容器中,这些在创建容器是都需要通过参数传进去。同时我们可以让这个容器等待我们编译代码完成再退出,同时我们也可以让这个容器自动销毁掉,因为在编译好代码后我们基本不会需要这个容器了。

    这样问题就出现了,我们如何知道代码是否编译成功?幸好docker有查找logs的接口,在我们启动容器之后,我们可以通过查看他的日志,来判断go install命令是否成功执行。首先我们知道go install命令成功执行后是不会有任何输出的(没有消息就是好消息哈哈哈),我们可以通过判断这个容器是否产生日志来判断是否编译成功。这个方法安全吗?

    可以告诉你,不安全,因为在查看logs的接口中,不会返回所有的日志信息,而且有可能即使产生日志,我们也可能通过这个接口查不到。原因大家可能也想到了,因为如果容器中一直产生日志,logs接口不可能将所有的日志到返回,所以基本上都是抓到第一屏的日志。所以这个方法不可以!

    接下来我们换一个方法,go install的执行结果是在bin目录下产生对应的文件(bin目录是指GOPATH下的bin,如果没有这个目录会自动创建,如果有多个GOPATH,则会找第一个GOPATH,我们也可以设置GOBIN目录指定将文件生成到哪里),我们可不可以通过判断这个文件是否产生来判断呢?答案同样是不可以,第一,如果文件没有产生,即编译失败,我们拿不到具体的失败原因。第二,当我们去判断文件是否存在时,很可能编译成功,但是文件还未产生。

    接下来说我得解决办法。我的思路是创建容器时执行一个脚本,脚本中执行go install,并且将结果重定向到指定文件,然后我们通过读取文件判断是否成功和对应的错误信息。脚本示例如下:

    const goInstallShell = #!/bin/sh a=$(go install main 2>&1) if [[ $? -eq 0 ]]; then echo "success" >> log else echo "fail:" >> log fi echo ${a} >> log
    这是docker的基本使用方法,下次继续写如果将这个可执行文件使用docker作为一个sever,感兴趣的可以点个赞,关注下,谢谢!公众号会持续为大家分享更多干货。

    后续会有更多的模式和算法以及区块链相关的,如果你是想学习go语言或者是对设计模式或者算法感兴趣亦或是区块链开发工作者,都可以关注一下。(微信公众号:Go语言之美,头条:Go语言之美。更多go语言知识信息等)。
    ————————————————
    版权声明:本文为CSDN博主「Go语言之美」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
    原文链接:https://blog.csdn.net/weixin_42522985/java/article/details/88955063

     docker是一个虚拟机,里面可以安装软件,C语言是一种镜像,Java是一种镜像,安装在自己的电脑里面如同在自己的电脑里面跑程序一样,

    在docker里面安装编译器之后即可进行编译相应的程序。编译的过程:通过分发器根据不同的编程语言选择不同的docker镜像和执行不同的

    指令模板,比如登陆、注册和编译模块等。将结果通过response返回给用户。

     图片来源:https://www.anycodes.cn/#/Help

    如何使用docker部署c/c++程序

    想要把c/c++程序运行在docker的容器中,就必须先创建一个docker镜像,通过镜像创建容器,来使我们的程序在容器中运行起来。
    #######简单介绍一下docker中镜像和容器的关系:
    • Images (镜像)
    Docker镜像是一个只读模板,包含创建Docker容器的说明。Docker镜像可以运行Docker镜像中的程序。
    • Container (容器)
    容器是镜像的可运行实例。镜像与容器类似与面向对象中类与对象的关系。可通过Docker API或者CLI命令起停,移动,删除等。

    明白了docker中镜像和容器的关系之后,我们想要把程序执行起来,其实就是将程序放在镜像中,通过镜像启动一个容器,在容器中执行我们的程序。

    那么我们运行一个c/c++程序到底该选择怎么样的镜像呢?其实也很简单,我们只要知道我们的程序如果不使用docker他是在什么系统或者说是环境中使用,那么我们就可以通过docker官方的仓库去下载这样的镜像来供我们创建包含我们程序的镜像了。

    我们现在有这样的一段代码,功能就是给一个叫t.txt的文件中写hello world!!!。下面我们就通过这个简单的代码来示范如果把一个c/c++程序放到docker镜像中制作一个新的镜像

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>


    int main()
    {
    FILE* file = fopen("t.txt","w+");
    if (file == NULL)
    {
    return 0;
    }

    char buf[20]="hello world!!! ";
    int len = strlen(buf);

    while(1)
    {
    fputs(buf,file);
    fflush(file);
    // printf("%s",buf);
    sleep(1);
    }

    fclose(file);

    return 0;
    }

    1. 镜像的选择:

    c/c++程序我们都是直接运行在linux系统上,所以我们可以直接选择centos或者ubuntu镜像,在这里我们是要把.c文件编译成一个可执行程序,docker还有一个gcc或者g++的镜像,使用gcc或者g++镜像的话,我们就不需要在ubunt或者centos镜像中再安装gcc 、g++了。

    推荐三种镜像:

    gcc 或者g++
    ubuntu
    centos
    ————————————————
    版权声明:本文为CSDN博主「Coldestmonth」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
    原文链接:https://blog.csdn.net/len_yue_mo_fu/article/details/80189035



  • 相关阅读:
    OLTP与OLAP
    Entity Framework(07):TPH、TPT、TPC与继承类
    Entity Framework(05):主从表的增删改
    Entity Framework(06):配置关系
    Entity Framework(04):主从表数据加载方式
    Entity Framework(03):Code First基础
    Entity Framework(02):模型优先 ,ObjectContext类
    Entity Framework(01):模型优先,Linq to Entities
    简介LINUX远程联机软件:PUTTY、SecureCRT、X-Manager
    php函数分割
  • 原文地址:https://www.cnblogs.com/shangstacey/p/12762356.html
Copyright © 2011-2022 走看看