You will first need to install docker and docker-compose on your development machine. I strongly recommend you use a Linux machine; the code below is all using Ubuntu 22.04
- First, let's create a new Laravel application using composer. If composer is installed on your development host, you can use it directly. Otherwise, you can use the compose Docker official image to do it:
# This command runs the official composer image in interactive mode (--interactive)
# in a pseudo-TTY (--tty)
# with the current directory mapped to /app in the container (--volume $PWD:/app)
# with the current user context (--user $(id -u):$(id -g)).
# It runs the composer command: "composer create-project laravel/laravel laravel-gis"
# which will install Laravel with composer in a directory called larave-gis
# The --rm flag will remove the container once the command as finished
docker run --rm --interactive --tty \
--volume $PWD:/app \
--user $(id -u):$(id -g) \
composer create-project laravel/laravel laravel-gis
- Create a few extra needed files, folders, and permissions in the new project directory:
cd laravel-gis
touch docker-compose.yml
mkdir -p docker/nginx
touch docker/nginx/nginx-site.conf
sudo chown -R 33:33 .
sudo chmod -R 777 .
We use some pretty dangerous permission settings here. Still, it's a development environment, and we will need write/execute permissions on pretty much all of our project files and directories. We will see how to set up security permissions for our production environment in a future post. Don't use this setup in production
- We will need two docker services to get our environment working with php-fpm and nginx; create two services in the docker-compose.yml file:
version: "3.7"
networks:
frontend:
backend:
services:
# nginx proxy service (based on nginx official image) to act as a web server and proxy server
proxy:
image: nginx:latest
# map local port 8080 to containers's port 80
ports:
- "8080:80"
# map the current directory to /var/www/app in the container
# and map our the nginx-site.conf to the nginx default site in the container
volumes:
- ./:/var/www/app
- ./docker/nginx/nginx-site.conf:/etc/nginx/conf.d/default.conf
networks:
- frontend
- backend
# php-fpm service (based on php official image) to process our php code
php:
image: php:8.1-fpm
# map the current directory to /var/www/app in the container (the same as for the proxy service)
volumes:
- ./:/var/www/app
networks:
- backend
- Put the following content in the docker/nginx/nginx-site.conf file:
server {
listen 80;
# our root directory points to the public Laravel directory
root /var/www/app/public;
index index.php;
server_name _;
# Redirects all queries to routes without extension (/dashboard for instance) to their
# equivalents but with a trailing /index.php (/dashboard/index.php) so it hits the next location
location / {
try_files $uri $uri/ /index.php$is_args$args;
}
# Sends all php queries to the php container (named php in our case) on port 9000
location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass php:9000;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
}
}
- Run "docker-compose up" and go to http://localhost:8080 in your browser; you should see the blank laravel welcome page confirming that everything is working properly:
We now have a php-fpm official docker image running our PHP and served through an Nginx proxy. However, we will need a few extra PHP extensions to run Laravel and Postgres. We will need to build our own PHP image based on the official one to do so. We will also install npm (nodejs) and composer in the development image. "Luckily," this can be achieved with a "simple" single one-liner in the Dockerfile.
- Create a new folder called docker/php and a new file called Dockerfile in it:
mkdir docker/php
touch docker/php/Dockerfile
- Put the following content in the file:
# php official fpm image
FROM php:8.1-fpm
# installs basic tools, then postgres ppa then nodejs ppa then nodejs and postgresql-client packages
# (and some other required dependencies). It then installs and configures several php extensions
# including pdo_pgsql and redis. Finally, it downloads and installs composer in the image.
RUN apt-get update \
&& apt-get install -y gnupg curl wget ca-certificates unzip lsb-release \
&& wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-key add - \
&& echo "deb http://apt.postgresql.org/pub/repos/apt/ `lsb_release -cs`-pgdg main" | tee /etc/apt/sources.list.d/pgdg.list \
&& curl -sL https://deb.nodesource.com/setup_18.x | bash - \
&& apt-get install -y \
libicu-dev \
libpq-dev \
libzip-dev \
nodejs \
postgresql-client-14 \
&& pecl install redis \
&& docker-php-ext-enable redis \
&& docker-php-ext-configure pgsql -with-pgsql=/usr/local/pgsql \
&& docker-php-ext-install intl pdo pdo_pgsql pgsql zip bcmath pcntl exif \
&& php -r "readfile('http://getcomposer.org/installer');" | php -- --install-dir=/usr/bin/ --filename=composer \
&& npm install -g npm \
&& apt-get -y autoremove \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* \
&& chown -R www-data:www-data /var/www
WORKDIR /var/www/app
USER www-data
- Now, let's make a few changes to our docker-compose.yml file:
version: "3.7"
networks:
frontend:
backend:
services:
proxy:
image: nginx:latest
ports:
- "8080:80"
volumes:
- ./:/var/www/app
- ./docker/nginx/nginx-site.conf:/etc/nginx/conf.d/default.conf
networks:
- frontend
- backend
php:
image: php:8.1-fpm
# give docker the build context, docker file and image name and tag
build:
context: ./docker/php
dockerfile: Dockerfile
image: laravelgis-php:latest
volumes:
- ./:/var/www/app
networks:
- backend
- We can now run "docker-compose build" and see if our image compiles correctly; the process of building the new image can take a few minutes:
- Run "docker-compose up" again and browse to http://localhost:8080 to make sure everything is still running correctly
We now have a fully functional Laravel / PHP development environment running in docker; in the next post, we will install and configure Postgresql and Redis.
The commit for this post is available here: laravel-php-and-docker
Also posted in #9 nginx reverse proxy as trying to get working using Sail.
I've also come back to also try building a new Docker container directly - would prefer to use this method but very limited experience using Docker (not that I'm much more experienced with Sail)
Initial installation works, local host set up, but docker-compose build falls over after a couple of mins. I've tried the code from above, and amendments in video to update to php 8.2 and postgres 15. The ammended version runs gets futhest but then stops at.
#0 155.7 All settings correct for using Composer
#0 155.7 Downloading...
#0 156.5
#0 156.5 Composer (version 2.5.8) successfully installed to: /usr/bin/composer
#0 156.5 Use it: php /usr/bin/composer
#0 156.5
#0 156.6 /bin/sh: 1: npm: not found
failed to solve: process "/bin/sh -c apt-get update && apt-get install -y gnupg curl wget ca-certificates unzip lsb-release && wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-key add - && echo "deb http://apt.postgresql.org/pub/repos/apt/
lsb_release -cs
-pgdg main" | tee /etc/apt/sources.list.d/pgdg.list && curl -sL https://deb.nodesource.com/setup_16.x | bash - && apt-get install -y libicu-dev libpq-dev libzip-dev nodejs postgresql-client-15 && pecl install redis && docker-php-ext-enable redis && docker-php-ext-configure pgsql -with-pgsql=/usr/local/pgsql && docker-php-ext-install intl pdo pdo_pgsql pgsql zip bcmath pcntl exif && php -r "readfile('http://getcomposer.org/installer');" | php -- --install-dir=/usr/bin/ --filename=composer && npm install -g npm && apt-get -y autoremove && apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* && chown -R www-data:www-data /var/www" did not complete successfully: exit code: 127Hello Steve,
Try changing this line in the Dockerfile:
with this line:
Let me know if it works and I will update the post.
Cheers!
Yes, update worked. Thanks very much.
Need to learn more about docker so I know how to keep the configurations upto date.
Hello Steve,
Thanks for your feedback, I updated the article!
Cheers!