20

composer install will install whenever stated in the composer.lock file, but composer update will update all the dependencies and create a new composer.lock file based on what is required in composer.json.

So many said only run composer update in development. But my question is doing composer update did replaced the old composer.lock file, if your app is going to break it will break, because there might be conflict with the new updated dependencies.

I came across with a situation where I must do composer update, the issue is related to pcntl extension. The only solution is to do composer update PHP pcntl module installation

I don't understand why people are afraid of running composer update on production.

yivi
  • 42,438
  • 18
  • 116
  • 138
Jessica Robertson
  • 377
  • 1
  • 5
  • 17
  • `composer update`, no args on a production box = professional suicide. It will often result in a broken system in dependency hell. Only composer update exactly what you need to update. Updating code that is working correctly is begging for trouble. https://www.ranum.com/security/computer_security/editorials/dumb/#:~:text=One%20clear%20symptom%20that%20you've%20got%20a%20case%20of,weapon%2C%20it%20works%20against%20you. read section on penetrate and patch. – Neil Davis Jun 12 '20 at 18:29

3 Answers3

26

TLDR;

Do not run composer update nor composer install in production. Execute it somewhere else and upload the result to the production server, but not to the same directory where the application is hosted. As a general rule, you shouldn't modify the application that's being served while it's being served. Create a different copy of the application and when it's ready replace it with the closest to instantaneous command you can (e.g. mv or ln -s).

But if you HAVE to run either: always run install and create a fresh installation; and never update. install is more predictable and reliable, with update you are at the mercy of any of the project's dependencies.


Composer works recursively. So even if you have very tight version constraints in your composer.json, by running composer update you would be updating not only your dependencies, but your dependencies' dependencies.

While most of the time this won't introduce breakage, sometimes it will. One dependency down the line may introduce a change of behaviour that may impact your code in a way you may have not tested against.

Also, it's basically using the wrong tool for the job. Composer is a dependency management tool, not a deployment tool. To deploy your code to production you should be using some sort of code deployment tool (even if that "tool" is as simple as an FTP upload and a couple of scripts).

The appropriate flow is:

  • Do all the require and update calls on your development machine, where you can test the project without risk. This generates a composer.lock, which is a known state for the whole project, with discrete installed versions.
  • Create a new installable version doing install --no-dev. On this step you also should dump an optimized autoloader, run after-install scripts, etc. I usually separate this in more than one step:
  1. composer install --prefer-dist --no-scripts --no-progress --no-suggest --no-interaction --no-dev:

    ^^ This for a complete, silent installation of everything, excluding development dependencies.

  2. composer dump-autoload --optimize --no-dev

    ^^ To dump an optimized autoloader script suitable for production.

  3. composer run-script --no-dev post-install-cmd

    ^^ This is mostly for Symfony, but if you have any post-install scripts to run (e.g. to copy assets to your "public" directory, warm-up some type of cache, anything like that), this would be a good moment to do it.

  • The result of the above step should be tested (in what typically is a staging environment), and then pushed to production whole (your client code, the vendor folder, the configuration tailored for prod, etc); using whatever deployment method you prefer.

Note that if you use any "slow" push method (FTP, copy, rsync, etc), you shouldn't write directly to the application filesystem, but create a fresh copy of the application and once the file transfer is ready, use a quick method to replace "production" with the new release. A popular and effective way is use a symlink as "production" root, so you only need to update the symlink once all of the above is done and ready, without impacting a running application (that otherwise could be temporarily broken, by virtue of suddenly containing files that belong to different versions of the application).

yivi
  • 42,438
  • 18
  • 116
  • 138
  • I've had issues with autoloaders when simply copying the result to production. I always remove vendor and run composer install to rebuild them dynamically on the box... my $.02. Further only run composer update on the libraries you _need_ to update, never just "composer update". For core that's: `composer update drupal/core webflo/drupal-core-require-dev --with-dependencies` Then work issues out from there. – Neil Davis Jun 12 '20 at 18:18
  • There is no reason to run composr install on production. Everybody should understand why composer update is not a good idea but it is not the same as composer install. Can you explain why should I use FTP if I can run git pull and composer install? – Čamo Feb 03 '21 at 10:54
  • 1
    @Čamo Because `install` is not a deployment tool. The installable artefact should be created somewhere else, and then transferred to the server. I personally use docker, so there is no FTP for me. If you run `install` as a deployment tool for the first deployment, how are you going to deploy the following versions to the server? Each deployment should be a fresh install, not an update. And if you are running a fresh install in a different directory and using `mv` to "deploy" (a not uncommon strategy), you are basically doing the same as using FTP: Copying the resulting artefact. – yivi Feb 03 '21 at 11:06
  • install is not a tool it is command. Production is full of commands. Also FTP tools uses commands aslo with full of errors. – Čamo Feb 03 '21 at 11:27
  • Can you tell me what is the problem with compser install? Docker is also full of commands. I did not see any argument for it. It looks like your opinion but no argument why it is not a good idea. – Čamo Feb 03 '21 at 11:30
  • 2
    @Čamo I think I explained it the answer and in my last comment. Again, it's not a "problem" with `composer install`, but that it's not the right tool for the job. I don't understand your comments about "production being full of commands". Sorry you disagree, I think you are wrong and that with time and experience you'll come to understand this. But on the meantime, just use whatever works for you. That's what we all do in the end. Bye! – yivi Feb 03 '21 at 11:40
  • Why you thing it is not the right tool? I have a deploy.sh script. If you are using docker you also have dockerfile with similar commands. So again why you think it is not the right way to call deploy.sh instead of complicated copy, ftp .... ? There is no answer only your talking about your experiences.... I am sorry. – Čamo Feb 03 '21 at 11:58
  • Not running composer install on production is entirely subjective. Depends on what software you're using, but at least with Craft CMS - it's better to run `composer install` and then migrations on the server rather than having 20,000 files in your repository – darylknight May 17 '21 at 18:32
  • How would this approach handle a folder under the public root with a massive amount of dynamic, uploaded content? – reformed Mar 15 '23 at 15:20
11

My thoughts about this are,

  • The current working state of the system is very important as I would assume some tests have been run against it.
  • To do composer update would mean that, libraries that are part of the app would have their updates and which may lead to breakage in the system. Because they are libraries that depends on libraries that depends on libraries.
  • Finally, I would rather do this if composer-update is needed:
    • Checkout on a dev environment and composer update,
    • Ensure the app is thoroughly tested on a dev environment
    • then install on live/production with composer install
  • 2
    means every time you must do full round of testing when u want to do composer update? – Jessica Robertson Feb 06 '17 at 10:57
  • 7
    @JessicaRobertson - yes, you should do a full round of testing when you want to use composer update; you should really do a full round of testing before any deployment; and you should have automated tests for precisely this purpose – Mark Baker Feb 06 '17 at 10:58
  • @JessicaRobertson Maybe not (if there are other means), but of course you have a list of tests active and having those tests `OK` means a lot. Personally to me, running `composer update` in live would mean making a change in production without testing. – Oluwatobi Samuel Omisakin Feb 06 '17 at 10:59
2

My thoughts here :

You should never use composer update without argument.

composer update reads every package listed on composer.json, and updates it to the latest available version compatible with the specified version constraints.

In a perfect world, all librairies would follow semver correctly, and it shouldn't have any side effects. But technically, that is never always true, and you could download a version incompatible with the previous one, or just a version with uncorrected bugs.

So, updating all your packages at once would probably lead to some issues, unless you have the time to check everything on your website to ensure nothing went wrong.

But of course, you'll have to update specific packages sometimes, so using composer update xxx/xxx is useful, assuming you'll check all your implementations of the package.

When the updated package is fully tested, you can commit your code to staging/production, and then run composer install to ensure you'll have the same exact version of package and dependencies on all your platforms.

Long story short, here's the process I use :

  • composer require xxx/xxx to install new packages
  • composer update xxx/xxx to update a specific package
  • composer install on all environments when the package.lock file has been updated.

Additional thoughts

I stumbled once upon an implementation which would give the exact version of the package in composer.json. The developer explained that this way you could use composer update without damage.

I disagree with this option, since even with the exact versions in composer.json, the dependencies are not fixed, and a composer update could lead to potential bugs in them.

Marc Brillault
  • 1,902
  • 4
  • 21
  • 41