这是使用docker开发多层C / C ++应用程序的好方法吗?

时间:2019-06-27 14:46:02

标签: c++ docker

我正处于一个新项目的高级设计阶段,我们正在认真考虑使用docker构建嵌入式应用程序。该应用程序应在具有嵌入式Linux发行版的ARM设备上运行。

应用程序将具有不同的层(在体系结构上,不一定是docker意义上的层)。这些层将或多或少地进行独立管理,每个层都有各自的版本控制。

该应用程序将使用C ++编写。出于这个问题,让我们假设底层是作为共享库实现的,顶层是使用该库的可执行文件。

我正在努力构建图层,以使图像尽可能小。

我当前的想法是为每个建筑层使用docker镜像。我认为我应该使用多阶段构建,以将构建工具保留在图像之外。

底层的docker文件现在看起来像这样:

library(plotly)

#Create dataset
ho_graph1 = data.frame(
  "Code" = c("G","L","K","I","B","N","O","M","F","D","H","C","J"),
  "Rate" = c(600, 550, 500, 450, 400, 350, 300, 250, 200, 150, 100, 50, 5),
  "AUR" = c(2.8, 2.6, 2, 1.5, 2.1, 1.6, 1.4, 1.3, 1.1, 0.8, 0.5, 0.3, 
            0.7),
  "Outlier Status" = c(rep("Bottom 25%", times=4), rep("Middle 50%", 
                                                       times=6), rep("Top 25%", times=3)))

#Sort by decreasing rate
ho_graph1$Code <- factor(ho_graph1$Code, levels = unique(ho_graph1$Code) 
                         [order(ho_graph1$Rate, decreasing = TRUE)])

#Graph
plot_ly(ho_graph1, type = 'bar', x = ~Code, y = ~Rate, color = 
          ~Outlier.Status, colors = c("red", "blue", "chartreuse3"), legendgroup = ~Outlier.Status,
        hoverinfo = "text", text = ~paste('BS-HO Prescribing Rate: ', Rate, "\n", 
                                          'Provider: ', Code)) %>% 
  add_trace(y = ~AUR, type = 'scatter', mode='markers', yaxis = 'y2', 
            showlegend = FALSE,
            marker = list(size = 13,
                          color = 'rgb(240,230,140)',
                          line = list(color = 'rgb(255,215,0)',
                                      width = 2)),
            hoverinfo = "text",
            text = ~paste('O:E: ', AUR, "\n", 'Provider: ', Code)) %>%
  layout(title = 'BS-HO Prescribing Rate and O:E by Provider, Mar-Apr 
2019',
         xaxis = list(title = ""),
         yaxis = list(side = 'left', title = 'BS-HO Prescribing Rate', showgrid = 
                        FALSE, zeroline = FALSE),
         yaxis2 = list(side = 'right', overlaying = "y", title = 'O:E', showgrid 
                       =  FALSE, zeroline = FALSE))

第二层:

# Stage #1: build

FROM gcc as build



WORKDIR /build

# copy and compile source files

COPY *.c *.h ./

RUN gcc -shared -fPIC -o libmylib.so mylib.c



# Stage 2

FROM gcr.io/distroless/cc

# copy build artefacts to image

COPY --from=build /build/libmylib.so /usr/lib/

COPY --from=build /build/mylib.h /usr/include/

这将导致相对较小的映像,该映像同时包含库和主可执行文件,并且不包含任何构建工具。所以这满足了我的需求。

但是我不喜欢这种解决方案,因为第二个dockerfile必须知道它在底层使用的所有文件的名称,因为它需要将它们复制到其构建阶段。如果构建阶段可以基于(“ FROM”)库映像,则将更加优雅,这样所有假象就已经存在。但这意味着我将不得不将所有构建工具引入这一阶段...

这是我普遍接受的解决方法吗?我想听听在docker中构建多层应用程序的最佳实践。

2 个答案:

答案 0 :(得分:1)

如果只有一个“底层”安装本地构建的共享库,则可以考虑在其中构建两个Docker映像。一个拥有一整套的开发工具,以及您的库及其头文件;另一个则具有最少的运行时库集,再加上您的库,并且没有头文件。

integration
e2e

已经让您的CI系统同时构建了这两者。请注意,第二个取决于第一个(# I am Dockerfile.builder FROM gcc WORKDIR /usr/src/mylib COPY . . RUN make && make install && ldconfig 是您用于第一个图像的任何图像名称)。

现在,在构建应用程序时,您将拥有一个包含本地构建工具和库的基本Docker映像,以及一个预先安装了该库的基本Docker映像。

# I am Dockerfile.runtime
FROM ubuntu
COPY --from=myname/builder /usr/lib/mylib.so* /usr/lib
RUN ldconfig

如果您要尝试分别构建和安装多个共享库,则这种方法将无法很好地工作(这是不能将两个独立的Docker映像合并的更普遍的规则的必然结果)。

另一种通用的方法(几乎在所有语言中都有效)是不使用Docker打包您的库。如果您使用的是类似Ubuntu运行时的软件,则可以将库打包为Debian软件包。这在开发和运行时软件包之间是有区别的,因此,在构建器映像中,您可以myname/builder开发版本(带有头文件),而在运行时只能运行时版本(使用usr共享库)。类似的方法适用于npm和Python包,Ruby gems ....

答案 1 :(得分:-1)

由于C / C ++更适合于低级开发,因此我不建议使用docker。相反,您可以选择使用Docker的GO,这也许可以实现相同的目标。

相关问题