Of course Docker is a fantastic tool that allows us to work more efficiently
and that offers new perspectives in terms of scalability, infrastructures, deployments,…
But first of all, Docker is used by a lot of people for development
with many different languages on many different platforms.
And for developers (like me), the use of Docker is not something very easy nor fun
if we have to type or copy/paste or run commands like…
I’m sure Symfony developers understand what I mean regarding how many times a day we can run this command.
So it’s absolutely necessary to use Docker through the power of complementary tools such as:
Shell scripting
Make / Makefile
Docker Compose
Shell Scripting
With your shell you will be able to simplify everything you need to use docker with no pain writing shell scripts.
But writing such scripts is not always really easy for developers without admin or DevOps skills.
To show you how to be more productive with Docker and shell scripts,
I’m gonna speak about the way I developed this Jekyll blog and how I work with it everyday.
A simple DO-FILE
You can see this full do.sh file here.
And there it is the explanation of each part of the file:
Variables
Comments are explicit enough I think…
The last line of this part, EXECUTE_AS="sudo -u bob HOME=$HOME_DIR"
allows to execute commands into docker container as the non-root bob user
created in the image as you can see in my Dockerfile.
Logging functions
The first one to log debug or info…
The other one to log errors
The Docker image
To run docker containers, you always need a docker image. An image is built thanks to a Dockerfile.
It’s really important to be able to rebuild the image easily (upgrades,…).
The shortcut functions
Each function is designed to execute an action in the installation or development process.
Reading these functions you will see that my Jekyll project is built with:
Node/npm
Bower
Jekyll (of course)
Grunt
The full installation function
When you start working on a new or an existing project,
it’s really handy to have a simple command to execute to install and run a fully working application.
The following function will call every previous explained ones in the correct order.
Image/containers management
When working with docker, it’s important to be able to check what happens with containers or images:
Log into a container
Stop a specific container by name
Start a specific container
Remove a specific container
Help function
Expose the available functions through a simple help function:
Run these functions
A shell script is generally executed with the following syntax:
./do.sh
But simply doing this, you will execute script instructions but you’ll never call your functions.
The last line $* of the do.sh script is VERY important.
It allows to call a function based on argument(s) passed to the script.
./do.sh install for instance will execute the install function.
With a do-file you will work with docker writing simple shell commands like:
./do.sh build
./do.sh install
./do.sh grunt
…
What about an alias for ./do.sh in your .bashrc/.zshrc ?
Make / Makefile
If you’re not familiar with shell scripting you can choose another tool… a Makefile.
Makefiles are files used to configure make, which is a build tool.
The principle is simple: to build a target, we indicate the dependencies and the command to build it.
make is in charge of traveling the tree to build targets in the correct order.
A big advantage of make and Makefiles is that it provides auto complete out of the box.
Many people like using Makefile in an uncommon way to run grouped commands like this for instance:
We could replace every symfony command with a docker run command just like in our do-file:
Be careful… When using Makefile you must use tab key/character in your commands.
Docker Compose
Docker compose is not a third way to work more easily with docker commands,
it is a tool allowing simple containers orchestration.
Compose is a tool for defining and running complex applications with Docker.
With Compose, you define a multi-container application in a single file,
then spin your application up in a single command which does everything that needs to be done to get it running.
Compose allows you to define the services/containers that make up your app in a docker-compose.yml file, so they can be run together in an isolated environment.
Example:
Then run docker-compose up and docker compose will start your entire app with correct links, environment variables,…