Learn how to create a docker-compose.yml
file for one of the most common web stacks. Postgres + Adminer + Mailcatcher
The stack
In this example I will show you how to setup docker containers using docker-compose
to work in this commonly used web stack.
Typically, a web application needs a database whether thats MySQL/Postgres or a NoSQL database and usually you need an interface to check explore your databases and also a service to catch mails. Setting all these in your local machine can be a headache. Thankfully with the help of docker
we can setup a standalone stack for each of our projects and start/stop it on demand.
This is also pretty handy when working on multiple projects and you may need to switch between them every now and then.
Set up a database service
First things first lets create our docker-compose.yml
in the root of our project and lets add the database service we are going to use in our project. In this case we would like to use postgres.
version: "3"
services:
db:
image: postgres:14.3-alpine
ports:
- 5432:5432
environment:
- POSTGRES_HOST=localhost
- POSTGRES_PORT=5432
- POSTGRES_USER=root
- POSTGRES_DB=myproject
- POSTGRES_PASSWORD=root
Our database is now setup however there is one issue. Our database data is not persistent. That means all the data in our database will be gone once we stop the running container.
To solve this we need to tell docker to use a volume
to persist the container's /var/lib/postgresql/data
path which contains all of the database data.
version: '3'
services:
db:
image: postgres:14.3-alpine
ports:
- 5432:5432
volumes:
- db-datavolume:/var/lib/postgresql/data
environment:
- POSTGRES_HOST=localhost
- POSTGRES_PORT=5432
- POSTGRES_USER=root
- POSTGRES_DB=myproject
- POSTGRES_PASSWORD=root
volumes:
db-datavolume:
Please note the :
after db-datavolume:
This is not a typo!
Add Adminer service
There are many options out there for database explorers. I personally like to use Adminer
because it's very simple and fast. Let's add the Adminer service to our docker-compose.yml
services:
#---------
adminer:
image: adminer:latest
ports:
- 8080:8080
That will make adminer available on port 8080
. You can login to your database using the environment settings we passed to db
service.
IMPORTANT: One thing to keep in mind here is that these services work under docker's networking and not on your local machine networking. Sometimes localhost
may not be available in your app is running outside docker. However, docker services can interact with each other by using the service name as the address to that service.
For example, since both adminer
and db
services are on the same docker network, we can use HOST=db
when trying to connect to our database from adminer. So to connect to the db
service using adminer we can use the following settings.
HOST=db
PORT=5432
DATABASE=myproject
USERNAME=root
PASSWORD=root
Add the MailCatcher service
Finally, let's add the MailCatcher service to our docker-compose.yml
. MailCatcher will catch all the mails sent through smtp://127.0.0.1:1025
. This makes it very easy to work with and debug your email templates if your application sends any.
services:
#---------
mailcatcher:
image: schickling/mailcatcher:latest
ports:
- 1080:1080
- 1025:1025
This configuration will make the mailcatcher interface available on port 1080
and we can use port 1025
in our application's SMTP settings so that every mail send will be caught by the mailcatcher service.
As explained before, if smtp://127.0.0.1:1025
doesn't work for you try using the service name as the host like so smtp://mailcatcher:1025
Summary
We have now have a nice virtual environment to work with for our project! We can now start this stack by running docker-compose up -d
.
Here is the final result
version: "3"
services:
db:
image: postgres:14.3-alpine
ports:
- 5432:5432
volumes:
- db-datavolume:/var/lib/postgresql/data
environment:
- POSTGRES_HOST=localhost
- POSTGRES_PORT=5432
- POSTGRES_USER=root
- POSTGRES_DB=myproject
- POSTGRES_PASSWORD=root
adminer:
image: adminer:latest
ports:
- 8080:8080
mailcatcher:
image: schickling/mailcatcher:latest
ports:
- 1080:1080
- 1025:1025
volumes:
db-datavolume:
References