## Problem
Following the official production deployment instructions (Docker
Compose or Coolify), the app container enters a restart loop with:
```
Could not open input file: artisan
```
Reproducible outside Coolify by pulling the published image directly:
```bash
docker run --rm --entrypoint sh \
ghcr.io/whisper-money/whisper-money:latest \
-c 'ls -la /app; test -f /app/artisan && echo OK || echo MISSING'
# /app is empty -> ARTISAN_MISSING
```
## Root cause
The `:latest` tag (and the bare `:<sha>` tag) were assigned to the
**development** image, not the production one:
| Image | Dockerfile | `COPY`s code into `/app`? | Tags (before) |
|---|---|---|---|
| Development | `Dockerfile` (`php:8.4-cli`) | ❌ No — relies on the dev
`compose.yaml` bind-mount `.:/app` | **`latest`**, `<sha>` |
| Production | `Dockerfile.production` | ✅ Yes (`COPY . /app/.`) |
`production`, `<sha>-production`, `v<ver>-production` |
The development image never copies the code into the container (it only
works with the `compose.yaml` bind-mount). Pulled standalone, `/app` is
empty and `artisan` is missing, hence the boot crash.
Both official deployment entrypoints point at that tag:
- `docker-compose.production.yml` → `image:
${WHISPER_IMAGE:-ghcr.io/whisper-money/whisper-money:latest}`
- `templates/coolify/whisper-money.yaml` → `image:
ghcr.io/whisper-money/whisper-money:latest`
Nothing in the repo consumes the development `:latest`/`:<sha>` (the dev
`compose.yaml` builds locally, it doesn't `pull`), so publishing the
code-less image under `:latest` was purely a footgun.
## Fix
Reassign the tags to the industry-standard convention (`:latest` = the
deployable production image), touching only the `docker/metadata-action`
metadata blocks in `ci.yml`:
- `:latest` and bare `:<sha>` → **production image**
(`Dockerfile.production`).
- The development image is now published as `:development` /
`:<sha>-development`.
- Existing `:production` and `:v<version>-production` tags are kept, so
current pins remain backward compatible.
Applied to both jobs (`build-image` amd64 and `build-arm64-images`
arm64) so the multi-platform manifests stay consistent.
With this, `docker pull …:latest`, `docker-compose.production.yml`, and
the Coolify template all work with no further changes.