使用Docker构建编译应用程序 我正在构建一个服务器,用C++编写,并希望使用DOCKER来部署它。“正确的方法”是什么?我应该从Dockerfile调用make,还是手动生成,上传到某个服务器,然后从Dockerfile复制二进制文件?更新

使用Docker构建编译应用程序 我正在构建一个服务器,用C++编写,并希望使用DOCKER来部署它。“正确的方法”是什么?我应该从Dockerfile调用make,还是手动生成,上传到某个服务器,然后从Dockerfile复制二进制文件?更新,c++,deployment,docker,docker-compose,C++,Deployment,Docker,Docker Compose,对于2017年之后访问此问题的任何人,请参见关于使用,这确实是一个比2015年我的答案(以下)更好的解决方案,而在这之前很久 旧答案 我的方法是在容器外运行构建,只将构建的输出(二进制文件和任何必要的库)复制到容器中。然后,您可以将容器上载到容器注册表(例如,使用托管的容器或运行自己的容器),然后从该注册表拉到生产机器上。因此,流可以如下所示: . ├── run │ └── Dockerfile ├── develop │ └── Dockerfile ├── build │ ├

对于2017年之后访问此问题的任何人,请参见关于使用,这确实是一个比2015年我的答案(以下)更好的解决方案,而在这之前很久


旧答案 我的方法是在容器外运行构建,只将构建的输出(二进制文件和任何必要的库)复制到容器中。然后,您可以将容器上载到容器注册表(例如,使用托管的容器或运行自己的容器),然后从该注册表拉到生产机器上。因此,流可以如下所示:

.
├── run
│   └── Dockerfile
├── develop
│   └── Dockerfile
├── build
│   ├── Dockerfile
│   └── removeOldImages.sh
└── deploy
    ├── Dockerfile
    └── pushImage.sh
  • 构建二进制文件
  • 测试/健全性检查二进制文件本身
  • 用二进制文件构建容器映像
  • 测试/健全使用二进制文件检查容器映像
  • 上载到容器注册表
  • 部署到staging/test/qa,从注册表中提取
  • 部署到prod,从注册表中提取
  • 由于在生产部署之前进行测试非常重要,因此您希望测试的内容与将在生产中部署的内容完全相同,因此您不希望在构建Docker映像后以任何方式提取或修改它


    我不会在您计划在prod中部署的容器中运行构建,因为这样您的容器将具有各种附加构件(例如临时构建输出、工具等)您在生产中不需要,并且不必要地使用部署时不会使用的东西来扩展容器映像。

    我的建议是完全在容器本身上开发、构建和测试。这确保了Docker的理念,即开发人员的环境与生产环境相同,请参阅

    尤其是在C++应用程序中,通常存在依赖于共享库/对象文件的依赖关系。 <>我认为在Docker上开发、测试和部署C++应用程序还没有一个标准化的开发过程,但是

    为了回答您的问题,我们目前的做法是将容器视为您的开发环境,并在团队中实施一系列实践,如:

  • 我们的代码库(配置文件除外)始终位于共享卷(本地计算机上)(在Git上进行版本控制)
  • 共享/依赖库、二进制文件等始终位于容器中
  • 提交映像之前,在容器和中构建和测试,清除不需要的对象文件、库等,并确保
    docker diff
    更改符合预期
  • 对环境的更改/更新(包括共享库、依赖项)始终记录在案,并与团队进行沟通

  • 我在使用
    docker compose
    自动化构建时遇到了困难,最终我使用
    docker build
    实现了所有功能:

    三层建筑

    跑→ 发展→ 建造

    然后,我将构建输出复制到“部署”映像中:

    跑→ 部署

    要使用的四层:

    • 包含运行应用程序所需的任何包-例如libsqlite3-0
    发展
    • FROM:run
    • 包含生成所需的包
      • e、 g.g++,cmake,libsqlite3开发
    • Dockerfile执行任何外部构建
      • e、 g.构建boost-python3的步骤(不在PackageManager存储库中)
    建造
    • FROM:develope
    • 包含源
    • Dockerfile执行内部构建(经常更改的代码)
    • 生成的二进制文件将从此映像中复制出来,以便在部署中使用
    部署
    • FROM:run
    • 将生成的输出复制到映像并安装
    • 用于启动应用程序的
      RUN
      ENTRYPOINT
    文件夹结构如下所示:

    .
    ├── run
    │   └── Dockerfile
    ├── develop
    │   └── Dockerfile
    ├── build
    │   ├── Dockerfile
    │   └── removeOldImages.sh
    └── deploy
        ├── Dockerfile
        └── pushImage.sh
    
    设置生成服务器意味着执行:

    docker build -f run -t <projName>:run
    docker build -f develop -t <projName>:develop
    
    docker build-f run-t:run
    docker build-f develope-t:develope
    
    每次构建时,都会发生以下情况:

    # Execute the build
    docker build -f build -t <projName>:build
    
    # Install build outputs
    docker build -f deploy -t <projName>:version
    
    # If successful, push deploy image to dockerhub
    docker tag <projName>:<version> <projName>:latest
    docker push <projName>:<version>
    docker push <projName>:latest
    
    #执行构建
    docker构建-f构建-t:build
    #安装生成输出
    docker构建-f部署-t:版本
    #如果成功,请将部署映像推送到dockerhub
    docker标记::最新
    docker推送:
    docker push:最新版本
    
    我建议人们将DockerFile作为关于如何构建/运行/安装项目的文档

    如果构建失败,并且输出不足以进行调查,我可以在
    :build
    中运行
    /bin/bash
    ,并查看哪里出了问题


    我把这个想法放在一起。它对C++来说很好,但是你可以用它来做任何事情。

    我还没有探究这个特性,但是@TaylorEdmiston指出,我在这里的模式与之非常相似,这是我提出这个时不知道的。这看起来是实现同样目标的一种更为优雅(且记录更为完整)的方法。

    而其他答案中提出的解决方案——特别是Misha Brukman在对的评论中提出的关于使用一个Dockerfile进行开发,一个用于生产的建议——在撰写问题时被认为是惯用的,应该注意的是,他们试图解决的问题——特别是清理构建环境以减小图像大小,同时仍然能够在开发和生产中使用相同的容器环境的问题——已经由有效地解决了,这在Docker 17.05中介绍

    这里的想法是将Dockerfile分为两部分,一部分基于您最喜欢的开发环境,例如一个成熟的Debian base映像,该映像负责创建您需要的二进制文件