
Nick SchuchOperations Lead
Its extremely important to have default values that you can rely on for local Drupal development, one of those is "localhost". In this blog post we will explore what is required to make our local development environment appear as "localhost".
In our journey migrating to Docker for local dev we found ourselves running into issues with "discovery" of services eg. Solr/Mysql/Memcache.
In our first iteration we used linking, allowing our services to talk to each other, some downsides to this were:
With this in mind, we hatched an idea.....
What if we could just use "localhost" for all interactions between all the containers.
All this can be achieved with Linux Network Namespaces in Docker Compose.
Linux Network Namespaces allow for us to isolate processes into their own "network stacks".
By default, the following happens when a container gets created in Docker:
However, if a container is created and told to share the same Network Namespace with an existing container, they will both be able to interface with each other on "localhost" or "127.0.0.1".
Here are working examples for both OSX and Linux.
OSX
version: "3"
services:
php:
image: previousnext/php:7.1-dev
# You will notice that we are forwarding port which do not belong to PHP.
# We have to declare them here because these "sidecar" services are sharing
# THIS containers network stack.
ports:
- "80:80"
- "3306:3306"
- "8025:8025"
volumes:
- .:/data:cached
db:
image: mariadb
network_mode: service:php
mail:
image: mailhog/mailhog
network_mode: service:php
Linux
All containers share the Network Namespace of the users' host, nothing else is required.
version: "3"
services:
php:
image: previousnext/php:7.1-dev
# This makes the container run on the same network stack as your
# workstation. Meaning that you can interact on "localhost".
network_mode: host
volumes:
- .:/data
db:
image: mariadb
network_mode: host
mail:
image: mailhog/mailhog
network_mode: host
To facilitate this approach we had to make some trade offs:
Since we split out our Docker Compose file to be "per OS" we wanted to make it simple for developers to use these files.
After a couple of internal developers meetings, we came up with some bash aliases that developers only have to setup once.
# If you are on a Mac.
alias dc='docker-compose -f docker-compose.osx.yml'
# If you are running Linux.
alias dc='docker-compose -f docker-compose.linux.yml'
A developer can then run all the usual Docker Compose commands with the shorthand dc
command eg.
dc up -d
This also keeps the command docker-compose
available if a developer is using an external project.
The following solution has also provided us with a consistent configuration fallback for local development.
We leverage this in multiple places in our settings.php
, here is 1 example:
$databases['default']['default']['host'] = getenv("DB_HOST") ?: '127.0.0.1';
While the solution may have required a deeper knowledge of the Linux Kernel, it has yielded us a much simpler solution for developers.
How have you managed Docker local dev networking? Let me know in the comments below.