compose: New TUI spams lines when pulling multiple images causing you to lose your terminal history

Description

@thaJeztah has asked me to open an issue after commenting on #8753

For your use-case, is there a specific reason why the new output is problematic for you? If so, could you describe your use-case? Perhaps there’s enhancements to be made to address.

I’m not the person who created this issue but I have one complaint about the new output as well. First of all, I love BuildKit’s output in docker build. But, compose’s implementation makes me question how this made it through an official 2.0 release.

https://user-images.githubusercontent.com/28601081/137222298-31ca5d3a-68be-4041-82e8-8d58cb8e8999.mp4

This can be reproduced in both Windows’ command prompt, Windows Terminal and probably others. It literally spams thousands of lines to the terminal ruining the ability to scroll back. Sorry if I’m hijacking the issue but it seemed fairly fitting as I have to resort to rolling back to a 1.x release.

_Originally posted by @clrxbl in https://github.com/docker/compose/issues/8753#issuecomment-942773151_

Steps to reproduce the issue:

  1. docker compose up on a docker-compose.yml file that contains multiple images & a small enough terminal window.

Describe the results you received: See the above video

Describe the results you expected: I should be able to scroll back and not lose all of my terminal history, even after the command is done.

Additional information you deem important (e.g. issue happens only occasionally): It seems like this issue isn’t present if you’re reproducing it in a large enough terminal window (e.g. fullscreen)

Output of docker compose version:

Docker Compose version 2.0.1

Output of docker info:

WARNING: Plugin "/usr/local/lib/docker/cli-plugins/docker-buildx" is not valid: failed to fetch metadata: fork/exec /usr/local/lib/docker/cli-plugins/docker-buildx: no such file or directory
WARNING: Plugin "/usr/local/lib/docker/cli-plugins/docker-compose" is not valid: failed to fetch metadata: fork/exec /usr/local/lib/docker/cli-plugins/docker-compose: no such file or directory
WARNING: Plugin "/usr/local/lib/docker/cli-plugins/docker-scan" is not valid: failed to fetch metadata: fork/exec /usr/local/lib/docker/cli-plugins/docker-scan: no such file or directory
Client:
WARNING: No blkio throttle.read_bps_device support
WARNING: No blkio throttle.write_bps_device support
WARNING: No blkio throttle.read_iops_device support
WARNING: No blkio throttle.write_iops_device support
 Context:    default
 Debug Mode: false
 Plugins:

Server:
 Containers: 12
  Running: 0
  Paused: 0
  Stopped: 12
 Images: 11
 Server Version: 20.10.9
 Storage Driver: overlay2
  Backing Filesystem: extfs
  Supports d_type: true
  Native Overlay Diff: true
  userxattr: false
 Logging Driver: json-file
 Cgroup Driver: cgroupfs
 Cgroup Version: 1
 Plugins:
  Volume: local
  Network: bridge host ipvlan macvlan null overlay
  Log: awslogs fluentd gcplogs gelf journald json-file local logentries splunk syslog
 Swarm: inactive
 Runtimes: io.containerd.runc.v2 io.containerd.runtime.v1.linux runc
 Default Runtime: runc
 Init Binary: docker-init
 containerd version: 8686ededfc90076914c5238eb96c883ea093a8ba.m
 runc version: v1.0.2-0-g52b36a2d
 init version: de40ad0
 Security Options:
  seccomp
   Profile: default
 Kernel Version: 5.10.60.1-microsoft-standard-WSL2
 Operating System: Arch Linux
 OSType: linux
 Architecture: x86_64
 CPUs: 12
 Total Memory: 15.63GiB
 Name: DESKTOP-BQ26BOE-wsl
 ID: CWUC:IOEW:TCJZ:EZJS:RTO5:YSBV:X7BE:YHNS:MQNY:V3VQ:N3NI:I4T4
 Docker Root Dir: /var/lib/docker
 Debug Mode: false
 Username: clrxbl
 Registry: https://index.docker.io/v1/
 Labels:
 Experimental: false
 Insecure Registries:
  127.0.0.0/8
 Live Restore Enabled: false

Additional environment details: Arch Linux WSL2 w/ systemd-genie

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Reactions: 36
  • Comments: 34 (8 by maintainers)

Most upvoted comments

I don’t think it just build, although multiple builds will definitely be adding to the output. The example video shows that pulling (if the compose-file has many images) can also be problematic if there’s more pulls than fit on the screen.

Doing a quick test with a stack that uses a postgres image (which has various layers);

services:
    foo:
        image: postgres

Produces this output (ignore the error at the end, it’s just for illustration):

docker compose up
[+] Running 14/14
 ⠿ foo Pulled                                          14.6s
   ⠿ e5ae68f74026 Pull complete                         5.6s
   ⠿ 7b8fcc7e1ad0 Pull complete                         6.0s
   ⠿ 7527d03e2f77 Pull complete                         6.1s
   ⠿ 80e55689f4d0 Pull complete                         6.2s
   ⠿ 8a79eb6d69c9 Pull complete                         6.7s
   ⠿ 397705f2d093 Pull complete                         6.8s
   ⠿ de36ec4eb0a5 Pull complete                         6.9s
   ⠿ 08d878a022c1 Pull complete                         7.0s
   ⠿ 7677029670ff Pull complete                        11.4s
   ⠿ 1d24b3d9557e Pull complete                        11.5s
   ⠿ e085b018338c Pull complete                        11.5s
   ⠿ 063b09ff12e9 Pull complete                        11.6s
   ⠿ a39fee215a44 Pull complete                        11.7s
[+] Running 2/2
 ⠿ Network compose-progress_default  Created            0.1s
 ⠿ Container compose-progress-foo-1  Created            1.4s
Attaching to compose-progress-foo-1
compose-progress-foo-1  | Error: Database is uninitialized and superuser password is not specified.
compose-progress-foo-1  |        You must specify POSTGRES_PASSWORD to a non-empty value for the
compose-progress-foo-1  |        superuser. For example, "-e POSTGRES_PASSWORD=password" on "docker run".
compose-progress-foo-1  |
compose-progress-foo-1  |        You may also use "POSTGRES_HOST_AUTH_METHOD=trust" to allow all
compose-progress-foo-1  |        connections without a password. This is *not* recommended.
compose-progress-foo-1  |
compose-progress-foo-1  |        See PostgreSQL documentation about "trust":
compose-progress-foo-1  |        https://www.postgresql.org/docs/current/auth-trust.html
compose-progress-foo-1 exited with code 1

While the pull is running, Downloading and Extracting progress bars are shown for each layer:

   ⠼ e5ae68f74026 Extracting      [==================================================>]  31.37MB/31.37MB    4.4s
   ⠼ 7b8fcc7e1ad0 Download complete                                                                         4.4s
   ⠼ 7527d03e2f77 Download complete                                                                         4.4s
   ⠼ 80e55689f4d0 Download complete                                                                         4.4s
   ⠼ 8a79eb6d69c9 Download complete                                                                         4.4s
   ⠼ 397705f2d093 Download complete                                                                         4.4s
   ⠼ de36ec4eb0a5 Download complete                                                                         4.4s
   ⠼ 08d878a022c1 Download complete                                                                         4.4s
   ⠼ 7677029670ff Downloading     [=============================>                     ]  53.55MB/91.23MB    4.4s
   ⠼ 1d24b3d9557e Download complete                                                                         4.4s

Based on that output, some ideas:

Remove the pull complete lines after they have completed / after the image has fully downloaded

Collapse the section, and replace with a summary.

⠿ foo Pulled                                          14.6s

Perhaps the summary should have more details than just “pulled”; users may be interested to know what image (and tag, digest?) was pulled, and how large it was in total (?), as well as the architecture that was pulled (?) haven’t given that a lot of thinking yet;

⠿ foo Pulled postgres:latest (digest sha256:xxx) linux/amd64, 12345MB                  14.6s

Use a single progress (or counter) per image during pull

Perhaps depending on the amount of available space or the number of services / pulls, perhaps it’s possible to group the progress bars. The size would show the total size / sum of all layers (I’m not sure if this works if layers are already downloaded before though);

postgres:latest  Downloading  3/13   [=============================>                     ]  53.55MB/91.23MB    4.4s
postgres:latest  Extracting   2/13   [==================================================>]  31.37MB/31.37MB    4.4s

I’m not sure line-height is the ultimate culprit here. I’m seeing hectic-as-heck output even with single service build in a full height terminal window on a laptop with a built-in 1600x1200 display with scaling disabled. It started happening with the release of v2.17. With v2.16, output with the same services was as-expected.

I’m at least still seeing this on Docker Compose version v2.17.3 with docker version 23.0.5

@williamdes this is Docker Desktop version https://github.com/docker/compose/issues/10256 would indeed be a better place as an open issue

Please open a fresh new issue. The main question to address is “how to display status for N services when N > terminal height?”. Any suggestion is welcome

Here’s my use case to reproduce the problem.

  • Docker 20.10.17
  • Docker Compose v2.6.0
  • This compose.yaml:
x-service: &default-service
  image: nginx:latest
  command: >
    bash -c "sleep 10 && nginx -g 'daemon off;'"
  healthcheck:
    test: service nginx status || exit 1
    interval: 2s
    timeout: 1s
    retries: 200
    start_period: 600s

services:
  svc_a:
    <<: *default-service
  svc_b:
    <<: *default-service
    depends_on:
      svc_a:
        condition: service_healthy
  svc_c:
    <<: *default-service
    depends_on:
      svc_b:
        condition: service_healthy
  svc_d:
    <<: *default-service
    depends_on:
      svc_c:
        condition: service_healthy
  svc_e:
    <<: *default-service
    depends_on:
      svc_d:
        condition: service_healthy
  svc_f:
    <<: *default-service
    depends_on:
      svc_e:
        condition: service_healthy
  svc_g:
    <<: *default-service
    depends_on:
      svc_f:
        condition: service_healthy
  svc_h:
    <<: *default-service
    depends_on:
      svc_g:
        condition: service_healthy
  svc_i:
    <<: *default-service
    depends_on:
      svc_h:
        condition: service_healthy
  svc_j:
    <<: *default-service
    depends_on:
      svc_i:
        condition: service_healthy
  svc_k:
    <<: *default-service
    depends_on:
      svc_j:
        condition: service_healthy
  svc_l:
    <<: *default-service
    depends_on:
      svc_k:
        condition: service_healthy
  • Make terminal 11 lines high
  • docker compose up -d
  • Notice terminal scroll

Have a large number of containers within a docker-compose file. Same problem:

  1. It spams the output buffer by jumping around like crazy
  2. it flashes as fireworks like crazy while it’s happening
  3. The ultimate output simply says “[container] Pulled … X.Xs” but provides no indications of which were up to date in the first place and which were actively pulled
  4. The ultimately output is a mix of 'containername Pulled", “XXXX already exists” and “xxxx pull complete” with some items showing the breakout of parts and others not.

As pointed out, it’s very easy to exceed a typical terminal height in this case.

Possible ideas:

  1. Do the docker compose pull sequentially or in batches, which reduces the number of pulls at any given time and thus concludes some items before the next few are started
  2. Spare the output of any that are “up to date” to the end. A quick test of whether the image is up to date, and if it is, output nothing until after all are updated and then output the “XXXX is up to date”
  3. A better terminal implementation

Boy is this a mess on a large compose pull. How about an option to just suppress individual layer progress? It doesn’t take much to overshoot the line height of most terminals with a reasonable compose file. Otherwise you have to either watch the fireworks, or resort to something like:

docker compose ps --services |xargs -n 1 docker compose pull

@ericslandry I can reproduce using your config.

I think the reason that v2.6.0 fixed it for me was because it made it so only one service would show the pull progress at the same time. After that change, my terminal was never small enough to not be able to fit it all on one screen without scrolling.

Your config works fine for me if my terminal is tall enough to fit it all (about 23 lines), but if I do 11 lines like you said, I see the issue happen again.

@thaJeztah buildkit indeed consider the build requests we schedule in parallel for services to be fully independent, and as such won’t do any magic on concurrent pulls for same layers.

@ericslandry for your information, this output is fully managed by buildx.