Docker 如何减少多阶段构建重复步骤的时间成本问题?
我有一个go应用程序,它取决于cgo。构建时,它需要Docker 如何减少多阶段构建重复步骤的时间成本问题?,docker,Docker,我有一个go应用程序,它取决于cgo。构建时,它需要libnaudev、libzmq3-dev、libczmq-dev,运行时还需要以上三个包 目前,我使用下一个多阶段构建:golang构建环境作为第一阶段&debian slim作为第二阶段。但是你可以看到3个软件包安装了两次,这浪费了时间(以后我可能会添加更多这样的软件包) 当然,我可以放弃多阶段构建,只需使用golang1.12.9-buster进行构建,然后继续运行,但这将使最终运行映像更大(这是多阶段构建的优势) 我是错过了什么,还是不
libnaudev、libzmq3-dev、libczmq-dev
,运行时还需要以上三个包
目前,我使用下一个多阶段构建:golang构建环境
作为第一阶段&debian slim
作为第二阶段。但是你可以看到3个软件包安装了两次,这浪费了时间(以后我可能会添加更多这样的软件包)
当然,我可以放弃多阶段构建,只需使用golang1.12.9-buster
进行构建,然后继续运行,但这将使最终运行映像更大(这是多阶段构建的优势)
我是错过了什么,还是不得不在以上两者之间做出选择?在
副本处代码>步骤,只要源代码发生更改,缓存就会崩溃,您将再次运行后面的所有步骤。您可以重新排序这些步骤,以允许docker缓存依赖项的安装。您还可以将apt get install
命令合并为一个命令,以减少处理package manager数据库的开销
FROM golang:1.12.9-buster AS builder
WORKDIR /src/pigeon
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
libsodium-dev \
libzmq3-dev \
libczmq-dev
COPY . .
RUN go build cmd/main/pgd.go
FROM debian:buster-slim
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
libsodium-dev \
libzmq3-dev \
libczmq-dev \
python3 \
python3-pip \
&& pip3 install jinja2
WORKDIR /root/
RUN mkdir logger
COPY --from=builder /src/pigeon/pgd .
COPY --from=builder /src/pigeon/logger logger
CMD ["./pgd"]
您仍将安装两次软件包,但现在这些安装将被缓存以供将来的版本使用。重用库的安装的方法是重新排序步骤,在公共基础映像中安装库,然后在构建阶段安装go编译器,但这几乎肯定比两次安装库的开销更大
使用BuildKit,您可以使用实验语法在构建之间共享apt缓存,但这要求所有构建都使用BuildKit(语法不向后兼容),并修改docker的Debian映像以保留apt包缓存。从BuildKit实验文档中,apt有以下示例:
# syntax = docker/dockerfile:experimental
FROM ubuntu
RUN rm -f /etc/apt/apt.conf.d/docker-clean; echo 'Binary::apt::APT::Keep-Downloaded-Packages "true";' > /etc/apt/apt.conf.d/keep-cache
RUN --mount=type=cache,target=/var/cache/apt --mount=type=cache,target=/var/lib/apt \
apt update && apt install -y gcc
在副本处代码>步骤,只要源代码发生更改,缓存就会崩溃,您将再次运行后面的所有步骤。您可以重新排序这些步骤,以允许docker缓存依赖项的安装。您还可以将apt get install
命令合并为一个命令,以减少处理package manager数据库的开销
FROM golang:1.12.9-buster AS builder
WORKDIR /src/pigeon
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
libsodium-dev \
libzmq3-dev \
libczmq-dev
COPY . .
RUN go build cmd/main/pgd.go
FROM debian:buster-slim
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
libsodium-dev \
libzmq3-dev \
libczmq-dev \
python3 \
python3-pip \
&& pip3 install jinja2
WORKDIR /root/
RUN mkdir logger
COPY --from=builder /src/pigeon/pgd .
COPY --from=builder /src/pigeon/logger logger
CMD ["./pgd"]
您仍将安装两次软件包,但现在这些安装将被缓存以供将来的版本使用。重用库的安装的方法是重新排序步骤,在公共基础映像中安装库,然后在构建阶段安装go编译器,但这几乎肯定比两次安装库的开销更大
使用BuildKit,您可以使用实验语法在构建之间共享apt缓存,但这要求所有构建都使用BuildKit(语法不向后兼容),并修改docker的Debian映像以保留apt包缓存。从BuildKit实验文档中,apt有以下示例:
# syntax = docker/dockerfile:experimental
FROM ubuntu
RUN rm -f /etc/apt/apt.conf.d/docker-clean; echo 'Binary::apt::APT::Keep-Downloaded-Packages "true";' > /etc/apt/apt.conf.d/keep-cache
RUN --mount=type=cache,target=/var/cache/apt --mount=type=cache,target=/var/lib/apt \
apt update && apt install -y gcc
以下是我对你的问题的看法:
FROM debian:buster-slim as base
RUN mkdir /debs /debs_tmp \
&& chmod 777 /debs /debs_tmp
WORKDIR /debs
RUN apt-get update \
&& apt-get install -y -d \
--no-install-recommends \
-o dir::cache::archives="/debs_tmp/" \
libsodium-dev \
libzmq3-dev \
libczmq-dev \
&& mv /debs_tmp/*.deb /debs \
&& rm -rf /debs_tmp \
&& apt-get install -y --no-install-recommends \
python3 \
python3-pip \
&& pip3 install jinja2 \
&& rm -rf /var/lib/apt/lists/*
##################
FROM golang:1.12.9-buster AS builder
COPY --from=base /debs /debs
WORKDIR /debs
RUN dpkg -i *.deb
WORKDIR /src/pigeon
COPY . .
RUN go build cmd/main/pgd.go
##################
FROM base
RUN rm -rf /debs
WORKDIR /root/
RUN mkdir logger
COPY --from=builder /src/pigeon/pgd .
COPY --from=builder /src/pigeon/logger logger
CMD ["./pgd"]
您可以在临时文件夹中下载所需的软件包,将DEB移动到新位置,最后在下一阶段复制DEB。最后,您只需使用您创建的第一个图像
顺便说一句,容器将作为根运行。这可能是一个问题,取决于软件做什么,你可能想考虑使用没有“权力”的用户。
编辑:很抱歉进行了编辑,但我在本地运行了几个示例,没有准备好go脚本。以下是我对您的问题的看法:
FROM debian:buster-slim as base
RUN mkdir /debs /debs_tmp \
&& chmod 777 /debs /debs_tmp
WORKDIR /debs
RUN apt-get update \
&& apt-get install -y -d \
--no-install-recommends \
-o dir::cache::archives="/debs_tmp/" \
libsodium-dev \
libzmq3-dev \
libczmq-dev \
&& mv /debs_tmp/*.deb /debs \
&& rm -rf /debs_tmp \
&& apt-get install -y --no-install-recommends \
python3 \
python3-pip \
&& pip3 install jinja2 \
&& rm -rf /var/lib/apt/lists/*
##################
FROM golang:1.12.9-buster AS builder
COPY --from=base /debs /debs
WORKDIR /debs
RUN dpkg -i *.deb
WORKDIR /src/pigeon
COPY . .
RUN go build cmd/main/pgd.go
##################
FROM base
RUN rm -rf /debs
WORKDIR /root/
RUN mkdir logger
COPY --from=builder /src/pigeon/pgd .
COPY --from=builder /src/pigeon/logger logger
CMD ["./pgd"]
您可以在临时文件夹中下载所需的软件包,将DEB移动到新位置,最后在下一阶段复制DEB。最后,您只需使用您创建的第一个图像
顺便说一句,容器将作为根运行。这可能是一个问题,取决于软件做什么,你可能想考虑使用没有“权力”的用户。
编辑:很抱歉进行了编辑,但我在本地运行了几个示例,没有准备好go脚本。请看一些人给我的建议,但是一个软件包安装可能会导致其他依赖软件包安装,我很难将所有包从一个阶段复制到另一个阶段,尽管我可以使用dpkg-L
查找所有内容。请看一些人给我的建议,但是一个包的安装可能会导致其他依赖性包的安装,虽然我可以使用dpkg-L
查找所有内容,但将所有包从一个阶段复制到另一个阶段对我来说非常困难。类似于buildkit apt cache,但此解决方案不需要实验性
支持。类似于buildkit apt cache,但此解决方案不需要实验性
支持。