Dissecting Docker for Laravel: Your first command.
Docker was one of those tools that I kept putting off but wish I started using way earlier. In Dissecting Docker I will share bite size chunks of how I approached learning Docker.
Why I wanted to learn Docker.
After spending hours helping new team members getting set up with Virtual Machines (VMs); Shipping code that worked perfectly locally only to have things go sideways in production; and having to run multiple resource hungry VMs for different projects. Docker seemed like the next logical step. The idea of packaging everything up and shipping them across multiple environments (development, staging, and production) sounded pretty intriguing to me too.
What is Docker?
There are number of resources out there that do a great job of explaining what Docker is. So instead here are some resource you might find useful:
- A Beginner-Friendly Introduction to Containers, VMs and Docker (Excellent article by Preethi Kasireddy probably the best explanation I have come across. Highly suggest reading this to understand many of the terms I will be using in this article.)
- What is Docker? and What is a Container? (from the official Docker site)
- What is Docker? (7:32 minute watch YouTube)
- Solomon Hykes — Why we built Docker (20:47 minute watch YouTube)
Here are the instructions for installing Docker on:
Running your first docker command
When I first installed Docker I asked myself well what is the simplest thing I can do with Docker right now? The first thing that came mind was can I install Laravel with Composer running in a container?
Yes my friend you sure can!
Initially I thought I would have to build my own PHP image that included Composer but luckily this wasn’t the case. A quick search on https://hub.docker.com for “composer” and the first result I found was the official Composer repository.
After reading the instructions and a bit of trial and error I ran my first successful Docker command.
docker run --rm --interactive --tty \
--volume /home/alex/.composer:/composer \
--volume $PWD:/app \
--user $(id -u):$(id -g) \
composer create-project --prefer-dist laravel/laravel blog
Note: if you following along make sure to replace
/home/alex/.composerwith the path to your own composer home directory.
If you thinking “Whoa that was a lot of typing!” don’t worry I will show you how to shorten it ;) But let first explain what this command actually does.
docker run: run the command in new container using the image specified (
--rm: as soon as the command has been executed delete the container.
--interactive --tty: both these flags together will start an interactive shell on the container.
--volume /home/alex/.composer:/composer: mount the local composer home directory
/home/alex/.composer(replace this with your own) to the
/composerdirectory inside the container. This is done to share caching between our local composer and the composer running in our container.
--volume $PWD:/app: mount the current working directory to the
/appdirectory inside the container. If you type
echo $PWDor just
pwdinside your console this will print your current working directory.
--user $(id -u):$(id -g): by default commands are executed as root. This means if you don’t specify a user when composer creates the
blogfolder with all the Laravel files they will be owned by root. So you need to set the user to your current
id -uprints your user id and
id -gprints your group id. Again running
echo $(id -u)or
id -uinside the console will yield the same result.
composer create-project --prefer-dist laravel/laravel blog: I now how composer works so no explanation needed. Now hold your horses tiger there is some trickery happening here. Firstly
composerhere isn’t referring to the actual command itself but rather the image used to spin up the container. Hence on the first run you should see a message
Unable to find image 'composer:latest' locally. At which point Docker will go ahead and pull the image in. The command you actually executing is
create-project --prefer-dist laravel/laravel blog. So how does this actually work then? Well if you take a look at the Dockerfile used to build the Composer image. On the last line right at the bottom you will see
CMD["composer"].What this does is set the default command to
composerwhen the container executes. So essentially
composerwill get prefixed to the command
create-project --prefer-dist laravel/laravel.
The biggest take away here is after Docker has pulled in the image. It only takes a few seconds (precisely 8 seconds on my set up) to spin up a container, install Laravel and delete the container like it never existed in first the place. How long would it take to spin up a VM and execute the same command?
Hate installing crap on your system just play with a new shiny toy you probably never going to use again, Docker has your back!
Want to try out a new version of PHP or Node.js? Just grab the image off of Docker Hub and spin up a container. Also if you like me and hate installing crap on your system just play with a new shiny toy you probably never going to use again, Docker has you back!
Don’t run random Docker images on your system.
With all that said don’t go running random images on your system from third-parties you don’t trust. This would be the equivalent of running random commands in your console without having a clue as to what they do. You wouldn’t do that would you? I sure as heck hope you don’t! Security is something we will cover in more detail as we move forward.
Now before I forget here is the less verbose version of the command:
docker run --rm -it \
-v $COMPOSER_HOME/composer \
-v $PWD:/app \
-u $(id -u):$(id -g) \
composer create-project --prefer-dist laravel/laravel blog
If you haven’t already you will need to export
COMPOSER_HOME by adding the below to your
Enjoyed this article…
If you enjoyed this article, hit that heart button below ❤ it lets me know you want to see more like this.
Also if learning how to build secure single page applications is something that sparks your interest. I am currently working on Looking at the Vue with Laravel.
Until next time, happy containerizing and thanks for reading!