使用docker-compose保持容器的运行并保持连接

12
我想使用docker-compose将php和几个数据库(orientdb,neo4j等)组合在一起。然后进入php容器并使用shell执行命令。
单独来说,我的所有容器都运行得很好,当我将它们组合在一起时,它们也都能正常运行。然而,我无论如何都无法弄清楚如何保持php容器的活动状态,以便我可以进入其中进行测试。
为了简单起见,我只会使用一个数据库:orient-db。
我的docker-compose.yml文件:
version: '2'
services:
  php:
    build: .
    links:
       - orientdb

  orientdb:
    image: orientdb:latest
    environment:
      ORIENTDB_ROOT_PASSWORD: rootpwd
    ports:
       - "2424:2424"
       - "2480:2480"

我的 "php" Dockerfile:
FROM php:5.6-cli
ADD . /spider
WORKDIR /spider
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/bin/ --filename=composer
RUN composer install --prefer-source --no-interaction

RUN yes | pecl install xdebug \
    && echo "zend_extension=$(find /usr/local/lib/php/extensions/ -name xdebug.so)" > /usr/local/etc/php/conf.d/xdebug.ini

我已经尝试过以下方法(还有其他方法):

  • 在一个终端中运行docker-compose up,然后在另一个终端中运行docker attach
  • 在我的compose文件中启用ttystdin_open
  • 使用/bin/bash命令
  • 尝试了不同的CMD exec vendor/bin/phpunit -D FOREGROUND变体

我还尝试了一些参考资料:


请添加 PHP 容器日志的粘贴。我们需要看到它是如何死亡的。 - L0j1k
当我运行 docker logs <容器名称> 时,我只得到了 交互式 Shell。容器正在正确构建,但一旦完成就立即退出。我需要一个保持其开启的命令。我尝试了 @tfg 的答案,但目前还没有成功。 - Apollo
1
请看这里 - 刚刚找到一个简单有效的解决方案:https://dev59.com/w18e5IYBdhLWcg3wZ5ys#38292749 - Serge Velikan
另外,您可以尝试使用php:5.6-apache镜像,因为它默认运行Apache进程并且不会退出。 - Jānis Elmeris
4个回答

11
因此,docker-compose只是docker-engine客户端的替代品。它与客户端保持功能平衡。对于诊断此类问题,您应该在使用常规的旧客户端之前放弃使用docker-compose。根据您在这里和其他答案中的评论,似乎您没有在前台运行带有守护进程的容器。如果要在Docker中运行交互式shell,则必须使用-it标志(-t分配tty,-i启动交互式会话)。如果不使用这些开关运行Docker,则您的容器将无法在您启动交互式shell(例如php -a)后继续存在。
将Docker视为运行进程的高级方式而不是虚拟机有所帮助。它不是存在于您正在运行的任何进程(及其子进程)的生命周期之外的某种“环境”。通常,PHP由某个服务器(例如Apache、Nginx等)调用。您在这里暗示的是,您需要一个PHP进程“永久”运行,以便您可以进入容器并测试一些东西。除了交互式shell外,这是不可能的,您需要特别使用-it开关来保持交互式shell进程在容器中保持活动状态。真正的答案是,如果没有相关的守护程序/服务器进程在前台监听,您无法在此处尝试的情况下(保持PHP容器运行)。原因是因为这不是PHP的工作方式。如果您真的想从PHP镜像进入容器,只需在其中放置一个shell即可:
docker run -it apollo/php /bin/bash

你可以从PHP镜像启动一个容器,并在容器上获得一个shell(只要你退出shell,容器就会停止运行)。但是,我仍然强调一下我的第一段话,docker-compose不是这里的最佳选择。

这很有道理,也是我担心的。我可以使用标志使php保持开放状态。我只是希望能够使用compose将我的容器链接在一起。php容器需要能够与orientdb容器通信。这可能是一个单独的问题。 - Apollo
你考虑过在OrientDB容器中安装PHP吗?这是我会做的事情。 - L0j1k
2
那是个好主意。如果有多个数据库,我只需要在一个容器内执行一次--而该容器保持运行状态。其他数据库可以链接到它上面。 - Apollo
无论如何,您已经回答了我的问题。谢谢。 - Apollo
虽然不推荐,但在一个容器内使用多个不同的进程也是可能的,可以使用supervisord来实现。我写了一篇文章,其中有一个使用cron的示例,但它与使用其他进程完全等效。之所以不推荐这样做,是因为Docker所指向的"微服务"设计模式,然而完全有可能实现,并且已经有很多相关工作的先例存在。就微服务架构而言,将PHP放在另一个容器中是正常的做法。 - L0j1k

8

我曾经在使用Docker Compose运行zsh shell容器时遇到了类似的问题:容器启动后立即关闭,退出代码为0。

下面最新回答中@Spock的评论实际上解决了问题,至少对于我来说是这样的。

将docker-compose命令设置为以下形式:

command: tail -f /dev/null

这可以保持进程的运行,同时也允许它优雅地关闭。

1
当您已经在使用命令进行其他操作时,这个命令就变得完全无用了。Docker不允许您运行多个命令。 - mae
如果您没有管理单个进程,请编写一个入口脚本!不要把怒火撒在信使身上。 - SeedyROM

5
如果您使用docker-compose up命令,终端没有输出错误,那么这表明服务停止是因为它已经完成了任务(而不是遇到了某些错误)。可能出现错误的一个原因是您向PHP发送了一些东西(比如安装composer),这将会关闭由php:5.6-cli镜像启动的交互式php终端。要重新启动交互式php shell,请在Dockerfile的末尾添加以下内容: CMD ["php", "-a"] 然后再次运行docker-compose up
另外,当一切正常运行时,您可以通过docker-compose up -d命令以守护进程模式运行,从而重新获得对终端的控制(所有的stdout和stderr都将记录在docker容器的相应日志文件中)。
然后,您可以附加到容器中进行操作。我发现docker exec -it <containerID> bashdocker attach <container id>更快捷。
希望这可以帮助到您。

我尝试了一些变化,但都不行。你是对的。当我运行 docker ps -a 时,它显示 php 已退出。 - Apollo
我刚刚尝试将 command: ["sleep", "60"] 添加到我的 yml 文件中,它使容器保持打开状态了整整一分钟,在此期间我可以执行 exec - Apollo
3
命令:"tail -f /dev/null" 可以让容器一直运行。 - Spock

5

将入口点加入以防止进程退出

version: "3.7"
services:
    debug-srv:
        container_name: "debug-srv"
        image: "alpine:latest"
        entrypoint: ["tail", "-f", "/dev/null"]
        networks:
            debug-net:
networks:
    debug-net:
        name: "debug-net"

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接