使用Docker构建已编译的应用程序

时间:2015-12-29 19:07:41

标签: c++ deployment docker docker-compose

我正在构建一个用C ++编写的服务器,并希望使用带有docker-compose的Docker来部署它。这样做的“正确方法”是什么?我应该从Dockerfile调用make还是手动构建,从Dockerfile上传到某个服务器然后上传COPY个二进制文件?

4 个答案:

答案 0 :(得分:19)

我在使用docker-compose自动构建时遇到了困难,最后我使用了docker build来处理所有内容:

构建三层

  

运行→开发→构建

然后我将构建输出复制到' deploy'图像:

  

运行→部署

可以使用四层:

  • 包含运行应用程序所需的所有包 - 例如libsqlite3-0
开发
  • FROM <projname>:run
  • 包含构建所需的包
    • e.g。 g ++,cmake,libsqlite3-dev
  • Dockerfile执行任何外部版本
    • e.g。构建boost-python3的步骤(不在包管理器存储库中)
建立
  • FROM <projname>:develop
  • 包含来源
  • Dockerfile执行内部构建(经常更改的代码)
  • 已从此映像中复制已构建的二进制文件以用于部署
部署
  • FROM <projname>:run
  • 复制到图像并已安装的构建输出
  • 用于启动应用程序的
  • RUNENTRYPOINT

文件夹结构如下所示:

.
├── 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

每次我们进行构建时,都会发生这种情况:

# 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

我将人们引用到Dockerfiles作为有关如何构建/运行/安装项目的文档。

如果构建失败并且输出不足以进行调查,我可以在/bin/bash中运行<projname>:build并查看错误。

我把这个想法放在一起a GitHub repository。它适用于C ++,但您可以将它用于任何事情。

答案 1 :(得分:6)

我的建议是完全开发,构建和测试容器本身。这确保了Docker的理念,即开发人员的环境与生产环境相同,请参阅 The Modern Developer Workstation on MacOS with Docker

特别是在C ++应用程序中,通常存在与共享库/目标文件的依赖关系。

我不认为在Docker上开发,测试和部署C ++应用程序存在标准化的开发过程。

要回答您的问题,我们现在的处理方式是将容器视为您的开发环境,并在团队中执行一系列实践,例如:

  1. 我们的代码库(配置文件除外)总是存在于共享卷上(在本地计算机上)(在Git上版本化)
  2. 共享/依赖库,二进制文件等始终生活在容器中
  3. 构建&amp;在提交图像之前测试容器和,清理不需要的目标文件,库等,并确保docker diff更改符合预期
  4. 对环境的更改/更新(包括共享库,依赖项)始终记录并与团队进行沟通。

答案 2 :(得分:5)

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

  1. 构建二进制文件
  2. test / sanity-检查二进制文件本身
  3. 使用二进制构建容器图像
  4. 使用二进制文件
  5. 测试/健全性检查容器图像
  6. 上传到容器注册表
  7. 从登记处
  8. 部署到staging / test / qa
  9. 部署到prod,从注册表中拉出来
  10. 由于您在生产部署之前进行测试非常重要,因此您希望测试与生产中部署完全相同的内容,因此您不希望以任何方式提取或修改Docker镜像建成之后。

    我不会在您计划在prod中部署的容器中运行内部的,因为那时您的容器将具有各种其他工件(例如临时构建输出,工具等)您不需要在生产中使用您未能用于部署的内容来不必要地增加容器图像。

答案 3 :(得分:2)

虽然其他答案中提出的解决方案-特别是Misha Brukman在对this answer的评论中关于使用一个Dockerfile进行开发而将一个Dockerfile进行生产的建议-在当时被认为是惯用的写下问题后,应该注意的是,他们正在尝试解决的问题-尤其是清理构建环境以减小映像大小,同时仍然能够在开发和生产中使用相同的容器环境的问题-有效地被Docker 17.05中引入的 multi-stage builds 解决。

这里的想法是将Dockerfile分为两个部分,一个基于您最喜欢的开发环境,例如成熟的Debian基本映像,该映像与创建要在Windows上部署的二进制文件有关。结束时,另一个仅在最小的环境(例如Alpine)中运行构建的二进制文件。

通过这种方式,您可以避免开发环境和生产环境之间可能存在的差异,如蓝皮书在评论中提到的那样,同时仍确保您的生产映像不会被开发工具污染。

该文档提供了以下Go应用程序多阶段构建示例,您将随后将其应用于C ++开发环境(一个陷阱是Alpine使用musl,因此在使用时必须小心在您的开发环境中进行链接)。

FROM golang:1.7.3
WORKDIR /go/src/github.com/alexellis/href-counter/
RUN go get -d -v golang.org/x/net/html  
COPY app.go .
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app .

FROM alpine:latest  
RUN apk --no-cache add ca-certificates
WORKDIR /root/
COPY --from=0 /go/src/github.com/alexellis/href-counter/app .
CMD ["./app"]