Repository navigation
gatk4 modules: shared gatk4+gcnvkernel container is ~2 GB, but only 3 modules need gcnvkernel #13031
Description
Description
64 of the 65 gatk4/* modules use the combined gatk4-main + gcnvkernel container (currently community.wave.seqera.io/library/gatk4-main_gcnvkernel:961440660027ec01; previously gatk4_gcnvkernel:edb12e4f0bf02cd3, which nf-core/sarek still pins). Only cnnscorevariants differs.
Only the germline CNV tools import gcnvkernel: gatk4/germlinecnvcaller, gatk4/determinegermlinecontigploidy and gatk4/postprocessgermlinecnvcalls. Every other GATK tool needs just Java and the GATK jar, yet pulls the whole gcnvkernel Python/R/PyTorch stack.
Impact
Measured on gatk4_gcnvkernel:edb12e4f0bf02cd3 (gatk4 4.6.2.0 + gcnvkernel 0.9). I did not measure the 4.7.0.0 image; it is built from the same recipe, so its size should be similar.
- One 1.98 GB compressed layer: 4.54 GiB uncompressed, 322 conda packages.
- Every GATK step on a fresh node downloads about 2 GB. That includes MarkDuplicates, BaseRecalibrator, ApplyBQSR, HaplotypeCaller, Mutect2 and MergeVcfs, even though none of them uses gcnvkernel.
- It is too large for the CDN cache. The single blob exceeds the usual per-object cache limit (512 MB on Cloudflare's standard plans), so every pull is served uncached from origin. Under heavy concurrent pulling (22–25 Sep 2026) downloads of this layer slowed down enough to miss 15-minute pull timeouts. sarek runs failed on
MergeVcfs,LearnReadOrientationModelandIntervalListToBed, none of which needs gcnvkernel.
Where the size comes from (measured, uncompressed)
| Component | Size | Needed? |
|---|---|---|
Intel MKL (blas=*=mkl, pytorch *mkl*) |
760 MiB | No, only as a BLAS backend (OpenBLAS is ~30 MiB) |
Python packages vendored a second time as .egg dirs inside the gcnvkernel conda package (numpy, scipy, pandas, arviz, …) |
371 MiB | No, duplicates of the conda copies |
| pytorch 2.1 + pytorch-lightning | 406 MiB | No, gcnvkernel never imports them |
| Qt / PyQt5 (matplotlib GUI backend) | 199 MiB | No |
| R 4.3 + ggplot2, dplyr, data.table, … | 136 MiB | No (GATK plotting helpers) |
| scikit-learn | 40 MiB | No |
| gcc / LLVM toolchain | 698 MiB | Yes: pytensor compiles its graphs at runtime |
| OpenJDK 17 + GATK jar | ~720 MiB | Yes |
The root cause is the bioconda gcnvkernel recipe. It pins GATK's full Python environment (pytorch 2.1.0 *mkl*, pytorch-lightning, r-base, r-ggplot2, scikit-learn, blas 1.0 mkl, …). gcnvkernel's code only imports numpy, pymc, pytensor, scipy, pandas, tqdm and vcf. Its own requires.txt lists pymc==5.10.0, pytensor==2.18.1, numpy==1.26.2, scipy==1.11.4 and tqdm==4.66.1.
Proposal
-
Split the container. The ~61 non-CNV modules would use a GATK-only environment,
bioconda::gatk4-mainalone, which needs onlyopenjdkandpython. Estimated from conda package sizes: ~570 MiB (GATK jar ~381 MiB + OpenJDK ~162 MiB + python), about 3.5× smaller. The combined gatk4 + gcnvkernel image stays only on the 3 CNV modules, plus the htslib/samtools variantmarkduplicatesneeds. -
Slim the bioconda
gcnvkernelrecipe (bioconda-recipes):- declare only the packages it imports (
pymc,pytensor,numpy,scipy,pandas,tqdm,pyvcf); - install with
pip install --no-depsso it stops vendoring duplicate.eggcopies; - drop pytorch, pytorch-lightning, the R packages, scikit-learn and the Qt backend.
Estimated saving: about 1.1 GiB uncompressed on the CNV image while keeping MKL.
- declare only the packages it imports (
-
Optional: OpenBLAS instead of MKL in the CNV image saves another ~0.7 GiB. It needs a numerical check of the gCNV outputs first.
The sizes in (1) and (2) are estimates from conda package archive sizes, not built images. Even a GATK-only image lands near 512 MB, because the GATK jar alone is ~381 MiB compressed. So keeping every layer under a 512 MB CDN limit would also need the JDK and GATK in separate layers. That is a Seqera Containers build concern, and we are looking at it separately.
I'm happy to help with the PRs.
Activity
adamrtalbot commentedon Sep 25, 2026
Looking at the history, this introduced the Seqera Containers with the gCNV kernel: #8401
Previously there was a mulled container:
quay.io/biocontainers/mulled-v2-d9e7bad0f7fbc8f4458d5c3ab7ffaaf0235b59fb:7cc3d06cbf42e28c5e2ebfc7c858654c7340a9d5-0but it's unclear to me if it includes the gCNV kernel.I'd agree, we should use the smallest possible container for each GATK4 tool.
Having said that, given Docker pulls are idempotent and lots of pipelines will use several GATK4 processes, it may be more efficient for local storage to use the same container for the majority of GATK4 modules. Perhaps a compromise is to make one container that does 80% of modules and make special containers for the unusual tools like CNV calling.
adamrtalbot commentedon Sep 25, 2026
ahhh looks like the bioconda recipe includes the kernel: https://github.com/bioconda/bioconda-recipes/blob/master/recipes/gatk4/meta.yaml#L35