Dockerize Laravel, Nginx, MariaDB, PhpMyAdmin, Redis and Npm
Using docker for developing Laravel web-apps is so fun and will prevent us from a headache of installation and configuration different services for our local environment.
To get started, make sure you have Docker installed on your system, and let’s dive into it. (You can clone the complete repository at this Github Repo.)
Let’s look at our file structure to have a better understand of what’s going on:
dockerfiles/
src/
mysql/
docker-compose.yml
.env
Inside dockerfiles/
folder we will create these:
nginx/
nginx.dockerfile
php.dockerfile
The nginx/
folder is for default.conf
and docker files are located here to create our custom images. Inside the nginx/
folder we have a regular config file (default.conf
) as below:
And now we can concentrate on our docker environment.
- Inside
nginx.dockerfile
we have:
First of all, we pull a light-weight Alpine image and then we set user ID and group ID as a non-root user for docker and if you wonder why, because if our container was running as root and we generated a file from our container through a volume back to our Docker host then the file will be owned by root:root
.
That could make it annoying to edit from your environment because you would need elevated privileges to write/delete that file.
By default, UID
and GID
are 1000
but in a multi-user environment you may end up with something different. If you want to see your UID/GID
simply run below command on your terminal:
id
And the output (for me) is:
uid=1000(reza) gid=1000(reza) groups=1000(reza-work),27(sudo),30(dip),46(plugdev),120(lpadmin),131(lxd),132(sambashare),998(docker)
After adding user, by using ADD
docker command (which exists on the line 16th of nginx.dockerfile
):
We will copy default.conf
file to desired location of nginx image.
Inside php.dockerfile
we have:
Php docker file is pretty straight forward and after configuring Composer, we can install any Php extensions that we need on our project but notice we want to use Laravel and this framework communicates with MySql through PDO, so installing this extension is a must!
We want to use Redis for cache purpose so let’s install phpredis
and enable Redis extension.
Until now we have our docker files and if you recall our files structure, we need to determine the docker-compose.yml
:
dockerfiles/
src/
mysql/
docker-compose.yml
.env
The docker-compose
file will have our desired containers as shown below, and we are going to explain each one of them.
The defined services will have the same network named laravel
, which will allow them to communicate with each other without any issues.
On build
section we will define the working directory as context
and the name of related dockerfile
as nginx.dockerfile
. So docker compose will go to context
directory and use nginx.dockerfile
.
First of all we will launch an instance of nginx
running in a container and using the created nginx configuration and defined image on ./dockerfile
.
We will set UID/GID
which we discussed earlier and expose port 80:80
(left one is one our system and right one is on docker). Binding ./src
on host to /var/www/html
will give access to nginx to serve our Laravel website and depends_on
section indicates that this service needs a list of services to run, and without them, nothing goes to happen.
What does delegated
mean on/var/www/html:delegated
?
- Use delegated on Volumes: whenever docker container performs changes, host is in read only mode.
- Use cached on Volumes: when the host performs changes, the container is in read only mode.
- Default: whenever both container and host actively and continuously perform changes on data.
Second of all, let’s create a mysql
container:
For this one we use official image of MariaDB
version 10.6
and restart: unless-stopped
option tells us once the container is stopped manually it will not restart automatically even after restarting the docker daemon, we should start it manually.
The tty
flag is a related concept to stdin, stdout
. A pseudo terminal (also known as a tty
) connects a user's terminal with ability of the stdin
and stdout
stream through a shell such as bash
.
By default, whenever we bring down the Docker network, our MySQL data will be removed after the containers are destroyed but we would like to have persistent data that remains after bringing containers so we bind ./mysql
folder to /var/www/html
.
As all of us know, each database needs some environment variables to deal with application so we will specify environment
and even timezone (TZ
) to have a more robust settings.
mysql/
docker-compose.yml
.env
The “${DB_DATABASE}”
means docker automatically look into .env
file on the same directory to complete desired key-values. The .env
file contains:
Third of all, we will make php
container:
Earlier, we wrote everything that will be needed on the php.dockerfile
, so this is a simple section for this container. We just need to make sure the context directory and dockerfile
are correct. Port 9000
will be exposed for our application, and the ./src
directory will be linked to the container to load our future Laravel web app.
Fourth of all, let’s configure PhpMyAdmin:
We use default image to create Phpmyadmin service and for login credentials, we will use the same mysql .env
password. The only important thing is the PMA_HOST
which must be equal to myql
service name so Phpmyadmin automatically connect to database and we don’t need to deal with IPs in docker.
Fifth of all, Redis container is another part of docker compose file:
Last step is creating Composer, Npm and Artisan containers. They are so simple and we can define them as below:
The only thing that is important to know is entrypoint
option. This instruction will be used to provide executables that will always execute when the container is launched.
For example if we determine below entrypoint
for a test
named container:
entrypoint: ["echo", "Hello World"]
After running:
docker run test
The output is:
Hello World
So when the container is run the ENTRYPOINT
instruction is executed, and Hello World
is echoed.
Let’s have look at our docker-compose.yml
:
Quite large docker-compose.yml
file, right? but that’s works well and You can clone the complete repository at this Github Repo.
What now?
Next, navigate in your terminal to the directory you cloned above repository and spin up the containers for the web server by running docker-compose up -d --build app
.
The following containers are built for our web server, with their exposed ports detailed:
- nginx —
:80
- mysql —
:3306
- app —
:9000
- redis —
:6379
- phpmyadmin —
:8081
Now we can use our ./src
folder by one these instructions:
- Clone your Laravel project or copy all of the files directly into this
src
directory. - Install a brand new Laravel project by running
docker-compose run --rm composer create-project laravel/laravel .
in your terminal inside./src
folder.
Three additional containers are included that handle Composer, NPM and Artisan commands without having to have these platforms installed on your local computer.
Use the following command examples from your project root, modifying them to fit your particular use case.
docker-compose run --rm composer update
docker-compose run --rm npm run dev
docker-compose run --rm artisan migrate
Access container as interactive shell and see output:
docker exec -it <container id> sh
Our docker application is accessible through http://localhost:9000.
That’s it.
READ MORE: