A Simple Docker Setup for Laravel Development
So, Laravel and the TALL stack – my go-to combo for building web apps 🚀. But, let’s be real, setting up a local development environment can sometimes feel like trying to fold a fitted sheet – frustrating and not much fun.
That’s where this blog post comes in. We’ll create a simpe & nifty docker-compose
setup that’ll make your Laravel development life a whole lot smoother. Say goodbye to the headaches of environment configuration and hello to more time spent actually building cool stuff. Let’s dive in!
Structure
Let’s closely examine the folder organization:
The app
folder is designated for your Laravel (or other code!) project. data
is reserved for database persistency, particularly if you favor a local volume, just like I do. The config
file encompasses all the additional configurations required, including the Dockerfile
for PHP. This is also the place where you can house your custom php.ini
and www.conf
if necessary.
my-app/
├─ docker-compose.yml
├─ app/
├─ data/
├─ config/
│ ├─ caddy/
│ │ ├─ Caddyfile
│ ├─ php/
│ │ ├─ Dockerfile
Dive into the Docker-verse: Your docker-compose.yml
Deconstructed
Let’s begin with the docker-compose.yml
file. It incorporates all the services essential for you to kickstart your work, primarily the app
service, along with redis
and mysql
. It’s worth noting that you have the flexibility to easily switch between versions or, for instance, substitute MySql with MariaDB.
version: '3.4'
networks:
app-network: # Our virtual space for services to chat with each other.
x-app-volume:
&app-volume # A volume alias, where we share files between your machine and the container.
type: bind
source: ./app
target: /var/www/html # The container's web directory.
x-app-dir: &app-dir /var/www/html # Another handy alias for directory paths.
services:
app:
build:
context: php/
dockerfile: Dockerfile # Your app service. Docker knows how to build it.
tty: true # Let's keep things chatty in the terminal.
restart: unless-stopped # The app restarts only when it needs to.
environment:
XDEBUG_CONFIG: "client_host=172.17.0.1"
XDEBUG_MODE: "debug"
XDEBUG_TRIGGER: "trigger" # Debugging goodness.
volumes:
- *app-volume # Share your code with the container.
working_dir: *app-dir # Work from the container's web directory.
networks:
- app-network # Our app needs a network to play with.
caddy:
image: caddy:2.6.4-alpine # Caddy's our web server.
ports:
- 80:80 # Access your app.
volumes:
- *app-volume # Share code with Caddy.
- ./caddy/Caddyfile:/etc/caddy/Caddyfile # Caddy's configuration.
depends_on:
- app
- mysql
networks:
- app-network
mysql:
image: mysql:8 # Our database.
restart: unless-stopped
tty: true
environment:
MYSQL_DATABASE: laravel
MYSQL_USER: laravel
MYSQL_PASSWORD: laravel
MYSQL_ROOT_PASSWORD: root
volumes:
- ./data:/var/lib/mysql # Data stays put with this volume.
ports:
- 3306:3306 # Database accessibility.
networks:
- app-network
redis:
image: redis:7 # Redis, if you need it for local development.
environment:
REDIS_PASSWORD: laravel
ports:
- 6379:6379
networks:
- app-network
You can also utilize an .env
file containing all the environmental variables you require. For instance:
DB_ROOT=root
DB_DATABASE=laravel
DB_USER=laravel
DB_PASSWORD=laravel
mysql:
image: mysql:8
restart: unless-stopped
tty: true
environment:
MYSQL_DATABASE: ${DB_DATABASE}
MYSQL_USER: ${DB_USER}
MYSQL_PASSWORD: ${DB_PASSWORD}
MYSQL_ROOT_PASSWORD: ${DB_ROOT}
volumes:
- ./data:/var/lib/mysql
ports:
- 3306:3306
networks:
- app-network
Inside the Dockerfile: Where the Magic Happens
Now, let’s talk about the Dockerfile
. In this streamlined setup, the objective is to have a single container responsible for both the application and its dependencies. This entails including both composer
and npm
within the same image.
FROM php:8.1-fpm-bullseye
# System dependencies
RUN apt-get update && apt-get install -y \
git \
curl \
ca-certificates \
gnupg \
libpng-dev \
libonig-dev \
libxml2-dev \
zip \
unzip \
libzip-dev
# Node
RUN mkdir -p /etc/apt/keyrings
RUN curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg
ENV NODE_MAJOR=20
RUN echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_$NODE_MAJOR.x nodistro main" | tee /etc/apt/sources.list.d/nodesource.list
RUN apt-get update && apt-get install -y nodejs
# Moving the cache to somewhere you have permission to write
ENV NPM_CONFIG_CACHE=/tmp/.npm
# Composer
COPY --from=composer:2.2.4 /usr/bin/composer /usr/local/bin/composer
# PHP extensions
RUN pecl install redis xdebug \
&& docker-php-ext-enable redis xdebug \
&& docker-php-ext-install pdo_mysql mbstring exif pcntl bcmath gd zip opcache
The Caddyfile: Making Local Development a Breeze
Lastly, the Caddyfile
, with HTTPS disabled to simplify our lives during local development. You can easily enable HTTPS by removing the http://
prefix from your site address.
http://localhost {
root * /var/www/html/public.
encode zstd gzip
php_fastcgi app:9000
file_server
tls internal
}
Let’s Get this Party Started: Docker at Your Command!
Now that you’ve got everything neatly set up, it’s time to kickstart your Laravel development playground. Here’s a quick guide on how to make the magic happen:
Starting Your Docker Environment:
docker-compose up -d
With this command, you’re launching your Docker containers in detached mode, meaning they’ll run in the background, leaving you free to continue your coding adventure.
Accessing the App Container:
To access your app container with the same user and group permissions as your host machine and run any composer
, npm
or artisan commands
:
docker-compose exec --user $(id -u):$(id -g) app bash
Conclusion
In conclusion, what we’ve explored here is a straightforward setup tailored for local development – a foundation upon which you can easily build and customize to suit your specific needs. Whether it’s tweaking configurations, adding new services, or refining it for deployment, this Docker-based environment is a place to start to craft the ideal development ecosystem for your projects. 🚀 🎨