Під час deployment ICanUp на новий VPS composer install зупинився на приватному GitLab package.
Composer повідомляв, що не зміг clone repository, і радив спробувати interactive mode.
Найцікавіше було далі: SSH-з'єднання з GitLab усередині Docker уже працювало.
Failed to clone the git@... repository,try running in interactive modedocker compose exec workspace \ ssh -T git@gitlab.comWelcome to GitLab, @username!
Спочатку я розділила одну помилку на три різні перевірки
Повідомлення Composer виглядає як одна проблема з GitLab, але насправді між composer install і private package є кілька окремих меж.
Кожну з них потрібно перевіряти окремо.
Рівень | Що він доводить |
|---|---|
| GitLab приймає SSH identity |
| Ця identity має доступ до конкретного repository |
| Composer запускає Git у правильному environment і використовує правильний repository URL |
ssh -T перевіряє account, а не конкретний package
Це була головна логічна пастка.
Якщо GitLab відповідає привітанням, легко зробити висновок, що SSH повністю справний.
Але ssh -T лише підтверджує, що key пов'язаний із GitLab account.
Доступ до окремого приватногорепозиторію є ще одною перевіркою авторизації.
Наступним тестом має бути саме repository
Тому після ssh -T я переходжу не до повторного Composer install, а до Git-команди для того самого репозиторію, який не зміг отримати Composer.
git ls-remote \ git@gitlab.com:group/private-package.gitgit ls-remote зручний тим, що перевіряє реальний repository URL і permissions, але не потребує повного clone.
Якщо ця команда падає, Composer ще не є головним підозрюваним.
Потім я перевіряю SSH agent, а не тільки SSH command
У Docker приватний ключ не обов'язково лежить усередині контейнера.
Кращий варіант - передати доступ до host SSH agent через socket.
Тоді container може використовувати identity, але private key не потрібно копіювати в image або project.
echo "$SSH_AUTH_SOCK" ssh-add -ldocker compose exec workspace \ sh -lc ' echo "$SSH_AUTH_SOCK" ssh-add -l ssh -T git@gitlab.com 'Мені важливі всі три результати: socket існує, агент бачить identity, GitLab її приймає.
Composer повинен запускатися в тому самому контексті
Ще одна пастка - перевірити SSH одним користувачем, а Composer запустити іншим.
У Docker або під час deployment це легко зробити непомітно.
Інший user може мати інший HOME, інший SSH_AUTH_SOCK, інший known_hosts і взагалі не бачити агента.
docker compose exec workspace \ sh -lc ' whoami id printf "HOME=%s\n" "$HOME" printf "SSH_AUTH_SOCK=%s\n" "$SSH_AUTH_SOCK" ssh-add -l 'SSH check і Composer потрібно порівнювати в одному container, під одним user і з тим самим environment.
sudo може прибрати SSH_AUTH_SOCK
Запуск Composer через sudo може змінити environment.
Тоді команда ssh -T від звичайного користувача працює, а Composer від root уже не має доступу до того самого agent socket.
# Avoid using this as a normal fix:sudo composer installRepository URL теж є частиною перевірки
SSH може працювати і permissions можуть бути правильними, але Composer все одно не отримає пакет, якщо URL репозиторію застарів або вказує не туди.
Це особливо важливо після перенесення GitLab проектів між групами або зміни ієрархії репозиторіїв.
composer config --list --source \ | grep -i gitlabТакож перевіряю composer.json і lock data, залежно від того, як приватний пакет підключений до проєкту.
grep -R "git@gitlab.com" \ composer.json \ composer.lockComposer -vvv показує, що він запускає насправді
Generic Failed to clone недостатньо для діагностики.
Verbose output дозволяє побачити URL репозиторію Git командою, на якому зупинився процес.
composer install \ --no-interaction \ -vvvЯ використовую цей output як доказ того, який URL і який transport Composer використовує, а не намагаюся вгадати це з composer.json.
Interactive mode не був справжнім поясненням
Фраза try running in interactive mode звучить так, ніби Composer просто хоче поставити запитання користувачу.
Але для приватного Git репозиторію це лише загальне повідомлення після невдалого клонування.
Я не сприймаю interactive mode як root cause. Спочатку потрібно знайти, чому саме Git не отримав repository.
known_hosts - окрема перевірка
SSH key і host verification вирішують різні задачі.
Агент може мати правильний key, але нове середовище ще не мати GitLab host key у known_hosts.
ssh-keygen -F gitlab.com ssh -vT git@gitlab.comЯ не копіюю private SSH key у Docker image
Найпростіше технічно рішення могло б виглядати як копіювання ~/.ssh/id_* у container.
Для мене це неправильна межа безпеки.
Private key не повинен ставати частиною image layer, repository або Docker build context.
Preferred: Host private key | vSSH agent | vforwarded socket | vDocker container | vGitLab Avoid: private key | vCOPY into Docker imageЧому я не починаю з composer clear-cache
Проблема клонування через SSH часто провокує очистити Composer cache.
Але якщо git ls-remote не має доступу до репозиторію, cache нічого не виправить.
Спочатку я перевіряю транспорт, ідентичність, дозволи сховища та контекст виконання.
Мій troubleshooting flow
Перевірка | Що означає результат |
|---|---|
| SSH identity працює |
| Агент бачить key |
| Є доступ саме до репозиторію пакета |
| Composer запускається в очікуваному environment |
| Видно реальний URL і Git command |
| URL репозиторію не застарів |
Порядок, який економить найбільше часу
- Не запускати Composer повторно десять разів з тією самою помилкою.
- Перевірити
SSH_AUTH_SOCK. - Перевірити identities через
ssh-add -l. - Перевірити
ssh -T git@gitlab.com. - Перевірити точний repository через
git ls-remote. - Звірити user,
HOMEі environment, у якому працює Composer. - Перевірити repository URL.
- Тільки після цього аналізувати
composer install -vvv.
Це продовження, а не повтор попереднього SSH agent setup
Раніше я вже описувала базове налаштування Composer, private GitLab repository і Docker SSH agent.
Цей кейс починається на наступному рівні: агент уже переданий, GitLab уже впізнає key, але одного цього факту недостатньо для успішного composer install.
Laradock wrapper не скасовує потребу перевіряти environment
У локальному середовищі я використовую Laradock wrappers, щоб команди виконувалися в потрібному runtime.
Це зручно, але wrapper не повинен приховувати від мене, під яким user запускається процес і який SSH socket він бачить.
Сам multi-PHP підхід я окремо описувала у Post про Laradock з кількома PHP runtime і командами dphp, dartisan та dcomposer.
Що я б не робила
Не вважала б успішний
ssh -Tдоказом доступу до конкретного приватного пакетаНе копіювала б приватний ключ у Docker image.
Не запускала б Composer через
sudoтільки для обходу SSH проблеми.Не вимикала б host verification назавжди.
Не починала б з очищення Composer cache без repository-level перевірки.
Не перевіряла б SSH одним користувачем, а Composer іншим.
Не ігнорувала б старий URL репозиторію після GitLab переміщення проекту.
Не оновлювала б залежності навмання, якщо
composer installпадає через transport.
Що я залишила собі на майбутнє
ssh -Tперевіряє account authentication, але не весь Composer flow.git ls-remoteє швидкою перевіркою доступу до конкретного репозиторію.SSH агента потрібно перевіряти через
SSH_AUTH_SOCKіssh-add -l.Composer і SSH діагностики мають виконуватися під одним user.
URL репозиторію потрібно перевіряти після переміщення або перейменування GitLab проекту.
composer install -vvvвикористовую для фактичного Git command і URL.Приватний ключ не копіюю в контейнер.
Generic Composer error розкладаю на authentication, authorization і execution context.
Успішний ssh -T означає: GitLab знає мій key. Він не означає: Composer точно може клонувати будь-який приватний репозиторій у цьому контейнер.
Висновок
У цьому кейсі найкориснішим результатом стало не знайти ще одну команду для Composer, а правильно розділити рівні проблеми.
GitLab уже впізнавав SSH identity всередині Docker, тому повторювати тільки ssh -T не мало сенсу.
Далі потрібно перевірити доступ до конкретного репозиторію, agent socket, user і environment Composer, актуальність URL репозиторію та реальний Git command у verbose output.
У ICanUp я після цього використовую просте правило: authentication success ще не дорівнює repository clone success.



