Compose: 运行后执行命令

创建于 2015-08-05  ·  131评论  ·  资料来源: docker/compose

你好

在YAML中使用诸如“ onrun”之类的东西在运行后能够运行命令将非常有帮助。 类似于https://github.com/docker/docker/issues/8860

mongodb:
    image: mongo:3.0.2
    hostname: myhostname
    domainname: domain.lan
    volumes:
        - /data/mongodb:/data
    ports:
        - "27017:27017" 
    onrun:
        - mongodump --host db2dump.domain.lan --port 27017 --out /data/mongodb/dumps/latest
        - mongorestore -d database /data/mongodb/dumps/latest/database

mongodb启动后,它将转储db2dump.domain.lan并将其还原。

当我停止然后启动容器时,将不执行onrun部分以保持幂等性。

编辑2020年6月15日

5年后,Compose不想“规范”规格,
请检查https://github.com/compose-spec/compose-spec/issues/84

最有用的评论

因此,要管理我的泊坞窗,您建议我使用脚本或Makefile。 那么为什么要创建compose
? 我们可以使用脚本||管理,缩放等容器。 dockerfile?

好的,我以这个示例为例,它就是我用来在CI流程中部署应用程序测试环境的工具。

rabbitmq:
    image: rabbitmq:3.5.1-management
    environment:
        RABBITMQ_NODENAME: rabbit
    hostname: rabbitmq
    domainname: domain.lan
    volumes:
        - /data/rabbitmq/db:/var/lib/rabbitmq
    ports:
        - "5672:5672" 
        - "15672:15672"
        - "25672:25672"
        - "4369:4369"

mongodb:
    image: mongo:3.0.2
    hostname: mongo
    domainname: domain.lan
    volumes:
        - /data/mongodb:/data
    ports:
        - "27017:27017" 

appmaster:
    image: appmaster
    hostname: master
    domainname: domain.lan
    environment:
        ...
    ports:
        - "80:80" 
        - "8080:8080"
    links:
        - mongodb
        - rabbitmq

celery:
    image: celery
    hostname: celery
    domainname: domain.lan
    environment:
        ...
    links:
        - rabbitmq

容器启动后,我必须配置mongodb,在Rabbitmq中管理队列和帐户

我今天正在做的是一个包含以下内容的脚本:

#!/bin/bash
PROJECT=appmaster
docker-compose -f appmaster.yml -p appmaster up -d
docker exec appmaster_rabbitmq_1 rabbitmqctl add_user user password
docker exec appmaster_rabbitmq_1 rabbitmqctl add_vhost rabbitmq.domain.lan
docker exec appmaster_rabbitmq_1 rabbitmqctl set_permissions -p rabbitmq.domain.lan password ".*" ".*" ".*"
docker exec appmaster_mongodb_1 mongodump --host mongo-prd.domain.lan --port 27017 --out /data/mongodb/dumps/latest
docker exec appmaster_mongodb_1 mongorestore -d database /data/mongodb/dumps/latest/database

使用onrun指令,我可以直接制作docker-compose -f appmaster.yml -p appmaster up -d
并且yml文件更具可读性

rabbitmq:
    ...
    onrun:
        - rabbitmqctl add_user user password
        - rabbitmqctl add_vhost rabbitmq.domain.lan
        - rabbitmqctl set_permissions -p rabbitmq.domain.lan password ".*" ".*" ".*"

mongodb:
    ...
    onrun:
        - mongodump --host mongo-prd.domain.lan --port 27017 --out /data/mongodb/dumps/latest
        - mongorestore -d database /data/mongodb/dumps/latest/database

所有131条评论

我认为这些应该是Dockerfile中的步骤

FROM mongo:3.0.2
ADD data/mongodb/dumps/latest /data/mongodb/dumps/latest
RUN mongorestore -d database /data/mongodb/dumps/latest/database

这样,您也可以在重建时将其缓存。

谢谢@dnephin。
当然,我可以制作一个Dockerfile并在构建中使用它而不是映像,或者可以使用docker exec。
MongoDB只是一个示例,您可以在此示例中使用mysql和帐户创建,或者在Rabbitmq和队列创建等中使用。

onrun将允许灵活地编排业务流程,compose将读取运行清单并在每个项目上制作docker exec

关键是,当您可以在Dockerfile或容器的启动脚本中将命令放入docker-compose.yml docker exec ,这是不必要的,当_not_时,这两种方法也将使您的容器更有用与Compose一起运行。

或者,使用运行适当的dockerdocker-compose命令的Shell脚本或Makefile启动应用程序。

该功能不值得添加到Compose中,除非它会比做任何一个都增加可观的价值,而且我认为对于您引用的用例来说,它不会。

因此,要管理我的泊坞窗,您建议我使用脚本或Makefile。 那么为什么要创建compose
? 我们可以使用脚本||管理,缩放等容器。 dockerfile?

好的,我以这个示例为例,它就是我用来在CI流程中部署应用程序测试环境的工具。

rabbitmq:
    image: rabbitmq:3.5.1-management
    environment:
        RABBITMQ_NODENAME: rabbit
    hostname: rabbitmq
    domainname: domain.lan
    volumes:
        - /data/rabbitmq/db:/var/lib/rabbitmq
    ports:
        - "5672:5672" 
        - "15672:15672"
        - "25672:25672"
        - "4369:4369"

mongodb:
    image: mongo:3.0.2
    hostname: mongo
    domainname: domain.lan
    volumes:
        - /data/mongodb:/data
    ports:
        - "27017:27017" 

appmaster:
    image: appmaster
    hostname: master
    domainname: domain.lan
    environment:
        ...
    ports:
        - "80:80" 
        - "8080:8080"
    links:
        - mongodb
        - rabbitmq

celery:
    image: celery
    hostname: celery
    domainname: domain.lan
    environment:
        ...
    links:
        - rabbitmq

容器启动后,我必须配置mongodb,在Rabbitmq中管理队列和帐户

我今天正在做的是一个包含以下内容的脚本:

#!/bin/bash
PROJECT=appmaster
docker-compose -f appmaster.yml -p appmaster up -d
docker exec appmaster_rabbitmq_1 rabbitmqctl add_user user password
docker exec appmaster_rabbitmq_1 rabbitmqctl add_vhost rabbitmq.domain.lan
docker exec appmaster_rabbitmq_1 rabbitmqctl set_permissions -p rabbitmq.domain.lan password ".*" ".*" ".*"
docker exec appmaster_mongodb_1 mongodump --host mongo-prd.domain.lan --port 27017 --out /data/mongodb/dumps/latest
docker exec appmaster_mongodb_1 mongorestore -d database /data/mongodb/dumps/latest/database

使用onrun指令,我可以直接制作docker-compose -f appmaster.yml -p appmaster up -d
并且yml文件更具可读性

rabbitmq:
    ...
    onrun:
        - rabbitmqctl add_user user password
        - rabbitmqctl add_vhost rabbitmq.domain.lan
        - rabbitmqctl set_permissions -p rabbitmq.domain.lan password ".*" ".*" ".*"

mongodb:
    ...
    onrun:
        - mongodump --host mongo-prd.domain.lan --port 27017 --out /data/mongodb/dumps/latest
        - mongorestore -d database /data/mongodb/dumps/latest/database

这将非常有用,并且可以解决用例。

:+1:

作为CD管道的一部分,它将使docker-compose更有可能用于门控测试

:+1:

这是#877,#1341,#468(和其他几个)的重复。

我认为支持此功能的正确方法是#1510,并在遇到所需事件时允许外部工具执行操作。

重复结束

这将非常有用。 我不明白“哦,您可以使用bash脚本来做到这一点”的说法。 当然,我们可以使用bash脚本来实现。 我还可以使用bash脚本来完成Docker-compose所做的一切。 但要点是,只有一个YAML文件可控制您的测试环境,并且可以使用简单的docker-compose up命令将其启动。

用Shell脚本或Makefile来完成_everything_并不是Compose的职责-我们必须在某处画一条线,以在有用性和避免膨胀之间取得平衡。

此外,Compose文件的一个重要属性是,它可以在各种机器(甚至Mac,Linux和Windows机器)之间移植。 如果我们允许人们在Compose文件中放置任意的shell命令,那么他们的可移植性将大大降低。

@aanand坦白地说,能够执行docker exec并不自动意味着x平台不兼容。

抱歉-我误解了此问题,因为它与在主机上执行命令有关。 尽管如此,我的第一点仍然是正确的。

我明白你的意思@aanand。 在我看来,这似乎并不超出范围,因为docker-compose已经完成了与常规docker引擎已经完成的很多事情,例如commandexposeportsbuild等。添加exec功能将为docker-compose增加更多功能,使其真正成为一站式设置商店开发环境。

@aanand许多开发人员和CI管道的主要问题是拥有非常接近生产环境的数据。 就像从数据库转储一样。 我在1年前创建了这张票,但docker compose中没有任何变化。

因此,您建议使用Makefile或Bashcript来运行某些exec https://github.com/docker/compose/issues/1809#issuecomment -128073224

我最初建议的是保持幂等的onrun (或oncreate)。 只需在第一次启动时运行即可。 如果容器已停止或暂停,则新的启动将不会在运行(或oncreate)时运行

最后,在我的git仓库中,我将有一个撰写文件,一个dockerfile和一个具有幂等性管理的makefile(可能makefile可以创建一个statefile)。 天才!

commandexpose等与exec之间有很大的区别。 第一组是容器选项, exec是命令/ api端点。 这是一个单独的函数,不是create container函数的选项。

已经有几种方法可以使用Compose(https://github.com/docker/compose/issues/1809#issuecomment-128059030)来完成此任务。 onrun已经存在。 它是command

关于从数据库中转储或加载数据的特定问题,这些是更多的“工作流”或“构建自动化”类型的任务,通常在Makefile中完成。 我一直在为名为dobi的那些用例

@dnephin onrun不是简单的command因为您只是错过了幂等性。

想象一下。 create用于创建容器,以后将不再执行(转储和还原)。

exec:
    create:
        - echo baby
    destroy:
        - echo keny
    start:
        - echo start
    stop:
        - echo bye

如果您需要更多示例:

感谢dobi,但是如果您需要创建一个工具来增强撰写,那么撰写就不好了,最好使用功能更强大的工具。

但是如果您需要创建一个工具来增强撰写,那么撰写就不好了,最好使用功能更强大的工具。

这就像在说:“如果您需要应用程序来增强操作系统,那么您的操作系统就不好了”。 没有一种工具可以做所有事情。 Unix的哲学是做一件事,并且做好。 这就是我们在这里所做的。 Compose做其一件事“协调用于运行应用程序的容器”。 它不是构建自动化工具。

这就像在说:“如果您需要应用程序来增强操作系统,那么您的操作系统就不好了”。 没有一种工具可以做所有事情。 Unix的哲学是做一件事,并且做好。 这就是我们在这里所做的。

哇,我认为我们达到了最佳的恶意。

不幸的是,一个简单的可重用组件并不是事情的进展。 Docker现在正在构建用于启动云服务器,用于集群的系统以及多种功能的工具:构建映像,运行映像,上传,下载甚至最终覆盖网络,所有这些都编译成一个整体二进制文件,主要作为服务器上的根目录运行。 标准容器清单已删除。 我们应该停止谈论Docker容器,而开始谈论Docker平台。 它并没有成为我们所设想的简单的可组合构建块。

因此,您可以保证我们永远不会在Docker整体二进制文件的Go inside中看到“ docker compose”字样来保持unix的哲学? https://www.orchardup.com/blog/orchard-is-joining-docker

为了继续实现最初的目标,我们加入了Docker。 除其他事项外,我们将继续努力使Docker成为您见过的最佳开发体验–既与Fig结合,又将Fig的最佳部分整合到Docker本身中。

简而言之,没有办法执行诸如通过compose ..加载灯具的事情。 我不得不说我很惊讶。
官方的方法是向我的生产容器中添加夹具负载? 还是在撰写文件周围编写Shell脚本? 在后一种情况下,我也可以像以前一样执行“ docker run”。

@discordianfish ,如果有人以某种方式醒来,CI / CD工程师需要至少能够在一个非常基本的水平上处理生命周期事件和编排的事实,那么知道docker / docker-compose的人可能会真正做到这一点。摆脱本地开发管道和测试基础架构的局限,并在更多生产环境中找到一席之地。 我希望在堆栈上工作的任何人都能解决这些问题,但是我不会屏住呼吸。

毕竟,在构建时需要完成的工作可能与运行时所需要的有所不同,并且运行时所需要的时间通常会因部署环境而异...

使我的外部脚本意识到up将要创建还是启动容器是一件令人烦恼的工作...

这些都是一些生命周期挂钩+命令+环境变量可以帮助的。

您可以在服务管理框架和其他编排工具中看到它...为什么不在docker-compose中看到它?

您可能对https://github.com/dnephin/dobi感兴趣,这是我一直在使用的针对这些工作流程设计的工具。

@dnephin停止使用您的工具发送此问题。 我们之前看到过您的评论,答案是相同的。 Makefile / bash可能比第n个“我的工具增强d​​ocker”更好。

感谢您的建设性评论。 我没有意识到,八个月前我已经在该线程上提到过dobi。

如果您对Makefile / bash感到满意,那就太好了! 很高兴您的问题已解决。

在此处添加了与此主题相关的评论: https :

@dnephin对此,我的评论可以应用:

遗憾的是,由于对进化论的某些抵触,这个问题已被关闭:失望:

泊坞窗组成的最大价值是标准化

这才是重点。 如果我们可以不使用Docker Compose来“只是”编写.sh文件或执行工作,那么为什么Docker Compose存在呢? :困惑:

我们可以理解,这是一项艰巨的工作,如@ shin-所说:

不幸的是,在项目的那个阶段,要负担太多的负担

:心:

但是您不能说“制作脚本”的意思是“嘿,太难了,我们不会成功”。

如果很难做到,只需说“您的想法很有趣,它可以满足一些需求,但确实很难做到,我们目前没有资源来做……也许您可以发展它并询问拉请求”或类似的东西:bulb:

在#1341中,我“仅”看到一种写入docker-compose.yml命令(如nmp install ,该命令将在某些事件(例如容器创建)之前或之后运行,就像对docker exec <container id> npm install例如

用例

我有一个自定义的NodeJS映像,我想在从其创建的容器中运行npm install ,并带有一个docker-compose up --build

我的问题是:应用程序代码未添加到容器中,而是通过docker-compose.yml定义的卷装入其中:

custom-node:
    build: ../my_app-node/
    tty: true
    #command: bash -c "npm install && node"
    volumes:
     - /var/www/my_app:/usr/share/nginx/html/my_app

所以我不能在Dockerfile中运行npm install ,因为它需要应用程序代码来检查依赖关系。 我在这里描述了行为: http :

要运行npm install ,我必须使用一种变通方法,即command语句:

command: bash -c "npm install && node"

这不是很干净:失望:而且我不能在Alpine版本上运行(它们没有安装Bash)。

我认为Docker Compose将提供一种在eG容器上运行exec命令的方法:

custom-node:
    build: ../my_app-node/
    tty: true
    command: node
    volumes:
     - /var/www/my_app:/usr/share/nginx/html/my_app
    exec:
     - npm install

但事实并非如此,我认为它确实缺失了!

我期望compose是为测试而设计的,但我可能错了,它打算更多地用于本地开发等。我遇到了其他一些粗糙的问题,例如孤立的容器以及项目名称,路径以及如何使用它来标识所有权之间的不清楚的关系,如果您在同一目录等中有多个撰写文件,将会发生什么情况。因此,总的来说,这似乎不太适合CI。
相反,我计划通过独立运行kubelet在CI中重用我的生产k8s清单。 这也将需要大量胶水,但是至少通过这种方式,我可以对dev,test和prod使用相同的声明。

@ lucile-sticky,您可以在高山地区使用sh -c

听起来您想要的是“构建自动化”,这不是docker-compose的角色。 你看过dobi吗?

两个问题:

  • 为什么这不是Docker Compose的角色?
  • 如果要只用一种工具来统治所有任务,为什么我要用另一种工具来完成Docker Compose无法完成的任务?

非常需要此功能!

@ lucile-sticky

为什么这不是Docker Compose的角色?

因为Compose的角色是明确定义的,并且不包括那些功能。

Compose是用于定义和运行多容器Docker应用程序的工具。 通过Compose,您可以使用Compose文件配置应用程序的服务。 然后,使用一个命令,从您的配置中创建并启动所有服务

如果要只用一种工具来统治所有任务,为什么我要用另一种工具来完成Docker Compose无法完成的任务?

我们不想成为统治所有人的一种工具。 我们遵循UNIX的理念,坚信“使每个程序都做得很好。要完成一项新工作,请重新构建而不是通过添加新功能来使旧程序复杂化。”
可以同意这种哲学,但是这就是我们Docker开发软件的方式。

我创建了这个问题,2015年8月,每年都有人发表评论,我们在相同的问题上使用相同的答案(当然,您会看到@dnephin为他的工具制作广告)。

@胫-

您无法在业务流程工具中分离“构建”和“供应”。

例如,您可能认识其中之一:

  • cloudformation: http ://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-init.html
  • 热度: https: //docs.openstack.org/developer/heat/template_guide/software_deployment#configuring -with-scripts
  • terraform: https

配置服务时,您必须对其进行配置。 如果部署了tomcat,则必须为其进行准备,如果创建DB,则必须注入数据等。无论必须如何启动容器(让图像维护者对其进行管理)。 在Compose案例中,“供应商”的主要目的是避免对“什么启动我的容器”和“什么提供它”之间的误解。

就像在撰写文档中所说的那样:“使用Compose,您可以使用Compose文件配置应用程序的服务。然后,使用一个命令,从配置中创建并启动所有服务”

Unix哲学? 让我笑了。 我向您指出了我在此问题中所做的相同答案https://github.com/docker/compose/issues/1809#issuecomment -237195021。
让我们看看“ moby”将如何在Unix哲学中发展。

@ shin- docker-compose完全不符合Unix哲学。 如果docker-compose遵循Unix Philosophy,则对于构建,启动,rm,启动,停止等每个命令都有离散的命令,并且每个命令都有行为稳定的可用stdin,stdout和stderr。 unix sysadmin拥有20多年的经验,包括System V,HP-UX,AIX,Solaris和Linux

让我们回到概述

Compose是用于定义和运行多容器Docker应用程序的工具。 通过Compose,您可以使用Compose文件配置应用程序的服务。 然后,使用单个命令,从您的配置中创建并启动所有服务。

最终,docker-compose是一个编排工具,用于根据从docker映像创建的容器管理一组服务。 它的主要功能是在docker-compose.yml文件中定义的“创建”,“开始”,“停止”,“缩放”和“删除”服务。

在每个生命周期过渡期间,许多服务都需要运行其他命令。 扩展数据库集群通常需要加入集群或从集群中删除成员。 扩展Web应用程序通常需要通知负载均衡器您已添加或删除成员。 一些偏执的系统管理员喜欢在关闭数据库时强制刷新数据库日志并创建检查点。

对于大多数业务流程工具而言,必须对状态转换采取措施。 您会在AWS的工具,Google的工具,领班,厨师等中找到它。这种编排空间中的大多数事物都有某种生命周期挂钩。

我认为这绝对是docker-compose的职责范围,因为它是一个编排工具并且知道状态变化。 我觉得事件或外部脚本不适合用例。 它们不是幂等的,要在事件发生之后编写“第二”服务要困难得多。 挂钩是在容器内部运行还是在容器外部运行都是实现细节。

归根结底docker -compose和@ dnephin ,@ shin-用户似乎表达了一种真正的需求。 希望将其包括在路线图中。

目前,这种功能正在阻止我在测试和生产生产部署中采用docker。 我真的很想看到以某种方式解决此问题,而不是将其驳回。

我认为这将非常有用!

对我来说,问题是当有一个应用程序容器A正在运行服务“ a”依赖于数据库容器B正在运行服务b时。 然后,除非设置了容器b,否则容器将失败。
我宁愿使用docker hub映像,而不是重写自己的Dockerfile。 但这意味着A失败,并且没有创建容器。 否则唯一的选择是

  1. 使用B作为基本映像并创建我自己的Dockerfile。
  2. 让A失败并在脚本中配置b并重新启动A。

我的使用案例与@ lucile-sticky完全相同。

@lekhnath对于我的情况,我通过在docker-compose.yml编辑command选项来解决:

command: bash -c "npm install && node"

TT太丑了

@ lucile-sticky应该注意的是,这会推翻容器Dockerfile中设置的任何命令。 我通过使用volumes安装自定义外壳程序脚本来解决此问题,使Docker Compose文件中的command运行该脚本,并在其中包含来自Dockerfile的原始CMD Dockerfile

为什么关闭此问题? _写一个bash脚本_或_使用我写的此工具不是关闭此问题的有效理由。

这是一个非常有用且重要的功能,在使用组合的许多用例中都是必需的。

@dnephin您是否认为运行初始化脚本超出了基于容器的应用程序部署范围? 毕竟,撰写是关于“使用Docker定义和运行多容器应用程序”。

如果没有,请有人看着dobi,在这里:)
image

猜测没有任何事情发生。 我很乐意在docker-compose文件中看到某种功能,在这里我们可以写出执行命令的时间,例如@ ahmet2mir给出的示例。

很遗憾地看到这个功能没有得到执行。

请实施此功能,我需要在docker-compose之后自动安装文件,因为必须在初始化容器之后创建必须复制文件的文件夹。
谢谢

令人难以置信的是,尚未实现此功能!

@dnephin是非常差的形式。 您已禁止实施似乎广为人知的自我推广功能,因此您甚至不愿继续对话。

抱歉,我想不出一种更温和的语言,与许多其他开发人员和团队一样,缺少此功能为我们的工作流程增加了一部分,而您却一直无法解决此问题。

哦,那就让它成为unix-way
_Just_(然后是多路复用)将docker-compose up stdin管道传输到每个容器的CMD吗?
这样的yaml文件

services:
  node:
    command: sh -

将使这项工作: cat provision.sh | docker-compose up
容器用于执行操作,我认为没有比传递命令更好的使用stdin了。

替代方法可以是:

services:
  node:
    localscript: provision.sh

尽管以外壳程序为中心,但可以解决99%的配置用例。

即使有有效的用例,对此也有很多支持……显然,它仍然被拒绝。 我和这里的许多其他人一样,感到羞耻会发现这非常有用。

将我的+1添加到现有+的大堆栈中

...这里还有+1!

我认为,如果对此功能有这样的要求,则应予以实施,这里有工具可以帮助我们实现目标,我们应该塑造它们,以帮助我们不让生活变得更艰难。
我了解有人坚持的哲学,但是添加某种“挂钩命令”应该不是问题。

+1 +1

在等待此功能时,我使用以下脚本执行类似的任务:

docker-start.sh

#!/usr/bin/env bash

set -e
set -x

docker-compose up -d
sleep 5

# #Fix1: Fix "iptable service restart" error

echo 'Fix "iptable service restart" error'
echo 'https://github.com/moby/moby/issues/16137#issuecomment-160505686'

for container_id in $(docker ps --filter='ancestor=reduardo7/my-image' -q)
  do
    docker exec $container_id sh -c 'iptables-save > /etc/sysconfig/iptables'
  done

# End #Fix1

echo Done

@ reduardo7然后,您最好完全放弃

@omeid ,你是对的! 这是执行类似任务的解决方法,抱歉!

@ reduardo7无需道歉,您发布的内容可能对某些人有用。
我只是指出原始问题仍然存在,不应该关闭。 :)

我了解@dnephin的立场,可以用足够不同的功能替换此处提到的功能。

但是,如果经常使用这种模式,那么如何提供一个指南(或一些测试),以便其他人可以轻松使用它呢?

对于这种模式可以经常使用似乎没有分歧。

@MaybeS唯一的不同是@dnephin宁愿看到他的dopey工具得到提升,而不是帮助使docker-compose一个更好的产品。

@omeid是的。

今天的例子,想要一种方法来做某种形式的onrun

version: "3.3"
services:
  gitlab:
    image: 'gitlab/gitlab-ce:latest'
    restart: always
    hostname: 'gitlab'
    environment:
      GITLAB_OMNIBUS_CONFIG: |
        # NOTE: this URL needs to be right both for users, and for the runner to be able to resolve :() - as its the repo URL that is used for the ci-job, and the pull url for users.
        external_url 'http://gitlab:9090'
        gitlab_rails['gitlab_shell_ssh_port'] = 2224
    ports:
      - '9090:9090'
      - '2224:22'
  gitlab-runner:
    image: gitlab/gitlab-runner:latest
    volumes:
    - /var/run/docker.sock:/var/run/docker.sock

当然,跑步者未注册-为此,我们需要

  1. 将令牌从gitlab中的数据库中拉出
  2. 在流道容器中运行寄存器

因此,除了使用docker-compose定义多容器应用程序的部署之外,我还需要使用一些辅助手段-在这种情况下...文档?

export GL_TOKEN=$(docker-compose exec -u gitlab-psql gitlab sh -c 'psql -h /var/opt/gitlab/postgresql/ -d gitlabhq_production -t -A -c "SELECT runners_registration_token FROM application_settings ORDER BY id DESC LIMIT 1"')
docker-compose exec gitlab-runner gitlab-runner register -n \
  --url http://gitlab:9090/ \
  --registration-token ${GL_TOKEN} \
  --executor docker \
  --description "Docker Runner" \
  --docker-image "docker:latest" \
  --docker-volumes /var/run/docker.sock:/var/run/docker.sock \
  --docker-network-mode  "network-based-on-dirname-ew_default"

嗯,我也许可以破解一些东西,从而使我有另一个带有docker socket的容器​​,以及docker exec's

有什么办法可以赌....

例如,我可以添加:

  gitlab-initializer:
    image: docker/compose:1.18.0
    restart: "no"
    volumes:
    - /var/run/docker.sock:/var/run/docker.sock
    - ./gitlab-compose.yml:/docker-compose.yml
    entrypoint: bash
    command: -c "sleep 200 && export GL_TOKEN=$(docker-compose -p sima-austral-deployment exec -T -u gitlab-psql gitlab sh -c 'psql -h /var/opt/gitlab/postgresql/ -d gitlabhq_production -t -A -c \"SELECT runners_registration_token FROM application_settings ORDER BY id DESC LIMIT 1\"') && docker-compose exec gitlab-runner gitlab-runner register -n --url http://gitlab:9090/ --registration-token ${GL_TOKEN} --executor docker --description \"Docker Runner\" --docker-image \"docker:latest\" --docker-volumes /var/run/docker.sock:/var/run/docker.sock --docker-network-mode  \"simaaustraldeployment_default\""

到我的撰写文件-尽管我需要某种循环/等待,因为gitlab尚未立即准备就绪- sleep 200可能还不够。

所以-您__can__可以直接在docker-compose.yml破解类似的模式-但就我个人而言,我更愿意提供一些更清洁的支持:

@SvenDowideit onrun已经存在,它是entrypointcmd

该映像的入口点脚本甚至为您提供了一个挂钩。 可以将$GITLAB_POST_RECONFIGURE_SCRIPT设置为在所有设置完成后将运行的脚本的路径(请参见图中的/assets/wrapper )。 将env变量设置为执行psql + register的脚本的路径,一切就绪。

即使图像没有提供此挂钩,也可以通过扩展图像相当容易地添加它。

尽管我需要某种循环/等待,因为gitlab尚未立即准备就绪-睡眠200可能还不够。

即使使用“启动后执行”选项,这也将是必要的。 由于入口点脚本实际上提供了一个挂钩,我认为该解决方案可能没有必要。

不,我(认为)您错过了我所显示的部分问题:

就我而言,我需要访问两个容器,而不仅仅是一个容器-所以入口点/命令确实不会给我这个。

GL_TOKEN来自gitlab容器,然后在gitlab-runner容器中使用进行注册。

所以我正在做的黑客操作是使用docker/compose图像添加第三个容器-这不是您可以修改一个容器的config / entrypoint / settings的东西,而这完全是一个(简单的)示例需要更多的多容器协调。

我一直在努力使它们变得更加神奇-这基本上意味着我的初始化容器具有一些睡眠循环,因为gitlab本身需要一些时间来初始化。

TBH,我开始感到使用脚本运行在使用组合文件本身和docker / compose映像的init容器中,_is_是隐藏这种复杂性的正确方法-对于非生产“尝试我出去,它就会工作”这样的情况。

_IF_我正在考虑使用一些怪异的语法糖来帮助您,也许我会选择类似的东西:

gitlab-initializer:
    image: docker/compose:1.18.0
    restart: "no"
    volumes:
    - /var/run/docker.sock:/var/run/docker.sock
    - ./gitlab-compose.yml:/docker-compose.yml
    entrypoint: ['/bin/sh']
    command: ['/init-gitlab.sh']
    file:
      path: /init-gitlab.sh
      content: |
            for i in $(seq 1 10); do
                export GL_TOKEN=$(docker-compose -f gitlab-compose.yml -p sima-austral-deployment exec -T -u gitlab-psql gitlab sh -c 'psql -h /var/opt/gitlab/postgresql/ -d gitlabhq_production -t -A -c "SELECT runners_registration_token FROM application_settings ORDER BY id DESC LIMIT 1"')
                echo "$i: token($?) == $GL_TOKEN"
                ERR=$?

                if [[ "${#GL_TOKEN}" == "20" ]]; then
                    break
                fi
                sleep 10
            done
            echo "GOT IT: token($ERR) == $GL_TOKEN"

            for i in $(seq 1 10); do
                if  docker-compose -f gitlab-compose.yml  -p sima-austral-deployment exec -T gitlab-runner \
                    gitlab-runner register -n \
                    --url http://gitlab:9090/ \
                    --registration-token ${GL_TOKEN} \
                    --executor docker \
                    --description "Docker Runner" \
                    --docker-image "docker:latest" \
                    --docker-volumes '/var/run/docker.sock:/var/run/docker.sock' \
                    --docker-network-mode  "simaaustraldeployment_default" ; then
                        echo "YAY"
                        break
                fi
                sleep 10
            done

即,就像cloud-init: http :

但是归根结底,我们有一个从docker-compose-yml内部协调复杂的多容器事物的解决方案。

如果您能够设置预定义的令牌,则可以从gitlab-runner的入口点脚本中进行设置。 没有办法设定时间吗?

@dnephin在您提到脚本的那一刻,您已经走了很差一点了。

onrunentrypointcmd

entrypoint / cmd用于配置将作为容器init / PID 1运行的可执行文件。

在此及许多相关问题中提到的想法大约是init scripts ,它在引导的上下文中与init不同,并且是关于应用程序初始化脚本,数据库设置的。

@dnephin ,如果您专注于一般问题集,而不是尝试解决特定容器集的问题,它可能会更有用。

从我所看到的,不,这是一个秘密,但是,实际上,即使在这种小型游戏系统中,这也不是唯一的多容器协调要求,这对我来说是最快的在公共场合原型。

这怎么可能,我们已经能够覆盖entrypointcommand以来V1一个撰写文件(https://docs.docker.com/compose/compose-file/compose-file -v1 /#entrypoint),并且还没有onrun的指令来在容器启动时运行命令?

TBH,我真的不认为onrun是合理的-Docker,或者协调器不知道“容器全部装满”是什么意思-在我的一种情况下,HEALTHCHECK将失败,直到我这样做一些额外的“东西”,我从一个容器中获取信息,并用它来踢其他容器中的其他东西。

如果我正确,这意味着我基本上需要一个Operator容器,该容器包含用于检测多容器系统的某些部分何时准备就绪以完成某些工作(漂洗和重复)的代码,直到它要么完成工作并退出,要么监视并修复它们。

在我看来,这是最理想的工作(在docker-compose中)是通过带有代码的docker-compose容器解决的。

我可能会研究如何将该运算符转换为可以处理docker swarm堆栈的对象(由于其他项目需求)。

我不完全确定可以在docker-compose中添加很多语法糖,除非它像将容器标记为“这是一个运算符,赋予它神奇的能力”之类。

很明显,开发人员不想听用户的声音。.我将看一下其他工具... docker-compose是一件很痛苦的事。.我不明白为什么您不明白那唯一有用的东西来自docker-composer的构建工具...我花了很多时间搜索如何运行SIMPLE命令将容器内部的权限添加到活动用户。

似乎docker-composer只是处于NOT DONE状态...

我也想要在撰写文件中有onrun东西

__但__,容器和组合都没有办法知道onrun含义。 这就是为什么存在运算符模式的原因,也是我在https://github.com/docker/compose/issues/1809#issuecomment -362126930中创建示例的原因

今天有可能做到这一点-本质上,您添加了一个onrun服务,该服务等到其他任何服务都准备好与之交互(在gitlab的情况下,这会花费很多时间),然后执行您需要做的任何事情来协调事情。

如果有不起作用的地方,请告诉我们,我们将看看是否可以解决!

我也想要一些可以在撰写文件中运行的内容

但是,容器和组合都没有办法知道onrun的含义。

如我所见,每个服务onrun表示第一个容器进程何时开始。 在很多情况下,容器无论如何都只运行一个进程,因为这是运行容器的推荐方法。

跨平台支持的问题早已解决,因为该命令可以通过docker exec完全与操作系统无关,就像RUN在Dockerfile中不必表示linux命令一样。
https://docs.microsoft.com/zh-cn/virtualization/windowscontainers/manage-docker/manage-windows-dockerfile

仍在等待onrun功能

我也需要这个onrun功能,我以为它在此工具中。 由于缺少此功能,我现在需要维护2个脚本人。

伙计们,如果我在此docker-compose周围做一个包装并允许此onrun功能怎么办? 你们会用吗?

@wongjiahau可能是这样的吗? https://github.com/docker/compose/issues/1809#issuecomment -348497289

@ reduardo7是的,我想到了将其包装在名为docker-composei的脚本中,并使用docker-composei.yml包含onrun属性。
顺便说一句, docker-composei表示docker-compose improved

真正的解决方案可能是构建一个“ Orchestrator”映像,该映像在内部运行和管理(通过bash脚本)“ App Images”(可能使用docker)。 否则,我们将一直要求为该工具提供更多功能,这些功能“并非旨在实现我们想要的功能”。

所以我们甚至应该考虑Docker中的Docker ...

只是为了添加我对此提议功能的支持。 onrun确实是有道理的,但是要扩大潜在的实用性并进一步证明它的未来,也许有人需要研究更广泛的“ onevent”架构,其中一个将处于运行状态。

考虑到容器的独立包装的主流方向,即每个容器提供一种服务,就其运行环境意识而言,容器必须自给自足。 该组合文件的内容应该是定义该文件的媒介,而不是附加脚本。 很难反驳,除非你是一些自我吸收的狂热者。

在我的情况下,我的redis容器在redis服务器启动后会加载lua脚本。 在正常的非容器环境中,我可以通过systemd运行启动后脚本。 简单且与系统架构一致。 考虑到它在设置容器运行上下文中的作用,应该存在类似的原理。

作为对维护人员的一般建议,请专注于经过验证的操作原则,而不是个人喜好。

所以解决方案(在阅读了所有这些线程之后)是使用bash脚本来完成这项工作...在这种情况下,我将删除docker-compose(我们可以使用docker cmd进行所有操作...)

thx开发者倾听正在使用您的东西的人:)

通过观察含论据和反驳战斗简单命题的邮件数量(例如具有onrun事件),我的第一个诚实的印象是,Github上的问题已经变成是其中_owners_(项目开发商)采用的方式展示他们的自尊心和机智的地方他们的知识和技术氩气反对用户的明智贡献。

请让我们真正实现_open_。

此功能有任何更新吗? 问题是什么?

@ v0lume我猜您实际上并没有在阅读本文中的回复

似乎仍然没有解决方案……不过,我想分享一个解决方法。
通过在docker-compose.yml中指定版本“ 2.1”,您可以滥用运行状况检查测试以在映像启动时在映像内运行其他代码。 这是一个例子:

version: '2.1'
services:
    elasticsearch:
        image: docker.elastic.co/elasticsearch/elasticsearch:5.4.3
        healthcheck:
            test: |
                curl -X PUT elasticsearch:9200/scheduled_actions -H "ContentType: application/json" -d '{"settings":{"index":{"number_of_shards":'1',"number_of_replicas":'0'}}}' &&
                curl --silent --fail localhost:9200/_cat/health ||
                exit 1
            interval: 11s 
            timeout: 10s 
            retries: 3
        environment:
            - discovery.type=single-node
            - ES_JAVA_OPTS=-Xms1g -Xmx1g
            - xpack.security.enabled=false
    main:
        image: alpine
        depends_on:
            elasticsearch:
                condition: service_healthy

如果您编写的运行状况检查测试脚本的代码> = 1退出,则可能会多次执行。
仅当另一个服务依赖于该服务并指定service_healthy条件时,才会执行该服务的运行状况检查,如示例所示。

我喜欢@ T-vK方法,以前已经成功使用过它。 但我想分享另一个... hack:

# Run Docker container here

until echo | nc --send-only 127.0.0.1 <PORT_EXPOSED_BY_DOCKER>; do
  echo "Waiting for <YOUR_DOCKER> to start..."
  sleep 1
done

# Do your docker exec stuff here

+1
我完全同意这一点,因为该功能是必需的,并且它已经由kubernetes等其他docker Orchestrators实现。 它已经具有用于容器的生命周期挂钩,并在此处进行了说明

但是,让我贡献一个用Dockerfile无法解决的用例。

假设您需要在运行时挂载卷,并创建一个从容器到该卷的符号链接,而无需事先知道该目录的确切名称。 我遇到了一个问题,它的目录名是动态的,具体取决于部署的环境,并将其作为变量传递。

当然,我找到了一种解决方法来解决此问题,并且不止一个。 另一方面,钩子可以为我提供灵活性和更好的方法来动态地进行更改,而无需冲动事物​​和替换Dockerfile的冲动。

很高兴发现这个问题。 几年来,我一直在玩弄Docker和Docker Compose。 现在认真地希望将其用作开始扩展系统的工具。 我将每隔一两年检查一次,但是基于项目维护者的态度,我将只使用脚本或其他工具即可获得帮助。 很高兴没有花太多时间,很早就发现了这一点。

专家提示:如果刚开始将工作流程转移到此类工具上的人员已经需要此处介绍的内容,那么可能值得重新考虑“为什么”构建此工具。 是的,您成功了,但这是因为人们首先使用了该工具,并且您可能非常愿意向他们提供所需的东西。

祝一切顺利。

如果实现了此功能,我就能为您提供任何想要的东西(我的女友除外),并且我将成为所有人中最幸福的人:)

只是为了添加我对此提议功能的支持。 onrun确实是有道理的,但是要扩大潜在的实用性并进一步证明它的未来,也许有人需要研究更广泛的“ onevent”架构,其中一个将处于运行状态。

那就太好了

为此,请考虑以下条件:

services:
    web:
        image: node:8-alpine
        depends_on:
            - db
    db:
        image: postgres:alpine
        onrun: "echo hi"

添加跨事件脚本是否过多?

    web:
        events:
            db_onrun: "connectAndMigrate.sh"

我认为将其添加到docker-compose很简单,不仅您(正在使用撰写文件和撰写堆栈),而且您团队中的其他开发人员也是如此。

  • 使用单独的容器-每个人都应该知道应该运行它们。
  • 编写自定义Dockerfile-我们有大约20个服务,对于每个服务,我都应该重写Dockerfile来运行某些命令。

例如,我们需要在每个环境上安装和配置mkcert来拥有受信任的证书。 它不是容器或Dockerfile的一部分,因为在阶段/生产中不需要。 这里安装工具的正确方法是什么,每个使用撰写文件的人甚至都不知道背后发生了什么?

添加另一个用例:

需要一个WordPress实例。 写下了我的docker-compose.yaml。 docker-compose up –糟糕! 需要设置plugins目录的文件权限...找不到使其工作的其他方法,必须在容器运行后设置权限,因为我要绑定主机中的某些文件,这似乎是唯一的方法要修复fs权限,请在容器内部执行chown -Rf www-data.www-data /var/www/wp-content 。 为此编写我自己的Dockerfile并进行构建? 在我看来这很愚蠢。

对我来说幸运的是,上面提供的healthcheck黑客使我得以实现这一目标。 我在网上看到其他页面谈论Docker卷上的设置权限问题,但是建议的解决方案不起作用。

很高兴地看到,这些看门人,@dnephin,@aanand,@ shin-,越来越吨的加热方法。 当整个社区尽可能大声尖叫时,这确实可以说明问题,而核心开发人员只是坐下来,站稳自己的立场并拒绝倾听。 如此典型。 让我们不仅计算出竖起大拇指的数量,还计算出说这是必需的34位用户:
01)舒绍夫
02)费斯科巴
03)桑多尔11
04)网络测试
05)v0lume
06)Webpolis
07)Skull0ne
08)usergoodvery
09)黄家豪
10)MFQ
11)优胜
12)拳击手
13)daqSam
14)omeid
15)但丁巴
16)威利扬
17)SharpEdge马歇尔
18)丢失的载具
19)鬼
20)rodrigorodriguescosta
21)数据类型无效
22)dextermb
23)列克纳斯
24)lucile-sticky
25)rav84
26)嫁妆
27)ahmet2mir
28)蒙特拉82
29)or鱼
30)杰森哈斯
31)法拉利
32)超演出
33)日光浴
34)竖琴

谁说不? 高达3:
01)肾上腺素
02)阿南德
03)shin-

嗯... 34到3 ...

@ rm-rf-etc良好的分析...我什至不认为@dnephin@aanand正在使用

添加另一个用例:

需要一个WordPress实例。 写下了我的docker-compose.yaml。 docker-compose up –糟糕! 需要设置plugins目录的文件权限...找不到使其工作的其他方法,必须在容器运行后设置权限,因为我要绑定主机中的某些文件,这似乎是唯一的方法要修复fs权限,请在容器内部执行chown -Rf www-data.www-data /var/www/wp-content

在这种情况下,您还可以在Compose文件中设置user属性

为此编写我自己的Dockerfile并进行构建? 在我看来这很愚蠢。

好像您形成了强烈的意见; 但实际上,编写Dockerfile修改基本映像以满足您的需求并没有“愚蠢”的事情。 这就是所有基本图像的初衷。

对我来说幸运的是,上面提供的healthcheck黑客使我得以实现这一目标。 我在网上看到其他页面谈论Docker卷上的设置权限问题,但是建议的解决方案不起作用。

很高兴地看到,这些看门人,@dnephin,@aanand,@ shin-,越来越吨的加热方法。

是的,态度很好的伴侣。 :D


@ rm-rf-etc良好的分析...我什至不认为@dnephin@aanand正在使用

是的,已经过去了几年-无需继续对旧问题进行追踪。

幸运的是,Docker计划弃用组合,而倾向于使用堆栈,这里不会再有团队抱怨了,我们将开始再次看到产品的进步。

🙄

@ shin-,但您只是通过该响应对其进行了ping操作

我最近再次遇到了此问题,即使可以按照我的解决方法进行操作,也只能在您指定2.1时有效,这会使imo感到不适。

对我而言,官方的立场似乎是令人困惑,您应该为所有内容创建自己的docker映像。
对我来说,这实际上是说“如果要更改任何程序中的设置,则必须修改源代码并重新编译它”。
每次添加新服务或要升级到..的较新版本(例如MongoDB或MySQL Docker映像)时,都必须制作一个新的Dockerfile,进行构建并将其潜在地推送到您的注册表中。
与仅在docker-compose.yml中将image: mongo:3.0.2更改image: mongo:3.0.3相比,这将浪费大量的时间和资源。
我并不在意构建时间长,我要这样一个事实,即当您只想更新或更改服务的参数(甚至可能根本不需要)时,您就不得不打扰Dockerfiles和docker build旨在用作基本图像。

而且每个应用程序只能做一件事和一件事的论点也真的很臭。 这甚至与实现一个全新的功能无关,只是将另一个参数传递给docker 。 这也引出了一个问题,为什么docker rundocker builddocker execdocker pull等都是同一应用程序的一部分。 该论点听起来有些虚伪,不是吗?

@ shin-,我点击了您的链接,但看不到user属性与设置绑定挂载目录的所有者有何关系。 似乎与端口有关。

回复:态度:看起来人们同意我的观点,因此请给予强烈的反馈。 抱歉,如果您不喜欢我的表达方式,但实际上似乎用户需求已被忽略,那么您还期望什么?

我来到这里是希望获得诸如onrun之类的功能:有人提出建议,因为我只用了两天就可以使用compose,对我而言,这样的工具应该具有此功能。

返回我的docker文件以使用功能的单独脚本更新每个文件似乎是多余的。 我只想将另一个容器中的令牌注入到我的dockerfile灵活的环境变量中,该变量现在已与docker-composer.yml和解决方案紧密结合,以实现简单目的。

该死的,我读了整个线程,找到答案“好的,我们终于意识到这很酷,我们将实现它”。 遗憾地看到这并没有向前推进。
+1进行中!

@fabiomolinar ,有一种解决方案,我们在生产群中广泛使用了这种解决方案,但是它并不像有一个事件那样好。

我们使用以下锚点

#### configure a service to run only a single instance until success
x-task: &task
  # for docker stack (not supported by compose)
  deploy:
    restart_policy:
      condition: on-failure
    replicas: 1
  # for compose (not supported by stack)
  restart: on-failure

重复任务直到成功。 我们创建用于迁移和设置任务的容器,这些任务具有幂等的结果,并在本地组合和堆栈中像这样运行它们。

如果配置工作未完成,则取决于任务的服务需要在一定程度上失败。 在大多数情况下,只要您对最终用户遇到一些错误感到满意,这将为您提供最终的一致性,该一致性将在大多数环境中很好地发挥作用。

它还假定您的服务容器可以同时处理任务完成前和任务完成后的状态。 在数据库迁移之类的用例中,依赖的服务应该能够同时使用迁移前和迁移后的模式。.显然,必须在开发和部署协调中考虑一些想法,但这对于那些滚动更新服务。

@fabiomolinar ,这是我们在撰写服务中如何使用此方法的示例...

#### configure a service to run only a single instance until success
x-task: &task
  # for docker stack (not supported by compose)
  deploy:
    restart_policy:
      condition: on-failure
    replicas: 1
  # for compose (not supported by stack)
  restart: on-failure

#### configure a service to always restart
x-service: &service
  # for docker stack (not supported by compose)
  deploy:
    restart_policy:
      condition: any
  # for compose (not supported by stack)
  restart: always

services: 
  accounts: &accounts
    <<: *service
    image: internal/django
    ports:
      - "9000"
    networks:
      - service
    environment:
      DATABASE_URL: "postgres://postgres-master:5432/accounts"
      REDIS_URL: "hiredis://redis:6379/"

  accounts-migrate:
    <<: *accounts
    <<: *task
    command: ./manage.py migrate --noinput

感谢您指出@dopry。 但是我的情况要简单一些。 我需要使服务器运行,然后,只有在服务器启动并运行后,我才需要执行一些部署任务。 今天,我找到了一种方法,可以通过在单个CMD行中进行一些小过程管理。 假设服务器和部署进程分别称为serverdeploy 。 然后,我使用了:

CMD set -m; server $ deploy && fg server

上面的行将bashes的监视模式设置为on,然后在后台启动server进程,然后运行deploy进程,最后将server进程引入到再次前景以避免$$$ Docker杀死容器。

当我们讨论此问题时,任何人都有关于在运行docker-compose up时如何在容器或主机上运行命令的任何技巧?

我知道在主机上运行任何命令都会损害安全性,但是我只想在容器启动之前或启动过程中为目录创建rm 。 在主机和容器上都可以访问目录。 我不想制作自定义Docker映像或拥有一个脚本,该脚本首先rm然后运行docker-compose

谢谢!

@fabiomolinar ,您提出的方法违反了12个因素的应用程序原则。 如果您要对基础架构进行容器化,强烈建议您严格遵循它们。

您的方法可能会引起一些问题

  1. 容器启动缓慢。
  2. 当使用容器扩展服务时,部署将为每个实例运行一次,这可能会导致一些有趣的并发问题。
  3. 很难从“任务”和服务中对日志进行排序以进行管理和调试。

我确实发现我首先建议的违反直觉的方法。 它在docker-compose,docker swarms和mesos / marathon集群下的本地开发环境中在实践中运行良好。 它也有效地解决了缺少“运行”的问题。

我使用的方法确实非常丑陋。 我使用它一段时间只是为了让我的开发环境运行。 但是我已经更改了它,以在服务器启动并运行后使用入口点脚本和at命令来运行脚本。 现在,我的容器以正确的进程作为PID 1运行,并正确响应了所有信号。

我们仍然需要这个。 我找不到一种方法,可以成功启动容器后又不将其放入大量Makefile中来执行数据库汇总。

@ victor-perov为汇总任务创建另一个容器,并将其作为单独的服务执行

以下是我们其中一个项目的一些片段,这些片段显示了一个任务服务来运行数据库迁移。

x-task: &task
  # run once deploy policy for tasks
  deploy:
    restart_policy: 
      condition: none
    replicas: 1

service:
  automata-auth-migrate:
    <<: *automata-auth
    <<: *task
    # without the sleep it can't lookup the host postgres.  maybe the command is ran before the network set is complete.
    command: sleep 5 && python /code/manage.py migrate --noinput

好,这是讨论的第四年。 因此,让我将+1添加到需要onrun 。 PS:我应该为整个主题买爆米花。

我也认为onrun或等价货币(运行后)是必须的。 添加包装器脚本并在容器中执行docker exec只是...丑陋。

IMO docker compose是一个出色的容器编排MVP,可以说服人们管理容器很容易。 也许随着社区的生产就绪编排解决方案(例如kubernetes)的激增,我们社区应该认为它处于“维护模式”。 当您具有诸如容器依赖项之类的高级功能,再加上诸如“在容器启动后执行此操作”之类的缺失功能时,似乎很符合开发速度刚刚停滞的说法。 至少应该将这个功能视为超出范围并不明显。

使用Dockerfile不能轻松完成所有事情。 假设您要将自己的脚本添加到容器中。
例如,以mysql容器为例,尝试添加一个简单的脚本以在发生某些事件时调用API。
您可以通过以下方式之一进行:

  • 更改Dockerfile的mysql,并在入口点之前将自己的脚本添加到容器中。 您不能添加CMDDockerfile ,因为这将是一个参数传递给ENTRYPOINT
  • 您可以运行容器,然后将脚本复制到正在运行的容器中并运行它[ docker cpdocker exec ]。

这就是为什么我还认为onrun很有用,因为更改Dockerfile并不总是足够的。

转储,为什么关闭此功能? 考虑一下情况,当您使用像cassandra这样的正式docker映像时,您需要在启动后加载架构...必须为此实现自己的bash脚本解决方案...丑陋

@somebi似乎compose已关闭...

仅剩我的两分钱:我登陆这里是因为当前每次启动容器时我都必须手动启用Apache模块(Docker Hub wordpress图像中默认未启用SSL)。 并不是世界末日,而是希望它每次上升时运行几个命令,这样我就可以无缝地上下移动容器而不必费劲。

仅剩我的两分钱:我登陆这里是因为当前每次启动容器时我都必须手动启用Apache模块(Docker Hub wordpress图像中默认未启用SSL)。 并不是世界末日,而是希望它每次上升时运行几个命令,这样我就可以无缝地上下移动容器而不必费劲。

好吧,如果您基于wordpress图像构建新图像并启用了所需的模块,则可以轻松解决此问题。 然后使用它代替例如dockerfile:

FROM wordpress:php7.1
RUN a2enmod ssl

另一个解决方案是下载wordpress Dockerfile并在其中添加模块激活。 然后使用docker build为自己生成一个新映像。 例如,这是带有php 7.1的wordpress 5.2的Dockerfile:

WordPress的dockerfile

您可以在第63行中启用更多模块,或者运行ssl genaration。

我认为我们在这里讨论的并非所有情况。 问题是在容器的生命周期中创建动态的挂钩,例如开始时结束等。

这将是docker-compose的一个不错的补充!

诸如此类的回答是Kubernetes保留Docker(技术)所赚钱的全部原因的原因,希望有人很快会购买Docker(公司)并改变欢迎社区提案/请求的方式,这并不是一件坏事。 /已分析...

之所以这样回答,是因为Kubernetes保留了“全部” _ Docker(技术)正在生产的钱,希望有人尽快购买Docker(公司)并改变社区建议/请求的方式,这并不是一件坏事。欢迎/分析...

我写了一篇类似的评论家,没有任何冒犯性的言论(正是_open source project并非完全开放源代码,其维护者在没有任何其他理由的情况下挑衅地忽略了论点,而没有显示他们拥有多少技术氩气),它得到了很多支持,并且邮件已删除。

这说明背后是什么样的傲慢自大的人。

当您的社区要求4年的东西并且您(Docker)闭上眼睛时,表明您与他们的方向不同:/

现在码头工人放弃了,卖光了。
因为他们听不见...他们迷路了。

丢脸-嘿。

真遗憾不存在这样的东西。 我很希望能够创建onFailure挂钩,当健康检查失败时可能会发生。

services:
  app:
    image: myapp:latest
    hooks:
      onFailure:
        - # Call a monitoring service (from the host machine) to tell it that the service is offline.

对于应用程序未绑定到套接字/端口的情况,这将很有用。 在这里,Kubernetes可能是必经之路,但这对于相当小的环境而言,这是一个相当大的基础架构更改和过度使用。

编辑:
为了解决这个问题,我最终更新了容器的入口点以“包装”监视功能。 即

# /app/bin/run_with_monitor
#!/bin/bash
set -eE

updateMonitoringSystem() {
 # do something here... This is run from the container, though, unfortunately.
 if [[ $? -eq 1 ]]; then
  # Failed!
 else
  # All is good!
 fi
}

trap 'updateMonitoringSystem' EXIT

$@
# Dockerfile
....
CMD ["/app/bin/run_with_monitor", "./my-app"

不过,无需修改图像就可以这样做。

:man_shrugging:来寻找竞争对手(Kubernetes)具有的基本功能,而我却发现了垃圾箱火。

真是可惜,现在我必须维护单独的docker映像以进行本地测试。

新年快乐:roll_eyes:

image

@LukeStonehm在这里

大量程序依赖于启动时存在的某些服务。 例如MySQL或MongoDB数据库。

因此,在这些情况下,没有使用docker-compose理智方法。

相反,用户应该:

  • 了解如何编写Dockerfiles (和编程)
  • 了解如何构建Docker images
  • 创建从原始图像继承的Dockerfiles ,添加代码以确保容器彼此等待
  • 定期检查基本映像的安全更新
  • 定期修改Dockerfiles以应用更新
  • 从这些Dockerfiles定期构建Docker images Dockerfiles

这很烂,因为:

  • 您浪费大量时间学习可能根本不需要的东西
  • 您经常会浪费自己的硬件资源来构建和存储Docker images甚至上传/下载(拉/推)它们
  • 您经常浪费时间写那些Dockerfiles ,构建它们,测试它们,修复它们等...
  • 由于您不知道自己在做什么,因此可能会损害图像的安全性
  • 您将失去仅运行经过官方验证/签名的Docker images

如果我们进行了启动检查,那么所有这些都将是不必要的,我们可以随时将需要完成的image: mysql:8.0.18更改image: mysql:8.0.19

实际上,这是现实世界中正在发生的事情:

  • 人们创建自己的Dockerfiles进行更改,以便与docker-compose
  • 他们一次建立自己的形象
  • 而且不要定期打补丁
  • 黑客开心

而且您不能说docker-compose只应该“做一件事”,因为它已经完成了几乎所有的工作。 更重要的是包括拉取和构建图像,使用depends_on属性指定依赖项。 这甚至与实现一个全新的功能无关,只是将另一个参数传递给docker

@ binman- docker @crosbymichael @dmcgowan @ebriney @ehazlett @eunomie @guillaumerose @jeanlaurent @justincormack @lorenrh @manishtomar @olegburov @routelastresort @spencerhcheng @StefanScherer @thaJeztah @tonistiigi @ulyssessouza @
请重新考虑此功能,或者至少让我们对此进行适当的讨论。

在这个关头, task service技术对我来说很好用,但是确实有它的特质。 我们已经在组合文件中应用了该模式,以进行广泛的迁移和应用程序初始化。 但是我同意一个更好的“ depends_on”,它可以等待成功的运行状况检查或成功的退出/任务完成,这将使许多任务变得更容易,更可靠。

这确实是一个有用的补充。

我认为值得强调的是,Kubernetes通过生命周期postStart具有此功能。

k8s!= docker-compose。 频道错误

抱歉,不清楚,但我的意思是:Kubernetes支持这一点,并且由于Kubernetes和Docker compose具有许多相同的用例/用途,因此将其包含在compose中是一个理由。 对不起,如果我不清楚。

好消息!!

我认为docker已听取了我们的意见(关于此问题以及其他一些问题)。 https://www.docker.com/blog/announcing-the-compose-specification/

让我们尝试按照那里的规范进行工作,以满足社区的需求。 通过重新启动,我们可以尝试使它成为一个开放友好的社区。

好消息!!

我认为docker已听取了我们的意见(关于此问题以及其他一些问题)。 https://www.docker.com/blog/announcing-the-compose-specification/

让我们尝试按照那里的规范进行工作,以满足社区的需求。 通过重新启动,我们可以尝试使它成为一个开放友好的社区。

有没有人建议这个改变? 邮件列表尚不可用,所以我认为下一个最好的地方是: https :

我没有看到描述此问题的问题,但不确定是不是正确的地方...

编辑:我在https://github.com/compose-spec/compose-spec/issues/84中打开了一个问题

您可以使用HEALTHCHECK进行其他操作,例如以下示例:

Dockerfile

FROM ubuntu

COPY healthcheck.sh /healthcheck.sh
RUN chmod a+x /healthcheck.sh

HEALTHCHECK --interval=5s CMD /healthcheck.sh

CMD bash -c 'set -x; set +e; while true; do cat /test.txt; sleep 3; done'

healthcheck.sh

#/usr/bin/env bash

set -e

FIRST_READY_STATUS_FLAG='/tmp/.FIRST_READY_STATUS_FLAG'

# Health check

echo 'Run command to validate the container status HERE'

# On success
if [ ! -f "${FIRST_READY_STATUS_FLAG}" ]; then
  # On first success...
  touch "${FIRST_READY_STATUS_FLAG}"

  # Run ON_RUN on first health check ok
  if [ ! -z "${DOCKER_ON_RUN}" ]; then
    eval "${DOCKER_ON_RUN}"
  fi
fi
  1. 运行_health check_。

    • 如果失败,则使用退出代码1从脚本中退出。

    • 如果_health check_正常,该脚本将继续。

  2. 如果它是第一个_health check OK_,并且如果存在DOCKER_ON_RUN环境变量,请执行它。

docker-compose.yml

version: "3.7"

services:
  test:
    build:
      context: .
    image: test/on-run
    environment:
      DOCKER_ON_RUN: echo x >> /test.txt

您可以使用DOCKER_ON_RUN环境变量传递自定义命令以在运行后执行。

执行结果

docker-compose build
docker-compose up

输出:

Creating network "tmp_default" with the default driver
Creating tmp_test_1 ... done
Attaching to tmp_test_1
test_1  | + set +e
test_1  | + true
test_1  | + cat /test.txt
test_1  | cat: /test.txt: No such file or directory
test_1  | + sleep 3
test_1  | + true
test_1  | + cat /test.txt
test_1  | cat: /test.txt: No such file or directory
test_1  | + sleep 3
test_1  | + true
test_1  | + cat /test.txt
test_1  | x
test_1  | + sleep 3
test_1  | + true
test_1  | + cat /test.txt
test_1  | x
test_1  | + sleep 3
test_1  | + true
test_1  | + cat /test.txt
test_1  | x
test_1  | + sleep 3
  • 在_health check_准备就绪之前,您会看到错误cat: /test.txt: No such file or directory
  • 你只能看到一个x/test.txt运行后

希望这可以帮助某人。

编辑1

如果不需要_health check_,则可以使用脚本的其余部分。

@ reduardo7
感谢您的解决方法。
只是想添加,以防万一您需要运行命令一(例如,用于创建用户等),您可以为touch "${FIRST_READY_STATUS_FLAG}"装载卷

这些解决方案中的许多是解决此问题的有效方法。 例如,制作入口点脚本也可以解决此问题:
ENTRYPOINT ["./entrypoint.sh"]

在运行实际的服务或流程之前,它将包含更复杂的逻辑。
这仍然不是一个钩子,尽管它可以使我们在容器生命周期中注入逻辑:

  • 在创建之前
  • 在开始之前
  • 开始之后
  • 销毁之前
  • 即使摧毁
  • 等...

我知道以上并非全部都是有意义的,但我希望您能理解,因为这是重点。
也可以使用以下指令将其包含在docker-compose

lifecycle:
    before_start: "./beforeStartHook.sh"
    after_destroy: "./afterDestroyHook.sh"

甚至像这样:

hooks:
    before_destroy: "./beforeDestroyHook.sh"
    before_create: "./fixFsRights.sh"

我无法使用钩子脚本或引导脚本方法覆盖需要root权限的文件,因为我们以非root用户身份启动容器

哇,这样的基本功能还没有实现。

此页面是否有帮助?
0 / 5 - 0 等级