bedezign/dchelper

增强 docker-compose 的额外开发者友好功能

0.0.5 2018-01-28 18:41 UTC

This package is not auto-updated.

Last update: 2024-09-15 03:24:09 UTC


README

(仍在开发中,使用风险自担)

请注意,此辅助程序(别名/代理)中相关的网络功能仅在 macOS 上有效。对此我深感抱歉。我也非常愿意帮助 Windows 用户,但事实是,它不支持大多数所需的功能。

如果您使用 docker compose,并且希望能够使用像 http://myproject.test 这样的合理 URL 来开发项目,而不是像 http://127.0.0.1:32721 这样几乎不需要额外设置的情况,请继续阅读!

此工具将围绕 docker-compose 运行,从而可以为您的开发环境添加一些新的功能。

请注意,此脚本需要某些命令的 sudo 权限。

安装

您可以通过 packagist/composer 简单地添加它

composer global require bedezign/dchelper

之后,您可能想在 .bashrc 文件中设置一个别名

alias docker-compose="php ~/.composer/bin/dchelper"

就这么简单!

注意

  • 目前 dchelper 假定每个服务将只有一个实例。它主要用于开发目的,并且直到有人请求对每个服务多个容器的支持,我都不会考虑增加的复杂性。
  • IP 地址和主机名映射目前只适用于第一个找到的 IP 地址(优先考虑别名而不是代理)。

它做什么?

简而言之

  • 为您的项目提供“专用 IP”(而不是 127.0.0.1
  • 无需指定端口
  • 自动创建/维护您的项目的域名。在浏览器中使用 myproject.test 而不是 IP 地址!
  • 轻松“shell”进入容器(使用 docker-compose shell 并在默认容器中获得登录 shell)。
  • 内置对 docker-compose v3.4(或更高版本)配置的帮助(目前有“envsubst”和“scriptrunner”,欢迎提出建议)
  • 所有这些都可以通过环境变量(.env)或 docker-compose.yml 设置来实现。

端口,端口,端口!

当从容器发布端口时,默认情况下,docker VM 将其映射到您的 localhost127.0.0.1)。

如果您未指定远程端口,则不会发生端口冲突,但您最终可能会得到一些晦涩的端口,如 32122。我不知道您的情况如何,但将我的开发站点托管在 http(s)://127.0.0.1:32122 并不觉得合适。即使将它分配给主机,只要总是需要指定端口,它看起来也不会更美观。

另一种选择是将它映射到默认远程端口,但这样您可能会遇到“端口已占用”等问题。

Docker 实际上已经为这个问题提供了解决方案,而 DCHelper 添加了第二种解决方案。

前提是我们可以为每个 docker-compose-project 添加额外的虚拟 IP。这意味着像 80 和 443 这样高度使用的端口始终在“您的”IP 上可用。

操作系统(Linux和macOS)中已经内置了解决方案:允许您向回环网络接口(即IP别名)添加“虚拟”IP。Docker和dchelper都可以使用这项功能来简化您的生活。

远程IP(Docker)

Docker(和Docker Compose)定义端口规范如下:[[remote_ip:]remote_port[-remote_port]:]port[/protocol]

这意味着,当您添加已发布端口时,您还可以指定要添加端口的IP。

container:
  ports:
    - 172.99.0.6:80:80

因此,上述命令告诉Docker将服务端口80链接到IP 172.99.0.6上的端口80(而不是127.0.0.1)。是不是很酷?但是有一个小问题:docker-compose不会将别名IP添加到您的网络接口。

但是dchelper会。

它会在提前解析docker-compose配置(以及找到的.env配置)后,确定需要哪些IP进行别名设置,以使您的配置正常工作。

如果它发现任何尚未存在的IP,它会在传递控制权给docker-compose之前为您注册它们。

使用这项功能很简单:您只需要对配置进行上述示例中所示的修改。

更详细的示例

.env:

COMPOSE_ALIAS_IP=172.99.0.1

docker-compose.yml:

services:
  db:
   ports:
      - ${COMPOSE_ALIAS_IP}:3306:3306
      
  nginx:
    ports:
      - ${COMPOSE_ALIAS_IP}:80:80

通过使用配置值,您在稍后更新IP时不需要做太多工作。因为变量会被docker-compose替换,dchelper仍会检测到实际的IP。

COMPOSE_ALIAS_IP有特殊含义:即使它在您的配置中未进一步使用,dchelper也会始终别名此IP。该变量也用于hosts功能。

这意味着在配置文件中需要稍作修改,但Docker会处理其余部分,不需要外部工具。

TCP代理/隧道(通过socat)

此功能使用socat(SOcket CAT),这是一个非常强大的工具,自称是“多功能中继”。(它可以通过HomeBrew轻松安装在mac上)

对于这个变体,您的端口配置保持不变

container:
  ports:
    - 80

这里的技巧是,您要么添加全局环境变量COMPOSE_PROXY_IP,要么在容器的环境中指定PROXY_IP

container:
  ports:
    - 80
  environment:
    PROXY_IP: 172.99.0.1  

(指定PROXY_IP允许您在设置中使用不同的IP。如果只需要一个IP,全局使用COMPOSE_PROXY_IP。)

在解析配置时,dchelper将检测所有已发布端口及其链接位置。然后,它将启动多个socat实例,在代理IP和随机分配的127.0.0.1上的docker端口之间建立隧道。

最终效果与“远程IP”方法相同,因此取决于您个人的喜好。这里的缺点是,这只能在运行up命令时从容器中分离出来时使用。隧道只能在“up”命令完成后才能建立(容器需要运行以检测配置),而这是在-d选项不使用的情况下不会发生的。

此示例产生相同的结果

.env:

COMPOSE_PROXY_IP=172.99.0.1

docker-compose.yml:

services:
  db:
   ports:
      - 3306
      
  nginx:
    ports:
      - 80

端口330680都将通过172.99.0.1可用。

如前所述:可以使用不同的IP为每个服务,只需使用PROXY_IP即可。

主机名

通过向环境添加COMPOSE_HOSTNAME,您告诉dchelper检查您的/etc/hosts文件,并在必要时添加新条目。使用的IP将是COMPOSE_ALIAS_IP,如果未设置,则为COMPOSE_PROXY_IP

目前没有支持每个服务/容器的特定主机,只有全局主机。 (如果有人请求,我会添加这个功能,目前我没有这个需求)

Shell

DCHelper 添加了一个 shell 命令。例如,通过执行 dchelper shell php,它将在相关容器中触发一个(登录)shell。这实际上会在后台运行 docker exec -it <container> <command>,但你可以指定 compose 服务名称,而不是必须找到 docker 容器名称。

由于 这个问题这个问题(伪终端大小未正确设置的问题),当前默认执行的命令实际上是 '/bin/bash -c "export COLUMNS=`tput cols`; export LINES=`tput lines`; exec bash -l"'

通过在您的环境中使用 COMPOSE_SHELL_DEFAULT=service-name,您可以指定在未指定服务时使用哪个服务。这也可以通过将 SHELL_DEFAULT=1 添加到您的服务环境定义之一来实现。

如果您有一个理解转义序列的终端应用程序(如 iTerm2),DCHelper 还可以为您更改标签页标题。您可以在服务的环境中使用 SHELL_TITLE 为每个服务指定一个标题,或者通过 COMPOSE_SHELL_TITLE 指定全局格式。在这种情况下,{CONTAINER} 将被容器名称替换。

例如:COMPOSE_SHELL_TITLE="${COMPOSE_HOSTNAME: {CONTAINER}"。主机名替换将由 docker compose 处理,{CONTAINER} 将由 DCHelper 替换。

辅助工具

这仅在您使用格式 v3.4 或更高版本的 compose 文件时才有效。这是第一个允许(忽略)特定供应商的根条目(x-...)的版本。

使用辅助工具

单个辅助工具

您可以指定要运行的单个命令。

x-dchelper:
  command:
    configuration...
x-dchelper:
  command:
    configuration...
  command2:   
    configuration...

多个辅助工具

如果您想运行同一个辅助工具多次,您可以添加一些“垃圾”来创建不同的键。

x-dchelper:
  command.serviceone:
    configuration...
  command.servicetwo:   
    configuration...

点后面的内容将被丢弃,所以您可以使用任何您想要的内容。

根目录

您可以将 root 作为辅助工具名称指定,并设置本地系统中每个相对 source/origin 目录的 '基础路径'。

x-dchelper:
  root: /generic/docker/folder/
  envsubst:
    files:
      - nginx.template:./.docker/nginx.conf

这将使用来自 /generic/docker/folder/nginx.template 的模板,并将其存储在 .docker/nginx.conf 相对位置,该位置位于 docker-compose.yml 旁边。它还会在源、目标和根指令中为您转换 ~-条目。

如果您有一个全局的 root 设置,并希望将特定部分的重置为项目目录,只需在该部分中将它设置为空即可。

x-dchelper:
  root: /generic/docker/folder/
  scriptrunner:
    root:
    files:
      - ./script.sh

script.sh 将从工作目录加载,而不是从 /generic/docker/folder

阶段

目前,辅助工具可以在 2 个阶段运行:pre.<command>post.<command>。(例如:在 docker-compose up 命令之前和之后)。通过在配置中指定 at,您可以覆盖此行为。post.up 只能在 up 命令完成后运行,所以如果您没有分离,它只会在您终止容器后运行。其他可能性还包括 pre.shell 等。

EnvSubst

如果您的 compose 项目需要基于您的环境值的配置文件,迄今为止的技巧是在某个地方插入一个 envsubst 调用,以处理这个问题。DCHelper 以原生和简单的方式支持此功能。

重要:辅助工具是以一种方式编写的,它将仅替换环境中已知的内容。这不会触及除了这一点之外的内容。所以 proxy_set_header Host $http_host; 是安全的,只要您没有定义 http_host

注意,这是一个内部功能。您不需要安装 envsubst 命令才能使此功能正常工作。

要生成配置文件,只需添加一个 envsubst 条目。

x-dchelper:
  envsubst:
    environment-file:
      - .env
    environment:
      - nginx
    files:
      - /generic/template/folder/nginx/site-fpm.conf:./.docker/site.conf

默认情况下,这将在 pre.up 下运行。

环境文件

要加载哪些文件作为环境文件。默认情况下(如果未指定),工作目录中的 .env 文件。

环境

要加载的 docker 容器环境。

在示例中,它将使用添加了 nginx 服务的 .env 文件。

文件

要替换的文件列表。源文件(甚至目标文件)不需要在项目目录中。

这允许您创建多个模板,然后在运行 docker-compose up 时为每个项目生成配置。

通过使用多个命令语法,您可以在需要不同环境的情况下多次运行 envsubst

通过将输出文件名前缀以服务名,配置将在相关容器中创建。此路径 必须是绝对路径。使用 docker cp 实现此功能。

上述示例

 x-dchelper:
   envsubst:
     files:
       - /generic/template/folder/aws/credentials.conf:aws-cli:/home/root/.aws/site.conf

dchelper 将确保在需要时为目标文件夹创建文件夹,并将文件复制到其中。

结果

envsubst 辅助程序在所有其他操作之前运行,因此生成的文件可在所有服务中使用

  nginx:
    image: nginx:latest
    volumes:
      - ./.docker/site.conf:/etc/nginx/conf.d/site.conf

ScriptRunner

scriptrunner 允许您在容器中运行 shell 脚本。无论脚本是否映射到容器中,它都将其作为一组 bash 命令执行。

如果没有指定,默认情况下在 post.up 下运行。

示例

x-dchelper:
  scriptrunner:
    service: php
    once:
      - /my/script/dir/php/install_pdo.sh
      - /my/script/dir/php/install_xdebug.sh      

注意,scriptrunner 支持 EnvSubst

此功能对于命令行(始终启用)有效,因此 ${SCRIPT_FOLDER}/script.sh 将有效)。默认情况下,还启用了在脚本内容中替换,但可以通过指定 envsubst: false 来关闭。与 EnvSubst 一样,您还可以指定 environment-fileenvironment-key 以进行更多配置。

服务

要针对哪个服务/容器运行。如果您想在主机本身上运行脚本,请使用 localhost。目前不支持在 localhost 上运行的脚本(仅支持容器)的 once 行为。

锁文件

此文件添加到容器中,用于记住已运行的哪些脚本。由 "once" 命令使用。如果未指定,则默认为 /.dchelper.scripts

once 与 always

您可以在 oncealways 下指定脚本。我想这种差异是显而易见的。

直接

对于在 localhost(与 always)上运行的脚本,您可以指定 direct: true。这强制 dchelper 以 shell 脚本的形式运行,而不是加载其内容并执行。请注意,在这种情况下文件内容的 envsubst 不会像这样工作。由于它在 localhost 上运行,因此您可以在这些脚本上始终使用 .env 文件。

完整示例

以下是一个完整的 docker-compose.yml 示例

version: '3.4'

services:
  php:
    image: php:7-fpm
    volumes:
      - .:/project:rw
    environment:
      - XDEBUG_CONFIG=remote_enable=1 remote_mode=req remote_port=9000 remote_host=172.99.0.100 remote_connect_back=0
      - PHP_IDE_CONFIG=serverName=docker-dev

  nginx:
    image: nginx:latest
    volumes:
      - .:/project:rw
      - ./storage/app/docker/site.conf:/etc/nginx/conf.d/site.conf
    ports:
      - ${COMPOSE_ALIAS_IP}:80:80

  db:
    image: mysql
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: ${DB_DATABASE}
      MYSQL_USER: ${DB_USERNAME}
      MYSQL_PASSWORD: ${DB_PASSWORD}
    volumes:
      - ~/tmp/dev-data/myproject.test/mysql:/var/lib/mysql:rw
    ports:
      - ${COMPOSE_ALIAS_IP}:3306:3306

x-dchelper:
  root: ~/Steve/Development/Docker
  envsubst:
    environment:
      - nginx
    files:
      - nginx/conf/site_php-fpm_php-9000.template:./storage/app/docker/site.conf
  envsubst.aws:
    at: post.up
    files:
      - aws/conf/credentials.template:php:/root/.aws/credentials 
  scriptrunner:
    service: php
    once:
      - debian/scripts/install_aws-cli.sh
      - debian/scripts/install_top.sh
      - debian/scripts/install_ping.sh
      - php/scripts/install_pdo_mysql.sh
      - php/scripts/install_xdebug.sh
      - php/scripts/laravel_artisan_xdebug.sh
      - php/scripts/fpm_reload.sh

.env 的一部分

COMPOSE_ALIAS_IP=172.99.0.1
COMPOSE_HOSTNAME=myproject.test
COMPOSE_SHELL_TITLE="${COMPOSE_HOSTNAME}: {CONTAINER}"

APP_URL=https://${COMPOSE_HOSTNAME}

这样做:此配置将为您提供具有端口号 803306 的可工作的 http://myproject.test。它在一个 3 容器结构上运行,所有容器都使用来自 docker hub 的未修改的镜像。

root 条目表示所有相对 位置都将映射到其中,目标位置不使用此条目。
~ 会对目标和源进行翻译。

注意:如果 root 也是相对路径,则它将以当前工作目录作为其基础(或如果使用 ~,则为主目录)。它可以在本地辅助配置中重写。

这里使用了 2 个 envsubst 命令。

  • nginx-one根据pre.up阶段的配置创建一个本地存储的文件。生成的文件被挂载到nginx容器中,以便在启动时使用。
  • aws-one将直接在容器中创建文件。由于该功能仅在容器启动后才能使用,我们在配置中使用了at: post.up

这也表明,只需追加一些随机的(最好是对你有意义的)内容,就可以使用多个envsubst条目。

scriptrunner命令运行我的某些实用脚本来在容器中安装东西,并跟踪容器内安装了什么。 once表示这些脚本只运行一次,如果尚未在lock-file中找到的话。

由于这些将执行“透传”,你将在控制台看到正在执行的操作,而无需查看容器日志来查看何时完成。(这是我使用替代入口脚本安装东西时个人感到烦恼的事情)。

示例中的APP_URL被添加以表明你还可以在那里重用变量。这里的目的是尽量减少修改以设置新的项目。