这是使用Docker开发多层C/C 应用程序的好方法

Is this a good approach for developing a multi-layered C/C++ application using docker?

本文关键字:应用程序 方法 Docker 开发      更新时间:2023-10-16

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

该应用程序将具有不同的层(在建筑上,不一定在Docker Sensic上(。这些层将或多或少地独立管理,每个层都具有自己的版本。

该应用程序应以C 编写。为了问题,让我们假装底层被用作共享库,而顶层是使用库的可执行文件。

我在如何构建图层上挣扎,以使图像尽可能小。

我当前的想法是为每个架构层使用制作Docker图像。我认为我应该使用多阶段建筑物来保持图像之外的构建工具。

底层的Docker文件现在看起来像:

# 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/

和第二层:

# 'dummy' from to get access to headers/libs of bottom layer in build layer
FROM mylib as mylib

FROM gcc as build

WORKDIR /build
# copy source files for this layer
COPY *.c ./

# copy headers and libraries from mylib - I DON'T LIKE THIS
COPY --from=mylib /usr/lib/libmylib.so /usr/lib
COPY --from=mylib /usr/include/mylib.h /usr/include

RUN gcc -o hello hello.c -lmylib

# Stage 3: create executable image
FROM mylib
COPY --from=build /build/hello /

# run main executable
CMD ["./hello"]

这将产生一个相对较小的图像,其中包含库和主可执行文件,并且不包含任何构建工具。所以这满足了我的需求。

,但我不喜欢这个解决方案,第二个Dockerfile必须知道其使用底层的所有文件的名称,因为它需要将它们复制到其构建阶段。如果构建阶段可以基于("来自"(图书馆的图像,那么所有伪像已经存在。但这意味着我将不得不将所有构建工具纳入此阶段...

我正在接近这一点的方式是这样做的吗?我想听听在Docker中构建多层应用程序的最佳实践。

如果您只有一个安装本地建造的共享库的"底层",则可以考虑从中构建两个docker映像。一个具有完整的开发工具,以及您的库及其标题文件;另一个具有最少的运行时库,以及您的库,没有标题文件。

# I am Dockerfile.builder
FROM gcc
WORKDIR /usr/src/mylib
COPY . .
RUN make && make install && ldconfig
# I am Dockerfile.runtime
FROM ubuntu
COPY --from=myname/builder /usr/lib/mylib.so* /usr/lib
RUN ldconfig

让您的CI系统构建 。请注意,第二个取决于第一个(myname/builder是您用于第一个图像的任何图像名称(。

现在,当您构建应用程序时,您拥有带有本地构建工具和库的基本Docker映像,以及带有库的基本码头图像。

FROM myname/builder AS build
WORKDIR /usr/src/app
COPY . .
RUN make && make install
FROM myname/runtime
COPY --from=build /usr/local/bin/app /usr/local/bin/app
CMD ["app"]

如果您有多个要单独构建和安装的共享库,则这种方法将无法正常运行(作为更通用的规则,您无法结合两个独立的Docker映像(。

另一种一般有用的方法(几乎所有语言都可以使用(是在不使用Docker的情况下打包您的库。如果您使用的是Ubuntu运行时,则可以将库包装到Debian软件包中。这在开发和运行时软件包之间具有分歧,因此在构建器映像中,您可以apt install开发版本(带有标题文件(,而在运行时仅运行时版本(带有USR共享库(。类似的方法适用于NPM和Python软件包,Ruby Gems,....

作为C/C 更适合低级开发,我不建议Docker使用。相反,您可以选择使用Docker,您可能可以实现相同的操作。

相关文章: