Rule of thumb for application containers: processes that can communicate over the network and can run on their own, should be in separate containers (using separate images).
It’s a whole different thing with tooling containers: the image should already include everything required to perform all the tasks it should do, except the code itself, as it’s either cloned from a git repository, or bind mounted from the host into the container
Images for ci/cd pipelines can be more specialized, as jobs can be chained to a pipeline, where jobs can store artifacts that can be made available to other jobs of the same pipeline execution, so they can pick up the process and perform their tasks..