Magento deployment with Deployer

Magento deployment with Deployer

Remember those days when you could easily deploy something to production without executing each time a number of commands and clearing cache a few times meanwhile? Yeah, me neither.

Every modern framework or platform has their own individual perks that shape our development and deploying process. Magento is no different here and its deployment process can be a challenge for newcomers.

In this post, we will introduce Deployer, automated deployment tool for PHP.

Since Deployer is just a PHP application distributed as a PHP Archive (.phar), extending its functionalities and customizing deployment tasks are quite easy. Most importantly, if something goes wrong, we see few PHP exceptions now and then so they can be fixed in no time.

Installing Deployer

We will start by downloading it down and setting it globally executable for our user

curl -LO https://deployer.org/deployer.phar
mv deployer.phar /usr/local/bin/dep
chmod +x /usr/local/bin/dep

Now you can execute dep command which will run Deployer. Position yourself at the root of your project and run

dep init

which will trigger the Deployer config generator. Here it will ask us about our project type, but that only means it will require a specific recipe. Recipes are nothing more than already written tasks for deploying a specific framework or platform.

As you can see, Magento is not listed here, but since we know it is part of the code by looking at source, we will start by manually creating deploy.php file to avoid refactoring. In this file we will require Magento 2 recipe like this:

namespace Deployer;
 
require 'recipe/magento2.php';

Magento 2 recipe already contains almost everything we need for deployment, we just need to make a few adjustments, like adding the project name and project repository:

// Project name
set('application', My awesome project);
 
// Project repository
set('repository', 'git@github.com:username/my-awesome-project.git');

We still didn’t define where we want to deploy, so we will start by defining a host.

For this simple example we will define only our local machine, but in practice, there is probably more than one environment where we want to deploy, like staging or production, so it is best to keep those definitions in a separate file.

In the root of your project create a new file called hosts.yml and write something like this inside:

localhost:
 stage: dev
 local: true
 branch: master
 deploy_path: /var/www/my-awesome-project

For different stages like staging or production, we most likely need to do an ssh which we don’t need in our example so you won’t need this local: true line, but you will have to add one more line at the end:

configFile: ~/.ssh/config

Some of your teammates can connect in a different way so it is best to keep that information at config level. Now when we have this defined, we can tell in our deploy.php where is this hosts file located:

// Hosts
inventory('hosts.yml');

And that is, actually, all there is. You can now run:

dep deploy dev

Well actually, there is an exception in the process. I got

[Exception]
Warning: array_replace_recursive(): Argument #1 is not an array in /var/www/my-awesome-project/releases/1/vendor/magento/framework/App/DeploymentConfig/Writer.php on line 135

That is because of missing env.php since cloned repository doesn’t have this file, so we will create it ourselves, or it could be already created for you by Deployer but it is empty.

Change the directory to your deploy path defined in hosts.yml and from here on you can edit this file on path shared/app/etc/env.php.

We will explain in a moment why is it located there, but don’t forget to set a production mode in here or you will get another exception if you try to deploy again with our current settings. Of course, this is done only once.

Let’s try again running

dep deploy dev

And yes, this time everything went fine:

How does it work

There are a lot of tasks that are executed but in theory the simplest explanation is that when you run command for deploying, Deployer will make an SSH to a specified remote server (unless we explicitly say that we want to deploy to local environment), create a new release folder and in it clone the VCS repository.

With the magic of symlinks, it will point your latest release to the current directory.

After deployment, you will see three main directories:

  • Current
  • Releases
  • Shared

Releases are your release folder where the code is cloned from the repository, while current is symlinked to the latest release.

In the current directory, there are symlinks to also files in a shared directory that contains something that is the same/shared for all releases, like env.php or media folder.

In practice, if you want to use Deployer for deployment of Magento 2 projects, your server should point to current/pub directory.

Conclusion

In this post, we haven’t created our custom tasks or overridden some of the existing ones, but I hope you get the basic idea how Deployer works and what is the idea behind it.

With the help of available documentation, you will be able to customize it according to projects specific needs. If you need any additional help, feel free to contact us!

And just one final pro tip

If you are running PHP-FPM on the server where you are deploying, create a new task for restarting this service after the deployment is done, because the symlinks can be cached and your server will end up serving the older release. Trust me, I learned this the hard way.

Related Inchoo Services

You made it all the way down here so you must have enjoyed this post! You may also like:

Is Hyvä Your Next Magento Frontend Solution? Tomislav Bilic
, | 1

Is Hyvä Your Next Magento Frontend Solution?

Most Needed UX Features For Magento Store Owners Patricia Kovacevic
Patricia Kovacevic, | 0

Most Needed UX Features For Magento Store Owners

Customize Currency Display in Magento 2 Danijel Vrgoc
, | 3

Customize Currency Display in Magento 2

2 comments

  1. Hi Antun,

    Nice article. I followed your article and in my case there is always issue with file/folders.
    I have a http-user magento and it belongs to wew-data group. So aftet the deployment, all the folders except the ones that needs to be writable has both file owner & file group as magento:magento. Because of this the website throws 500 internal server error. If I run ‘chown -R :www-data .’ from releases/current folder the the sites works without 500 error. Do you also have this issue ? How did you fixed it?

  2. Hi Antun Matanovic.
    Is there a way in the deployer to restart PHP-FPM docker container if I deployed inside?
    As I understand, after deploy I need to additionally connect to the host machine to use smth like docker restart?

    Thanks.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <blockquote cite=""> <code> <del datetime=""> <em> <s> <strike> <strong>. You may use following syntax for source code: <pre><code>$current = "Inchoo";</code></pre>.

Tell us about your project

Drop us a line. We'd love to know more about your project.