0% прочитано

Composer у Docker не має доступу до GitLab: як передати SSH Agent

На хості SSH до GitLab працює, але Composer усередині Docker просить username і password або повертає Permission denied (publickey). Показую на реальному Laradock-кейсі, як знайти причину та передати SSH Agent у container.

17 серпня 2026 р. 4 хв читанняLaradock
Composer у Docker не мав доступу до приватного GitLab repository, хоча SSH на хості працював без проблем. Під час оновлення приватного Composer-пакета замість звичайного git fetch я раптом отримала Permission denied (publickey), а Composer почав просити GitLab username і password.

Спочатку це виглядало як проблема з GitLab або доступом до самого пакета. Але на хості я могла підключитися до GitLab через SSH, тому почала перевіряти не credentials, а різницю між host environment і Docker workspace.

У моєму випадку Composer запускається всередині Laradock workspace. І саме там виявилася справжня причина: Docker container не бачив SSH Agent, який уже працював на хості.

Симптом: Composer просить GitLab credentials

Проблема проявилася під час звичайного оновлення приватного пакета через Composer.

Composer update
dcomposer update avn/laravel-localization --with-dependencies

Замість оновлення package Composer спробував звернутися до приватного GitLab repository і не зміг пройти SSH authentication.

Після цього він запропонував ввести GitLab credentials. Це було важливим сигналом: проблема не обов'язково була в Composer. Він просто не міг використати той спосіб доступу до GitLab, який працював у мене на хості.

Що просив Composer
Permission denied (publickey). Username:Password:

Перевіряю SSH на хості

Першою я перевірила найпростішу річ: чи взагалі працює SSH до GitLab поза Docker.

Check GitLab SSH on host
ssh -T git@gitlab.com
Успішна відповідь SSH
Welcome to GitLab, @xmarynkam!
Цей результат одразу звузив пошук. SSH key був валідний, GitLab його приймав, а мій користувач мав доступ. Отже, додавати новий Personal Access Token або змінювати пароль не було сенсу.

А що бачить Docker workspace?

Ту саму перевірку я запустила вже всередині Laradock workspace, де реально працює Composer.

Перевірка GitLab SSH всередині Docker
docker compose exec workspace-85 ssh -T git@gitlab.com
Docker SSH error
git@gitlab.com: Permission denied (publickey).

Ось тут різниця стала очевидною: на тому самому комп'ютері GitLab SSH працював на хості, але не працював усередині container.

Наступною перевіркою був SSH Agent. На хості він уже містив мої ключі, а в Docker workspace змінна SSH_AUTH_SOCK була порожньою.

Перевірка SSH агента
echo "SSH_AUTH_SOCK=$SSH_AUTH_SOCK"ssh-add -l
До
text
Host SSH key → ssh-agent → GitLab ✓  Docker Composer → Git → SSH          no SSH agent ✗
Після
text
Host ssh-agent      │ mounted socketDocker workspace      └── Git / Composer → GitLab ✓

Причина була в SSH_AUTH_SOCK

SSH Agent працює як окремий процес на хості й тримає доступ до вже завантажених SSH keys. Програми звертаються до нього через socket, шлях до якого знаходиться в SSH_AUTH_SOCK.

Docker container автоматично не отримує цей socket. Тому Git усередині workspace не міг скористатися моїм SSH Agent, навіть попри те, що на хості все було налаштовано правильно.

Для мене це і було ключем до проблеми: не потрібно було переносити SSH key у container. Потрібно було дати container доступ до вже працюючого host SSH Agent.

Передаю SSH Agent у Laradock

Я винесла налаштування SSH Agent в окремий Docker Compose anchor, щоб не дублювати його для кожної PHP workspace.

YAML
x-local-ssh-agent: &local-ssh-agent  environment:    SSH_AUTH_SOCK: /ssh-agent  volumes:    - "${SSH_AUTH_SOCK}:/ssh-agent"

Host socket монтується всередину container як /ssh-agent, а SSH_AUTH_SOCK уже всередині workspace вказує саме на нього.

У мене є кілька Laradock workspace для різних PHP versions, тому цей anchor я підключила до кожної CLI workspace.

YAML
services:  workspace:    <<: [*local-host-config, *local-ssh-agent]   workspace-84:    <<: [*local-host-config, *local-ssh-agent]   workspace-85:    <<: [*local-host-config, *local-ssh-agent]
Я не копіюю private SSH keys у Docker image або container. Container отримує лише доступ до socket SSH Agent, який уже працює на хості.

Recreate workspace після зміни Compose

Зміна volume та environment не з'явиться в уже запущеному container сама, тому workspace потрібно recreate.

Recreate Laradock workspace
docker compose up -d \  --force-recreate \  --no-deps \  workspace-85

Перевіряю SSH Agent усередині container

Після recreate я спочатку перевірила не Composer, а сам SSH Agent. Так простіше зрозуміти, чи інфраструктурна частина вже працює.

Verify forwarded SSH Agent
docker compose exec --user laradock workspace-85 sh -lc 'echo "SSH_AUTH_SOCK=$SSH_AUTH_SOCK"ssh-add -l'

Коли список ключів з'явився всередині workspace, я повторила пряме SSH-підключення до GitLab.

bash
docker compose exec --user laradock workspace-85 \  ssh -o StrictHostKeyChecking=accept-new -T git@gitlab.com
Successful Docker SSH response
Welcome to GitLab, @xmarynkam!

І тільки тоді повертаюся до Composer

Після цього я повторила ту саму Composer-команду, з якої все почалося. Цього разу Composer зміг звернутися до приватного GitLab repository через Git і оновив package без запиту username або password.

Сам dcomposer у мене є частиною локального multi-PHP workflow з dphp, dartisan і dcomposer, де для кожного проєкту автоматично вибирається правильний Laradock workspace.

Для мене це хороший приклад того, чому корисно перевіряти проблему шарами:

  1. спочатку GitLab SSH,

  2. потім Docker,

  3. потім SSH Agent

  4. і лише після цього Composer.

Composer update after the fix
dcomposer update avn/laravel-localization --with-dependencies

Чого я б тут не робила

  • Копіювати приватний SSH key всередину Docker image або container.

  • Зберігати GitLab password у container.

  • Вводити Personal Access Token щоразу, коли Composer просить credentials.

  • Вважати проблему Composer-проблемою, не перевіривши спочатку звичайний git/SSH доступ із того самого environment.

Що я вз'яла з цього кейсу

У моєму випадку Composer лише показав симптом. Реальна проблема була на рівень нижче: Git усередині Docker не мав доступу до host SSH Agent.

Після того як я передала SSH_AUTH_SOCK через Docker Compose і змонтувала agent socket у Laradock workspace, той самий SSH key почав працювати і на хості, і всередині container.

Тепер це налаштування використовується всіма моїми PHP workspaces, а приватні Composer packages можна оновлювати без копіювання ключів і без окремих credentials усередині Docker.