This guide will help you get started with Laravel 7 and Docker on Windows.

To continue ensure you have Docker and Git installed on your windows PC.

Being a windows user,

When you mount volumes in Docker for database use, it does not let you access that volume via the windows host file system, (this applies to volume mounts not bind mounts) as “When running linux based containers on a windows host, the actual volumes will be stored within the linux VM and will not be available on the host’s file system” .

Which becomes an issue when you want to backup your databases. So I prefer to have MySQL, Mongo etc. installed on my host PC, making backups, and data manipulation easier.

I use Laragon for this purpose which starts up with windows and starts my MySQL and Mongo Db’s automatically.

For my development I use the Visual Studio Code IDE.

2 changes to make your life easier are. 1. Install the docker plugin, which will allow you to manage containers and images in your IDE, and set your default terminal to bash.

Create a folder with your desired project name

md laravel-dockerized cd laravel-dockerized

Lets clone latest Laravel version into current directory

git clone https://github.com/laravel/laravel.git .

Delete the .git folder

DEL .git

Create a copy of .env.example and name it as .env

Now we will create a folder to hold our docker files and docker container configurations , and we will have a docker-compose.yml file which will be used in development to launch our containers. Create the following folders and files

Docker Compose is a tool for defining and running multi-container Docker applications. With Compose, you use a YAML file to configure your application’s services. Then, with a single command, you create and start all the services from your configuration.

//Folders docker docker

ginx docker

ginx\conf.d docker

ginx\certs docker\php //Files docker-compose.yml Dockerfile docker\php\local.ini docker

ginx\certs\localhost.crt docker

ginx\certs\localhost.key docker

ginx\conf.d\app.conf

Contents for each of the files are below.



Customize container names accordingly in your docker-compose , webpack.mix.js and app.conf (line 12)



Container name can not contain spaces, use slug style names.

docker/nginx/conf.d/app.conf

( This file is the configuration which tells NGINX container to proxy requests to your PHP container. Change line 12 to match your PHP container name)

server { listen 80; listen 443 ssl; ssl_certificate /etc/nginx/certs/localhost.crt; ssl_certificate_key /etc/nginx/certs/localhost.key; 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 php-my-app:9000; #change this to match your app container name 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; } }

docker/nginx/certs/localhost.crt

(We use self signed certificates for SSL)

-----BEGIN CERTIFICATE----- MIIDRzCCAi+gAwIBAgIBATANBgkqhkiG9w0BAQsFADAUMRIwEAYDVQQDEwlsb2Nh bGhvc3QwHhcNMjAwMzE0MjIxMDA0WhcNMzAwMzE0MjIxMDA0WjAUMRIwEAYDVQQD Ewlsb2NhbGhvc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCaisZY L9fKlcIFcEvyHdYsMu9eMq9YWeP6aGQTA6/PBnTv9BU4A12XRV/JSHhW9XUcHDRo E4ny8TdJPGwAuVtw48+FEvggCGmerLHcf7LMfavkPG2dMZvVikIaqiQBdZNtKOnV JmVi1ZwMqdfcoCozJ2GbfbvE8TTan23QmgjWSjr275n7KAiRIAgYAQYGaGthOy5q 7T7k804ZCN5TmrHyRG55fWkhpY5GODbvfx/AogQxw1KjfrQ5bJH+6J8fzFzPAYri wKgLIsDr7ITRcioI9JeWJG8yH22tpNYzmWXz7hh06cNgVL0LP3t71kIvxxcFCAqa 1rwMZji+GRPjOWkvAgMBAAGjgaMwgaAwDAYDVR0TBAUwAwEB/zALBgNVHQ8EBAMC AvQwOwYDVR0lBDQwMgYIKwYBBQUHAwEGCCsGAQUFBwMCBggrBgEFBQcDAwYIKwYB BQUHAwQGCCsGAQUFBwMIMBEGCWCGSAGG+EIBAQQEAwIA9zAUBgNVHREEDTALgAls b2NhbGhvc3QwHQYDVR0OBBYEFJbCxsIacT7hFUdsiE+1/Y7RTnthMA0GCSqGSIb3 DQEBCwUAA4IBAQCNExAOV1kZLu7JdeKHtWTWSC8A99zAXwQj1AuLy+gE6mDSac2I D96zHqsXvr/loCJim0WNOuKLtu6Dv6UNSGN7z8IvW45EIg/LaBV9HXshCv9Uex/Q F9/mKKwem2y8SKwgZBho4J7trtSiYMaNZ5KFCXZ7zhCXYDP0uSf3W2LO7tqYQh3o mG9LtLUmE5vwi93IWbhvF0iW3VYXj8dLw7jqWcV4B3UpFr9KKbcrLZV0PIfEO480 nQ2cteQ7b6ovL46iTStjx4zCCxCuHL61lRmqzdOc66GtKM+y37ipUaRe1WnZpn51 6ljJ7bGdhc1u0/w/Z49wniY8lnlYiPbP6EMh -----END CERTIFICATE-----

docker/nginx/certs/localhost.key

(We use self signed certificates for SSL)

-----BEGIN RSA PRIVATE KEY----- MIIEogIBAAKCAQEAmorGWC/XypXCBXBL8h3WLDLvXjKvWFnj+mhkEwOvzwZ07/QV OANdl0VfyUh4VvV1HBw0aBOJ8vE3STxsALlbcOPPhRL4IAhpnqyx3H+yzH2r5Dxt nTGb1YpCGqokAXWTbSjp1SZlYtWcDKnX3KAqMydhm327xPE02p9t0JoI1ko69u+Z +ygIkSAIGAEGBmhrYTsuau0+5PNOGQjeU5qx8kRueX1pIaWORjg2738fwKIEMcNS o360OWyR/uifH8xczwGK4sCoCyLA6+yE0XIqCPSXliRvMh9traTWM5ll8+4YdOnD YFS9Cz97e9ZCL8cXBQgKmta8DGY4vhkT4zlpLwIDAQABAoIBADIdNlx6hzuGfLhO xhHpYv5KNh0RypKX87nMCEeyNlyn91uohwj27m6TbJBVE9D/H87RxpzJWT6Swh7Z nRxO/zwIY87/a77Xe4ic78BVGKH/TrJgdhs3bxU8FFuZOLvQaNJJJiqcnNwD8Oqa WQmOVqDn8Fr/1tfyb/VFJdMzYBI81tKj6ponWC0bIXkQqipfiRh6Eg7HLQkxdOUV tG7vGXINzwod/XH7JpEkJ3LYAeSzRGIRqK7CBtSVPrjcaaXFy4qme+vB89simdpb 71N0bM9IRwvi0cDnsyENVzL1rohuf8ZVnKTKbN9thRDZDOoMx7lV5LpBPf8Z8K+3 qyy1IoECgYEA0r7P1B/bAscjt8PJ0T8TD8cCVIeGSrsCIsDBmW/Se0TSwTZBjPHE Zzd+eSnmf3339lpEsMJv1oLcsBYrGxWspv9pTIZsL4A88tdBTT8zRVay+WyCkD3o A9xMM3M58vEv0hAV3aeGR/wN8OAFWIyEyOgkJibJd6/FHn1WYqi5y98CgYEAu7pU 549vr9LoblhVbTaeBnYw0nUw8SwIOWJE8CB/yfYQ3NIiYE6dD/lY7uIUTgCXJyuZ Sv+37G0IZfSOQ/oiMy32UL1lxgJEbQb2jluDEfG/1MC2w0zCtka3UE43Daep5Ap3 cfSpbqDrnvY7O5vqJ+CwdJ3/AGsueeCtjZFrDLECgYBBQ+aJAvSIf7OIDZJKwwXc NP17wBzOt+uJZ7iNFBxTIJVEUNEsHRN+A6mfTGKdyR0ppfrv4sdP32cJAVSIJsY5 UZACqv6GF2jIq/EFQzVVm+wBYqFsmj9oMqlGpcCkhB0TKPgclOz5Dg4jMr11Fs9o iLvpNMnfzwd00cwW8bnYcQKBgGg4aiqkVz0luiSIpeScDd9IfpJYvXMnHum8xMkL Qea91V7CypLtEgVsSRNWMC+d5Ey6x7/7eACqB5+Sxei3VYVUXws0GuxzFcnxs7AU 3g94Rye2VcDXPMI1QFA1HBtYmdkgdm+thOMGM8lsqjXNuZGqDEyx6oAxAPxo3/FY ajYBAoGAaOO46iOzk7otEv0aVx+bdVqSXo39oIOO5VFm8Na75iAB6VNiBHNVcMko DwKxuDy/589EawlnP2kxHoeBk9x/HFMl6Acggg6uxrAKXgZ6VrnWlnYlUKq9MQos eDQKFE0fOeCWfOleXRGUmDAyOwbW1+BuHcPv2zefk711V01jfxg= -----END RSA PRIVATE KEY-----

docker/php/local.ini

(Add any php ini settings you would like to overwrite in here)

upload_max_filesize=128M post_max_size=32M

docker-compose.yml

(if you are app does not have a UI , then you can remove the Node container and access your app on https://localhost . If you want to run a database as a container , you can add it here.

version: '3.1' services: #PHP Service app: build: context: . dockerfile: Dockerfile image: app container_name: php-my-app restart: unless-stopped tty: true environment: SERVICE_NAME: php-app working_dir: /var/www volumes: - ./:/var/www - /var/www/vendor #ignores the folder on host - ./docker/php/local.ini:/usr/local/etc/php/conf.d/local.ini networks: - app-network #Nginx Service For Development Only webserver: image: nginx:alpine container_name: webserver-my-app restart: unless-stopped tty: true ports: - "80:80" - "443:443" volumes: - ./:/var/www - ./docker/nginx/conf.d/:/etc/nginx/conf.d/ - ./docker/nginx/certs/:/etc/nginx/certs/ networks: - app-network #Node Service For Development Only node: image: node:10 container_name: node-my-app restart: unless-stopped tty: true working_dir: /var/www volumes: - ./:/var/www - /var/www/node_modules #ignores the folder on host ports: - "9056:9056" command: "tail -f /dev/null" #command to keep container running networks: - app-network #Docker Networks networks: app-network: driver: bridge

Dockerfile

(The PHP container is managed from this file. you will run migrations and artisan commands against this container as explained later)

FROM php:7.2-fpm # 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 #RUN mkdir -p vendor RUN chown www /var/www # Change current user to www USER www #Install Dependencies RUN composer install # Expose port 9000 and start php-fpm server EXPOSE 9000 CMD ["php-fpm"]

Edit you Laravel webpack.mix.js file

(Setup browser sync to a specific port that we exposed in our docker-compose.yml file)

let mix = require('laravel-mix'); mix .js('resources/js/app.js', 'public/js/app.js') .sass('resources/sass/app.scss', 'public/css/app.css') .browserSync({ proxy: 'https://webserver-my-app', //Webserver container name port: 9056 //exposed node container port });

That’s all the boiler plate you need to get started.

In order to connect to MYSQL or any database on you host PC , in your .env set your DB_HOST=host.docker.internal

Building Your Containers

docker-compose build

Starts Containers

docker-compose up -d

On first run to install node modules

docker exec node-my-app npm install

Once done and subsequent runs (Hot reloading)

Access your app on https://localhost:9056

docker exec node-my-app npm run watch

Compiling Assets for production:

Run all Mix tasks and minify output…

docker exec node-my-app npm run production

PHP artisan commands can be run in the same manner against your php app container

Code can be found on https://github.com/zaidk26/laravel-dockerized

To get your application deployed to production environment, a great tool to use is Dokku. Dokku helps you build and manage the lifecycle of applications. It will allow you to git push your code to your server, which will automatically re-bulid and and deploy your container with the new changes. Digital Ocean is a great and cost effective VPS provider that has one click installs for Dokku, (Tip. use a VPS with a least 2 GB of Memory) .

Drop a comment if you would like a tutorial on deploying Laravel Application on Dokku.