我正处于一个新项目的高级设计阶段,我们正在认真考虑使用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中构建多层应用程序的最佳实践。
答案 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,这也许可以实现相同的目标。