exteon / docker-recipes
一个库,用于聚合多个Dockerfile的多阶段文件,并添加可重用模板
Requires
- php: ~8.0.0 || ~8.1.1
- exteon/file-helper: ^1.6.2
- symfony/yaml: ^5.3
This package is auto-updated.
Last update: 2024-09-16 02:11:25 UTC
README
允许合并 Dockerfile 和 docker-compose.yml 脚本的库,增加了docker脚本的模块化和可重用性
概念
模板
在 docker-recipes 的上下文中,模板是 Dockerfile 的一个片段,使用相同的语法,用于拼接最终 Dockerfile。
一个模板可以需要多个其他模板。
Dockerfile
使用 docker-recipes,源 Dockerfile 是一个常规的 Dockerfile,增加了包含任何数量模板的语法。
docker-compose.yml
docker-recipes 提供了一种机制,可以将多个 docker-compose.yml 合并到一个目标 docker-compose.yml 中。同时,在 docker-compose.yml 中引用的模板 Dockerfile 将被管理,以便指向生成的合并 docker-compose.yml 中的生成 Dockerfile。
AppEnv的
很多时候,一个应用程序可以在多个运行环境中运行。例如,它可以有一个 live 环境,具有最小的占用空间,以及一个 dev 环境,其中在容器中添加了多个调试工具(例如 xdebug)。
从 v3.0 开始,docker-recipes 提供了一种机制,可以指定 Dockerfile 模板以及 docker-compose 文件的 app-env。每个 Dockerfile 和 docker-compose 文件都与一个 app-env 相关联,基于目录结构确定(更多详细信息请参见 定位器)。
在编译 Dockerfile 和 docker-compose 文件时,可以提供一个 app-env 栈作为数组
- 然后根据提供的 app-env 的顺序查找 Dockerfile(索引 0 优先)。
- docker-compose 文件按照提供的 app-env 的逆序堆叠和合并(索引 0 在顶部)。
Dockerfile 组成和语法
在 Dockerfile 和模板中,要求另一个模板的语法是
#TEMPLATE[ template-name ]
-或-
#TEMPLATE[ app-env/template-name ]
也就是说,一个以注释开始的行,后面跟着一个单行注释井号,然后没有空格地跟着 TEMPLATE[。在方括号之间,提供模板名称,可能前面跟着 app-env 和一个斜杠。模板定位的机制请参见 定位器。
该库的目的在于,对于每个源 Dockerfile,生成一个包含所有编译进来的模板的目标 Dockerfile。
当一个模板被多次要求时(可能由多个不同的其他模板要求),它将被去重并只包含在编译的 Dockerfile 中一次;功能模板(可调用/可参数化)的概念尚未实现,但考虑在未来的版本中实现。
在 Dockerfile 模板/镜像中,例如,当你有一个 COPY 指令时,你需要模板目录的路径。为此,你需要使用 $TEMPLATE_DIR 变量,它将被编译成正确的路径,即
COPY $TEMPLATE_DIR/supervisord/supervisord.conf /etc/supervisord.conf
(参见此 示例模板)
docker-compose.yml 组成和语法
最终将生成一个 docker-compose.yml 文件,该文件是通过合并每个定位器返回的 docker-compose.yml 文件来生成的。没有特殊的语法,除非你需要引用最终运行 compose 的上下文的路径。这也被称为“项目路径”,并作为 $projectRoot 传递给 DockerComposeCompiler 构造函数(请参见 docker-compose 编译)。
要引用该目录,请在源代码中的 docker-compose.yml 文件中使用环境变量 ${PROJECT_DIR}。
(参见此 示例)
定位器
镜像和模板通过名称引用。为了定位并将它们映射到源文件,使用一个或多个定位器。提供了一个标准定位器实现,包含类 StdDockerfileLocator 和 StdDockerComposeLocator,这些类接收一个根目录作为构造函数参数;每个根目录包含一系列模板和一系列镜像,在 StdDockerComposeLocator 的情况下,还包含零个或一个 docker-compose.yml 文件。
文件结构如下
<root_dir>
├ templates
│ ├ template_name_1
│ │ └ Dockerfile
│ └ some_other_template
│ └ Dockerfile
├ image_name_1
│ └ Dockerfile
├ some_other_image
│ └ Dockerfile
└ docker-compose.yml
两个定位器之间的区别在于
StdDockerfileLocator由DockerfileCompiler使用,并且只会处理镜像和模板StdDockerComposeLocator由DockerComposeCompiler使用,除了处理镜像和模板外,还会处理docker-compose.yml文件。
如果您需要不同的目录结构,可以创建自定义定位器,实现 DockerComposeLocator 和 DockerfileLocator 接口。
AppEnv 的目录结构
上述目录结构适用于默认的 '' (空白) app-env。对于使用多个 app-env,目录结构将如下所示
<root_dir>
├ common
│ ├ templates
│ │ ├ template_name_1
│ │ │ └ Dockerfile
│ │ └ some_other_template
│ │ └ Dockerfile
│ ├ image_name_1
│ │ └ Dockerfile
│ ├ some_other_image
│ │ └ Dockerfile
│ └ docker-compose.yml
├ live
│ ├ templates
│ │ └ template_name_1
│ │ └ Dockerfile
│ └ docker-compose.yml
└ dev
└ docker-compose.yml
然后当使用 ['live', 'common'] 作为实例的 app-env 链时,则
- 当在未指定 app-env 的
#TEMPALTE[ ]标签中引用时,或在 docker-compose 文件中引用时,模板和镜像将首先在live中查找,然后在common目录中查找 common/docker-compose.yml和live/docker-compose.yml将按此顺序合并。
Dockerfile 编译
从模板编译镜像是通过 DockerfileCompiler 完成的,其实例化方式如下
/** * @param DockerfileLocator[] $locators * @param string $targetDir * @param string[] $appEnv */ public function __construct( array $locators, string $targetDir, array $appEnv = [''] )
$targetDir 是编译后的镜像文件将要写入的目标目录。
要编译镜像,您使用
/** @var \Exteon\DockerRecipes\DockerfileCompiler $compiler */ $compiler->compile();
这将生成一个目标目录,对于上述示例源目录,将生成
<target_dir>
├ image_name_1
│ └ Dockerfile
└ some_other_image
└ Dockerfile
因此,对于每个源镜像,都会从模板编译出目标镜像。
docker-compose 编译
使用 DockerComposeCompiler 编译 docker-compose 脚本,它从定位器的 docker-compose.yml 文件编译出镜像(与 DockerfileCompiler 相同)和一个 docker-compose.yml 文件。它的实例化方式如下
/** * @param DockerComposeLocator[] $locators * @param string $dockerfilesTargetDir * @param string $composeFileTargetPath * @param string $projectRoot * @param string[] $appEnv */ public function __construct( array $locators, string $dockerfilesTargetDir, string $composeFileTargetPath, string $projectRoot, array $appEnv = [''] )
$dockerfilesTargetDir 是编译后的镜像的目标目录。有关更多信息,请参阅 Dockerfile 编译。
$composeFileTargetPath 是要编译的 docker-compose.yml 文件的目标路径。
$projectRoot 是用于在 docker-compose.yml 文件中替换 ${PROJECT_DIR} 的目录的路径。
$appEnv 是用于组合文件的 app-env 堆栈顺序。
要编译图像/组合文件,您使用
/** @var \Exteon\DockerRecipes\DockerComposeCompiler $compiler */ $compiler->compile();
当从多个来源(提供多个 docker-compose.yml 的多个定位器)编译 docker-compose.yml 时,目标文件将使用以下算法从所有源文件合并:递归地,对于 yml 文件中的所有字符串键,值将被合并(如果为标量则被覆盖)。对于所有顺序数组,内容将被附加。
示例
毕竟“熟能生巧”,您可以查看example目录中的示例,了解如何使用模板编译一个包含Web服务器的CentOS8镜像,这些模板可以用于构建其他不同的镜像(例如supervisor-rhel8模板)。
要运行示例,只需在命令行中运行php example.php。生成的centos8-web镜像配方将位于example/target,而docker-compose文件位于example/docker-compose.yml。要构建和运行容器,请在example目录下运行composer up -d。