在 perl6 中休眠在 docker-compose 上无法正常工作

Sleep in perl6 doesnt works correctly on docker-compose

我写了一个简单的程序,应该打印 1 到 9 之间的等待 1 秒的数字。

#!/usr/bin/env perl6

my $x = 1;
while $x < 10 {
    say $x++;
    sleep(1);
}

当我从命令行运行它时,它按预期工作

Video 1

我试图使用 docker 容器和程序来达到同样的效果打印第一个数字,然后冻结 9 秒并打印其余数字。

Video 2

我的docker-撰写

version: "3.1"
services:
    cron:
      build: phpdocker/cron
      container_name: docker-perl6
      volumes:
        - ./cron:/cron
      working_dir: /cron
      command: "app.pl"

和 Dockerfile

FROM jjmerelo/alpine-perl6

版本

docker -v
Docker version 18.03.1-ce, build 9ee9f40

docker-compose -v
docker-compose version 1.15.0, build e12f3b9

perl6 -v
This is Rakudo version 2018.03-136-g768cf9f built on MoarVM version 2018.03-56-g85fc758
implementing Perl 6.c.

更新

我把say $x++;改成了say "{time}: {$x++}";

docker-perl6 | 1527933936: 1
docker-perl6 | 1527933937: 2
docker-perl6 | 1527933938: 3
docker-perl6 | 1527933939: 4
docker-perl6 | 1527933940: 5
docker-perl6 | 1527933941: 6
docker-perl6 | 1527933942: 7
docker-perl6 | 1527933943: 8
docker-perl6 | 1527933944: 9

正如@elizabeth-mattijsen 和@melpomene 提到的那样,问题与 docker 的缓冲输出有关。

首先,感谢您使用我的 perl6 docker 容器。我将对您的程序进行一些尝试,以找出真正的问题所在。我想你想知道,一般来说,这类程序在 docker 中会发生什么,而不是在特定的 docker-compose 环境中,对吧?

运行 docker 容器中的程序

你可以这样做:

docker run -it --rm  --entrypoint sh  jjmerelo/alpine-perl6

然后在容器内创建文件(例如使用cat > con)。我已经测试过了,它运行正常,完全没有问题。

运行 docker 容器外的程序

你可以这样做:

docker run -it --rm -v $PWD:/app  jjmerelo/alpine-perl6 /app/app.pl

仍然没问题,它每秒打印一个东西。它本身似乎并不是 docker 缓冲问题。让我们尝试更进一步

docker-compose 有问题?

你在这里做的是组合两个 docker 容器,你是 运行 一个容器。我们几乎已经确定 alpine-perl6 可能没有问题。难道是在phpdocker? My money is on that, although it's not clear which container are you using, this gist seems to point at that container actually using buffering。在更新的答案中,并不是真正让它打印的时间,而是您正在打印的字节数,足以填充缓冲区。尝试将 $x 更改为 "a good amount of bytes, including $x" 以查看是否是这种情况。

无论如何,我会像@lizmat 所说的那样研究 phpdocker 容器的配置。此外,如果你想要的只是cron,你可以, install cron for alpine, or use other containers such as this one

就像其他人已经说过的那样,缓存是由您使用的间接寻址引起的。手动地,你会 运行 一个像这样交互的容器:

docker run -it --rm author/image-name

重要的部分是 -it 开关:

--interactive , -i      Keep STDIN open even if not attached
--tty , -t              Allocate a pseudo-TTY

虽然 docker-compose run 默认分配一个 tty,但大多数 docker-compose 命令不会。如果您真的需要它们(99% 的时间您不需要),请查看 docker-compose.yaml config 添加这些选项,特别是 stdin_opentty.