
Unless you are working in a fully automated build environment like a CI runner, you will need to have some version of Composer running within your PHP codebase to be able to pull packages and configure autoloading.
Composer has the ability to enforce certain environmental constraints such as: which version of PHP is required, any extensions that must be present, etc. These environment checks are great, but they don’t work properly if you don’t run Composer locally. If you were to try and run Composer on your local machine and mount the files into your image, it would probably work but, you lose the enforcement of those environment constrains. Instead Composer is checking that your local machine meets the requirements—which is problematic at best and reckless at worst.
Installing
The Old Way
Installing Composer has gotten a bit more complicated over the years. Originally we has this simple construct of downloading the installer, piping it through php
and then moving it into the path.
sudo curl -s https://getcomposer.org/installer | php
sudo mv composer.phar /usr/local/bin/composer
This method was indeed easy, but it wasn’t (and isn’t) the most secure. If the getcomposer.org website were ever compromised we would be running whatever php code it provided as root
. Yuck.

The Secure Way
The updated guidance for installing looks more like this:
php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
php -r "if (hash_file('sha384', 'composer-setup.php') === '<hash>') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"
php composer-setup.php
php -r "unlink('composer-setup.php');"
This is better since we are checking that the downloaded file matches the known file hash. This helps to let us know the installer is legit and can be used safely. This method though requires you to lookup the current versions hash and insert it into your commands (where I have <hash>
, above). Sure, you can copy and paste it quickly from the website, but still a bit of a pain.
The Automated Way
To eliminate the need for checking in with the website all the time, the folks at Composer also provide a script that can be used to install Composer.
#!/bin/sh
EXPECTED_CHECKSUM="$(wget -q -O - https://composer.github.io/installer.sig)"
php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
ACTUAL_CHECKSUM="$(php -r "echo hash_file('sha384', 'composer-setup.php');")"
if [ "$EXPECTED_CHECKSUM" != "$ACTUAL_CHECKSUM" ]
then
>&2 echo 'ERROR: Invalid installer checksum'
rm composer-setup.php
exit 1
fi
php composer-setup.php --quiet
RESULT=$?
rm composer-setup.php
exit $RESULT
This works well if you are on a *NIX based machine and you keep this bash script handy any time you want to install Composer. This does allow for automated installation but things are getting complicated here when you compare to the original install method.
Multi-Stage Docker Build
This is by far my favorite way to install Composer. It takes advantage of a relatively new feature in Docker called multi-stage builds. In this method we can install Composer in exactly ONE line of code. That’s right: one!
FROM php:7.4
COPY --from=composer /usr/bin/composer /usr/bin/composer
# The rest of your Dockerfile goes here.
Using a multi-stage build, you can pull the official Composer Docker image and copy it’s composer
binary directly to your own Docker image. After that the Composer Docker image is disposed of and you are on your way to glory.
This is literally one line of code and you’re off to the races. Can’t beat that.
