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:
docker exec
-it bash
> cd /var/www/html
> php artisan