116

I try to work out a way to create a dev environment using docker and laravel.

I have the following dockerfile:

FROM php:7.1.3-fpm

RUN apt-get update && apt-get install -y libmcrypt-dev \
    mysql-client libmagickwand-dev --no-install-recommends \
    && pecl install imagick \
    && docker-php-ext-enable imagick \
&& docker-php-ext-install mcrypt pdo_mysql
&& chmod -R o+rw laravel-master/bootstrap laravel-master/storage

Laravel requires composer to call composer dump-autoload when working with database migration. Therefore, I need composer inside the docker container.

I tried:

RUN curl -sS https://getcomposer.org/installer | php -- \
--install-dir=/usr/bin --filename=composer

But when I call

docker-compose up
docker-compose exec app composer dump-autoload

It throws the following error:

rpc error: code = 13 desc = invalid header field value "oci runtime error: exec failed: container_linux.go:247: starting container process caused \"exec: \\\"composer\\\": executable file not found in $PATH\"\n"

I would be more than happy for advice how I can add composer to the PATH within my dockerfile or what else I can do to surpass this error.

Thanks for your support. Also: this is the gitub repository if you need to see the docker-compose.yml file or anything else.

Andre
  • 4,185
  • 5
  • 22
  • 32
  • 2
    Is there a need to reinvent the wheel? Why not use out-of-the-box solutions for docker, PHP and Laravel (like [Laradock](http://laradock.io/) that covers pretty much everything you need and is easily configurable)? – d3jn Jul 20 '18 at 13:30
  • Alternatively, there is always the possibility to use composer as `.phar` checked in as part of the repository. – Namoshek Jul 20 '18 at 13:31
  • 1
    Are you sure your container is successfully build? This script already makes composer executable. docker run -it --rm php:7.1.3-fpm bash curl -sS https://getcomposer.org/installer | php -- \ --install-dir=/usr/bin --filename=composer composer --version Composer version 1.6.5 2018-05-04 11:44:59 So problem is not in the docker or composer itself, probable wrong-config or some issue with docker-compose – AlTak Jul 20 '18 at 13:57
  • @AITak, thanks for the answer, I will check it out! – Andre Jul 21 '18 at 08:30
  • 1
    @d3jn this is the first time I work with docker and I want to rebuild this laravel + docker walking skeleton to learn from it. Thanks anyway for pointing it Laradock! – Andre Jul 21 '18 at 08:31
  • 1
    @d3jn of course not, but this is only one possible scenario - try to think of all the people who will arrive at this post because they have a custom image build that also needs composer. Workarounds for specific use cases tend not to be very useful on SO. – Peter Kionga-Kamau Aug 05 '21 at 00:51

10 Answers10

306

You can perform an in-line Multi-stage build using composer image so you will basically just copy composer binary into the PHP docker image.

In Dockerfile :

COPY --from=composer:latest /usr/bin/composer /usr/local/bin/composer
noraj
  • 3,964
  • 1
  • 30
  • 38
ybenhssaien
  • 3,427
  • 1
  • 10
  • 12
  • 7
    Just be aware that `--from` is fairly new and won't be available in all environments. – Fuzzy76 Mar 25 '20 at 09:39
  • 7
    Note if you have packages in your `composer.json` which can only be installed from source then you will also need to install `git`. – luukvhoudt Jun 30 '20 at 11:10
  • 1
    What about the xdebug? – FabianoLothor Jul 24 '21 at 05:03
  • 3
    If you need a specific Version, this works fine, Tank you. I am using this `COPY --from=composer:2.1.8 /usr/bin/composer /usr/local/bin/composer` – YusufFidan Oct 04 '21 at 17:40
  • 1
    I received following error: `invalid from flag value composer:latest: Get "https://registry-1.docker.io/v2/": net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)` – soroush Jan 28 '22 at 06:21
  • 2
    My problem solved. I just stopped `firewalld` service on system – soroush Jan 28 '22 at 08:42
  • 1
    This is SO fast and amazing! Does anyone know if it's safe to use this with other libraries such as nodejs for instance? – Lukas Aug 15 '22 at 10:13
158

I can install composer adding this line on my test dockerfile:

# Install Composer
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer

Here is the dockerfile:

FROM php:7.1.3-fpm

RUN apt-get update && apt-get install -y libmcrypt-dev \
    mysql-client libmagickwand-dev --no-install-recommends \
    && pecl install imagick \
    && docker-php-ext-enable imagick \
&& docker-php-ext-install mcrypt pdo_mysql

# Install Composer
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer

It works for me, to test if the composer are installed i access to my container bash and execute:

composer --version
Composer version 1.6.5 2018-05-04 11:44:59
Marcin Orlowski
  • 72,056
  • 11
  • 123
  • 141
Brayan Caldera
  • 2,001
  • 2
  • 11
  • 20
  • Isnt composer --version just returning output from host machine? Or where do you call it? – Darius.V Oct 21 '20 at 13:21
  • 4
    you need to run the image generated with `docker run -dit my-image` command, after that you need to execute `docker exec -it container-id sh`, and with this command you can access to the container terminal, when you are on the container terminal you can execute the `composer --version` command to validate that this is installed on your container – Brayan Caldera Oct 21 '20 at 21:17
  • 1
    Since Composer 2.0 is out and many projects still need the 1.x version, you can also pass --version to the installer for a specific Composer version as such: `RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer --version=1.10.22 ` – Mihai MATEI Jun 28 '21 at 08:13
  • 2
    Better to get it like so: `COPY --from=composer:latest /usr/bin/composer /usr/local/bin/composer`, from [this answer](https://stackoverflow.com/a/58694421/1155833) – rkeet Jul 11 '21 at 07:05
7

This is how i do it with Laravel 8.4 in 2021 to deploy it to CloudRun in Google Cloud:

Dockerfile

#Get Composer
FROM composer:2.0 as vendor

WORKDIR /app

COPY database/ database/
COPY composer.json composer.json
COPY composer.lock composer.lock

RUN composer install \
    --no-interaction \
    --no-plugins \
    --no-scripts \
    --no-dev \
    --prefer-dist

COPY . .
RUN composer dump-autoload

// some more custom steps like

FROM node:14.9 as frontend
...
FROM php:7.4-fpm
...

// Copy Composer dependencies

# Copy Composer dependencies
COPY --from=vendor app/vendor/ ./vendor/
COPY . .

// Some more custom steps

...

End of my Dockerfile to launch app with cleared optimized cache

# Run Laravel commands
RUN php artisan optimize:clear

CMD php artisan serve --host=0.0.0.0 --port=8080

EXPOSE 8080
hannes_rd
  • 150
  • 1
  • 8
  • 4
    be aware that it's not recommended using `artisan serve` for production. – HoseinGhanbari Nov 14 '21 at 08:38
  • I had to add `--ignore-platform-reqs` since the Composer image didn't have all the requirements like php version that are in my `composer.json` – Jerry Jul 07 '22 at 22:46
4

Create an executable of your composer file using

RUN curl -sS https://getcomposer.org/installer | php -- \
--install-dir=/usr/bin --filename=composer && chmod +x /usr/bin/composer 
FULL STACK DEV
  • 15,207
  • 5
  • 46
  • 66
  • Unfortunately, still the same error code. Do you have an idea what could possibly be still missing? – Andre Jul 20 '18 at 15:30
3

use composer in dockerfile using curl

RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer

Dockerfile

FROM 8.1.4-fpm

RUN apt-get update && apt-get install -y \
    git \
    curl \
    zip \
    unzip

RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer

WORKDIR /var/www
Mhammed Talhaouy
  • 1,129
  • 10
  • 14
1

We have basicly the same command running with the difference,

--install-dir=/usr/local/bin

Alternatively, you should add the composer bin files path to the $PATH variable.

export PATH=$PATH":/usr/bin"
mutas
  • 361
  • 2
  • 8
0

I'd just like to suggest another way.

Dockerfile:

RUN php -r "readfile('http://getcomposer.org/installer');" | php -- --install-dir=/usr/bin/ --filename=composer
Pankaj Salunkhe
  • 235
  • 1
  • 5
  • 8
0
FROM php:7.3-fpm-alpine
RUN docker-php-ext-install pdo pdo_mysql
RUN docker-php-ext-install mysqli && docker-php-ext-enable mysqli

RUN php -r "readfile('http://getcomposer.org/installer');" | php -- --install-dir=/usr/bin/ --filename=composer
RUN apk update
RUN apk upgrade
RUN apk add bash
RUN alias composer='php /usr/bin/composer'
Leonel Kahameni
  • 793
  • 8
  • 10
0

Use actual docs:

Dockerfile:

# Install composer
RUN php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" \
    && php composer-setup.php \
    && php -r "unlink('composer-setup.php');" \
    && mv composer.phar /usr/local/bin/composer
-6

My problem solved. I just stopped firewalld service on system

soroush
  • 170
  • 2
  • 9