How can I run composer with ddev? - ddev

I need to run composer on my ddev project and don't have it on my Windows machine. For example, the project requires a composer install before startup. How can I use composer in this environment, especially on Windows?

Updated 2018-11-15 to show native ddev support (ddev composer command)
There are several ways to run composer for your project.
ddev v1.4.0 now has the ddev composer and ddev composer create commands. These run composer inside the container, so you're guaranteed to get composer behavior that matches the in-container hosting environment. (This matters most for Windows users.)
ddev composer require swiftmailer/swiftmailer
ddev composer update
ddev composer install
ddev composer create drupal-composer/drupal-project:8.x-dev --stability dev
Note that ddev composer create is not exactly the same as composer create-project so you don't have to understand complexities of the underlying filesystem. There are drupal and TYPO3 ddev composer create examples in the docs.
Nothing here prevents you from using any composer technique that you're comfortable with, but this is a great way to get predictable on-linux in-container composer builds. It should be hugely important for people using Windows OS, where composer is less available and has some unpredictable behavior.
Install on the host the old fashioned way: If composer is installed on your computer/host, just composer install. However, that only works on macOS and Linux, and only works if you have the right versions of php related components. It does not work well at all on Windows (NTFS) because the symlinks composer creates are not compatible with usage inside the (Linux) web container. (Composer is not hard to install on Windows: Use chocolatey and choco install -y composer. You'll want to enable the gd and curl extensions in c:\tools\php72\php.ini)
All the normal composer behavior has always been installed inside your web container, so you can use that whether or not you have composer on your host computer. For example: ddev exec composer install -d /var/www/html will do a composer install in the root of your repository, exactly the same as ddev composer install. You can also do ddev ssh and operate on the command line in the container.
Try this hooks approach to running composer install inside the container (on the mounted partition) every time your project starts:
hooks:
post-start:
- exec: composer install -d /var/www/html
For some older ideas on composer patterns (mostly obsoleted by ddev composer, See
How to: Use "composer create-project" and DDEV to start a new Drupal 8 site when Composer isn't installed on the host machine and
How to: Set up a D8/Composer site on Pantheon without CircleCI, custom upstreams

To expand on the accepted answer, DDEV now has a composer-specific hook.
hooks:
post-start:
- composer: install -d /var/www/html
The reason for using this instead of exec, I assume, is that there are also pre-composer and post-composer hooks, so maybe this also executes those hooks. I'm not sure of that or the actual difference, though.

Related

How to install composer globally for laravel app in windows?

I have a question related to composer and laravel. My question is whenever I install the fresh laravel app using command :
composer create-project laravel/laravel blog
Inside my C://xampp/htdocs/ directory and then change path to C://xampp/htdocs/blog/, here I am unable to run the composer command but I had already installed composer from its official website globally in C://xampp/htdocs/ directory. So is there any way to use composer command globally whenever I install fresh laravel app, so that I don't want to install composer in the laravel app directory everytime.
Now I guess they provide direct setting up global installation,
Check here
I did it like this a lot earlier,
Change to the path (or you can add that directory to your path later), and run the installer as mentioned on composer download site to download composer.phar.
Create a new composer.bat file alongside composer.phar.
Using cmd.exe:
run
echo #php "%~dp0composer.phar" %*>composer.bat
Then set it to path environment variable(see this)
Test with a new terminal:
composer -V
Will return
Composer version 1.10.6 2020-05-06 10:28:10
go to composer website and download the exe file, you should have it gloablly if you install it that way.
Good luck ^_^

Drupal 8 run composer as root

My host provider allows me to use only root user (the only one with /bin/bash) on my virtual machine that I'm using to host a drupal 8 site installed with composer.
From composer website I see they strongly advise to avoid running composer as super-user/root, they say to use composer install --no-plugins
I tried the command apt-get composer install --no-plugins but outputs the error
E: Command line option --no-plugins is not understood in combination
with the other option
I'm still running composer as root, even thought there is always an alert, how can avoid that?
If Composer is already installed, there is no need to call apt-get, which is the standard package installer on Debian systems. composer install --no-plugins does the job

How to enable php-Mcrypt extension in Laravel Homestead

I am trying to get an old Laravel 4.1.x app up and running again so that it can be modernized. This requires an environment with PHP 5.6 and the Mcrypt extension. I have installed Homestead 9.0.3 (the latest stable version). Within the VM, I have set the PHP version to 5.6
sudo update-alternatives --config php
I have then installed the php-mcrypt extension
sudo apt-get install php5.6-mcrypt
I am now able to create a new Laravel 4.1.x project, which is a process that requires Mcrypt to complete, so we're certainly getting somewhere:
composer create-project laravel/laravel="4.1.*" myAppName
However, when I browse to the webpage for myAppName, I see the message:
Mcrypt PHP extension required.
I have also tried steps that are usually recommended for this problem, ie:
sudo ln -s /etc/php/5.6/conf.d/mcrypt.ini /etc/php/5.6/mods-available/mcrypt.ini
sudo phpenmod mcrypt
sudo service php5.6-fpm restart
But I still get the same message in the browser.
What step have I missed?
With homestead v9 you should be up and running with php5.6 out of the box as stated in
here, but unfortunately it is not your case, and I understand that...
Old packages were not installed by default (php5.6-mcrypt), as you mentioned and they should be added by hand via:
sudo apt-get install php5.6-mcrypt
After that all packages are ready, up and working, especially php5.6-mcrypt.
The root of your problem is in multiple site definitions under your homestead.yaml.
Most probably some of them are overlapping and your nginx is referring to the wrong resource/site_definition, and wrong paths.
Therefore you might think some strange php versions or routes are run/executed.
You can verify that, by deleting some/all of them, leaving the only one important for you - in (/etc/nginx/sites-enabled/...).
Of course please do that inside the container and issue sudo service nginx restart, afterwards...
All of your problems should be gone after that.
If something goes wrong. You could easily recover your current installation to current state using vagrant destroy and vagrant up afterwards, cause all is saved in Homestead.yaml.
In my installation Homestead v9 is running with php5.6 on laravel 4.1 without any problems...
Hope it helps #jsm...
Because all the PHP versions installed on homestead you need to set the PHP version for a site in the Homestead.yaml.
First check what version the server is running with phpinfo();
Check the file /etc/nginx/sites-enabled/homestead.test and look for this line:
fastcgi_pass unix:/var/run/php/php5.6-fpm.sock;
If you didn't set the php version on the sites list, this file will be pointing to the php7.3.sock.
In this case the version 5.6 has mcrypt installed, but 7.3 don't.
You can just replace the line
fastcgi_pass unix:/var/run/php/php7.3-fpm.sock;
for
fastcgi_pass unix:/var/run/php/php5.6-fpm.sock;
and then reload nginx with sudo nginx -s reload.
Or set the php version on Homestead.yaml:
sites:
- map: homestead.test
to: /home/vagrant/code/public
php: "5.6"
And then run vagrant provision, it will change the nginx configuration for PHP 5.6.

difference between composer and composer.phar

What is the difference between composer and composer.phar?
Example:
composer install
composer.phar install
Is there a reason why I keep seeing code writen using composer.phar all the time when composer does the same?
There is no difference - composer.phar is the executable and composer can be an alias or symlink for it, depending on the way you've installed composer. As rob006 pointed out, there can be multiple ways to install composer: the official documentation at https://getcomposer.org/doc/00-intro.md#globally recommends to move the downloaded PHAR file to /usr/local/bin/composer which will make it callable through composer for all users of your system.
If you would move the file to another destination, like /usr/local/bin/composer.phar, the same composer binary would be available under that different command composer.phar.
And finally, if you would not have the chance to install composer globally, you could put it under either name in any local place

How to cache package manager downloads for docker builds?

If I run composer install from my host, I hit my local composer cache:
- Installing deft/iso3166-utility (1.0.0)
Loading from cache
Yet when building a container having in its Dockerfile:
RUN composer install -n -o --no-dev
I download all the things, e.g.:
- Installing deft/iso3166-utility (1.0.0)
Downloading: 100%
It's expected, yet I like to avoid it. As even on a rebuilt, it would also download everything again.
I would like to have a universal cache for composer that I could also reshare for other docker projects.
I looked into this and found the approach to define a volume in the Dockerfile:
ENV COMPOSER_HOME=/var/composer
VOLUME /var/composer
I added that to my Dockerfile, and expected to only download the files once, and hit the cache afterwards.
Yet when I modify my composer, e.g. remove the -o flag, and rerun docker build ., I expected to hit the cache on build, yet I still download the vendors again.
How are volumes supposed to work to have a data cache inside a docker container?
Use the experimental feature : Docker buildkit (Supported Since docker 18.09, docker-compose 1.25.4)
In your dockerfile
# syntax=docker/dockerfile:experimental
FROM ....
# ......
RUN --mount=type=cache,target=/var/composer composer install -n -o --no-dev
Now before building, make sure the env var is exported:
export DOCKER_BUILDKIT=1
docker build ....
If you are using docker-compose, make sure to export also COMPOSE_DOCKER_CLI_BUILD :
export COMPOSE_DOCKER_CLI_BUILD=1 DOCKER_BUILDKIT=1
docker-compose build ...
If it does not work with docker-compose, make sure your docker-compose version is above 1.25.4
docker-compose version
I found two ways of dealing with this problem, yet none deal with composer volumes anymore.
Fasten composer download process: Use hirak/prestissimo
composer global require "hirak/prestissimo:^0.3"
💡 With Composer 2.0, the above step is no longer required for faster downloads. In fact, it won't install on Composer 2.0 environments.
Force docker to use a cached composer install. Docker uses a cache on a RUN if the added files didn't change. If you only do COPY . /your-php-app, docker build will refresh all the cashes and re-run composer install even if only one unrelated file in the source tree changed. In order to make docker build to run composer install only install on package changes, one has to add composer.json and composer.lock file before adding the source files. Since one also needs the source files anyway, one has to use different folders for composer install and rsync the content back to the then added folder; furthermore one then has to run the post-install scripts manually. It should look something like this (untested):
WORKDIR /tmp/
COPY composer.json composer.lock ./
RUN composer install -n -o --no-dev --no-scripts
WORKDIR /your-php-app/
COPY . /your-php-app/
RUN rsync -ah /tmp/* /your/php-app/
RUN composer run-script post-install-cmd
or combine the two =)
I would like to have a universal cache for composer that I could also reshare for other docker projects.
Using a shared volume for the Composer cache works great when working with containers. If you want to go broader than just containers, and use a shared cache for e.g. local development as well, I've developed a solution for that called Velocita - how it works.
Basically, you use one global Composer plugin for local projects and inside and build containers. This not only speeds up downloads tremendously, it also helps with 3rd party outage for example.
I would consider utilizing the $HOME/.composer/cache/files directory. This is where composer reads/write to when using composer install.
If you are able to mount it from your host to your container that would work. Also you could just tar it up after each time your run composer install and then drop that in before you run composer install the next time.
This is loosely how Travis CI recommends doing this.
Also, consider using the --prefer-dist flag with your composer install command.
Info on that can be found here: https://getcomposer.org/doc/03-cli.md#install
--prefer-dist: Reverse of --prefer-source, composer will install from dist if possible. This can speed up installs substantially on build servers and other use cases where you typically do not run updates of the vendors. It is also a way to circumvent problems with git if you do not have a proper setup.
Some references on utilizing the composer cache for you:
https://blog.wyrihaximus.net/2015/07/composer-cache-on-travis/
https://github.com/travis-ci/travis-ci/issues/4579

Resources