I need to run php composer in a docker utility container as a part of setting up a PHP development environment.
I am using the official composer
docker image, and following steps in the dockerhub documentation.
composer install
as current local user so that the vendor directory created with same permissions.It seems to be a common requirement and a ready solution available in the doc
eval $(ssh-agent); \
docker run --rm --interactive --tty \
--volume $PWD:/app \
--volume $SSH_AUTH_SOCK:/ssh-auth.sock \
--volume /etc/passwd:/etc/passwd:ro \
--volume /etc/group:/etc/group:ro \
--env SSH_AUTH_SOCK=/ssh-auth.sock \
--user $(id -u):$(id -g) \
composer install
But it did not works for me and composer asking for a github token (Running Docker version 26.0.0 from Ubuntu 23).
The command looks good for me as it binds the SSH_SOCKET
to the container and also the /etc/passwd
and /etc/group
files.
But why does the SSH agent forward doesn't works as expected?
What I've tried so far,
I've tried to check the SSH connection to github with docker command sh -c "ssh -T git@github.com"
instead of install
- That gives error Could not create directory '/home/<user>/.ssh'
and permission denied to github.
I've tried to add my SSH key to ssh-agent and run the docker command, but received same error (also with composer install
command)
eval $(ssh-agent -s) && \
ssh-add ~/.ssh/<my_private_key> && \
docker run --rm --interactive --tty \
--volume $PWD:/app \
--volume $SSH_AUTH_SOCK:/ssh-auth.sock \
--volume /etc/passwd:/etc/passwd:ro \
--volume /etc/group:/etc/group:ro \
--env SSH_AUTH_SOCK=/ssh-auth.sock \
--user $(id -u):$(id -g) \
composer \
sh -c "ssh -T git@github.com"
Tried to bind my system SSH keys to container as a next solution, but I don't know how to do that correctly, composer uses alpine
linux base image, and I think the default location SSH looks for keys is /home/<user>/.ssh
, I ve tried creating users and home directory using a Dockerfile but that also failed.
The last resort is to use a github token for pulling private composer dependencies, but is there a way to do this with SSH?
Answering my own question,
The issue was with the ssh-add
command,
eval $(ssh-agent); \
docker run --rm --interactive --tty \
...
This alone did not works and I need to add my ssh key after the ssh-agent
initialization like this,
eval $(ssh-agent -s) && \
ssh-add ~/.ssh/id_rsa && \
docker run --rm --interactive --tty \
...
(Note: This was already mentioned in the question, but It was a mistake that I got multiple ssh keys and provided the wrong one that time.
Also made some changes from the documentation mentioned approach that is mentioned below)
This is not an elegant way to run composer like this (as suggested by @david-maze in the question comments), but if your requirement is to keep everything in isolated containers, you can check this one.
So need to run this long command every time I need to do a composer install, which is not convenient and also there is no caching (packages will be downloaded every time) also there is this ssh known-host
prompt that appears every time you are connecting to github to pull a private repo.
The authenticity of host 'github.com (20.111.11.82)' can't be established.
ECDSA key fingerprint is SHA256:XXXXX.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
And in my case, I am using this in a development environment setup, so I can create a user with a Dockerfile
at the setup time so that the /etc/passwd
and /etc/group
bindings can be removed,
So created a docker compose
configuration like this,
composer:
build:
context: .
dockerfile: ./dockerfiles/composer.dockerfile
args:
USER_ID: ${C_UID}
GROUP_ID: ${C_GID}
UNAME: ${C_USER}
container_name: util-composer
user: "${C_UID}:${C_GID}"
# For the container
environment:
SSH_AUTH_SOCK: "/ssh-auth.sock"
volumes:
- "$PWD:/app"
- "util_composer_cache:/tmp"
# docker host ssh forwarding
- "$SSH_AUTH_SOCK:/ssh-auth.sock"
command: "update --no-progress --no-interaction --ignore-platform-reqs"
stdin_open: true
tty: true
networks:
- my-network
--ignore-platform-reqs
is required as the source code php dependent libraries will not be there in your composer utility container.util_composer_cache:/tmp
- a named volume is attached to /tmp
which is the path composer stores cache.This is the Dockerfile
.
FROM composer
ARG USER_ID=1000
ARG GROUP_ID=1000
ARG UNAME=nonrootuser
RUN addgroup -g $GROUP_ID $UNAME \
&& adduser -G $UNAME -g $UNAME -s /bin/sh -u $USER_ID -D $UNAME \
&& mkdir -p /home/$UNAME/.ssh \
&& chmod 700 /home/$UNAME/.ssh \
&& chown $USER_ID:$GROUP_ID /home/$UNAME/.ssh \
&& su - $UNAME -c "ssh-keyscan github.com >> /home/$UNAME/.ssh/known_hosts"
known_hosts
listNow run command like this for the default command,
eval $(ssh-agent -s) && \
ssh-add ~/.ssh/id_rsa && \
C_USER=$(whoami) C_UID=$(id -u) C_GID=$(id -g) docker compose run --rm composer
Now at last to simplify the command - Add this in ~/.zshrc
/~/.bashrc
to use as alias
composer-util() {
eval $(ssh-agent -s)
ssh-add "${HOME}/.ssh/id_rsa"
C_USER=$(whoami) C_UID=$(id -u) C_GID=$(id -g) docker compose run --rm composer "$@"
}
finally, use like this,
# This will run the default command - "update --no-progress --no-interaction --ignore-platform-reqs" in my case
composer-util
# but can be override with any composer command (as the composer is the ENTRYPOINT set)
composer-util dump-autoload -o