7

I wrote simple program that should print digits from 1 to 9 waiting 1 second between printing.

#!/usr/bin/env perl6

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

It works as expected when I run it from command line

Video 1

I was trying to achieve the same effect using docker container and program printed first digit, then froze on 9 seconds and printed rest of digits.

Video 2

My docker-compose

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

and Dockerfile

FROM jjmerelo/alpine-perl6

Versions

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.

Update

I changed say $x++; to 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

So as @elizabeth-mattijsen and @melpomene mentioned it is issue connected with buffering output by docker.

Daniel
  • 7,684
  • 7
  • 52
  • 76
  • 4
    "*froze on 9 seconds and printed rest of digits*" - That typically indicates that the output is buffered. You probably need to flush stdout or something. – melpomene Jun 02 '18 at 09:03
  • 5
    If you change the `say` to: `say "{time}: {$x++}";`, do you see different values for `time` ? If so, it definitely is a buffering issue that feels to me would be a Docker config setting that would need to be changed. – Elizabeth Mattijsen Jun 02 '18 at 09:08

2 Answers2

4

First, thanks for using my perl6 docker container. I will try a few things with your program, to find out what's really the problem. I gather you want to know, in general, what happens with these kind of programs in docker, and not in the particular docker-compose environment, right?

Run the program from inside the docker container

You can do this:

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

and then create the file inside the container (use cat > con for instance). I've tested it and it runs correctly, no problem at all.

Run the program from outside the docker container

You can do this:

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

Still no problem at all, it prints stuff one a second. It does not seem to be, by itself, a docker buffering problem. Let's try to go a bit further

Problems with docker-compose?

What you are doing here is composing two docker containers, you are running one container from the other. We have pretty much established that alpine-perl6 might not have a problem. Could it be in 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. In the updated answer it's not really the time what makes it print, but the amount of bytes you are printing, good enough for filling the buffer. Try to change $x to "a good amount of bytes, including $x" to see if that's the case.

At any rate, I would look into the configuration of the phpdocker container as @lizmat says. Besides, if what you want is just cron, you can follow this advice, install cron for alpine, or use other containers such as this one

jjmerelo
  • 22,578
  • 8
  • 40
  • 86
  • Change of `$x` to `"a good amount of bytes, including $x"` not influenced on behavior of program. This question does not have any connection with `phpdocker` it is only name of catalog because of I had this problem in project containing php in other indepenedent docker-compose services. Thank you for exhausted explanation. – Daniel Jun 03 '18 at 08:30
  • @Daniel The point is to fill the buffer so that it's actually printed, same as was done above including the time. But nxadm response is probably the way to go, or else include cron services without using docker-compose. – jjmerelo Jun 03 '18 at 08:46
4

Like others said already, the caching is caused by the indirection you're using. Manually you would run a container interactively like this:

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

The important part is the -it switches:

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

While docker-compose run assigns by default a tty, most docker-compose commands don't. Have a look at the docker-compose.yaml config for adding these options if you really need them (99% of the time you don't), specifically stdin_open and tty.

nxadm
  • 2,079
  • 12
  • 17