Зачем нужен Docker in Docker (Dind)?
Могу объяснить: когда вы запускаете Job-ы в docker контейнере и вам потребовалось обрати ться к демону докера (чтобы собрать образы напрмер) у вас есть два варианта: подключиться к тому же демону, в котором вы сами сидите (путем проброса сокета демона докера в контейнер, так назывемый socket binding), однако в таком случае возникают серьезные проблемы с безопасностью, так как из job-ы становится возможным управлять основным демоном и соответственно глушить чужие job-ы или вытаскивать чужие образы, которые собирались на этом же демоне. Поэтому пременяется другой подход: праллельно с контейнером в котором работает ваша job-а стартует еще один контейнер с демоном docker-in-docker, который доступен только для этой job-ы и не оставляет следов после ее завершения.
возможность запускать контейнер внутри контейнера нужна тогда, когда нет возможности запустить контейнер вне контейнера. например, когда для Gitlab CI/CD используется pipeline в контейнере (контейнер с gitlab-runner'ом), и в скриптах .gitlab-ci.yml имеются запуски других контейнеров (т. е. внутри контейнера с gitlab-runner'ом).