How I Set Up Laravel in Docker Container

Sreejith B
4 min readJul 15, 2019

--

Today I am explaining how I was set up my first Laravel app in Docker container.

Prerequisites

Before start, I had the following.

  1. Ubuntu 18.04
  2. Composer installed
  3. Installed docker — https://docs.docker.com/install/linux/docker-ce/ubuntu/
  4. Installed docker compose — https://docs.docker.com/compose/install/

Step 1 — Installed Laravel app

Created a Laravel app via composer create-project

composer create-project — prefer-dist laravel/laravel laradock

Moved to my project directory

cd laradock

Given write permission for thestorage folder and thecache folder within the bootstrapfolder.

sudo chmod 777 -R storage/
sudo chmod 777 -R bootstrap/cache/

Next, Then used Docker’s composer image to mount the directories that y I need for your Laravel app and avoid the installing Composer globally.

docker run --rm -v $(pwd):/app composer install

Step 2 — Create Docker Compose File

touch docker-compose.yml

I have used port number 8080 and 8443 for webserver because I have already installed apache web service in my PC. Also, I have used port number 33061 for MySQL because I have already installed MySQL server on my PC.

Step 3 — Persist Data

Docker has features for persisting data. In my application, I had make use of volumes and bind mounts for persisting the database, and application and configuration files.

Under db service definition in docker-compose.ymlfile, defined a volume called dbdata to persist the MySQL database.

...
#MySQL Service
db:
...
volumes:
- dbdata:/var/lib/mysql
networks:
- app-network
...

The dbdata volume persists the contents of the var/lib/mysqlfolder present inside the container. This allowed to stop and restart the db service without losing data.

At the end of the compose file, added the definition for the dbdata volume:

...
#Volumes
volumes:
dbdata:
driver: local

Then, added a bind mount to the db service for the MySQL configuration files.

...
#MySQL Service
db:
...
volumes:
- dbdata:/var/lib/mysql
- ./mysql/my.cnf:/etc/mysql/my.cnf
...

Next, added bind mounts to the webserver service. There were will be two: one for your application code and another for the Nginx configuration.

#Nginx Service
webserver:
...
volumes:
- ./:/var/www
- ./nginx/conf.d/:/etc/nginx/conf.d/
networks:
- app-network

Finally, added the following bind mounts to the app service for the application configuration files and code:

#PHP Service
app:
...
volumes:
- ./:/var/www
- ./php/local.ini:/usr/local/etc/php/conf.d/local.ini
networks:
- app-network

The app service is bind-mounting the laradock folder, which contains the application code, to the /var/www folder in the container.

Finally the docker-compose.yml were look like this.

Step 4 — Created the Dockerfile

touch Dockerfile

This docker file will set the base image and specify the required commands and instructions.

Step 5 — Configured PHP

To configure PHP created alocal.inifile.

mkdir php
touch php/local.ini

I have added the following PHP configurations to this file.

upload_max_filesize=10M
post_max_size=10M

This is the file that I have bind-mounted to /usr/local/etc/php/conf.d/local.ini inside the container in Step 2.

Step 6 — Configure NGINX

To configure Nginx, I have created a fileapp.conffile with the service configurations in the nginx/conf.d folder.

mkdir -p nginx/conf.d
touch nginx/conf.d/app.conf

Added the following code to your app.conf file.

server {
listen 80;
index index.php index.html;
error_log /var/log/nginx/error.log;
access_log /var/log/nginx/access.log;
root /var/www/public;
location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass app:9000;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
}
location / {
try_files $uri $uri/ /index.php?$query_string;
gzip_static on;
}
}

Step 7 — Configured MySQL

For configuring MySQL I was created a configuration file my.cnf inside mysql folder.

mkdir  mysql
touch mysql/my.cnf

I have added the following code to my.cnf enable the query log and set the log file location.

[mysqld]
general_log = 1
general_log_file = /var/lib/mysql/general.log

Step 8 — Ran the containers

At last, I have defined all the services in the docker-compose file and created the configuration files for those services. Then I started the containers by running the command given below.

docker-compose up -d

It downloaded all the necessary Docker images. After that, I have listed all the running containers and their status using the following command.

docker ps

Step 9— Created a MySQL User

To create a new user, execute an interactive bash shell on the db container with docker-compose exec:

docker-compose exec db bashroot@18833a170621:/# mysql -u root -p

Then, created a user and given all privileges to the user.

mysql> GRANT ALL ON laravel.* TO 'laraveluser'@'%' IDENTIFIED BY 'my_password';

Flushed the privileges to apply the changes.

mysql> FLUSH PRIVILEGES;
mysql> EXIT;
root@18833a170621:/# exit

Step 10 — Update the environment settings

I edited the environment files of my laravel app.

docker-compose exec app vim .env

Updated the database credentials and app URL.

APP_URL=http://0.0.0.0:8080DB_CONNECTION=mysql
DB_HOST=db
DB_PORT=3306
DB_DATABASE=laravel
DB_USERNAME=laraveluser
DB_PASSWORD=my_password

Step 11 — Migrated the database

docker-compose exec app php artisan migr

Finally, I had able to access my Laravel app on http://0.0.0.0:8080/

I have deployed this app to GitHub.

https://github.com/SreejithEzhakkad/laravel-docker

--

--

Sreejith B

Web developer, Laravel geek, WordPress lover, CakePHP master, MERN Stack beginner, DevOps enthusiast, Minimalist, Problem solver, and Progressive thinker