Skip to content

[BUG] docker compose up --pull missing sometimes recreates container without pulling #14016

Description

@felixfontein

Description

In the CI for the Ansible collection community.docker, I noticed anohter problem with the latest Compose version. This one happens in a Ubuntu 22.04 VM and also in a RHEL 10.2 VM (probably also RHEL 9.8, didn't test that), but does not happen for example on my Arch Linux box.

docker-compose.yml:

services:
  foo:
          image: ghcr.io/ansible-collections/simple-1:tag
          command: 10m
          stop_grace_period: 1s

Steps To Reproduce

  1. Make sure image is not present: docker rmi ghcr.io/ansible-collections/simple-1:tag
  2. Bring up compose with pulling: docker compose --ansi never --progress json up --detach --quiet-pull --pull missing --
  3. Bring up compose again, should not pull: docker compose --ansi never --progress json up --detach --quiet-pull --pull missing --
  4. For good measure, another time: docker compose --ansi never --progress json up --detach --quiet-pull --pull missing --

Note that 2. as expected pulls the image, creates the network and container, and starts the container:

{"id":"Image ghcr.io/ansible-collections/simple-1:tag","status":"Working","text":"Pulling"}
{"id":"Image ghcr.io/ansible-collections/simple-1:tag","status":"Done","text":"Pulled"}
{"id":"Network t_default","status":"Working","text":"Creating"}
{"id":"Network t_default","status":"Working","text":"Creating"}
{"id":"Network t_default","status":"Done","text":"Created"}
{"id":"Network t_default","status":"Done","text":"Created"}
{"id":"Container t-foo-1","status":"Working","text":"Creating"}
{"id":"Container t-foo-1","status":"Done","text":"Created"}
{"id":"Container t-foo-1","status":"Working","text":"Starting"}
{"id":"Container t-foo-1","status":"Done","text":"Started"}

Then 3. re-creates the container, even though the image is already there!

{"id":"Container t-foo-1","status":"Working","text":"Recreate"}
{"id":"Container t-foo-1","status":"Done","text":"Recreated"}
{"id":"Container t-foo-1","status":"Working","text":"Starting"}
{"id":"Container t-foo-1","status":"Done","text":"Started"}

Interestingly, when running the command again (4.), everything's fine:

{"id":"Container t-foo-1","status":"Done","text":"Running"}

Every further run results in the same.

Compose Version

Docker Compose version v5.4.0

Docker Environment

Client: Docker Engine - Community
 Version:    29.7.2
 Context:    default
 Debug Mode: false
 Plugins:
  buildx: Docker Buildx (Docker Inc.)
    Version:  v0.36.1
    Path:     /usr/libexec/docker/cli-plugins/docker-buildx
  compose: Docker Compose (Docker Inc.)
    Version:  v5.4.0
    Path:     /usr/libexec/docker/cli-plugins/docker-compose

Server:
 Containers: 1
  Running: 1
  Paused: 0
  Stopped: 0
 Images: 1
 Server Version: 29.7.2
 Storage Driver: overlayfs
  driver-type: io.containerd.snapshotter.v1
 Logging Driver: json-file
 Cgroup Driver: systemd
 Cgroup Version: 2
 Plugins:
  Volume: local
  Network: bridge host ipvlan macvlan null overlay
  Log: awslogs fluentd gcplogs gelf journald json-file local splunk syslog
 CDI spec directories:
  /etc/cdi
  /var/run/cdi
 Swarm: inactive
 Runtimes: io.containerd.runc.v2 runc
 Default Runtime: runc
 Init Binary: docker-init
 containerd version: aad11006b869517fcd3009450b6f82da282e1a9b
 runc version: v1.4.3-0-gbb14dabe
 init version: de40ad0
 Security Options:
  apparmor
  seccomp
   Profile: builtin
  cgroupns
 Kernel Version: 6.8.0-1061-aws
 Operating System: Ubuntu 22.04.5 LTS
 OSType: linux
 Architecture: x86_64
 CPUs: 2
 Total Memory: 3.727GiB
 Name: ip-192-168-5-65
 ID: 14c2997c-3861-4156-97f9-84463d814926
 Docker Root Dir: /var/lib/docker
 Debug Mode: false
 Experimental: false
 Insecure Registries:
  ::1/128
  127.0.0.0/8
 Live Restore Enabled: false
 Firewall Backend: iptables
  EnableUserlandProxy: true
  UserlandProxyPath: /usr/bin/docker-proxy

Anything else?

This also can be reproduced in the same environment as in #14014. It does not happen on my Arch Linux box with the same Docker Compose and Docker deamon versions, or in the GHA based tests (which use Docker daemon from GHA's ubuntu:latest).

Activity

  1. ndeloof commented on Aug 11, 2026

    @ndeloof
    Contributor

    Verified against a containerd-image-store daemon: this is the "phantom recreate after pull" instance of the digest-identity class fixed by #14011 (which supersedes and includes #13998).

    The first up records the com.docker.compose.image label from the pull path (index digest); on the next up the image is local, so the identity is recomputed from the local inspect (per-platform manifest digest). The two digest kinds differ for the very same image, hence one phantom recreate that rewrites the label — which is why the third run is stable, and why graphdriver hosts (your Arch box) don't reproduce.

    With #14011's build the second up reports Running — no recreate. The scenario is locked by a dedicated e2e test in that PR, TestUpIdempotentContainerdStore, which removes the image first so the first up deterministically exercises the pull path.

    Side note: your step 2 log shows a pull despite --pull never — I could not reproduce that on current main (up --pull never with a missing image fails with No such image, no pull attempted).

  2. felixfontein commented on Aug 12, 2026

    @felixfontein
    ContributorAuthor

    Thanks for looking into this!

    Side note: your step 2 log shows a pull despite --pull never — I could not reproduce that on current main (up --pull never with a missing image fails with No such image, no pull attempted).

    Ah, I must have screwed something up when copying the commands I was running. As the subject says, the commands should be using --pull missing, not --pull never. I've changed the post accordingly. I've also run this again on a RHEL 10.2 VM, and the commands with --pull missing produce the posted output.

    (For the second and third run, --pull never also produces the same result. Maybe I did try that at some point, and accidentally copied that one instead of the --pull missing command... 🤷)

  3. felixfontein commented on Aug 17, 2026

    @felixfontein
    ContributorAuthor

    Thanks for fixing this! I can confirm that this no longer happens with Docker Compose 5.5.0.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions