Are you looking for steps to set up Laravel, Nginx, and MySQL with Docker Compose? Take a peek at this blog.
Here at Bobcares, we have seen several such Docker related queries as part of our Docker Hosting Support for Docker users, web hosts, and online service providers.
Today we’ll take a look at how to set up Laravel, Nginx, and MySQL with Docker Compose.
How To Set Up Laravel, Nginx, and MySQL with Docker Compose
Now let’s take a look at how our Support Engineers set up Laravel, Nginx, and MySQL with Docker Compose.
1. Downloading Laravel and Installing Dependencies
First, we get the latest version of Laravel and install the dependencies.
We make sure that we are in the home directory and clone the latest Laravel release to a directory called laravel-app:
$ cd ~
$ git clone https://github.com/laravel/laravel.git laravel-app
Then we move into the laravel-app directory:
$ cd ~/laravel-app
Next, we use Docker’s composer image to mount the directories that you will need for your Laravel project.
$ docker run –rm -v $(pwd):/app composer install
Finally, we set permissions on the project directory so that it is owned by your non-root user:
$ sudo chown -R $USER:$USER ~/laravel-app
2. Creating the Docker Compose File
If we build our application with docker compose file then it simplifies the process of setting up and versioning the infrastructure. So to set up a Laravel application, we will write a docker-compose file that defines our web server, database, and application services.
First, we open the file.
$ nano ~/laravel-app/docker-compose.yml
Here, in the docker-compose file, we will define three services: app, web server, and DB. For that, we add the following code.
Note: Make sure to replace the root password for MYSQL_ROOT_PASSWORD
version: '3' services: #PHP Service app: build: context: . dockerfile: Dockerfile image: digitalocean.com/php container_name: app restart: unless-stopped tty: true environment: SERVICE_NAME: app SERVICE_TAGS: dev working_dir: /var/www networks: - app-network #Nginx Service webserver: image: nginx:alpine container_name: webserver restart: unless-stopped tty: true ports: - "80:80" - "443:443" networks: - app-network #MySQL Service db: image: mysql:5.7.22 container_name: db restart: unless-stopped tty: true ports: - "3306:3306" environment: MYSQL_DATABASE: laravel MYSQL_ROOT_PASSWORD: your_mysql_root_password SERVICE_TAGS: dev SERVICE_NAME: mysql networks: - app-network #Docker Networks networks: app-network: driver: bridge
Each container_name property defines a name for the container that corresponds to the name of the service. So we need to define this property.
For providing communication between containers, the services are connected to a bridge network called app-network.
3. Persisting Data
Docker has suitable features for persisting data. Here, we will make use of volumes and bind mounts for persisting the database, and application and configuration files.
In the docker-compose file, we define a volume called dbdata under the db service definition to persist the MySQL database:
... #MySQL Service db: ... volumes: - dbdata:/var/lib/mysql networks: - app-network ...
The named volume dbdata persists in the contents of the /var/lib/mysql folder that is present inside the container. This will allow us to stop and restart the DB service without losing data.
We add the definition for the dbdata volume at the bottom of the file.
... #Volumes volumes: dbdata: driver: local
Then we will add a bind mount to the DB service for the MySQL configuration files we will create in Step 7.
... #MySQL Service db: ... volumes: - dbdata:/var/lib/mysql - ./mysql/my.cnf:/etc/mysql/my.cnf ...
This bind mount will bind ~/laravel-app/mysql/my.cnf to /etc/mysql/my.cnf in the container.
After that, we add bind mounts to the webserver service.
#Nginx Service webserver: ... volumes: - ./:/var/www - ./nginx/conf.d/:/etc/nginx/conf.d/ networks: - app-network
Finally, we add the below bind mounts to the app service for the application code and configuration files:
#PHP Service app: ... volumes: - ./:/var/www - ./php/local.ini:/usr/local/etc/php/conf.d/local.ini networks: - app-network
Now, our docker-compose file will now look like this:
version: '3' services: #PHP Service app: build: context: . dockerfile: Dockerfile image: digitalocean.com/php container_name: app restart: unless-stopped tty: true environment: SERVICE_NAME: app SERVICE_TAGS: dev working_dir: /var/www volumes: - ./:/var/www - ./php/local.ini:/usr/local/etc/php/conf.d/local.ini networks: - app-network #Nginx Service webserver: image: nginx:alpine container_name: webserver restart: unless-stopped tty: true ports: - "80:80" - "443:443" volumes: - ./:/var/www - ./nginx/conf.d/:/etc/nginx/conf.d/ networks: - app-network #MySQL Service db: image: mysql:5.7.22 container_name: db restart: unless-stopped tty: true ports: - "3306:3306" environment: MYSQL_DATABASE: laravel MYSQL_ROOT_PASSWORD: your_mysql_root_password SERVICE_TAGS: dev SERVICE_NAME: mysql volumes: - dbdata:/var/lib/mysql/ - ./mysql/my.cnf:/etc/mysql/my.cnf networks: - app-network #Docker Networks networks: app-network: driver: bridge #Volumes volumes: dbdata: driver: local
Finally, we save the file and exit the editor after making changes.
4. Creating the Dockerfile
In Docker, we can specify the environment inside of individual containers with a Dockerfile. Also, Dockerfile helps in creating custom images that we can use to install the software required by our application and configure settings.
Our Dockerfile will be located in our ~/laravel-app directory. Create the file:
$ nano ~/laravel-app/Dockerfile
This Dockerfile will set the base image. Also, it will specify the necessary commands and instructions to build the Laravel application image. Then we add the following code to the file:
FROM php:7.2-fpm # Copy composer.lock and composer.json COPY composer.lock composer.json /var/www/ # Set working directory WORKDIR /var/www # Install dependencies RUN apt-get update && apt-get install -y \ build-essential \ libpng-dev \ libjpeg62-turbo-dev \ libfreetype6-dev \ locales \ zip \ jpegoptim optipng pngquant gifsicle \ vim \ unzip \ git \ curl # Clear cache RUN apt-get clean && rm -rf /var/lib/apt/lists/* # Install extensions RUN docker-php-ext-install pdo_mysql mbstring zip exif pcntl RUN docker-php-ext-configure gd --with-gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ --with-png-dir=/usr/include/ RUN docker-php-ext-install gd # Install composer RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer # Add user for laravel application RUN groupadd -g 1000 www RUN useradd -u 1000 -ms /bin/bash -g www www # Copy existing application directory contents COPY . /var/www # Copy existing application directory permissions COPY --chown=www:www . /var/www # Change current user to www USER www # Expose port 9000 and start php-fpm server EXPOSE 9000 CMD ["php-fpm"]
Finally, we save the file and exit the editor after making the changes.
5. Configuring PHP
In order to configure PHP, we will first create a local.ini file within the PHP folder. This is the file that we bind-mounted to /usr/local/etc/php/conf.d/local.ini inside the container in Step 2.
We run the below command to create the PHP directory.
$ mkdir ~/laravel-app/php
Next, we open the local.ini file:
$ nano ~/laravel-app/php/local.ini
In order to demonstrate the configuration of PHP, we’ll add the following code to set size limitations for uploaded files:
upload_max_filesize=40M post_max_size=40M
Finally, we save the file and exit the editor.
6. Configuring Nginx
In order to configure Nginx, we will create an app.conf file with the service configuration in the ~/laravel-app/nginx/conf.d/ folder.
First, we will create the nginx/conf.d/ directory:
$ mkdir -p ~/laravel-app/nginx/conf.d
Next, we create the app.conf configuration file.
$ nano ~/laravel-app/nginx/conf.d/app.conf
After that, we add the following code to the file to specify the Nginx configuration:
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; } }
Finally, we save the file and exit the editor.
7. Configuring MySQL
In order to configure MySQL, we will create my.cnf file in the MySQL folder. This is the file that we bind-mounted to /etc/mysql/my.cnf inside the container in Step 2.
First, we will create the MySQL directory by running the below command.
$ mkdir ~/laravel-app/mysql
Next, we make my.cnf file.
$ nano ~/laravel-app/mysql/my.cnf
In the above file, we add the following code to enable the query log and set the log file location:
[mysqld] general_log = 1 general_log_file = /var/lib/mysql/general.log
Finally, we save the file and exit the editor.
8. Modifying Environment Settings and Running the Containers
Now, we have defined all of our services in the docker-compose file and created the configuration files for these services.
We will make a copy of the .env.example file that Laravel includes by default and name the copy .env.
$ cp .env.example .env
Now, we shall modify the .env file on the app container. In the file. we will add some specific details about our setup. We run the below command to open a text editor.
$ nano .env
Then we will modify the fields such as DB_HOST, DB_DATABASE, DB_USERNAME, and DB_PASSWORD.
The code will look as below.
DB_CONNECTION=mysql DB_HOST=db DB_PORT=3306 DB_DATABASE=laravel DB_USERNAME=laraveluser DB_PASSWORD=your_laravel_db_password
We save the changes and exit the editor.
We start all of the containers that are defined in our docker-compose file.
$ docker-compose up -d
The above command will download all of the necessary Docker images, which might take a while. Once the process completes, we run the below command to list all of the running containers:
$ docker ps
Now, we will run the below command to set the application key for the Laravel application. This command will generate a key and copy it to the .env file. Also, it ensures that the user sessions and encrypted data remain secure.
$ docker-compose exec app php artisan key:generate
After that, we cache the settings into a file which will boost the application’s load speed.
$ docker-compose exec app php artisan config:cache
The configuration settings will be loaded into /var/www/bootstrap/cache/config.php on the container.
Finally, we visit http://your_server_ip in the browser. As a result, we can see below the Laravel application:
9. Creating a User for MySQL
Now, we will create a new user. For that, we execute an interactive bash shell on the db container with docker-compose exec:
$ docker-compose exec db bash
Within the container, we log into the MySQL root administrative account:
mysql -u root -p
We enter the password when prompted. We then check for existing databases by running the below command.
mysql> show databases;
As a result, we see the laravel database listed in the output.
Next, we create the user account that will be allowed to access this database. The username will be ‘laraveluser’. Also, we ensure that the username and password here match the details we set in our .env file in the previous step.
mysql> GRANT ALL ON laravel.* TO 'laraveluser'@'%' IDENTIFIED BY 'your_laravel_db_password';
Then we flush the privileges to notify the MySQL server of the changes.
mysqL> FLUSH PRIVILEGES;
Then we exit MySQL.
mysqL> EXIT;
Finally, we exit the container.
exit
10. Migrating Data and Working with the Tinker Console
With the application running, we can migrate the data and experiment with the tinker command. Using the tinker command we can interact with the Laravel application from the command line in an interactive shell.
First, we test the connection to MySQL by running the below Laravel artisan migrate command.
$ docker-compose exec app php artisan migrate
This command will migrate the default Laravel tables.
After the migration completes, we run a query to check if we are properly connected to the database using the tinker command:
$ docker-compose exec app php artisan tinker
Then we test the MySQL connection by getting the data we just migrated:
\DB::table('migrations')->get();
As a result, we will see the below output.
Output => Illuminate\Support\Collection {#2856 all: [ {#2862 +"id": 1, +"migration": "2020_12_12_000000_create_users_table", +"batch": 1, }, {#2865 +"id": 2, +"migration": "2020_12_12_100000_create_password_resets_table", +"batch": 1, }, ], }
[Need any further assistance with Docker related queries? – We’re available 24*7]
Conclusion
Today, we saw how our Support Engineers set up Laravel, Nginx, and MySQL with Docker Compose
0 Comments