如何在没有构建工具的情况下为 Ruby 项目构建 Docker 图像?

How do I build a Docker image for a Ruby project without build tools?

我正在尝试为 Ruby 项目构建 Docker 图像。问题是该项目有一些 gem 依赖项需要构建本机扩展。我的理解是我有几个选择:

  1. 从已安装构建工具的基础映像开始。
  2. 使用没有构建工具的基础映像,安装构建工具作为 运行 bundle install.
  3. 之前 Docker 文件中的一个步骤
  4. 在主机上预编译本机扩展,供应 gem,然后简单地将生成的包复制到映像中。

1 和 2 似乎要求生成的图像包含构建本机扩展所需的构建工具。出于安全原因,我试图避免这种情况。 3 很麻烦,但是可行,并且可以完成我想要的。

有没有我遗漏的选项或者我误解了什么?

我一直使用选项 3,目标是最终得到一个只有我需要的图像 运行(不编译)

例如,here I build and install Apache first,在使用生成的图像作为我的(修补和重新编译的)Apache 设置的基础图像之前。

构建:

if [ "$(docker images -q apache.deb 2> /dev/null)" = "" ]; then
  docker build -t apache.deb -f Dockerfile.build . || exit 1
fi

Dockerfile.build 声明了一个卷,其中包含重新编译的 Apache(在 deb 文件中)

RUN checkinstall --pkgname=apache2-4 --pkgversion="2.4.10" --backup=no --deldoc=yes --fstrans=no --default
RUN mkdir $HOME/deb && mv *.deb $HOME/deb
VOLUME /root/deb

安装:

if [ "$(docker images -q apache.inst 2> /dev/null)" = "" ]; then
    docker inspect apache.deb.cont > /dev/null 2>&1 || docker run -d -t --name=apache.deb.cont apache.deb
    docker inspect apache.inst.cont > /dev/null 2>&1 || docker run -u root -it --name=apache.inst.cont --volumes-from apache.deb.cont --entrypoint "/bin/sh" openldap -c "dpkg -i /root/deb/apache2-4_2.4.10-1_amd64.deb"
    docker commit apache.inst.cont apache.inst
    docker rm apache.deb.cont apache.inst.cont
fi

这里我使用另一个镜像(在我的例子中 'openldap')作为基础镜像来安装 deb:

docker run -u root -it --name=apache.inst.cont --volumes-from apache.deb.cont --entrypoint "/bin/sh" openldap -c "dpkg -i /root/deb/apache2-4_2.4.10-1_amd64.deb"
docker commit apache.inst.cont apache.inst

最后我有一个 regular Dockerfile 从我刚提交的图像开始。

FROM apache.inst:latest

psmith points out in the comments to Building Minimal Docker Image for Rails App from Jari Kolehmainen.
对于 ruby 应用程序,您可以使用以下方法轻松删除构建所需的部分:

bundle install --without development test && \
apk del build-dependencies

因为无论如何 运行 应用程序都需要 ruby,所以在这种情况下效果很好。

我的情况,我仍然需要一个单独的图像来构建,因为 gcc 不需要 运行 Apache(而且它非常大,带有多个依赖项,其中一些是需要的Apache 在 运行 时间,有些不是...)