1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
|
# images4docker — Troubleshooting
## Overview
This document covers common issues encountered when building, pushing, or
using images4docker images, and how to diagnose and resolve them.
---
## Build Failures
### "Qt6 toolchain not found"
**Symptom:** The Docker build fails with:
```
Qt6 toolchain not found
```
**Cause:** The Qt6 verification gate ran after package installation and could
not find any of the expected binaries (`qmake6`, `qmake-qt6`, `qtpaths6`) in
any of the searched paths.
**Diagnosis:**
1. Check that the correct `PACKAGES` build argument was passed. For example,
on Debian/Ubuntu, the package is `qt6-base-dev`, not `qt6-base`:
```bash
docker build \
--file dockerfiles/debian-bookworm.Dockerfile \
--build-arg PACKAGES="qt6-base-dev" \
--tag test .
```
2. Check that Qt6 is actually available in the distribution's repositories.
Run an interactive container:
```bash
docker run --rm -it debian:bookworm sh
apt-get update
apt-cache search qt6
```
3. For RHEL-family distributions, check if CRB/PowerTools or EPEL needs to be
enabled. Use `CUSTOM_INSTALL`:
```bash
docker build \
--file dockerfiles/alma-9.Dockerfile \
--build-arg CUSTOM_INSTALL="dnf config-manager --enable crb && dnf install -y epel-release qt6-qtbase-devel" \
--tag test .
```
4. Verify the Qt6 binary location inside the container:
```bash
docker run --rm -it <base_image>:<tag> sh
# Install Qt6 packages manually, then:
find / -name 'qmake*' -o -name 'qtpaths*' 2>/dev/null
```
If the binaries are in an unexpected path, the Dockerfile may need the
extended path variant (with `/usr/libexec/qt6`).
**Resolution:**
- Ensure correct Qt6 package names for the distribution.
- Enable required repositories (CRB, EPEL, backports).
- If the distribution does not provide Qt6 at all, it should be excluded from
the active CI matrix.
---
### "manifest not found" or "pull access denied"
**Symptom:** The build fails immediately at the `FROM` instruction:
```
ERROR: pull access denied, repository does not exist or may require authentication
```
or:
```
ERROR: manifest for <image>:<tag> not found
```
**Cause:** The upstream base image tag no longer exists. This can happen when:
- A distribution reaches end-of-life and its Docker image is removed.
- A distribution renames or reorganises its official images.
- A registry changes its namespace (as CentOS did from Docker Hub to Quay.io).
**Diagnosis:**
```bash
docker pull <base_image>:<tag>
```
If this fails, the tag is no longer available.
**Resolution:**
- Check the distribution's official Docker Hub / Quay.io page for the current
tag names.
- Update the `FROM` line in the Dockerfile.
- If the distribution is EOL, remove the Dockerfile and its workflow matrix entry.
---
### Package installation fails
**Symptom:** The `dnf install`, `apt-get install`, or other package manager
command fails with "No package found" or similar.
**Cause:** Package names vary between distribution versions. For example:
- Fedora uses `qt6-qtbase-devel`, Debian uses `qt6-base-dev`.
- Some RHEL versions need `qt6-qtbase-devel`, others `qt6-qtbase-devel`.
- Alpine uses `qt6-qtbase-dev` (with musl, not glibc).
**Diagnosis:**
Run an interactive container and search for packages:
```bash
# Debian/Ubuntu
docker run --rm -it debian:bookworm sh -c 'apt-get update && apt-cache search qt6'
# Fedora/RHEL
docker run --rm -it fedora:42 sh -c 'dnf search qt6'
# Alpine
docker run --rm -it alpine:3.22 sh -c 'apk search qt6'
# openSUSE
docker run --rm -it opensuse/tumbleweed:latest sh -c 'zypper search qt6'
# Arch
docker run --rm -it archlinux:latest sh -c 'pacman -Ss qt6'
```
**Resolution:**
- Use the correct package names for the distribution.
- If a package was renamed, update the `PACKAGES` in the workflow matrix.
- If a package is missing, try `CUSTOM_INSTALL` to enable additional repositories.
---
### "set -u: unbound variable"
**Symptom:** The build fails with a message about an unbound variable.
**Cause:** The `set -u` flag (part of `set -eux`) causes the shell to fail
on any reference to an unset variable. However, all `ARG` values default to
empty strings (`ARG PACKAGES=`), so this should not normally occur.
**Diagnosis:** Check that all `ARG` declarations are present in the Dockerfile
and that they have default values:
```dockerfile
ARG PACKAGES=
ARG CUSTOM_INSTALL=
ARG UPDATE_CMD=
ARG CLEAN_CMD=
```
**Resolution:** Ensure all four `ARG` lines are present with `=` (defaulting
to empty string).
---
## Push Failures
### GHCR authentication failure
**Symptom:** `docker push` fails with "authentication required" or
"denied: permission denied".
**Cause:**
- The `GITHUB_TOKEN` does not have `packages: write` permission.
- The workflow permissions are not configured correctly.
**Resolution:**
- Ensure the workflow has:
```yaml
permissions:
packages: write
contents: read
```
- Verify the repository settings allow GitHub Actions to push packages.
---
### Image size unexpectedly large
**Symptom:** A pushed image is much larger than expected.
**Cause:** The cleanup command did not run, or it was overridden with an
empty / incorrect value.
**Diagnosis:**
Check the image size:
```bash
docker images --format "{{.Repository}}:{{.Tag}} {{.Size}}" | grep project-tick
```
Compare with the base image size:
```bash
docker images --format "{{.Repository}}:{{.Tag}} {{.Size}}" | grep <base_image>
```
**Resolution:**
- Verify the cleanup command is correct for the package manager.
- Check that `CLEAN_CMD` is not set to an empty string (which would skip
the default cleanup).
- For apt-based images, ensure `rm -rf /var/lib/apt/lists/*` runs after install.
- For dnf-based images, ensure `dnf clean all` runs.
---
## Runtime Issues
### "command not found" in CI jobs
**Symptom:** A CI job using a images4docker image reports "command not found"
for tools like `cmake`, `gcc`, or `make`.
**Cause:** The image was built without the complete `PACKAGES` list, or the
build argument was incorrect.
**Diagnosis:**
```bash
docker run --rm ghcr.io/project-tick-infra/images/<name>:<tag> which cmake
```
**Resolution:**
- Check the `PACKAGES` build argument in the workflow matrix.
- Rebuild the image with the correct package list.
---
### Qt6 binaries not in PATH
**Symptom:** CI jobs report `qmake6: command not found` even though the
image was built successfully.
**Cause:** The `export PATH=...` in the Dockerfile's `RUN` instruction only
applies during the build. It does **not** persist as an environment variable
in the final image.
**Diagnosis:**
```bash
docker run --rm ghcr.io/project-tick-infra/images/<name>:<tag> sh -c 'echo $PATH'
```
If the Qt6 paths are not in the output, they need to be set at runtime.
**Resolution:**
- In CI jobs, explicitly set the PATH:
```yaml
env:
PATH: "$PATH:/usr/lib/qt6/bin:/usr/lib64/qt6/bin"
```
- Or use the full path to the binary: `/usr/lib64/qt6/bin/qmake6`.
- Consider adding an `ENV PATH=...` line to the Dockerfiles (this is a
design decision — currently not done to keep images generic).
---
### Alpine: "Error relocating" or linking errors
**Symptom:** Compiled binaries on Alpine fail at runtime with relocation
errors or "not found" for shared libraries.
**Cause:** Alpine uses `musl libc`, not `glibc`. Binaries compiled on
glibc-based distributions are not compatible.
**Resolution:**
- Ensure all dependencies are compiled against musl on Alpine.
- This is not an images4docker issue per se — it is an Alpine-specific constraint.
- Use a glibc-based image (Debian, Fedora, etc.) if glibc compatibility is required.
---
## Debugging Techniques
### Interactive Build
Add `--progress=plain` to see the full build output:
```bash
docker build --progress=plain \
--file dockerfiles/<distro>.Dockerfile \
--build-arg PACKAGES="..." \
--tag test .
```
### Shell into a Failed Build
If the build fails, start a container from the base image and manually
run the install commands:
```bash
docker run --rm -it <base_image>:<tag> sh
```
Then manually execute the RUN commands to see where they fail.
### Check Build Arguments
Print the build arguments to verify they are being passed correctly:
```bash
docker build \
--file dockerfiles/<distro>.Dockerfile \
--build-arg PACKAGES="qt6-base-dev cmake" \
--build-arg UPDATE_CMD="echo UPDATE_CMD is set" \
--tag test .
```
The `set -x` (from `set -eux`) will print each command, including the
expanded variable values.
### Compare with a Working Image
If a new Dockerfile fails but a similar one works, diff them:
```bash
diff dockerfiles/fedora-42.Dockerfile dockerfiles/fedora-43.Dockerfile
```
The only difference should be the `FROM` line.
### Inspect a Built Image
```bash
# Check image layers
docker history ghcr.io/project-tick-infra/images/<name>:<tag>
# Check image metadata
docker inspect ghcr.io/project-tick-infra/images/<name>:<tag>
# Get a shell in the image
docker run --rm -it ghcr.io/project-tick-infra/images/<name>:<tag> sh
```
---
## Known Limitations
### No Qt5 fallback
If a distribution cannot provide Qt6, there is no option to fall back to Qt5.
The image will fail the verification gate. This is intentional.
### No multi-arch support
Currently all images are built for `linux/amd64` only. There is no
`linux/arm64` or other architecture support.
### PATH not persisted
The `export PATH=...` in the `RUN` instruction does not create a persistent
`ENV` in the image. CI jobs may need to set `PATH` themselves.
### Single-layer constraint
All package installation happens in a single `RUN` instruction. If you need
to debug which specific package fails, you must do so interactively rather
than by inserting intermediate `RUN` instructions (which would change the
template structure).
---
## Getting Help
1. Check the CI workflow logs (GitHub Actions) for the exact error message.
2. Reproduce locally with `docker build --progress=plain`.
3. Run an interactive container from the base image to test package availability.
4. Consult the distribution's documentation for Qt6 package names.
5. Review the [Base Images](base-images.md) documentation for distribution-specific notes.
---
## Related Documentation
- [Overview](overview.md) — project summary
- [Architecture](architecture.md) — Dockerfile template structure
- [Base Images](base-images.md) — per-distribution details
- [Qt6 Verification](qt6-verification.md) — the verification gate
- [CI/CD Integration](ci-cd-integration.md) — workflow details
- [Creating New Images](creating-new-images.md) — adding new distributions
|