Setup Docker with Laravel 8 (Apache ,PostgreSQL)
There are a lot of article about setting up Laravel with Docker but I couldn’t find anything which also had PostgreSQL and Apache.
So here’s how to do this with explanations to the best of my knowledge.
Folder Structure
This is how the folder structure will look :
app
|__laravel
| |__app
| |__bootstrap
| |__. . . .
| . . . .
| webpack.mix.js
|__pgsql
| |__init
| | |__
| | 0_schema.sql
| |__pgdata
| Dockerfile
|__server
| |__
| Dockerfile
docker-compose.yml
So there is three main folder inside the app directory and a docker-compose.yml file. I will explain all of these in their respective section below.
Setting up
Before going any further please make sure you have composer installed already. Otherwise, you can’t do the next steps. Although it’s possible to do this without installing the composer. But I haven’t done that way in this article.
laravel
First create the parent folder called app. Then open a command terminal and write the following code :
cd app
– Go thethe
app directory.composer create-project --prefer-dist laravel/laravel laravel
– This will create a laravel 8 base.
For reference, this is how it will look inside the laravel folder :
laravel
|__app
|__bootstrap
|__config
|__database
|__public
|__resources
|__routes
|__storage
|__tests
.editorconfig
.env
.env.example
.gitattributes
.gitignore
artisan
CHANGELOG.md
composer.json
package.json
phpunit.xml
readme.md
server.php
webpack.mix.js
With this the laravel portion is over. Now let’s setup the server, where we will run this laravel app.
server
Let’s create a new folder named server
inside the parent folder app. And inside this folder create a Dockerfile
with the following code:
FROM php:7.4.1-apache
# 1. development packages
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
nano \
libicu-dev \
git \
zip \
unzip \
vim \
&& rm -rf /var/lib/apt/lists/*
# 2. apache configs + document root
ENV APACHE_DOCUMENT_ROOT=/var/www/html/public
RUN sed -ri -e 's!/var/www/html!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/sites-available/*.conf
RUN sed -ri -e 's!/var/www/!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/apache2.conf /etc/apache2/conf-available/*.conf
# 3. mod_rewrite for URL rewrite and mod_headers for .htaccess extra headers like Access-Control-Allow-Origin-
RUN a2enmod rewrite headers
# 4. start with base php config, then add extensions
RUN mv "$PHP_INI_DIR/php.ini-development" "$PHP_INI_DIR/php.ini"
ADD https://raw.githubusercontent.com/mlocati/docker-php-extension-installer/master/install-php-extensions /usr/local/bin/
RUN chmod uga+x /usr/local/bin/install-php-extensions && sync \
&& install-php-extensions bz2 \
gettext \
intl \
exif \
pdo_pgsql \
bcmath \
So with this, I can build the container already apache installed and then add some configurations so that it can run the Laravel app properly and added some extensions for the database.
Next we will add configurations for the database.
pgsql
Now let’s create the pgsql folder inside the main parent folder app. Inside this, create two folder, one is init
, another is pgdata. And the file Dockerfile
. Note that the file doesn’t have any file extension.
The init
folder is optional explained below. And pgdata is needed, so that any kind of settings changes for database is saved here.
Now put the following code in the file Dockerfile
:
FROM postgres:12
// The following code is optional, for people in Japanese region
RUN localedef -i ja_JP -c -f UTF-8 -A /usr/share/locale/locale.alias ja_JP.UTF-8
ENV LANG ja_JP.utf8
ENV TZ Asia/Tokyo
This will install the postgres version 12. and adding some regional changes for Japan.
init folder (optional)
You can add .sql
files here to create tables when creating the database container. Here’s an example of inside 0_schema.sql
:
create table unsubscribe_contacts (
id serial UNIQUE
, contact_id bigint default 0 not null
, is_deleted boolean default false not null
, updated_at timestamp default CURRENT_TIMESTAMP not null
, created_at timestamp default CURRENT_TIMESTAMP not null
, constraint unsubscribe_contacts_PKC primary key (id)
) ;
This will create a table inside the database when creating the container. And other informations related to the database will be added in the docker-compose.yml
file. See the next sections for this.
docker-compose.yml
You have create a file called docker-compose.yml
inside the parent folder app. This file will run all the docker files together and connect it in the same network. After creating this file, write the following code :
version: '3.7'
services:
server:
build: ./server
ports:
- 80:80
volumes:
- ./laravel:/var/www/html
pgsql:
build: ./pgsql
ports:
- 5431:5432
volumes:
- ./pgsql/init:/docker-entrypoint-initdb.d # When the container is created from image, the sql in here will run
- ./pgsql/pgdata:/var/lib/postgresql # Get the data from container to the host
environment:
- POSTGRES_PASSWORD=secret
- POSTGRES_USER=postgres
- POSTGRES_DB=mail # Write/change the database name in the .env file
- DATABASE_HOST=localhost
- POSTGRES_HOST_AUTH_METHOD=trust # No password is needed when this option is on
Now inside the parent app folder, run the following code to build and run :
docker-compose up --build
And with this every thing should run fine.
Warnings
- As there is an active issue related to mount files in wsl2 to host. If this issue is still not solved, the server which will run the Laravel could be slow. If you find this problem, please rebuild the container with wsl1 and it should be fine.