You may come across weird situations in development using Docker, specifically docker compose, and the way networking is done. I use WSL2 with Docker Desktop to make my life easy and recently had to figure out aliases for hostnames so that containers could reference each other without an ip address or the service name, i.e. while using an http client to make a request from service a to service b.
Hopefully this will shed some light for people or just make it easier to use docker in general which is a great tech for development.
this is not intended for production or staging use. for development purposes only
Setting Up
I'll assume you have 3 laravel apps, and that NGINX is your proxy server (web server). That means we'll use PHP-FPM since all requests to your services are proxy passed from NGINX to the PHP-FPM service for the given application. FPM then runs the actual code and returns the response to NGINX.
We'll add in an assumed database service just so our docker-compose file looks complete. We'll walk through each part of the compose file paying more attention to the networking portions.
Lets pretend we have 3 laravel apps:
one each for management, payroll, and marketing.
services:
management:
build:
context: .
container_name: management
image: laravel-example/management
restart: unless-stopped
tty: true
working_dir: /var/www/management
volumes:
- ./:/var/www/management
networks:
- laravel-example
payroll:
build:
context: ../payroll
container_name: payroll
image: laravel-example/payroll
restart: unless-stopped
tty: true
working_dir: /var/www/payroll
volumes:
- ../payroll:/var/www/payroll
networks:
- laravel-example
marketing:
build:
context: ../marketing
container_name: marketing
image: laravel-example/marketing
restart: unless-stopped
tty: true
working_dir: /var/www/marketing
volumes:
- ../marketing:/var/www/marketing
networks:
- laravel-example
nginx:
image: nginx:latest
container_name: nginx
restart: unless-stopped
tty: true
ports:
- 80:80
- 443:443
volumes:
- ../payroll:/var/www/payroll
- ../marketing:/var/www/marketing
- ./:/var/www/management
- ./build/dev/nginx/conf:/etc/nginx/conf.d
- ./build/dev/nginx/certs/:/etc/nginx/ssl
networks:
laravel-example:
aliases:
- payroll.bigcorp.test
- marketing.bigcorp.test
- management.bigcorp.test
depends_on:
- marketing
mariadb:
image: mariadb:10.2
container_name: mariadb
ports:
- 33065:3306
environment:
MYSQL_ROOT_PASSWORD: "password"
MYSQL_DATABASE: "your_db"
MYSQL_USER: "root"
MYSQL_PASSWORD: "password"
MYSQL_ALLOW_EMPTY_PASSWORD: "yes"
volumes:
- laravel-mariadb:/var/lib/mysql
networks:
- laravel-example
restart: on-failure
healthcheck:
test: ["CMD", "mysqladmin", "ping"]
networks:
laravel-example:
driver: bridge
external: false
name: laravel-example
volumes:
laravel-mariadb:
driver: local
The yaml file may seem large, but it's actually fairly easy to break down service by service and understand what each part does. Our main concern for this post is understanding the hostname aliases. Normally docker will assign an ip to a service based on its internal networking, so you'll never have the same ip address for a given service on a given build or run. Services can "talk" to each other by their name since docker will resolve the service name to an ip address. Where this breaks down is a service making an http request within the docker network to another service. The call will fail since the hostname will not resolve, there is no DNS server of course. To fix this we need to look at two things:
Our networks key in the compose file says "make me a network named laravel-example, and use the bridge driver, this is not an external (already existing network).
Each of our services is built in this network. The key to making the hostname resolve within docker like DNS would is the networks key in our NGINX service
networks:
laravel-example:
aliases:
- payroll.bigcorp.test
- marketing.bigcorp.test
- management.bigcorp.test
Basically we're just saying, "resolve any of these hostnames to the NGINX service". This works because of course all requests to NGINX get passed to server blocks that are proxied to a PHP-FPM service. We can look at how that works in a later post.
Hopefully this sheds some light on dockers networking in a practical way for development purposes.
Top comments (0)