We are building a 12 factor app with Drupal. This is part two in our series, building a 12 factor app. Today I'm talking about Factor Two: Dependency Management.
What's up internet? Tom Friedhof here, Solutions Architect here at activelamp. If you didn't catch my last video on factor one, go check it out. I'll walk you through how to set up a local development environment on Docker. Today, I'm picking up where we left off and continuing to build on top of that app that we started from factor one. Factor two states Explicitly Declare and Isolate Dependencies. What are your dependencies in a Drupal app? Well, if you're building a Drupal site, one of your dependencies is Drupal core. If you're using any contributed modules, those are also dependencies. Basically, you can think of a dependency as any code that you're not maintaining yourself.
These dependencies you don't want in your working repository, keep these out of your working repository. How do you bring those dependencies into your app? That's what a dependency manager is for. I'm going to show you today, how to use composer and how to pull down Drupal core and any contributed modules that we want to use.
One of the other benefits that you get with keeping your dependencies out of your working repository as it makes upgrading your dependencies a piece of cake. Basically, if you want to update Drupal core, it's a matter of changing a version number in a composer.json file and then rerunning your build. Composer will bring down the dependency that you asked for and put it into its place where it's supposed to go. Only your custom code unique to your application should be in your repository. Let's jump back into a demo with that Drupal app that we started in the last video and start defining some dependencies with composer.
All right, so here we are back in our 12-factor-demo app that we started in the last video. And just as a reminder, if you want to go grab this off of GitHub, you can go to the activelamp repository and grab it at 12 factor demo. Now, I have added one commit since the last video. And so if we go take a look at that, essentially all I did was update to the latest Docker sync there and remove some settings that we no longer need due to the upgraded Docker sync. All right, so let's go ahead and boot this app up. And so if we head over to our terminal and type in Make Start, that'll actually start the stack up and just to kind of remind you of what that command actually did is we have a make file over here that has the different commands that we can execute using the new Make Command and so make start essentially executes this bundle exec docker-sync-start command.
What that did over here is that started up our docker stack with docker sync. You can see we have three containers that started up here, then we have DB container, the PHP container, and the Nginx container. There was also a sync container that was started as well called Drupal-sync. All of that was covered in the first video. If you're not familiar with what I'm talking about, definitely go check out that first video because that's where we covered all this information. And just real quick, if I go into this Docker compose file, you'll see there's where those containers are defined as well.
All right, so in this video, we're going to introduce the composer dependency manager in PHP. So if we hop over to a browser and type in Composer, you'll see the first like in Google is this Dependency Manager for PHP. And so this is how we're going to pull in our dependencies for Drupal. As I was mentioning earlier, when you're building a Drupal site, Drupal core is actually a dependency, and so we're going to pull in Drupal core with Composer. Now, in the previous video, the way we were actually pulling in Drupal core was using this Drupal image from Docker Hub, and that included Drupal core in there. We're going to continue to use this image but we're not going to use any of the code in that image.
Now, you could just switch this over to a PHP image, but for simplicity sake, I'm just going to keep this particular image and then just pull in our own code so that we're not tackling any Docker configuration in this video. We just want to mess with the Composer Dependency Manager with PHP. There's a composer template that you can go use to do this. If you just Google for Composer Template Drupal, you'll see that there are some docs here to actually create a Drupal composer project. That's exactly what we're going to do in our code base. And so let's grab this command, and we'll head back into our terminal here. Let's actually get to the correct directory.
All right. Right now, the way we have this directory structure set up on our local file system is in the source directory we have this web directory and inside that web directory we have the Profiles Directory which just has our custom code in it. We need to pull our custom code out so that we can use the Composer Template here, and so our custom code lives in this activelamp directory. Let's for now grab that activelamp directory and move it out of the source directory. We'll just say move web profiles activelamp and let's move that up one directory, and then we're going to get rid of the source directory completely.
All right, so now we can paste that Composer command that we got from the Composer Template file. Instead of creating this project in a directory called [inaudible 00:07:02], we're going to create this project and a directory called source. Basically, what this is doing, is this is pulling out the, it's checking out the Drupal Composer, Drupal Project Template, and it's putting that into this source directory. Now, with the composer template, you get quite a bit of functionality. This is probably a topic for another video, we really won't get into everything that this composer template gives you, but this README file is definitely worth checking out on the Composer Dump Template for Drupal projects on GitHub. Let's see how far this has gotten.
All right, so now we have a Drupal core in our source directory, so if we head back to our code editor now, this should have Drupal core in our code editor. Like I was saying earlier, the dependencies are the files that you don't manage yourself, you don't want to have in your repository. And so let's see what actually is in our repository. Now, if we type in git status, these are all the files that are going to get committed to our repository. Now, some of these files come from what's called the Drupal scaffold. If I go back over to this Composer Template for Drupal projects, the Composer Template uses something called the Drupal scaffold which basically creates files like the index.php or the update.php file for you when you run a composer update.
If I click into this project here, this will tell us which files are provided by this scaffold, and so we can actually add these files to our .gitignore file as well so that we're not actually adding this to our composer. Excuse me, our project repository. Let's go into the .gitignore file here and let's go down to the bottom and we'll just say ignore scaffold files and then let's paste that there and then this, that, and that aren't file names, so we'll remove that.
Now, let's go ahead and save this and then look at, see what a terminal looks like, see if it looks a little bit better. Okay, so there's fewer files that we're adding now, but these files are actually files that we do want to add in. Some of these are empty directories like the modules directory in the themes directory, if we look in there. Those are empty directories that we need to actually have in place, so that Composer has a directory to place modules when we're asking for a module dependency from drupal.org. This activelamp directory right here, we need to actually move that into the profiles directory, so let's do that real quick.
This is going to go inside the source web profiles directory. All right. And so now this looks like this can be ready to be committed. We're not going to commit it just yet, we're gonna finish setting up our stack here. So now that we have the entire Drupal root inside this source directory, we actually need to update our Drupal or excuse me, our Docker sync config. files. Let's go in there because before Docker sync was just syncing over the web profiles into the container. And so now we actually want to sync all of source into the container. I'm just going to delete that, so basically this whole directory is going to get synced in to the Docker container.
Let me go to our Docker compose dev file, so that sync container is going to be mounted in our PHP container here. We actually don't want it to be in HTML profiles anymore. We just want it to be at var/www. On the Docker compose file, let's see. We are sharing a volume with the Nginx container, so we're sharing val/www/html with the Nginx container. We actually need to have this say web now because the Composer Template actually creates a web directory and not an HTML directory. Let's go ahead and change that real quick. I'm not going to change it in the dockercompose.yemo file. I'm gonna change it in the dockercompose.dev file because this is really for dev environments. When we create these containers to be shipping containers that we can push to production, we'll spend a little bit more time on this Docker compose yemo file. But for now I'm just going to create the volume and the Docker compose Dev yemo file so that we at least have the volume set up in our dev environment.
Let's change this to Nginx and back this up like so. All right, so now in our Nginx container, we'll get the same mount that the PHP container has to that Drupal-sync container that's created by Docker sync. All right. So that Composer Template sets up the Drupal doc route in a web directory. We previously had our Nginx Server configured to look at the HTML directory, and so just we go in here. We can see we're putting in a configuration file on the internet server that's coming from our config directory Nginx site.com. If I come in here, we have a root here specified as var/www/html. We need to change this to web here so that it'll actually pick up the correct directory that we're syncing in.
That should be all that we need to do to get the stack working again. I'm going to go back to the terminal and I'm going to stop this by hitting control C, and then I'm going to run Make Clean. This will basically clean out the containers and the volumes and let us start from a fresh slate. I can type in Make Start and this will boot up the containers again from scratch, create the Docker-sync container and sync the files again. And once that's done, we should be able to hit the browser and see the latest version of Drupal that we pulled down with Composer.
All right. Now that our stack is back up and fully booted, let's hit the browser and see if we can get Drupal to load and just for review the Nginx servers listening on port 7080. Let's hit that and see what happens. I open up a new tab here within a local host, and we'll go to 7080, and there we go. There is our Drupal install. We're running the 8.5.6 version of Drupal. And again, we are in that act of lamp profile. So it's picking up that profile that we put into that directory, and now we can install this as we did before.
One thing that the Drupal Composer Template does for you is it puts your configuration sync directory outside of your files directory, and so you need to actually create this config sync directory. For now what I'm going to do is create this manually. When you've got this on your web server, you want to make sure that the web server has access to be able to do this itself, but I'm just going to do this right now manually. I'm going to go into this source directory and create a config. directory. And right now, I'm just going to make it world readable, but really, this should only be read in readable by your web server.
Now if I go back to the Install screen, I should be able to hit try again, and there we go. Now I can actually install this is. Our credentials are Drupal, and this is on a server called [inaudible 00:16:35].
All right, so there's our freshly installed site, and so just to show that it did install the profile, I look for the 12 factor module that we created in video one. It is, in fact, here. Here's where Composer really becomes a huge benefit when you're using the Composer Template for Drupal is when you want to add new modules, all you have to do is just run a composer require statement and it will run out to Drupal and download that dependency, put it in your composer that JSON file and place it in the correct spot in your Drupal install. Let's go ahead and give that a shot. I go back to our terminal here. I'm in the source directory of the code base. I can run a Composer Require. Let's pull down the Drupal JSON API module.
What this did is it went out to Drupal.org and grabbed the latest version of the JSON API module and it put it in our Drupal site. Now, if we go back to our code base, and we go inside of our web directory and into our modules directory, into control, we can see there's the JSON API module. So let's verify that we actually see this in our code base. Let's go back to our terminal. I'll just to show you that when we add new files, the sync is automatically watching, and so that synced over to our code base.
Let's get into the site again, hit the Refresh button here. If I type in JSON API, that should show up. And so there, in fact, it is. Another benefit that we get with Composer as well as if we need to make version changes, it's real simple to make version changes because it's all handled in a manifest file called composer.json. Let me go back to the code base and show you what that looks like. In our source directory, we have a composer.json file that shows us all of our dependencies. Most of these dependencies actually pretty much all the dependencies came from the Composer Template that we were looking at earlier.
If we want to specify a specific version of Drupal, we can come over here and update this Drupal core version and put in whatever version we want. If for example we wanted the latest version of 8.4, we can come in here and type in 8.4. If we wanted to require a specific version of 8.5, say for example we wanted 8.5.5, we can basically take away this Tilda and then run the Composer update.
You can see here that it took Druple 8.5.6 and moved it down to 8.5.5. And then the scaffolding that I was showing a little bit earlier downloaded the 8.5.5 versions of those files and put them in the correct spot. Now if we go back into the Drupal site, and then come under the reports, so the database is already updated for 8.5.6, this isn't really good example. Let's go ahead and re populate that database so I can finish demonstrating that this did in fact work.
Now again, if you're moving forward, this is likely not going to be an issue but because there were likely schema changes going from 8.5.5 to 8.5.6, that's why this is likely happening. Let's try something here.
Let me just delete the database so that we can reinstall this. I'm going to clear the stack and then I'm gonna do a docker volume ls. Do a docker volume ls and grep 12. That doesn't work. Let's do factor. There we go. I'm gonna delete the data here. All right. Delete the container that's using that data and then delete the data. And so now if we start this again, it'll recreate that my SQL database and that we should be able to install 8.5.5 from scratch. Let's see what happens.
There we go. There's 8.5.5. As you can see, using a dependency manager makes managing your dependencies much easier than not doing it. If you weren't using a dependency manager, you would actually have to move those files in and out of where they're supposed to go manually. Also, one of the benefits that we get is all of these dependencies like the JSON API and Drupal core aren't actually going to be committed to your repository. If we look at this repository, we can see the only things that are going to get committed are these files, we don't see the core, Drupal core, we don't see the JSON API module in there. It's just the files that we really need to manage. Let me go ahead and add those files to our repo, and push that up to our repo in GitHub.
As you can see, we've got a lean code base that we're managing in our repository. And we've got an easy way to pull an updated dependencies with Composer. Not only that, we've even specified our infrastructure as a dependency of our app. Your code needs something to run on, right? But executing a few commands, we're able to build our app and have it served by Docker containers that will eventually ship to production. That's all I've got for you today. If you liked this video, make sure to give us a thumbs up and hit that Subscribe button. See you next time.
Subscribe on YouTube
We update the channel regularly with the latest client work and special event videos.