We cover how to make running complex Docker commands quickly and easily.

We saw how we could use docker-compose to easily get a dev environment up and running.

However, we had to run some commands that get pretty long. For example:

docker run -it --rm \ -v $(pwd)/application:/opt \ -w /opt \ --network=zondaroad_appnet \ shippingdocker/php \ php artisan make:auth

This gets to be a huge pain when running commands often, such as running phpunit or artisan commands to generate scaffolding.

A Makefile

To combat the pain of writing long Docker commands, we can create a script to help us out. Bash can be used here, but I like using a Makefile , as the syntax is easy to get started with.

For example, which a file named Makefile , we can create command "foo":

foo: bar

And use it:

make foo

Pretty easy!

Let's make a simple one:

.PHONY: up down up: docker-compose up down: docker-compose down

We can run make up , make down .

What we've done:

Let Make know that the listed commands are "phony" - they don't generate artifacts (files) Command up will start our services Command down will stop our services

More Advanced Makefile

Let's add onto this:

.PHONY: up down # Set dir of Makefile to a variable to use later MAKEPATH := $(abspath $(lastword $(MAKEFILE_LIST))) PWD := $(dir $(MAKEPATH)) up: docker-compose up down: docker-compose down test: docker run -it --rm \ -v $(PWD):/opt \ -w /opt \ --network=zondaroad_appnet \ shippingdocker/php:latest \ ./vendor/bin/phpunit

We created a command make test which will spin up a PHP container within our network and run phpunit.

Logs

We can tail some logs too. I spent some time to try to get colorized output of log files too:

.PHONY: up down log # Modified From http://bytefreaks.net/gnulinux/bash/tail-logs-with-color-for-monolog log: tail -f $(PWD)storage/logs/laravel.log | awk '\ {matched=0}\ /INFO:/ {matched=1; print "\033[0;37m" $$0 "\033[0m"}\ /WARNING:/ {matched=1; print "\033[0;34m" $$0 "\033[0m"}\ /ERROR:/ {matched=1; print "\033[0;31m" $$0 "\033[0m"}\ /Next/ {matched=1; print "\033[0;31m" $$0 "\033[0m"}\ /ALERT:/ {matched=1; print "\033[0;35m" $$0 "\033[0m"}\ /Stack trace:/ {matched=1; print "\033[0;35m" $$0 "\033[0m"}\ matched==0 {print "\033[0;33m" $$0 "\033[0m"}\ '

We can use make log to tail the laravel.log file, and use awk to give it some color based on output.

Artisan

Let'see how we can use artisan more easily.

Tinker

I use tinker a bunch, and we can start tinker from the Makefile as well:

.PHONY: up down log tinker tinker: docker run -it --rm \ -e "HOME=/home" \ -v $(PWD).tinker:/home/.config \ -v $(PWD):/opt \ -w /opt \ --network=zondaroad_appnet \ shippingdocker/php:latest \ php artisan tinker

Similar to our test command, we spin up a container and run tinker . Just type make tinker .

Other Commands

This one is the hairiest, and perhaps warrants a bash script over Makefile , but we can still accomplish our goal of arbitrary artisan commands.

.PHONY: up down log tinker artisan ART="" artisan: docker run -it --rm \ -e "HOME=/home" \ -v $(PWD).tinker:/home/.config \ -v $(PWD):/opt \ -w /opt \ --network=zondaroad_appnet \ shippingdocker/php:latest \ php artisan $(ART)

We create a variable ART and give it an empty string value. We also spin up a container and run artisan commands within it, passing the ART altho as our artisan command.

Try make artisan to get a listing of available commands. Use make artisan ART=route:list to get a listing of routes.

It's a little rough, but not too bad.

The Complete Makefile

Here's the complete Makefile:

.PHONY: up down log tinker artisan test # Set dir of Makefile to a variable to use later MAKEPATH := $(abspath $(lastword $(MAKEFILE_LIST))) PWD := $(dir $(MAKEPATH)) up: docker-compose up -d down: docker-compose down log: tail -f $(PWD)storage/logs/laravel.log | awk '\ {matched=0}\ /INFO:/ {matched=1; print "\033[0;37m" $$0 "\033[0m"}\ /WARNING:/ {matched=1; print "\033[0;34m" $$0 "\033[0m"}\ /ERROR:/ {matched=1; print "\033[0;31m" $$0 "\033[0m"}\ /Next/ {matched=1; print "\033[0;31m" $$0 "\033[0m"}\ /ALERT:/ {matched=1; print "\033[0;35m" $$0 "\033[0m"}\ /Stack trace:/ {matched=1; print "\033[0;35m" $$0 "\033[0m"}\ matched==0 {print "\033[0;33m" $$0 "\033[0m"}\ ' tinker: docker run -it --rm \ -e "HOME=/home" \ -v $(PWD).tinker:/home/.config \ -v $(PWD):/opt \ -w /opt \ --network=zondaroad_appnet \ shippingdocker/php:latest \ php artisan tinker ART="" artisan: docker run -it --rm \ -e "HOME=/home" \ -v $(PWD).tinker:/home/.config \ -v $(PWD):/opt \ -w /opt \ --network=zondaroad_appnet \ shippingdocker/php:latest \ php artisan $(ART) test: docker run -it --rm \ -v $(PWD):/opt \ -w /opt \ --network=zondaroad_appnet \ shippingdocker/php:latest \ ./vendor/bin/phpunit

Exec

Lastly, we can also use Docker's exec to make it all a tad easier. Here we'll run bash inside if our already-running PHP container: