Setup Docker Compose to run Laravel 8 on LEMP stack for local development
Tags: docker, laravel, nginxm, devops
Published: 2020-09-24 17:27:22

##Prologue
I recently went through the [great tutorial written by Digital Ocean](https://www.digitalocean.com/community/tutorials/how-to-set-up-laravel-nginx-and-mysql-with-docker-compose) about how to setup a Laravel app on top of a LEMP stack (Linux, Nginx, MySQL, PHP) using Docker compose. 

I did not use a server with Ubuntu 18.04 as they suggest in their prerequisites, but instead my local machine running **Windows 10 Pro**. That being said, I faced several bugs following their tutorial word by word so I would like to mention them and provide solutions below.  

##Step 0: Use Windows Pro or Enterprise
I tried running Docker on Windows Home before and it just brings so much pain since there is always something failing and you constantly need to find workarounds. Remove the hassle by upgrading your Windows version, you will then be able to enjoy Docker and Kubernetes powers simply by installing [Docker Desktop](https://www.docker.com/products/docker-desktop).

##First bug: Incorrect Dockerfile
Everything is pretty straightforward on the tutorial until step 8, when you finally have to launch your full environment defined by the *docker-composer.yml* file.

Indeed `docker-compose up -d` came with its bag of bugs and warnings:
- missing composer.lock file
- missing libzip-dev dependencies
- unnecessary mbstring dependency
- wrong php version, you need php >= 7.3 for Laravel 8

The working Dockerfile looks like this after the corrections:

```
FROM php:7.3-fpm

# Copy composer.lock and composer.json
COPY 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 \
    libzip-dev

# Clear cache
RUN apt-get clean && rm -rf /var/lib/apt/lists/*

# Install extensions
RUN docker-php-ext-install pdo_mysql 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"]
```

##Second bug: "Artisan command not found" and -T option
The tutorial forgets to mention that you need to run the `composer install` command inside the **app** container to install Laravel dependencies and create the *vendor* folder. To execute a command inside the container, use the following: 

`docker-compose exec -T composer install` 

> You will see an error saying "*the input device is not a TTY.  If you are using mintty, try prefixing the command with 'winpty'*" if you don't use the option -T after exec

Then you can successfully run : 
`docker-compose exec app php artisan key:generate`

Your Laravel app should be visible at [http://localhost](http://localhost) from now and you can run all `php artisan ...` inside the app container smoothly.

## Some tips

1. Instead of running commands inside your containers with `docker-compose exec ...`, you can use Docker Desktop GUI, from where you can open a separate terminal for each container. 

2. [Install MySQL Workbench](https://www.mysql.com/fr/products/workbench/) to visualize your database more easily

Hope this can help!
Best