puppetlabs / puppetlabs-docker

The Puppet Docker repository
Apache License 2.0
91 stars 311 forks source link

Docker compose restarting service with docker.io/library/ container #967

Open linuxdaemon opened 9 months ago

linuxdaemon commented 9 months ago

Describe the Bug

docker_compose will not register a service as running if one of the containers uses an image in the form docker.io/library/<name>. This seems to be an old format but it is still valid and used (eg. by authentik).

Expected Behavior

The provider should handle prefixes like this and ignore them when looking for running containers. The running container will show <name>:<version> rather than docker.io/library/<name>:<version>.

Steps to Reproduce

Steps to reproduce the behavior:

  1. Deploy authentik with the docker_compose resource
    1. Something like
      docker_compose { 'authentik':
      ensure => present,
      compose_files => ['/my.compose.yaml']
      }
  2. Run puppet several times, each time it will report the service is not running and restart it.

Environment

Additional Context

I followed the authentik docs for setup and then moved the .env and docker-compose.yaml files to puppet

LordVeovis commented 3 weeks ago

I confirm the bug in version 10.0.1. It is located in lib/puppet/provider/docker_compose/ruby.rb around line 45 in the exists? function.

What's happening?

The function exists? compares the compose.yaml with what is currently running: It executes first:

/usr/bin/docker compose -f compose.yaml -p netbox config

and then fetches the .services[].image (yq query). If you have written docker.io/your-image in your compose.yaml, it will output docker.io/your-image. Then it executes:

/usr/bin/docker ps --format '{{.Label "com.docker.compose.service"}}-{{.Image}}' --filter label=com.docker.compose.project=your_project_name

this will output the image name of the running container, with docker.io omitted because it's hardcoded as the default provider.

In my case with the netbox stack:

# reading current conf
vm-prod-netbox2 [/srv/netbox]# /usr/bin/docker ps --format '{{.Label "com.docker.compose.service"}}-{{.Image}}' --filter label=com.docker.compose.project=netbox
netbox-housekeeping-netboxcommunity/netbox:v4.1.4-3.0.2
netbox-worker-netboxcommunity/netbox:v4.1.4-3.0.2
nginx-nginx:alpine-slim
netbox-netboxcommunity/netbox:v4.1.4-3.0.2
redis-valkey/valkey:8.0-alpine
postgresql-postgres:13-alpine
redis-cache-valkey/valkey:8.0-alpine
# reading conf from compose.yaml file
vm-prod-netbox2 [/srv/netbox]# /usr/bin/docker compose -f /srv/netbox/compose.yaml -p netbox config | yq .services[].image
netboxcommunity/netbox:v4.1.4-3.0.2
netboxcommunity/netbox:v4.1.4-3.0.2
netboxcommunity/netbox:v4.1.4-3.0.2
nginx:alpine-slim
postgres:13-alpine
docker.io/valkey/valkey:8.0-alpine
docker.io/valkey/valkey:8.0-alpine

exists? tests that count is the same (7 on both side), but images name are not the same, so puppet concludes that the stack must be reapplied. The difference here is on the valkey image.

If I drop the docker.io/ from my compose.yaml, my node changes his status to "UNCHANGED"

LordVeovis commented 3 weeks ago

Maybe we can use this regexp to "canonicalize" the image name from the config, at the end of the get_image function:

^(?:docker.io\/)?(?:library\/)?(?<image>.+?)(?:\:latest)?$

This regexp