Running Scheduled Laravel Tasks with Docker

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hey everyone andrew here i've had a few people ask how you might run scheduled laravel tasks using docker so i thought i'd put together this video demonstrating three ways that you can accomplish that just as a quick note the methods that i show should work for both production and development environments so with that being said let's get started what you're seeing here is a basic local docker development environment that i use for my laravel apps i've linked the repo that i use and have been building on in the description if you'd like to check that out essentially what we have here is a variety of services that our app uses we have one for nginx called site and it relies on our php and mysql services there's also three more for composer npm and artisan let's talk about our larval app i've already scaffolded out a super basic application consisting of a single model price you can see in the migration for the prices table that i'm just storing two values a decimal for usd and euros these correlate to the current price of bitcoin the routes web file contains a single route the landing page and it calls the price controller's index method which that method just paginates the latest 50 price model objects and returns a price's index view equally as simplistic as the rest of the app this view is just a bootstrap table displaying a list of the bitcoin prices gathered by our controller all of this was created so that i could showcase a custom artisan command if we check out the console commands directory i've created a single command class get price opening it up you can see that we have our actual command price colon get and under the handle method i'm just calling this public coindesk api endpoint to get the latest exchange rates price of bitcoin the prices in usd and euros are being temporarily stored in an array before being used to create a new price object finally some helpful information is returned back to the user's console let's see what this all looks like working together first we'll bring up the docker environment by going to our console and using the docker compose up command with the d and build flags for detached mode and asking docker to build from our docker files respectively i'm also specifying the site service which will just bring up nginx php and mysql since we won't need the other three services at startup once those are up and running we need to get our database structure added using our artisan service this is easy just run docker compose run rm which destroys the container after it's finished artisan migrate okay i think we're done let's take a look at our site looks good except the table's blank right now but that's expected we don't have any data in our database we can change that though let's use the custom artisan command to get the latest bitcoin price and save it to our database docker compose run rm artisan price get and refresh our site perfect we have our price displaying in our table as we expected now this command seems like something that would be perfect for a regular cron job we'd want it to run on a fairly frequent basis and update our database with the latest price returned that's where laravel scheduling comes in heading over to their docs it's super easy to get started we need a cron that runs each minute calling artisan's schedule run command and then we just need to define what commands we want to schedule at what time let's head back into our app and open up that kernel class file in the schedule method we'll remove the default commented outline and put our own in there since we're calling an artisan command schedule command then our price get command and finally how often we want it to run for this example let's do every two minutes alright that's all we have to do well almost all we have to do we still need a cron to run the artisan schedule run command every minute so here's where our first method comes into play this is arguably the easiest way and the most recommended that i've come across we're simply going to use the local cron tab of the machine that's currently running our docker setup in this case that's my macbook but it could be a linux server or a desktop if i run crontab e locally it opens up this blank file in vim it's blank since i don't have anything scheduled by cron locally let's actually expand this view a little bit so i have a little more room and time to start working on the cron job line first i'm adding this path line in here so i don't have to use absolute values for the commands that are going to follow next are actual cron following a similar structure to the one in the laravel docks every minute we're going to cd into the project directory then instead of running php artisan we're going to use the artisan docker service docker compose run rm artisan schedule run and using the same method as the docs passing our console output and error output to devnull let's save this and exit our terminal editor i'm going to open it up again real quick just to make sure that our change is saved okay that looks good now it's just time to wait all right it's been about seven minutes let's refresh our site we have three new entries all made two minutes apart it looks like our crown is working all right so that looks great but what if we don't want to use a local cron tab let's move on to our next method but first let's bring down our development environment using docker compose down uh-oh i'll have to remove this cron first actually i'll just use crontab r and get rid of the whole thing okay sites down good this next method is going to utilize one of our docker containers the php one to be precise we are building that off of this php docker file and if we open that up we can see that the image we're using is based off of alpine linux this is great because that os has a cron system already installed and in place all we have to do is utilize it well how are we going to write a cron to the cron tab on the container which by the way resides at etc crontabs root we could ssh into the container after its initialize and manually edit it but that's not great if you spin up or down this docker network pretty frequently instead we can create a separate file that holds our cron job and copy it over at build time let's get started with that first create our file that will hold our cron jobs i'll just call it crontab and in here we'll add in our larvale scheduler cron every minute cd into the project root directory which in our environment is set to var www.html then run php artisan schedule run which we can do since this container is running php and has everything installed for using artisan and just like before outputting everything to dev null all that's left to do is add a line into our php docker file copy which moves one file locally into our container crontab to etc crontabs root let's bring everything up again using docker compose up d build site once that's finished we can actually scroll up and see that during the php build our crontab file was copied over successfully and we can even verify that further by using docker compose exact on the php container and running cat on etc crontabs root there's our cron job let's run artisan migrate again to get our database structure up and we'll open up our site and wait to see what happens okay another seven minutes have passed and nothing there's no data added in well let's take a look at the processes that are running in our php container by using docker compose exec php ps aux there's only a handful in here running and they're all associated with php no data is being added because the cron process isn't running fortunately though for us it's super easy to get it started up using docker compose exec we'll add on the d flag which just like the up command means that this will run detached and in the background then specify our php service the cron d process and the f flag which runs kron d in the foreground the reason we're doing this kind of weird combination between running exec in the background and cron d in the foreground is that it allows the cron process to continue running in our container while also freeing up our terminal now if we run ps aux again on the php container we can see our cron service running successfully let's wait some more and see what happens all right another seven minutes have passed let's refresh our site perfect we have three data points pulled in two minutes apart exactly what we expected if we wanted to bring down the cron it's not that difficult first we'll get the process list just like we did previously and then just run docker compose exec on the php container kill and the process number now our crons aren't running anymore and we could start them back up if we wanted to but that's not what we're going to do right now instead let's try out a third and final way of getting scheduled laravel tasks running with docker first things first let's bring down our local environment again using docker compose down once that's done if we head into our dockercompose.yml file we're going to be building a whole new service under our artisan container let's specify one called cron just like our php and artisan containers this one will be built from a local dockerfile specify the container name as cron the volumes as the same as our php and artisan containers and attach our larval network to it next we need to create the docker file that will build this container just like php and artisan this service is built with php fpm alpine and just like the php docker file we'll install pdo and pdo mysql since we're running artisan commands on it we're copying over our cron tab just like we did in the php docker file and then finally we're adding in a cmd keyword followed by an array containing cron d and dash f this cmd call tells docker this is the command that i want you to run once the container has been set up and initialized normally this would be controlled by the docker image the container is being built from so that would be php running instead however we're hijacking this and using it to start up cron d after initialization instead of having to manually start it through docker compose exact all right time to see how this works docker compose up d build site again and we'll wait for nginx php and mysql to boot up then run our migrations through docker again and now if we want to start our crons we just use docker compose up d cron if we run docker compose ps we can see the cron service running in the background just as expected let's load up our site again and wait to see what happens it's been seven minutes so let's refresh perfect just as expected we're treated to three data points again spaced out two minutes apart stopping our crops is even easier now we just run docker compose stop cron now what if we brought up the cron service again but excluded the d flag this means that the output of the container will be piped directly to our terminal and our terminal will be perpetually open until we hit control c the problem with this is that we're seeing output from the cron d process the commands we've told it to run it would be way more helpful if we saw the output from the actual artisan schedule run command enabling that is actually really easy let's open up our crontab file and change out this dev null to dev std out this way any output from the schedule run command will be piped through to the console output if we bring back up the cron service using the build flag to bring in our new changes we can immediately see that we're getting back a different output this is what's returned back from the artisan schedule run command and if we speed things up a little we'll eventually see it running the price get command as scheduled refreshing our browser after that a new line of data was added and that's about it for this video you've learned three different ways to run scheduled larval tasks with docker using a local systems cron tab running the scheduled cron inside an existing php container and creating a specialized container separately just for this schedule run cron personally i like the first method as it allows multiple artisan containers to be spun up each time the scheduler is ran allowing jobs to be handled that might overlap or take longer to complete than anticipated huge thanks to my github sponsors and everybody else who continues to support these videos as always if you have any questions about this or any other web development topics please feel free to reach out to me in the comments or on my twitter linked below thanks for watching
Info
Channel: Andrew Schmelyun
Views: 7,035
Rating: 4.9431281 out of 5
Keywords: docker, docker tutorials, laravel, laravel tutorials, laravel docker, docker laravel, laravel scheduled tasks, laravel scheduler, web development, web dev, web dev tutorial, php tutorial, php docker, docker php
Id: 2UTHJpBRGpY
Channel Id: undefined
Length: 16min 55sec (1015 seconds)
Published: Mon Sep 07 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.