2017-07-20 159 views
0

我想在应用程序的官方Docker基础映像中包含并启用一些自定义插件。Dockerfile中的循环/迭代

下面是目录结构的样子;

. 
+-- Dockerfile 
+-- plugins 
| +-- plugin_1 
| +-- plugin_2 
| +-- plugin_3 
| +-- ... 
| +-- plugin_n 

Dockerfile如下所示,如果我需要包括插件plugin_1plugin_3plugin_7plugin_8;

FROM myapp_officialimage 

COPY plugins/plugin_1/* /usr/lib/myapp/plugins/ 
RUN myapp-plugins.sh enable plugin_1 

COPY plugins/plugin_3/* /usr/lib/myapp/plugins/ 
RUN myapp-plugins.sh enable plugin_3 

COPY plugins/plugin_7/* /usr/lib/myapp/plugins/ 
RUN myapp-plugins.sh enable plugin_7 

COPY plugins/plugin_8/* /usr/lib/myapp/plugins/ 
RUN myapp-plugins.sh enable plugin_8 

CMD ["myapp-start.sh"] 

问题是,是否有可能重复/遍历一个列表,以消除上述样板?

例如,像下面这样的Dockerfile会更干净,更易于维护;

FROM myapp_officialimage 

ENV CUSTOM_PLUGIN_LIST="plugin_1 plugin_3 plugin_7 plugin_8" 

for plugin in $CUSTOM_PLUGIN_LIST; \ 
do \ 
    COPY plugins/$plugin/* /usr/lib/myapp/plugins/ \ 
    RUN myapp-plugins.sh enable $plugin \ 
done 

CMD ["myapp-start.sh"] 
+2

这将为每个插件在图像中创建两个图层。你不能用shell脚本来做到这一点吗?那将是一个'RUN'。 – Grimmy

+0

这些插件可以以某种形式下载为包吗?然后,您将制作需求清单并将软件包下载到映像中。 – Grimmy

+0

'docker build'发生在构建服务器上,而构建的映像将在生产环境中执行。生产中的主机不包括'plugins'目录,生产网络无法访问下载插件文件。我需要在编译和构建时间之前将这些插件捆绑在一起,然后将生成的图像发布到生产环境中。 –

回答

0

在你的情况我会准备一个新的插件与安装它们(可能产生的或手工)脚本一起文件夹中。将真实的插件文件夹添加到.dockerignore。然后,您复制新文件夹并运行安装脚本。这也减少了在开始构建之前上传到Docker的上下文的大小。无论如何,你都是亲自挑选依赖关系,所以事先做好工作(在你之前build)应该可以正常工作。

在构建系统,你,你应该这样做:

collect_plugins.sh # Creates the new plugin folder and install script 
docker build <params> 

两层便可设为:

COPY plugins_selected/ /usr/lib/myapp/plugins/ 
RUN /usr/lib/myapp/plugins/install.sh 

如果你准备要发送到泊坞窗就会使上下文Dockerfile更简单(一件好事)。我们只是在build之前解决问题。

通常使用包管理器通过网络获取依赖关系,或者只需通过http下载它们。像你在做的那样将它们复制到构建上下文中并不一定是错误的,但它会变得更加尴尬。

让我们来看看docker如何处理Dockerfile(略微模仿)。

当您使用build时,docker会将上下文中的所有文件上传到码头引擎(.dockerignore中提及的路径除外)并开始处理Dockerfile。目的是生成代表最终映像的文件系统层。

当您执行像RUN这样的操作时,docker实际上会启动一个容器来执行命令,然后将生成的图层添加到图像中。生产中唯一实际运行的是您在CMDDockerfile末尾指定的或ENTRYPOINT

尽量创建尽可能少的图层。

dockerfile best practices guide covers the basics